i_color *c;
c = i_color_new(red, green, blue, alpha);
ICL_DESTROY(c);
- i = i_img_new();
+ i = i_img_8_new();
i_img_destroy(i);
// and much more
void i_linker_bug_fake(void) { ceil(1); }
/*
-=item i_img_alloc()
+=item im_img_alloc(aIMCTX)
+X<im_img_alloc API>X<i_img_alloc API>
=category Image Implementation
+=synopsis i_img *im = im_img_alloc(aIMCTX);
+=synopsis i_img *im = i_img_alloc();
Allocates a new i_img structure.
}
/*
-=item i_img_init(C<img>)
+=item im_img_init(aIMCTX, image)
+X<im_img_init API>X<i_img_init API>
=category Image Implementation
+=synopsis im_img_init(aIMCTX, im);
+=synopsis i_img_init(im);
Imager internal initialization of images.
-Currently this does very little, in the future it may be used to
-support threads, or color profiles.
+See L</im_img_alloc(aIMCTX)> for more information.
=cut
*/
im_log((aIMCTX,1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a));
- if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n");
+ if ( (cl=mymalloc(sizeof(i_color))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
cl->rgba.r = r;
cl->rgba.g = g;
cl->rgba.b = b;
im_log((aIMCTX,1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
if (cl == NULL)
if ( (cl=mymalloc(sizeof(i_color))) == NULL)
- i_fatal(2,"malloc() error\n");
+ im_fatal(aIMCTX, 2,"malloc() error\n");
cl->rgba.r=r;
cl->rgba.g=g;
cl->rgba.b=b;
im_log((aIMCTX, 1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a));
- if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n");
+ if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n");
cl->rgba.r = r;
cl->rgba.g = g;
cl->rgba.b = b;
dIMCTXim(im);
im_log((aIMCTX, 1,"i_img_destroy(im %p)\n",im));
i_img_exorcise(im);
- if (im) { myfree(im); }
+ myfree(im);
im_context_refdec(aIMCTX, "img_destroy");
}
i_img_info(i_img *im, i_img_dim *info) {
dIMCTXim(im);
im_log((aIMCTX,1,"i_img_info(im %p)\n",im));
- if (im != NULL) {
- im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
- "mask=%ud\n",
- i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
- im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata));
- info[0] = im->xsize;
- info[1] = im->ysize;
- info[2] = im->channels;
- info[3] = im->ch_mask;
- } else {
- info[0] = 0;
- info[1] = 0;
- info[2] = 0;
- info[3] = 0;
- }
+
+ im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d "
+ "mask=%ud\n",
+ i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask));
+ im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata));
+ info[0] = im->xsize;
+ info[1] = im->ysize;
+ info[2] = im->channels;
+ info[3] = im->ch_mask;
}
/*
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>)
i_img_dim mx,my;
i_img_dim fx,fy;
i_img_dim x,y;
- int ch,c;
+ int ch;
i_img *new_img,*new_img2;
i_color val1,val2,dval1,dval2;
dIMCTXim(im);
new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
- c=0;
for(y=0;y<my;y++) for(x=0;x<fx;x++) {
i_gpix(im,x*2,y,&val1);
i_gpix(im,x*2+1,y,&val2);
for(x = 0; x < samp_cnt; ) {
colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
x += 3;
- if (colorcnt > maxc) {
+ if (colorcnt > maxc) {
+ myfree(samp);
octt_delete(ct);
return -1;
}
colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
x += 3;
if (colorcnt > maxc) {
- octt_delete(ct);
+ octt_delete(ct);
+ myfree(samp);
return -1;
}
}
}
}
-struct magic_entry {
- unsigned char *magic;
- size_t magic_size;
- char *name;
- unsigned char *mask;
-};
-
static int
-test_magic(unsigned char *buffer, size_t length, struct magic_entry const *magic) {
+test_magic(unsigned char *buffer, size_t length, struct file_magic_entry const *magic) {
if (length < magic->magic_size)
return 0;
if (magic->mask) {
{ (unsigned char *)(magic ""), sizeof(magic)-1, type, (unsigned char *)(mask) }
const char *
-i_test_format_probe(io_glue *data, int length) {
- static const struct magic_entry formats[] = {
+im_test_format_probe(im_context_t ctx, io_glue *data, int length) {
+ static const struct file_magic_entry formats[] = {
FORMAT_ENTRY("\xFF\xD8", "jpeg"),
FORMAT_ENTRY("GIF87a", "gif"),
FORMAT_ENTRY("GIF89a", "gif"),
/* JPEG 2000
This might match a little loosely */
FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"),
+
+ /* FLIF - Free Lossless Image Format - https://flif.info/spec.html */
+ FORMAT_ENTRY("FLIF", "flif")
};
- static const struct magic_entry more_formats[] = {
+ static const struct file_magic_entry more_formats[] = {
/* these were originally both listed as ico, but cur files can
include hotspot information */
FORMAT_ENTRY("\x00\x00\x01\x00", "ico"), /* Windows icon */
}
#endif
+ {
+ im_file_magic *p = ctx->file_magic;
+ while (p) {
+ if (test_magic(head, rc, &p->m)) {
+ return p->m.name;
+ }
+ p = p->next;
+ }
+ }
+
for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
- struct magic_entry const *entry = formats + i;
+ struct file_magic_entry const *entry = formats + i;
if (test_magic(head, rc, entry))
return entry->name;
return "tga";
for(i=0; i<sizeof(more_formats)/sizeof(more_formats[0]); i++) {
- struct magic_entry const *entry = more_formats + i;
+ struct file_magic_entry const *entry = more_formats + i;
if (test_magic(head, rc, entry))
return entry->name;
if (im->type == i_palette_type
&& i_colorcount(im) == 2) {
i_color colors[2];
- i_getcolors(im, 0, colors, 2);
+ if (!i_getcolors(im, 0, colors, 2))
+ return 0;
if (im->channels == 3) {
if (colors[0].rgb.r == 255 &&
colors[0].rgb.g == 255 &&