7 image.c - implements most of the basic functions of Imager and much of the rest
13 c = i_color_new(red, green, blue, alpha);
21 image.c implements the basic functions to create and destroy image and
22 color objects for Imager.
24 =head1 FUNCTION REFERENCE
26 Some of these functions are internal.
36 #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) )
38 /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */
39 void fake() { ceil(1); }
42 =item ICL_new_internal(r, g, b, a)
44 Return a new color object with values passed to it.
46 r - red component (range: 0 - 255)
47 g - green component (range: 0 - 255)
48 b - blue component (range: 0 - 255)
49 a - alpha component (range: 0 - 255)
55 ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
58 mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
60 if ( (cl=mymalloc(sizeof(i_color))) == NULL) m_fatal(2,"malloc() error\n");
65 mm_log((1,"(0x%x) <- ICL_new_internal\n",cl));
71 =item ICL_set_internal(cl, r, g, b, a)
73 Overwrite a color with new values.
75 cl - pointer to color object
76 r - red component (range: 0 - 255)
77 g - green component (range: 0 - 255)
78 b - blue component (range: 0 - 255)
79 a - alpha component (range: 0 - 255)
85 ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) {
86 mm_log((1,"ICL_set_internal(cl* 0x%x,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a));
88 if ( (cl=mymalloc(sizeof(i_color))) == NULL)
89 m_fatal(2,"malloc() error\n");
94 mm_log((1,"(0x%x) <- ICL_set_internal\n",cl));
100 =item ICL_add(dst, src, ch)
102 Add src to dst inplace - dst is modified.
104 dst - pointer to destination color object
105 src - pointer to color object that is added
106 ch - number of channels
112 ICL_add(i_color *dst,i_color *src,int ch) {
115 tmp=dst->channel[i]+src->channel[i];
116 dst->channel[i]= tmp>255 ? 255:tmp;
123 Dump color information to log - strictly for debugging.
125 cl - pointer to color object
131 ICL_info(i_color *cl) {
132 mm_log((1,"i_color_info(cl* 0x%x)\n",cl));
133 mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a));
139 Destroy ancillary data for Color object.
141 cl - pointer to color object
147 ICL_DESTROY(i_color *cl) {
148 mm_log((1,"ICL_DESTROY(cl* 0x%x)\n",cl));
153 =item IIM_new(x, y, ch)
155 Creates a new image object I<x> pixels wide, and I<y> pixels high with I<ch> channels.
162 IIM_new(int x,int y,int ch) {
164 mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch));
166 im=i_img_empty_ch(NULL,x,y,ch);
168 mm_log((1,"(0x%x) <- IIM_new\n",im));
174 IIM_DESTROY(i_img *im) {
175 mm_log((1,"IIM_DESTROY(im* 0x%x)\n",im));
184 Create new image reference - notice that this isn't an object yet and
185 this should be fixed asap.
195 mm_log((1,"i_img_struct()\n"));
196 if ( (im=mymalloc(sizeof(i_img))) == NULL)
197 m_fatal(2,"malloc() error\n");
206 im->i_f_ppix=i_ppix_d;
207 im->i_f_gpix=i_gpix_d;
210 mm_log((1,"(0x%x) <- i_img_struct\n",im));
215 =item i_img_empty(im, x, y)
217 Re-new image reference (assumes 3 channels)
220 x - xsize of destination image
221 y - ysize of destination image
227 i_img_empty(i_img *im,int x,int y) {
228 mm_log((1,"i_img_empty(*im 0x%x,x %d,y %d)\n",im,x,y));
230 if ( (im=mymalloc(sizeof(i_img))) == NULL)
231 m_fatal(2,"malloc() error\n");
237 im->bytes=x*y*im->channels;
238 if ( (im->data=mymalloc(im->bytes)) == NULL) m_fatal(2,"malloc() error\n");
239 memset(im->data,0,(size_t)im->bytes);
241 im->i_f_ppix=i_ppix_d;
242 im->i_f_gpix=i_gpix_d;
245 mm_log((1,"(0x%x) <- i_img_empty\n",im));
250 =item i_img_empty_ch(im, x, y, ch)
252 Re-new image reference
255 x - xsize of destination image
256 y - ysize of destination image
257 ch - number of channels
263 i_img_empty_ch(i_img *im,int x,int y,int ch) {
264 mm_log((1,"i_img_empty_ch(*im 0x%x,x %d,y %d,ch %d)\n",im,x,y,ch));
266 if ( (im=mymalloc(sizeof(i_img))) == NULL)
267 m_fatal(2,"malloc() error\n");
273 im->bytes=x*y*im->channels;
274 if ( (im->data=mymalloc(im->bytes)) == NULL) m_fatal(2,"malloc() error\n");
275 memset(im->data,0,(size_t)im->bytes);
277 im->i_f_ppix=i_ppix_d;
278 im->i_f_gpix=i_gpix_d;
281 mm_log((1,"(0x%x) <- i_img_empty_ch\n",im));
286 =item i_img_exorcise(im)
296 i_img_exorcise(i_img *im) {
297 mm_log((1,"i_img_exorcise(im* 0x%x)\n",im));
298 if (im->data != NULL) { myfree(im->data); }
304 im->i_f_ppix=i_ppix_d;
305 im->i_f_gpix=i_gpix_d;
310 =item i_img_destroy(im)
312 Destroy image and free data via exorcise.
320 i_img_destroy(i_img *im) {
321 mm_log((1,"i_img_destroy(im* 0x%x)\n",im));
323 if (im) { myfree(im); }
327 =item i_img_info(im, info)
329 Return image information
332 info - pointer to array to return data
334 info is an array of 4 integers with the following values:
339 info[3] - channel mask
346 i_img_info(i_img *im,int *info) {
347 mm_log((1,"i_img_info(im 0x%x)\n",im));
349 mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask));
350 mm_log((1,"i_img_info: data=0x%d\n",im->data));
353 info[2]=im->channels;
364 =item i_img_setmask(im, ch_mask)
366 Set the image channel mask for I<im> to I<ch_mask>.
371 i_img_setmask(i_img *im,int ch_mask) { im->ch_mask=ch_mask; }
375 =item i_img_getmask(im)
377 Get the image channel mask for I<im>.
382 i_img_getmask(i_img *im) { return im->ch_mask; }
385 =item i_img_getchannels(im)
387 Get the number of channels in I<im>.
392 i_img_getchannels(i_img *im) { return im->channels; }
396 =item i_ppix(im, x, y, col)
398 Sets the pixel at (I<x>,I<y>) in I<im> to I<col>.
400 Returns true if the pixel could be set, false if x or y is out of
406 i_ppix(i_img *im,int x,int y,i_color *val) { return im->i_f_ppix(im,x,y,val); }
409 =item i_gpix(im, x, y, &col)
411 Get the pixel at (I<x>,I<y>) in I<im> into I<col>.
413 Returns true if the pixel could be retrieved, false otherwise.
418 i_gpix(i_img *im,int x,int y,i_color *val) { return im->i_f_gpix(im,x,y,val); }
421 =item i_ppix_d(im, x, y, col)
425 This is the function kept in the i_f_ppix member of an i_img object.
426 It does a normal store of a pixel into the image with range checking.
428 Returns true if the pixel could be set, false otherwise.
433 i_ppix_d(i_img *im,int x,int y,i_color *val) {
436 if ( x>-1 && x<im->xsize && y>-1 && y<im->ysize ) {
437 for(ch=0;ch<im->channels;ch++)
438 if (im->ch_mask&(1<<ch))
439 im->data[(x+y*im->xsize)*im->channels+ch]=val->channel[ch];
442 return -1; /* error was clipped */
446 =item i_gpix_d(im, x, y, &col)
450 This is the function kept in the i_f_gpix member of an i_img object.
451 It does normal retrieval of a pixel from the image with range checking.
453 Returns true if the pixel could be set, false otherwise.
458 i_gpix_d(i_img *im,int x,int y,i_color *val) {
460 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) {
461 for(ch=0;ch<im->channels;ch++)
462 val->channel[ch]=im->data[(x+y*im->xsize)*im->channels+ch];
465 return -1; /* error was cliped */
469 =item i_ppix_pch(im, x, y, ch)
471 Get the value from the channel I<ch> for pixel (I<x>,I<y>) from I<im>
474 Returns zero if x or y is out of range.
476 Warning: this ignores the vptr interface for images.
481 i_gpix_pch(i_img *im,int x,int y,int ch) {
482 if (x>-1 && x<im->xsize && y>-1 && y<im->ysize) return ((float)im->data[(x+y*im->xsize)*im->channels+ch]/255);
488 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
490 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
491 (tx,ty) specifies the upper left corner for the target image.
492 pass NULL in trans for non transparent i_colors.
498 i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans) {
500 int x,y,t,ttx,tty,tt,ch;
502 mm_log((1,"i_copyto_trans(im* 0x%x,src 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,tx %d,ty %d,trans* 0x%x)\n",im,src,x1,y1,x2,y2,tx,ty,trans));
504 if (x2<x1) { t=x1; x1=x2; x2=t; }
505 if (y2<y1) { t=y1; y1=y2; y2=t; }
517 for(ch=0;ch<im->channels;ch++) if (trans->channel[ch]!=pv.channel[ch]) tt++;
518 if (tt) i_ppix(im,ttx,tty,&pv);
519 } else i_ppix(im,ttx,tty,&pv);
527 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
529 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
530 a rectangle the same size with it's top-left corner at (tx,ty) in the
533 If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
539 i_copyto(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty) {
543 if (x2<x1) { t=x1; x1=x2; x2=t; }
544 if (y2<y1) { t=y1; y1=y2; y2=t; }
546 mm_log((1,"i_copyto(im* 0x%x,src 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,tx %d,ty %d)\n",im,src,x1,y1,x2,y2,tx,ty));
553 i_ppix(im,ttx,tty,&pv);
561 =item i_copy(im, src)
563 Copies the contents of the image I<src> over the image I<im>.
569 i_copy(i_img *im,i_img *src) {
573 mm_log((1,"i_copy(im* 0x%x,src 0x%x)\n",im,src));
577 i_img_empty_ch(im,x1,y1,src->channels);
579 for(y=0;y<y1;y++) for(x=0;x<x1;x++) {
587 =item i_rubthru(im, src, tx, ty)
589 Takes the image I<src> and applies it at an original (I<tx>,I<ty>) in I<im>.
591 The alpha channel of each pixel in I<src> is used to control how much
592 the existing colour in I<im> is replaced, if it is 255 then the colour
593 is completely replaced, if it is 0 then the original colour is left
599 i_rubthru(i_img *im,i_img *src,int tx,int ty) {
600 i_color pv,orig,dest;
603 mm_log((1,"i_rubthru(im 0x%x,src 0x%x,tx %d,ty %d)\n",im,src,tx,ty));
605 if (im->channels != 3) { fprintf(stderr,"Destination is not in rgb mode.\n"); exit(3); }
606 if (src->channels != 4) { fprintf(stderr,"Source is not in rgba mode.\n"); exit(3); }
609 for(x=0;x<src->xsize;x++)
612 for(y=0;y<src->ysize;y++)
614 /* fprintf(stderr,"reading (%d,%d) writing (%d,%d).\n",x,y,ttx,tty); */
616 i_gpix(im,ttx,tty,&orig);
617 dest.rgb.r=(pv.rgba.a*pv.rgba.r+(255-pv.rgba.a)*orig.rgb.r)/255;
618 dest.rgb.g=(pv.rgba.a*pv.rgba.g+(255-pv.rgba.a)*orig.rgb.g)/255;
619 dest.rgb.b=(pv.rgba.a*pv.rgba.b+(255-pv.rgba.a)*orig.rgb.b)/255;
620 i_ppix(im,ttx,tty,&dest);
634 if ((x >= 2.0) || (x <= -2.0)) return (0.0);
635 else if (x == 0.0) return (1.0);
636 else return(sin(PIx) / PIx * sin(PIx2) / PIx2);
640 =item i_scaleaxis(im, value, axis)
642 Returns a new image object which is I<im> scaled by I<value> along
643 wither the x-axis (I<axis> == 0) or the y-axis (I<axis> == 1).
649 i_scaleaxis(i_img *im, float Value, int Axis) {
650 int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd;
651 int LanczosWidthFactor;
652 float *l0, *l1, OldLocation;
653 int T, TempJump1, TempJump2;
654 float F, PictureValue[MAXCHANNELS];
656 i_color val,val1,val2;
659 mm_log((1,"i_scaleaxis(im 0x%x,Value %.2f,Axis %d)\n",im,Value,Axis));
662 hsize = (int) ((float) im->xsize * Value);
668 TempJump1 = (hsize - 1) * 3;
669 TempJump2 = hsize * (vsize - 1) * 3 + TempJump1;
672 vsize = (int) ((float) im->ysize * Value);
681 new_img=i_img_empty_ch(NULL,hsize,vsize,im->channels);
683 if (Value >=1) LanczosWidthFactor = 1;
684 else LanczosWidthFactor = (int) (1.0/Value);
686 lMax = LanczosWidthFactor << 1;
688 l0 = (float *) mymalloc(lMax * sizeof(float));
689 l1 = (float *) mymalloc(lMax * sizeof(float));
691 for (j=0; j<jEnd; j++) {
692 OldLocation = ((float) j) / Value;
693 T = (int) (OldLocation);
694 F = OldLocation - (float) T;
696 for (l = 0; l < lMax; l++) {
697 l0[lMax-l-1] = Lanczos(((float) (lMax-l-1) + F) / (float) LanczosWidthFactor);
698 l1[l] = Lanczos(((float) (l + 1) - F) / (float) LanczosWidthFactor);
703 for (i=0; i<iEnd; i++) {
704 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
705 for (l=0; l < lMax; l++) {
706 i_gpix(im,T+l+1, i, &val1);
707 i_gpix(im,T-lMax+l+1, i, &val2);
708 for (k=0; k<im->channels; k++) {
709 PictureValue[k] += l1[l] * val1.channel[k];
710 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
713 for(k=0;k<im->channels;k++) {
714 psave = (short)( PictureValue[k] / LanczosWidthFactor);
715 val.channel[k]=minmax(0,255,psave);
717 i_ppix(new_img,j,i,&val);
722 for (i=0; i<iEnd; i++) {
723 for (k=0; k<im->channels; k++) PictureValue[k] = 0.0;
724 for (l=0; l < lMax; l++) {
725 i_gpix(im,i, T+l+1, &val1);
726 i_gpix(im,i, T-lMax+l+1, &val2);
727 for (k=0; k<im->channels; k++) {
728 PictureValue[k] += l1[l] * val1.channel[k];
729 PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
732 for (k=0; k<im->channels; k++) {
733 psave = (short)( PictureValue[k] / LanczosWidthFactor);
734 val.channel[k]=minmax(0,255,psave);
736 i_ppix(new_img,i,j,&val);
744 mm_log((1,"(0x%x) <- i_scaleaxis\n",new_img));
751 =item i_scale_nn(im, scx, scy)
753 Scale by using nearest neighbor
754 Both axes scaled at the same time since
755 nothing is gained by doing it in two steps
762 i_scale_nn(i_img *im, float scx, float scy) {
764 int nxsize,nysize,nx,ny;
768 mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy));
770 nxsize = (int) ((float) im->xsize * scx);
771 nysize = (int) ((float) im->ysize * scy);
773 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
775 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
776 i_gpix(im,((float)nx)/scx,((float)ny)/scy,&val);
777 i_ppix(new_img,nx,ny,&val);
780 mm_log((1,"(0x%x) <- i_scale_nn\n",new_img));
787 =item i_transform(im, opx, opxl, opy, opyl, parm, parmlen)
789 Spatially transforms I<im> returning a new image.
791 opx for a length of opxl and opy for a length of opy are arrays of
792 operators that modify the x and y positions to retreive the pixel data from.
794 parm and parmlen define extra parameters that the operators may use.
796 Note that this function is largely superseded by the more flexible
797 L<transform.c/i_transform2>.
799 Returns the new image.
801 The operators for this function are defined in L<stackmach.c>.
806 i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) {
808 int nxsize,nysize,nx,ny;
812 mm_log((1,"i_transform(im 0x%x, opx 0x%x, opxl %d, opy 0x%x, opyl %d, parm 0x%x, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen));
817 new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
818 /* fprintf(stderr,"parm[2]=%f\n",parm[2]); */
819 for(ny=0;ny<nysize;ny++) for(nx=0;nx<nxsize;nx++) {
820 /* parm[parmlen-2]=(double)nx;
821 parm[parmlen-1]=(double)ny; */
826 /* fprintf(stderr,"(%d,%d) ->",nx,ny); */
827 rx=op_run(opx,opxl,parm,parmlen);
828 ry=op_run(opy,opyl,parm,parmlen);
829 /* fprintf(stderr,"(%f,%f)\n",rx,ry); */
830 i_gpix(im,rx,ry,&val);
831 i_ppix(new_img,nx,ny,&val);
834 mm_log((1,"(0x%x) <- i_transform\n",new_img));
839 =item i_img_diff(im1, im2)
841 Calculates the sum of the squares of the differences between
842 correspoding channels in two images.
844 If the images are not the same size then only the common area is
845 compared, hence even if images are different sizes this function
851 i_img_diff(i_img *im1,i_img *im2) {
852 int x,y,ch,xb,yb,chb;
856 mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2));
858 xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
859 yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
860 chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
862 mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
865 for(y=0;y<yb;y++) for(x=0;x<xb;x++) {
866 i_gpix(im1,x,y,&val1);
867 i_gpix(im2,x,y,&val2);
869 for(ch=0;ch<chb;ch++) tdiff+=(val1.channel[ch]-val2.channel[ch])*(val1.channel[ch]-val2.channel[ch]);
871 mm_log((1,"i_img_diff <- (%.2f)\n",tdiff));
875 /* just a tiny demo of haar wavelets */
883 i_img *new_img,*new_img2;
884 i_color val1,val2,dval1,dval2;
892 /* horizontal pass */
894 new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
895 new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels);
898 for(y=0;y<my;y++) for(x=0;x<fx;x++) {
899 i_gpix(im,x*2,y,&val1);
900 i_gpix(im,x*2+1,y,&val2);
901 for(ch=0;ch<im->channels;ch++) {
902 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
903 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
905 i_ppix(new_img,x,y,&dval1);
906 i_ppix(new_img,x+fx,y,&dval2);
909 for(y=0;y<fy;y++) for(x=0;x<mx;x++) {
910 i_gpix(new_img,x,y*2,&val1);
911 i_gpix(new_img,x,y*2+1,&val2);
912 for(ch=0;ch<im->channels;ch++) {
913 dval1.channel[ch]=(val1.channel[ch]+val2.channel[ch])/2;
914 dval2.channel[ch]=(255+val1.channel[ch]-val2.channel[ch])/2;
916 i_ppix(new_img2,x,y,&dval1);
917 i_ppix(new_img2,x,y+fy,&dval2);
920 i_img_destroy(new_img);
925 =item i_count_colors(im, maxc)
927 returns number of colors or -1
928 to indicate that it was more than max colors
933 i_count_colors(i_img *im,int maxc) {
940 mm_log((1,"i_count_colors(im 0x%08X,maxc %d)\n"));
947 for(y=0;y<ysize;y++) for(x=0;x<xsize;x++) {
949 colorcnt+=octt_add(ct,val.rgb.r,val.rgb.g,val.rgb.b);
950 if (colorcnt > maxc) { octt_delete(ct); return -1; }
957 symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
958 i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
959 i_img_info,i_img_setmask,i_img_getmask,i_ppix,i_gpix,
960 i_box,i_draw,i_arc,i_copyto,i_copyto_trans,i_rubthru};
964 =item i_gen_reader(i_gen_read_data *info, char *buf, int length)
966 Performs general read buffering for file readers that permit reading
967 to be done through a callback.
969 The final callback gets two parameters, a I<need> value, and a I<want>
970 value, where I<need> is the amount of data that the file library needs
971 to read, and I<want> is the amount of space available in the buffer
972 maintained by these functions.
974 This means if you need to read from a stream that you don't know the
975 length of, you can return I<need> bytes, taking the performance hit of
976 possibly expensive callbacks (eg. back to perl code), or if you are
977 reading from a stream where it doesn't matter if some data is lost, or
978 if the total length of the stream is known, you can return I<want>
985 i_gen_reader(i_gen_read_data *gci, char *buf, int length) {
988 if (length < gci->length - gci->cpos) {
990 memcpy(buf, gci->buffer+gci->cpos, length);
996 memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos);
997 total += gci->length - gci->cpos;
998 length -= gci->length - gci->cpos;
999 buf += gci->length - gci->cpos;
1000 if (length < (int)sizeof(gci->buffer)) {
1004 && (did_read = (gci->cb)(gci->userdata, gci->buffer, length,
1005 sizeof(gci->buffer))) > 0) {
1007 gci->length = did_read;
1009 copy_size = min(length, gci->length);
1010 memcpy(buf, gci->buffer, copy_size);
1011 gci->cpos += copy_size;
1014 length -= copy_size;
1018 /* just read the rest - too big for our buffer*/
1020 while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) {
1030 =item i_gen_read_data_new(i_read_callback_t cb, char *userdata)
1032 For use by callback file readers to initialize the reader buffer.
1034 Allocates, initializes and returns the reader buffer.
1036 See also L<image.c/free_gen_read_data> and L<image.c/i_gen_reader>.
1041 i_gen_read_data_new(i_read_callback_t cb, char *userdata) {
1042 i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data));
1044 self->userdata = userdata;
1052 =item free_gen_read_data(i_gen_read_data *)
1058 void free_gen_read_data(i_gen_read_data *self) {
1063 =item i_gen_writer(i_gen_write_data *info, char const *data, int size)
1065 Performs write buffering for a callback based file writer.
1067 Failures are considered fatal, if a write fails then data will be
1074 i_gen_write_data *self,
1078 if (self->filledto && self->filledto+size > self->maxlength) {
1079 if (self->cb(self->userdata, self->buffer, self->filledto)) {
1087 if (self->filledto+size <= self->maxlength) {
1089 memcpy(self->buffer+self->filledto, data, size);
1090 self->filledto += size;
1093 /* doesn't fit - hand it off */
1094 return self->cb(self->userdata, data, size);
1098 =item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length)
1100 Allocates and initializes the data structure used by i_gen_writer.
1102 This should be released with L<image.c/free_gen_write_data>
1106 i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb,
1107 char *userdata, int max_length)
1109 i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data));
1111 self->userdata = userdata;
1112 self->maxlength = min(max_length, sizeof(self->buffer));
1113 if (self->maxlength < 0)
1114 self->maxlength = sizeof(self->buffer);
1121 =item free_gen_write_data(i_gen_write_data *info, int flush)
1123 Cleans up the write buffer.
1125 Will flush any left-over data if I<flush> is non-zero.
1127 Returns non-zero if flush is zero or if info->cb() returns non-zero.
1129 Return zero only if flush is non-zero and info->cb() returns zero.
1135 int free_gen_write_data(i_gen_write_data *info, int flush)
1137 int result = !flush ||
1138 info->filledto == 0 ||
1139 info->cb(info->userdata, info->buffer, info->filledto);