Some of these functions are internal.
-=over 4
+=over
=cut
*/
#define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) )
/* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
-void fake(void) { ceil(1); }
+static void fake(void) { ceil(1); }
static int i_ppix_d(i_img *im, int x, int y, i_color *val);
static int i_gpix_d(i_img *im, int x, int y, i_color *val);
static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val);
static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
static int i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
-static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
-static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);
+static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
+static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
+/*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
+ static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
/*
=item ICL_new_internal(r, g, b, a)
{
0, /* channels set */
0, 0, 0, /* xsize, ysize, bytes */
- ~0, /* ch_mask */
+ ~0U, /* ch_mask */
i_8_bits, /* bits */
i_direct_type, /* type */
0, /* virtual */
void
i_img_destroy(i_img *im) {
- mm_log((1,"i_img_destroy(im* 0x%x)\n",im));
+ mm_log((1,"i_img_destroy(im %p)\n",im));
i_img_exorcise(im);
if (im) { myfree(im); }
}
i_img_getchannels(i_img *im) { return im->channels; }
-/*
-=item i_ppix(im, x, y, col)
-
-Sets the pixel at (I<x>,I<y>) in I<im> to I<col>.
-
-Returns true if the pixel could be set, false if x or y is out of
-range.
-
-=cut
-*/
-int
-(i_ppix)(i_img *im, int x, int y, i_color *val) { return im->i_f_ppix(im, x, y, val); }
-
-/*
-=item i_gpix(im, x, y, &col)
-
-Get the pixel at (I<x>,I<y>) in I<im> into I<col>.
-
-Returns true if the pixel could be retrieved, false otherwise.
-
-=cut
-*/
-int
-(i_gpix)(i_img *im, int x, int y, i_color *val) { return im->i_f_gpix(im, x, y, val); }
-
-/*
-=item i_ppix_pch(im, x, y, ch)
-
-Get the value from the channel I<ch> for pixel (I<x>,I<y>) from I<im>
-scaled to [0,1].
-
-Returns zero if x or y is out of range.
-
-Warning: this ignores the vptr interface for images.
-
-=cut
-*/
-float
-i_gpix_pch(i_img *im,int x,int y,int ch) {
- /* FIXME */
- if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) return ((float)im->idata[(x+y*im->xsize)*im->channels+ch]/255);
- else return 0;
-}
-
/*
=item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
}
+
+
+
+
+
+
+
+
+i_img*
+i_scaleaxis_3ch_8bit(i_img *im, int size, int Axis) {
+
+ int i, j;
+ int iEnd, jEnd;
+
+ int hsize, vsize;
+
+ short psave;
+ unsigned long *pixels;
+ i_color val;
+ i_img *new_img;
+
+ mm_log((1,"i_scaleaxis_3ch_8bit(im %p, size %d,Axis %d)\n",im, size, Axis));
+
+ if (Axis == XAXIS) {
+ hsize = size;
+ vsize = im->ysize;
+
+ jEnd = hsize;
+ iEnd = vsize;
+ pixels = mymalloc(sizeof(*pixels) * im->xsize);
+ } else {
+ hsize = im->xsize;
+ vsize = size;
+
+ jEnd = vsize;
+ iEnd = hsize;
+ pixels = mymalloc(sizeof(*pixels) * im->ysize);
+ }
+
+ new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
+
+
+ if (Axis == XAXIS) {
+
+ for (i=0; i<iEnd; i++) {
+ int end = im->xsize;
+
+ for(j=0; j<im->xsize; j++) {
+ i_gpix(im, j, i, &val);
+ pixels[j] = (val.rgba.r<<24) | (val.rgba.g<<16) | (val.rgba.b<<8) | (val.rgba.a<<0);
+ }
+
+ /* printf("jEnd = %d, end = %d\n", jEnd, end); */
+ while ((end+1)/2>=size) {
+ int lend = end/2;
+ end = (end+1) / 2;
+
+ for(j=0; j<lend; j++) {
+ unsigned long a = pixels[2*j];
+ unsigned long b = pixels[2*j+1];
+ pixels[j] = (((a ^ b) & 0xfefefefeUL) >> 1) + (a & b);
+ }
+ if (end>lend) {
+ pixels[j] = pixels[2*j];
+ j++;
+ }
+ }
+
+ printf("end = %d size = %d\n", end, size);
+
+ /* Replace this with Bresenham later */
+ for(j=0; j<size; j++) {
+ float f = i;
+ /* if ((i*size)/end <) */
+ unsigned long t = pixels[j];
+ val.rgba.r = (t >> 24) & 0xff;
+ val.rgba.g = (t >> 16) & 0xff;
+ val.rgba.b = (t >> 8) & 0xff;
+ val.rgba.a = t & 0xff;
+ i_ppix(new_img, j, i, &val);
+ }
+ }
+ }
+
+ return new_img;
+}
+
+
+
+
+
+
+
/*
=item i_scaleaxis(im, value, axis)
int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
int LanczosWidthFactor;
float *l0, *l1, OldLocation;
- int T, TempJump1, TempJump2;
+ int T;
+ float t;
float F, PictureValue[MAXCHANNELS];
short psave;
i_color val,val1,val2;
i_img *new_img;
- mm_log((1,"i_scaleaxis(im 0x%x,Value %.2f,Axis %d)\n",im,Value,Axis));
+ mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
+
if (Axis == XAXIS) {
- hsize = (int) ((float) im->xsize * Value);
+ return i_scaleaxis_3ch_8bit(im, (int)(0.5+im->xsize*Value), Axis);
+
+ hsize = (int)(0.5 + im->xsize * Value);
vsize = im->ysize;
jEnd = hsize;
iEnd = vsize;
-
- TempJump1 = (hsize - 1) * 3;
- TempJump2 = hsize * (vsize - 1) * 3 + TempJump1;
} else {
hsize = im->xsize;
- vsize = (int) ((float) im->ysize * Value);
-
+ vsize = (int)(0.5 + im->ysize * Value);
+
jEnd = vsize;
iEnd = hsize;
-
- TempJump1 = 0;
- TempJump2 = 0;
}
- new_img=i_img_empty_ch(NULL,hsize,vsize,im->channels);
-
- if (Value >=1) LanczosWidthFactor = 1;
- else LanczosWidthFactor = (int) (1.0/Value);
+ new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels);
+ /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */
+ LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value);
lMax = LanczosWidthFactor << 1;
- l0 = (float *) mymalloc(lMax * sizeof(float));
- l1 = (float *) mymalloc(lMax * sizeof(float));
+ l0 = mymalloc(lMax * sizeof(float));
+ l1 = mymalloc(lMax * sizeof(float));
for (j=0; j<jEnd; j++) {
OldLocation = ((float) j) / Value;
T = (int) (OldLocation);
F = OldLocation - (float) T;
- for (l = 0; l < lMax; l++) {
+ for (l = 0; l<lMax; l++) {
l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
- l1[l] = Lanczos(((float) (l + 1) - F) / (float) LanczosWidthFactor);
+ l1[l] = Lanczos(((float) (l+1) - F) / (float) LanczosWidthFactor);
}
- if (Axis== XAXIS) {
+ /* Make sure filter is normalized */
+ t = 0.0;
+ for(l=0; l<lMax; l++) {
+ t+=l0[l];
+ t+=l1[l];
+ }
+ t /= (float)LanczosWidthFactor;
+
+ for(l=0; l<lMax; l++) {
+ l0[l] /= t;
+ l1[l] /= t;
+ }
+
+ if (Axis == XAXIS) {
for (i=0; i<iEnd; i++) {
for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
- for (l=0; l < lMax; l++) {
- i_gpix(im,T+l+1, i, &val1);
- i_gpix(im,T-lMax+l+1, i, &val2);
+ for (l=0; l<lMax; l++) {
+ int mx = T-lMax+l+1;
+ int Mx = T+l+1;
+ mx = (mx < 0) ? 0 : mx;
+ Mx = (Mx >= im->xsize) ? im->xsize-1 : Mx;
+
+ i_gpix(im, Mx, i, &val1);
+ i_gpix(im, mx, i, &val2);
+
for (k=0; k<im->channels; k++) {
- PictureValue[k] += l1[l] * val1.channel[k];
+ PictureValue[k] += l1[l] * val1.channel[k];
PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
}
}
for(k=0;k<im->channels;k++) {
- psave = (short)( PictureValue[k] / LanczosWidthFactor);
+ psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
val.channel[k]=minmax(0,255,psave);
}
- i_ppix(new_img,j,i,&val);
+ i_ppix(new_img, j, i, &val);
}
} else {
for (i=0; i<iEnd; i++) {
for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
for (l=0; l < lMax; l++) {
- i_gpix(im,i, T+l+1, &val1);
- i_gpix(im,i, T-lMax+l+1, &val2);
+ int mx = T-lMax+l+1;
+ int Mx = T+l+1;
+ mx = (mx < 0) ? 0 : mx;
+ Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx;
+
+ i_gpix(im, i, Mx, &val1);
+ i_gpix(im, i, mx, &val2);
for (k=0; k<im->channels; k++) {
- PictureValue[k] += l1[l] * val1.channel[k];
+ PictureValue[k] += l1[l] * val1.channel[k];
PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
}
}
for (k=0; k<im->channels; k++) {
- psave = (short)( PictureValue[k] / LanczosWidthFactor);
- val.channel[k]=minmax(0,255,psave);
+ psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
+ val.channel[k] = minmax(0, 255, psave);
}
- i_ppix(new_img,i,j,&val);
+ i_ppix(new_img, i, j, &val);
}
}
myfree(l0);
myfree(l1);
- mm_log((1,"(0x%x) <- i_scaleaxis\n",new_img));
+ mm_log((1,"(%p) <- i_scaleaxis\n", new_img));
return new_img;
}
}
}
+/*
+=item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
+
+Returns an image of the same type (sample size).
+
+For paletted images the equivalent direct type is returned.
+
+=cut
+*/
+
+i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) {
+ if (src->bits == 8) {
+ return i_img_empty_ch(NULL, xsize, ysize, channels);
+ }
+ else if (src->bits == i_16_bits) {
+ return i_img_16_new(xsize, ysize, channels);
+ }
+ else if (src->bits == i_double_bits) {
+ return i_img_double_new(xsize, ysize, channels);
+ }
+ else {
+ i_push_error(0, "Unknown image bits");
+ return NULL;
+ }
+}
+
/*
=item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
parm[1]=(double)ny;
/* fprintf(stderr,"(%d,%d) ->",nx,ny); */
- rx=op_run(opx,opxl,parm,parmlen);
- ry=op_run(opy,opyl,parm,parmlen);
+ rx=i_op_run(opx,opxl,parm,parmlen);
+ ry=i_op_run(opy,opyl,parm,parmlen);
/* fprintf(stderr,"(%f,%f)\n",rx,ry); */
i_gpix(im,rx,ry,&val);
i_ppix(new_img,nx,ny,&val);
return colorcnt;
}
-
-symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
- i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
- i_img_info,i_img_setmask,i_img_getmask,i_ppix,i_gpix,
- i_box,i_draw,i_arc,i_copyto,i_copyto_trans,i_rubthru};
-
-
/*
=back
=cut
*/
+static
int
i_ppix_d(i_img *im, int x, int y, i_color *val) {
int ch;
=cut
*/
+static
int
i_gpix_d(i_img *im, int x, int y, i_color *val) {
int ch;
if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
for(ch=0;ch<im->channels;ch++)
- val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
+ val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch];
return 0;
}
+ for(ch=0;ch<im->channels;ch++) val->channel[ch] = 0;
return -1; /* error was cliped */
}
=cut
*/
+static
int
i_glin_d(i_img *im, int l, int r, int y, i_color *vals) {
int ch, count, i;
=cut
*/
+static
int
i_plin_d(i_img *im, int l, int r, int y, i_color *vals) {
int ch, count, i;
=cut
*/
+static
int
i_ppixf_d(i_img *im, int x, int y, i_fcolor *val) {
int ch;
=cut
*/
+static
int
i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) {
int ch;
=cut
*/
+static
int
i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
int ch, count, i;
=cut
*/
+static
int
i_plinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) {
int ch, count, i;
=cut
*/
-int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
- int *chans, int chan_count) {
+static
+int
+i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps,
+ const int *chans, int chan_count) {
int ch, count, i, w;
unsigned char *data;
=cut
*/
-int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
- int *chans, int chan_count) {
+static
+int
+i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps,
+ const int *chans, int chan_count) {
int ch, count, i, w;
unsigned char *data;
for (ch = 0; ch < chan_count; ++ch) {
=cut
*/
int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
- int *chans, int chan_count) {
+ int const *chans, int chan_count) {
i_sample_t *work;
if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) {
gci->cpos = 0;
gci->length = did_read;
- copy_size = min(length, gci->length);
+ copy_size = i_min(length, gci->length);
memcpy(buf, gci->buffer, copy_size);
gci->cpos += copy_size;
buf += copy_size;
}
/*
-=item free_gen_read_data(i_gen_read_data *)
+=item i_free_gen_read_data(i_gen_read_data *)
Cleans up.
=cut
*/
-void free_gen_read_data(i_gen_read_data *self) {
+void i_free_gen_read_data(i_gen_read_data *self) {
myfree(self);
}
Allocates and initializes the data structure used by i_gen_writer.
-This should be released with L<image.c/free_gen_write_data>
+This should be released with L<image.c/i_free_gen_write_data>
=cut
*/
i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
self->cb = cb;
self->userdata = userdata;
- self->maxlength = min(max_length, sizeof(self->buffer));
+ self->maxlength = i_min(max_length, sizeof(self->buffer));
if (self->maxlength < 0)
self->maxlength = sizeof(self->buffer);
self->filledto = 0;
}
/*
-=item free_gen_write_data(i_gen_write_data *info, int flush)
+=item i_free_gen_write_data(i_gen_write_data *info, int flush)
Cleans up the write buffer.
=cut
*/
-int free_gen_write_data(i_gen_write_data *info, int flush)
+int i_free_gen_write_data(i_gen_write_data *info, int flush)
{
int result = !flush ||
info->filledto == 0 ||
return result;
}
+
+
+/*
+=item i_test_format_probe(io_glue *data, int length)
+
+Cleans up the write buffer.
+
+Will flush any left-over data if I<flush> is non-zero.
+
+Returns non-zero if flush is zero or if info->cb() returns non-zero.
+
+Return zero only if flush is non-zero and info->cb() returns zero.
+ie. if it fails.
+
+=cut
+*/
+
+
+char *
+i_test_format_probe(io_glue *data, int length) {
+
+ static struct {
+ char *magic;
+ char *name;
+ } formats[] = {
+ {"\xFF\xD8", "jpeg"},
+ {"GIF87a", "gif"},
+ {"GIF89a", "gif"},
+ {"MM\0*", "tiff"},
+ {"II*\0", "tiff"},
+ {"BM", "bmp"},
+ {"\x89PNG\x0d\x0a\x1a\x0a", "png"},
+ {"P1", "pnm"},
+ {"P2", "pnm"},
+ {"P3", "pnm"},
+ {"P4", "pnm"},
+ {"P5", "pnm"},
+ {"P6", "pnm"},
+ };
+ unsigned int i;
+ char head[18];
+ char *match = NULL;
+ ssize_t rc;
+
+ io_glue_commit_types(data);
+ rc = data->readcb(data, head, 18);
+ if (rc == -1) return NULL;
+ data->seekcb(data, -rc, SEEK_CUR);
+
+ for(i=0; i<sizeof(formats)/sizeof(formats[0]); i++) {
+ int c;
+ ssize_t len = strlen(formats[i].magic);
+ if (rc<len) continue;
+ c = !strncmp(formats[i].magic, head, len);
+ if (c) {
+ match = formats[i].name;
+ break;
+ }
+ }
+
+ if (match && !strcmp(match, "jpeg")) {
+ unsigned int x0, x1;
+ rc = data->readcb(data, head, 18);
+ if (rc == -1) return NULL;
+ x0 = (unsigned char)head[0];
+ x1 = (unsigned char)head[1];
+ data->seekcb(data, -rc, SEEK_CUR);
+ printf("Jpeg reread: %x %x\n", x0, x1);
+ }
+
+ if (!match &&
+ (rc == 18) &&
+ tga_header_verify(head)) return "tga";
+ return match;
+}
+
+
+
+
/*
=back
+=head1 AUTHOR
+
+Arnar M. Hrafnkelsson <addi@umich.edu>
+
+Tony Cook <tony@develop-help.com>
+
=head1 SEE ALSO
L<Imager>, L<gif.c>