The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# setting -file dodgy ...
# must start from an open file ... ?



# Copyright 2011, 2012, 2013 Kevin Ryde

# This file is part of Math-Image.
#
# Math-Image is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3, or (at your option) any later
# version.
#
# Math-Image is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with Math-Image.  If not, see <http://www.gnu.org/licenses/>.


package App::MathImage::Image::Base::BMP;
use 5.004;
use strict;
use Carp;
use Image::BMP ();

use vars '$VERSION', '@ISA';
$VERSION = 110;

use Image::Base;
@ISA = ('Image::Base');

# uncomment this to run the ### lines
#use Devel::Comments '###';

sub new {
  my ($class, %params) = @_;
  ### Image-Base-BMP new(): %params

  # $obj->new(...) means make a copy, with some extra settings
  if (ref $class) {
    croak "Cannot clone";
  }

  if (! defined $params{'-imagebmp'}) {
    $params{'-imagebmp'} = Image::BMP->new (Width  => ($params{'-width'}||0),
                                            Height => ($params{'-height'}||0));
  }
  my $self = bless {}, $class;
  $self->set (%params);

  if (defined $params{'-file'}) {
    $self->load;
  }

  ### new made: $self
  return $self;
}


my %attr_to_get_field = (-width    => 'Width',
                         -height   => 'Height',
                         -file     => 'file',
                         -ncolours => 'ColorsUsed',
                        );
### %attr_to_get_field
sub _get {
  my ($self, $key) = @_;
  ### Image-Base-BMP _get(): $key

  if (my $field = $attr_to_get_field{$key}) {
    ### $field
    ### is: $self->{'-imagebmp'}->{$field}
    return  $self->{'-imagebmp'}->{$field}
  }
  return $self->SUPER::_get ($key);
}

sub set {
  my ($self, %param) = @_;
  ### Image-Base-BMP set(): \%param

  foreach my $key ('-ncolours') {
    if (exists $param{$key}) {
      croak "Attribute $key is read-only";
    }
  }

  # apply this first
  if (my $bmp = delete $param{'-imagebmp'}) {
    $self->{'-imagebmp'} = $bmp;
  }

  foreach my $key (keys %param) {
    ### $key
    ### value: $param{$key}
    ### field: $attr_to_get_field{$key}
    if (my $field = $attr_to_get_field{$key}) {
      $self->{'-imagebmp'}->{$field} = delete $param{$key};
    }
  }

  %$self = (%$self, %param);
}

sub load {
  my ($self, $filename) = @_;
  ### Image-Base-BMP load(): @_
  my $bmp = $self->{'-imagebmp'};
  if (@_ == 1) {
    ### load() existing ...
    $bmp->load;
  } else {
    ### load(): $filename
    $bmp->load($filename);
  }
}

sub save {
  my ($self, $filename) = @_;
  ### Image-Base-BMP save(): @_
  my $bmp = $self->{'-imagebmp'};
  if (@_ == 1) {
    $bmp->load;
  } else {
    $bmp->load($filename);
  }
}

sub xy {
  my ($self, $x, $y, $colour) = @_;
  ### Image-Base-BMP xy: $x,$y,$colour
  my $bmp = $self->{'-imagebmp'};
  if (@_ == 4) {
    if ($colour =~ /^#(([0-9A-F]{3}){1,4})$/i) {
      my $len = length($1)/3; # of each group, so 1,2,3 or 4
      $bmp->xy_rgb ($x,$y,
                    (map {hex(substr($_ x 2, 0, 2))}  # first 2 chars
                     substr ($colour, 1, $len),
                     substr ($colour, 1+$len, $len),
                     substr ($colour, -$len)));
    } else {
      croak "Unrecognised colour: $colour";
    }

  } else {
    return sprintf ('#%02X%02X%02X', $bmp->xy_rgb ($x, $y));
  }
}

# sub add_colours {
#   my $self = shift;
#   ### add_colours: @_
#   $self->{'-imagebmp'}->addcolors (colors => \@_);
# }


1;
__END__

=for stopwords BMP filename Ryde RGB Image-Base-BMP

=head1 NAME

App::MathImage::Image::Base::BMP -- draw BMP images using Image::BMP

=head1 SYNOPSIS

 use App::MathImage::Image::Base::BMP;
 my $image = App::MathImage::Image::Base::BMP->new (-width => 100,
                                                    -height => 100);
 $image->rectangle (0,0, 99,99, '#FFF'); # white
 $image->xy (20,20, '#000');             # black
 $image->line (50,50, 70,70, '#FF00FF');
 $image->line (50,50, 70,70, '#0000AAAA9999');
 $image->save ('/some/filename.bmp');

=head1 CLASS HIERARCHY

C<App::MathImage::Image::Base::BMP> is a subclass of C<Image::Base>,

    Image::Base
      App::MathImage::Image::Base::BMP

=head1 DESCRIPTION

C<App::MathImage::Image::Base::BMP> extends C<Image::Base> to create or
update image files using the C<Image::BMP> module.

=head2 Colour Names

There's no named colours as such, only hex

    #RGB
    #RRGGBB
    #RRRGGGBBB
    #RRRRGGGGBBBB

=head1 FUNCTIONS

=over 4

=item C<$image = App::MathImage::Image::Base::BMP-E<gt>new (key=E<gt>value,...)>

Create and return a new image object.  A new image can be started with
C<-width> and C<-height>,

    $image = App::MathImage::Image::Base::BMP->new (-width => 200, -height => 100);

Or an existing file can be read,

    $image = App::MathImage::Image::Base::BMP->new (-file => '/some/filename.bmp');

Or an C<Image::BMP> object can be given,

    my $bmpobj = Image::BMP->new (20, 10);
    $image = App::MathImage::Image::Base::BMP->new (-imagebmp => $bmpobj);

=item C<$new_image = $image-E<gt>new (key=E<gt>value,...)>

There's no image clone as yet.

=item C<$image-E<gt>load ()>

=item C<$image-E<gt>load ($filename)>

Read the C<-file>, or set C<-file> to C<$filename> and then read.

=item C<$image-E<gt>save ()>

=item C<$image-E<gt>save ($filename)>

Save to C<-file>, or with a C<$filename> argument set C<-file> then save to
that.

=back

=head1 ATTRIBUTES

=over

=item C<-width> (integer)

=item C<-height> (integer)

The size of the image.

=item C<-imagebmp>

The underlying C<Image::BMP> object.

=back

=head1 SEE ALSO

L<Image::Base>,
L<Image::BMP>

=cut