return;
}
}
+ elsif (%hsh) {
+ Imager->_set_error("new: supply xsize and ysize or a file access parameter or no parameters");
+ return;
+ }
return $self;
}
# Sets an image to a certain size and channel number
# if there was previously data in the image it is discarded
+my %model_channels =
+ (
+ gray => 1,
+ graya => 2,
+ rgb => 3,
+ rgba => 4,
+ );
+
sub img_set {
my $self=shift;
my %hsh=(xsize=>100, ysize=>100, channels=>3, bits=>8, type=>'direct', @_);
- if (defined($self->{IMG})) {
- # let IIM_DESTROY destroy it, it's possible this image is
- # referenced from a virtual image (like masked)
- #i_img_destroy($self->{IMG});
- undef($self->{IMG});
+ undef($self->{IMG});
+
+ if ($hsh{model}) {
+ if (my $channels = $model_channels{$hsh{model}}) {
+ $hsh{channels} = $channels;
+ }
+ else {
+ $self->_set_error("new: unknown value for model '$hsh{model}'");
+ return;
+ }
}
if ($hsh{type} eq 'paletted' || $hsh{type} eq 'pseudo') {
}
unless ($self->{IMG}) {
- $self->{ERRSTR} = Imager->_error_as_msg();
+ $self->_set_error(Imager->_error_as_msg());
return;
}
return i_img_getchannels($self->{IMG});
}
+my @model_names = qw(unknown gray graya rgb rgba);
+
+sub colormodel {
+ my ($self, %opts) = @_;
+
+ $self->_valid_image("colormodel")
+ or return;
+
+ my $model = i_img_color_model($self->{IMG});
+
+ return $opts{numeric} ? $model : $model_names[$model];
+}
+
+sub colorchannels {
+ my ($self) = @_;
+
+ $self->_valid_image("colorchannels")
+ or return;
+
+ return i_img_color_channels($self->{IMG});
+}
+
+sub alphachannel {
+ my ($self) = @_;
+
+ $self->_valid_image("alphachannel")
+ or return;
+
+ return scalar(i_img_alpha_channel($self->{IMG}));
+}
+
# Get channel mask
sub getmask {
align_string() - L<Imager::Draw/align_string()> - draw text aligned on a
point
+alphachannel() - L<Imager::ImageTypes/alphachannel()> - return the
+channel index of the alpha channel (if any).
+
arc() - L<Imager::Draw/arc()> - draw a filled arc
bits() - L<Imager::ImageTypes/bits()> - number of bits per sample for the
close_log() - L<Imager::ImageTypes/close_log()> - close the Imager
debugging log.
+colorchannels() - L<Imager::ImageTypes/colorchannels()> - the number
+of channels used for color.
+
colorcount() - L<Imager::ImageTypes/colorcount()> - the number of
colors in an image's palette (paletted images only)
+colormodel() - L<Imager::ImageTypes/colorcount()> - how color is
+represented.
+
combine() - L<Imager::Transformations/combine()> - combine channels
from one or more images.
i_img_get_height(im)
Imager::ImgRaw im
+int
+i_img_color_model(im)
+ Imager::ImgRaw im
+
+int
+i_img_color_channels(im)
+ Imager::ImgRaw im
+
+int
+i_img_alpha_channel(im)
+ Imager::ImgRaw im
+ CODE:
+ if (!i_img_alpha_channel(im, &RETVAL))
+ XSRETURN(0);
+ OUTPUT:
+ RETVAL
void
i_img_is_monochrome(im)
sub make_func_list {
- my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log mm_log i_img_color_channels i_img_has_alpha i_img_dim i_DF i_DFc i_DFp i_DFcp i_psamp_bits i_gsamp_bits i_psamp i_psampf);
+ my @funcs =
+ qw(i_img i_color i_fcolor i_fill_t mm_log mm_log i_color_model_t
+ im_context_t i_img_dim i_img_dim_u im_slot_t
+ i_polygon_t i_poly_fill_mode_t i_mutex_t
+ i_img_has_alpha i_DF i_DFc i_DFp i_DFcp i_psamp_bits i_gsamp_bits
+ i_psamp i_psampf);
open FUNCS, "< imexttypes.h"
or die "Cannot open imexttypes.h: $!\n";
my $in_struct;
return im->ysize;
}
+/*
+=item i_img_color_model(im)
+=category Image Information
+=synopsis i_color_model_t cm = i_img_color_model(im);
+
+Returns the color model for the image.
+
+A future version of Imager will allow for images with extra channels
+beyond gray/rgb and alpha.
+
+=cut
+*/
+i_color_model_t
+i_img_color_model(i_img *im) {
+ return (i_color_model_t)im->channels;
+}
+
+/*
+=item i_img_alpha_channel(im, &channel)
+=category Image Information
+=synopsis int alpha_channel;
+=synopsis int has_alpha = i_img_alpha_channel(im, &alpha_channel);
+
+Work out the alpha channel for an image.
+
+If the image has an alpha channel, sets C<*channel> to the alpha
+channel index and returns non-zero.
+
+If the image has no alpha channel, returns zero and C<*channel> is not
+modified.
+
+C<channel> may be C<NULL>.
+
+=cut
+*/
+
+int
+i_img_alpha_channel(i_img *im, int *channel) {
+ i_color_model_t model = i_img_color_model(im);
+ switch (model) {
+ case icm_gray_alpha:
+ case icm_rgb_alpha:
+ if (channel) *channel = (int)model - 1;
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/*
+=item i_img_color_channels(im)
+=category Image Information
+=synopsis int color_channels = i_img_color_channels(im);
+
+Returns the number of color channels in the image. For now this is
+always 1 (for grayscale) or 3 (for RGB) but may be 0 in some special
+cases in a future release of Imager.
+
+=cut
+*/
+
+int
+i_img_color_channels(i_img *im) {
+ i_color_model_t model = i_img_color_model(im);
+ switch (model) {
+ case icm_gray_alpha:
+ case icm_rgb_alpha:
+ return (int)model - 1;
+
+ case icm_gray:
+ case icm_rgb:
+ return (int)model;
+
+ default:
+ return 0;
+ }
+}
+
/*
=item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
int i_img_getchannels(i_img *im);
i_img_dim i_img_get_width(i_img *im);
i_img_dim i_img_get_height(i_img *im);
+i_color_model_t i_img_color_model(i_img *im);
+int i_img_alpha_channel(i_img *im, int *channel);
+int i_img_color_channels(i_img *im);
/* Base functions */
typedef struct i_render_tag i_render;
+/*
+=item i_color_model_t
+=category Data Types
+=order 95
+
+Returned by L<i_img_color_model(im)> to indicate the color model of
+the image.
+
+An enumerated type with the following possible values:
+
+=over
+
+=item *
+
+C<icm_unknown> - the image has no usable color data. In future
+versions of Imager this will be returned in a few limited cases,
+eg. when the source image is CMYK and the user has requested no color
+translation is done.
+
+=item *
+
+C<icm_gray> - gray scale with no alpha channel.
+
+=item *
+
+C<icm_gray_alpha> - gray scale with an alpha channel.
+
+=item *
+
+C<icm_rgb> - RGB
+
+=item *
+
+C<icm_rgb_alpha> - RGB with an alpha channel.
+
+=back
+
+=cut
+*/
+
+typedef enum {
+ icm_unknown,
+ icm_gray,
+ icm_gray_alpha,
+ icm_rgb,
+ icm_rgb_alpha
+} i_color_model_t;
+
#ifdef IMAGER_FORMAT_ATTR
#define I_FORMAT_ATTR(format_index, va_index) \
__attribute ((format (printf, format_index, va_index)))
i_poly_poly_aa,
i_poly_poly_aa_cfill,
i_poly_aa_m,
- i_poly_aa_cfill_m
+ i_poly_aa_cfill_m,
+
+ /* level 10 */
+ i_img_alpha_channel,
+ i_img_color_model,
+ i_img_color_channels
};
/* in general these functions aren't called by Imager internally, but
#define im_push_errorf (im_extt->f_im_push_errorf)
+#define i_img_alpha_channel(im, channel) ((im_extt->f_i_img_alpha_channel)((im), (channel)))
+#define i_img_color_model(im) ((im_extt->f_i_img_color_model)((im)))
+#define i_img_color_channels(im) ((im_extt->f_i_img_color_channels)((im)))
+
#ifdef IMAGER_LOG
#ifndef IMAGER_NO_CONTEXT
#define mm_log(x) { i_lhead(__FILE__,__LINE__); i_loog x; }
will result in an increment of IMAGER_API_LEVEL.
*/
-#define IMAGER_API_LEVEL 9
+#define IMAGER_API_LEVEL 10
typedef struct {
int version;
const double *y, i_poly_fill_mode_t mode,
i_fill_t *fill);
- /* IMAGER_API_LEVEL 10 functions will be added here */
-
+ /* IMAGER_API_LEVEL 10 */
+ int (*f_i_img_alpha_channel)(i_img *im, int *channel);
+ i_color_model_t (*f_i_img_color_model)(i_img *im);
+ int (*f_i_img_color_channels)(i_img *im);
+ /* IMAGER_API_LEVEL 11 functions will be added here */
} im_ext_funcs;
#define PERL_FUNCTION_TABLE_NAME "Imager::__ext_func_table"
=cut
*/
-#define i_img_has_alpha(im) ((im)->channels == 2 || (im)->channels == 4)
-
-/*
-=item i_img_color_channels(C<im>)
-
-=category Image Information
-
-The number of channels holding color information.
-
-=cut
-*/
-
-#define i_img_color_channels(im) (i_img_has_alpha(im) ? (im)->channels - 1 : (im)->channels)
+#define i_img_has_alpha(im) (i_img_alpha_channel((im), NULL))
/*
=item i_psamp(im, left, right, y, samples, channels, channel_count)
int channels = i_img_getchannels(img);
i_img_dim width = i_img_get_width(im);
i_img_dim height = i_img_get_height(im);
+ i_color_model_t cm = i_img_color_model(im);
+ int alpha_channel;
+ int has_alpha = i_img_alpha_channel(im, &alpha_channel);
+ int color_channels = i_img_color_channels(im);
# Image quantization
# Logging
+ # mutex
+ i_mutex_t mutex;
+
# Mutex functions
i_mutex_t m = i_mutex_new();
i_mutex_destroy(m);
May be larger than int on some platforms.
+=for comment
+From: File imdatatypes.h
+
+=item i_color_model_t
+
+Returned by L</i_img_color_model(im)> to indicate the color model of
+the image.
+
+An enumerated type with the following possible values:
+
+=over
+
+=item *
+
+C<icm_unknown> - the image has no usable color data. In future
+versions of Imager this will be returned in a few limited cases,
+eg. when the source image is CMYK and the user has requested no color
+translation is done.
+
+=item *
+
+C<icm_gray> - gray scale with no alpha channel.
+
+=item *
+
+C<icm_gray_alpha> - gray scale with an alpha channel.
+
+=item *
+
+C<icm_rgb> - RGB
+
+=item *
+
+C<icm_rgb_alpha> - RGB with an alpha channel.
+
+=back
+
+
=for comment
From: File imdatatypes.h
=over
-=item i_img_color_channels(C<im>)
+=item i_img_alpha_channel(im, &channel)
+
+ int alpha_channel;
+ int has_alpha = i_img_alpha_channel(im, &alpha_channel);
+
+Work out the alpha channel for an image.
+If the image has an alpha channel, sets C<*channel> to the alpha
+channel index and returns non-zero.
-The number of channels holding color information.
+If the image has no alpha channel, returns zero and C<*channel> is not
+modified.
+
+C<channel> may be C<NULL>.
=for comment
-From: File immacros.h
+From: File image.c
+
+=item i_img_color_channels(im)
+
+ int color_channels = i_img_color_channels(im);
+
+Returns the number of color channels in the image. For now this is
+always 1 (for grayscale) or 3 (for RGB) but may be 0 in some special
+cases in a future release of Imager.
+
+
+=for comment
+From: File image.c
+
+=item i_img_color_model(im)
+
+ i_color_model_t cm = i_img_color_model(im);
+
+Returns the color model for the image.
+
+A future version of Imager will allow for images with extra channels
+beyond gray/rgb and alpha.
+
+
+=for comment
+From: File image.c
=item i_img_get_height(C<im>)
From: File log.c
+=back
+
+=head2 mutex
+
+=over
+
+=item i_mutex_t
+X<i_mutex>
+
+ i_mutex_t mutex;
+
+Opaque type for Imager's mutex API.
+
+
+=for comment
+From: File imdatatypes.h
+
+
=back
=head2 Mutex functions
=item *
+B<i_img_dim_u>
+
+=item *
+
+B<i_poly_fill_mode_t>
+
+=item *
+
+B<i_polygon_t>
+
+=item *
+
+B<im_context_t>
+
+=item *
+
B<im_lhead>
=item *
=item *
+B<im_slot_t>
+
+=item *
+
B<mm_log>
=item *
+C<model> - this overrides the value, if any, supplied for C<channels>.
+This can be one of C<gray>, C<graya>, C<rgb> or C<rgba>.
+
+=item *
+
C<bits> - The storage type for samples in the image. Default: 8.
Valid values are:
my $img = Imager->new(file => $filename)
or die Imager->errstr;
+If none of C<xsize>, C<ysize>, C<file>, C<fh>, C<fd>, C<callback>,
+C<readcb> or C<data> is supplied, and other parameters I<are> supplied
+C<< Imager->new >> will return failure rather than returning an empty
+image object.
+
=item img_set()
img_set destroys the image data in the object and creates a new one
Same details apply as for L</getwidth()>.
=item getchannels()
+X<getchannels() method>X<methods, getchannels()>
print "Image has ",$img->getchannels(), " channels\n";
-To get the number of channels in an image C<getchannels()> is used.
+Returns the number of channels in an image.
+
+Note: previously the number of channels in an image mapped directly to
+the color model of the image, ie a 4 channel image was always RGBA.
+This may change in a future release of Imager.
+
+Returns an empty list if the image object is not initialized.
+
+=item colorchannels()
+X<colorchannels() method>X<methods, colorchannels()>
+
+Returns the number of color channels.
+
+Currently this is always 1 or 3, but may be 0 for some rare images in
+a future version of Imager.
+
+Returns an empty list if the image object is not initialized.
+
+=item colormodel()
+X<colormodel method>X<methods, colormodel>
+
+Returns the color model of the image, including whether there is an
+alpha channel.
+By default this is returned as a string, one of C<unknown>, C<gray>,
+C<graya>, C<rgb> or C<rgba>.
+
+If you call C<colormodel()> with a true numeric parameter:
+
+ my $model = $img->colormodel(numeric => 1);
+
+then the color model is returned as a number, mapped as follows:
+
+ Numeric String
+ ------- ------
+ 0 unknown
+ 1 gray
+ 2 graya
+ 3 rgb
+ 4 rgba
+
+=item alphachannel()
+X<alphachannel() method>X<methods, alphachannel()>
+
+Returns the channel index of the alpha channel of the image.
+
+This is 1 for grayscale images with alpha, 3 for RGB images with alpha
+and will return C<undef> for all other images.
+
+Returns an empty list if the image object is not initialized.
=item bits()
# slower but more precise
}
+Returns an empty list if the image object is not initialized.
+
=item type()
The type() method returns either 'direct' for direct color images or
}
}
+Returns an empty list if the image object is not initialized.
+
=item virtual()
The virtual() method returns non-zero if the image contains no actual
If a real bi-level organization image is ever added to Imager, this
function will return true for that too.
+Returns an empty list if the image object is not initialized.
+
=back
=head2 Direct Type Images
# to make sure we get expected values
use strict;
-use Test::More tests => 466;
+use Test::More tests => 492;
BEGIN { use_ok(Imager => qw(:handy :all)) }
is($impal2->type, 'paletted', "check type");
is($impal2->getwidth, 200, "check width");
is($impal2->getheight, 201, "check height");
+is($impal2->colormodel, "rgb", "check color model (string)");
+is($impal2->colormodel(numeric => 1), 3, "check color model (numeric)");
+is($impal2->alphachannel, undef, "check alpha channel (has none)");
+is($impal2->colorchannels, 3, "check colorchannels");
{
my $red_idx = $impal2->addcolors(colors=>[$red]);
is($im->errstr, "getmask: empty input image", "check message");
is($im->setmask, undef, "can't set mask of empty image");
is($im->errstr, "setmask: empty input image", "check message");
+ is($im->colorchannels, undef, "can't get colorchannels of empty image");
+ is($im->errstr, "colorchannels: empty input image", "check message");
+ is($im->alphachannel, undef, "can't get alphachannel of empty image");
+ is($im->errstr, "alphachannel: empty input image", "check message");
+ is($im->colormodel, undef, "can't get colormodel of empty image");
+ is($im->errstr, "colormodel: empty input image", "check message");
}
{ # basic checks, 8-bit direct images
"check error message");
}
+{
+ my @tests =
+ (
+ [ "gray", 1, undef ],
+ [ "graya", 1, 1 ],
+ [ "rgb", 3, undef ],
+ [ "rgba", 3, 3 ],
+ );
+ for my $test (@tests) {
+ my ($model, $color_channels, $alpha) = @$test;
+ my $im = Imager->new(model => $model, xsize => 10, ysize => 10)
+ or die "Cannot create $model image:", Imager->errstr;
+ ok($im, "make a $model image via model");
+ is($im->colormodel, $model, "check colormodel is $model");
+ is($im->alphachannel, $alpha, "check alphachannel");
+ is($im->colorchannels, $color_channels, "check colorchannels");
+ }
+}
+
Imager->close_log();
unless ($ENV{IMAGER_KEEP_FILES}) {
print STDERR "Inline version $Inline::VERSION\n";
-plan tests => 117;
+plan tests => 120;
require Inline;
Inline->import(with => 'Imager');
Inline->import("FORCE"); # force rebuild
return 1;
}
+int
+color_channels(Imager im) {
+ return i_img_color_channels(im);
+}
+
+int
+color_model(Imager im) {
+ return (int)i_img_color_model(im);
+}
+
+int
+alpha_channel(Imager im) {
+ int channel;
+ if (!i_img_alpha_channel(im, &channel))
+ channel = -1;
+
+ return channel;
+}
+
EOS
my $im = Imager->new(xsize=>50, ysize=>50);
is($im->type, "paletted", "make sure we kept the image type");
}
+{
+ my $rgb = Imager->new(xsize => 10, ysize => 10);
+ is(color_model($rgb), 3, "check i_img_color_model() api");
+ is(color_channels($rgb), 3, "check i_img_color_channels() api");
+ is(alpha_channel($rgb), -1, "check i_img_alpha_channel() api");
+}
+
ok(test_mutex(), "call mutex APIs");
ok(test_slots(), "call slot APIs");
eg
equalities
gaussian
+grayscale
ie
infix
invocant