• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Base image support for CUPS.
3  *
4  *   Copyright 2007-2011 by Apple Inc.
5  *   Copyright 1993-2005 by Easy Software Products.
6  *
7  *   These coded instructions, statements, and computer programs are the
8  *   property of Apple Inc. and are protected by Federal copyright
9  *   law.  Distribution and use rights are outlined in the file "COPYING"
10  *   which should have been included with this file.
11  *
12  * Contents:
13  *
14  *   cupsImageClose()         - Close an image file.
15  *   cupsImageGetCol()        - Get a column of pixels from an image.
16  *   cupsImageGetColorSpace() - Get the image colorspace.
17  *   cupsImageGetDepth()      - Get the number of bytes per pixel.
18  *   cupsImageGetHeight()     - Get the height of an image.
19  *   cupsImageGetRow()        - Get a row of pixels from an image.
20  *   cupsImageGetWidth()      - Get the width of an image.
21  *   cupsImageGetXPPI()       - Get the horizontal resolution of an image.
22  *   cupsImageGetYPPI()       - Get the vertical resolution of an image.
23  *   cupsImageOpen()          - Open an image file and read it into memory.
24  *   _cupsImagePutCol()       - Put a column of pixels to an image.
25  *   _cupsImagePutRow()       - Put a row of pixels to an image.
26  *   cupsImageSetMaxTiles()   - Set the maximum number of tiles to cache.
27  *   flush_tile()             - Flush the least-recently-used tile in the cache.
28  *   get_tile()               - Get a cached tile.
29  *   _cupsImageReadEXIF()     - to read exif metadata of images
30  *   trim_spaces()            - helper function to extract results from string
31  *                              returned by exif library functions
32  *   find_bytes()             - creates character array from image file, to
33  *                              make use in exif library functions
34  */
35 
36 /*
37  * Include necessary headers...
38  */
39 
40 
41 #include "image-private.h"
42 
43 
44 /*
45  * Local functions...
46  */
47 
48 static int		flush_tile(cups_image_t *img);
49 static cups_ib_t	*get_tile(cups_image_t *img, int x, int y);
50 static void             trim_spaces(char *buf);
51 static unsigned char    *find_bytes(FILE *fp, long int *size);
52 
53 
54 /*
55  * 'cupsImageClose()' - Close an image file.
56  */
57 
58 void
cupsImageClose(cups_image_t * img)59 cupsImageClose(cups_image_t *img)	/* I - Image to close */
60 {
61   cups_ic_t	*current,		/* Current cached tile */
62 		*next;			/* Next cached tile */
63 
64 
65  /*
66   * Wipe the tile cache file (if any)...
67   */
68 
69   if (img->cachefile >= 0)
70   {
71     DEBUG_printf(("Closing/removing swap file \"%s\"...\n", img->cachename));
72 
73     close(img->cachefile);
74     unlink(img->cachename);
75   }
76 
77  /*
78   * Free the image cache...
79   */
80 
81   DEBUG_puts("Freeing memory...");
82 
83   for (current = img->first, next = NULL; current != NULL; current = next)
84   {
85     DEBUG_printf(("Freeing cache (%p, next = %p)...\n", current, next));
86 
87     next = current->next;
88     free(current);
89   }
90 
91  /*
92   * Free the rest of memory...
93   */
94 
95   if (img->tiles != NULL)
96   {
97     DEBUG_printf(("Freeing tiles (%p)...\n", img->tiles[0]));
98 
99     free(img->tiles[0]);
100 
101     DEBUG_printf(("Freeing tile pointers (%p)...\n", img->tiles));
102 
103     free(img->tiles);
104   }
105 
106   free(img);
107 }
108 
109 
110 /*
111  * 'cupsImageGetCol()' - Get a column of pixels from an image.
112  */
113 
114 int					/* O - -1 on error, 0 on success */
cupsImageGetCol(cups_image_t * img,int x,int y,int height,cups_ib_t * pixels)115 cupsImageGetCol(cups_image_t *img,	/* I - Image */
116         	int          x,		/* I - Column */
117         	int          y,		/* I - Start row */
118         	int          height,	/* I - Column height */
119         	cups_ib_t    *pixels)	/* O - Pixel data */
120 {
121   int			bpp,		/* Bytes per pixel */
122 			twidth,		/* Tile width */
123 			count;		/* Number of pixels to get */
124   const cups_ib_t	*ib;		/* Pointer into tile */
125 
126 
127   if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize)
128     return (-1);
129 
130   if (y < 0)
131   {
132     height += y;
133     y = 0;
134   }
135 
136   if ((y + height) > img->ysize)
137     height = img->ysize - y;
138 
139   if (height < 1)
140     return (-1);
141 
142   bpp    = cupsImageGetDepth(img);
143   twidth = bpp * (CUPS_TILE_SIZE - 1);
144 
145   while (height > 0)
146   {
147     ib = get_tile(img, x, y);
148 
149     if (ib == NULL)
150       return (-1);
151 
152     count = CUPS_TILE_SIZE - (y & (CUPS_TILE_SIZE - 1));
153     if (count > height)
154       count = height;
155 
156     y      += count;
157     height -= count;
158 
159     for (; count > 0; count --, ib += twidth)
160       switch (bpp)
161       {
162         case 4 :
163             *pixels++ = *ib++;
164         case 3 :
165             *pixels++ = *ib++;
166             *pixels++ = *ib++;
167         case 1 :
168             *pixels++ = *ib++;
169             break;
170       }
171   }
172 
173   return (0);
174 }
175 
176 
177 /*
178  * 'cupsImageGetColorSpace()' - Get the image colorspace.
179  */
180 
181 cups_icspace_t				/* O - Colorspace */
cupsImageGetColorSpace(cups_image_t * img)182 cupsImageGetColorSpace(
183     cups_image_t *img)			/* I - Image */
184 {
185   return (img->colorspace);
186 }
187 
188 
189 /*
190  * 'cupsImageGetDepth()' - Get the number of bytes per pixel.
191  */
192 
193 int					/* O - Bytes per pixel */
cupsImageGetDepth(cups_image_t * img)194 cupsImageGetDepth(cups_image_t *img)	/* I - Image */
195 {
196   return (abs(img->colorspace));
197 }
198 
199 
200 /*
201  * 'cupsImageGetHeight()' - Get the height of an image.
202  */
203 
204 unsigned				/* O - Height in pixels */
cupsImageGetHeight(cups_image_t * img)205 cupsImageGetHeight(cups_image_t *img)	/* I - Image */
206 {
207   return (img->ysize);
208 }
209 
210 
211 /*
212  * 'cupsImageGetRow()' - Get a row of pixels from an image.
213  */
214 
215 int					/* O - -1 on error, 0 on success */
cupsImageGetRow(cups_image_t * img,int x,int y,int width,cups_ib_t * pixels)216 cupsImageGetRow(cups_image_t *img,	/* I - Image */
217                 int          x,		/* I - Start column */
218                 int          y,		/* I - Row */
219                 int          width,	/* I - Width of row */
220                 cups_ib_t    *pixels)	/* O - Pixel data */
221 {
222   int			bpp,		/* Bytes per pixel */
223 			count;		/* Number of pixels to get */
224   const cups_ib_t	*ib;		/* Pointer to pixels */
225 
226 
227   if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize)
228     return (-1);
229 
230   if (x < 0)
231   {
232     width += x;
233     x = 0;
234   }
235 
236   if ((x + width) > img->xsize)
237     width = img->xsize - x;
238 
239   if (width < 1)
240     return (-1);
241 
242   bpp = img->colorspace < 0 ? -img->colorspace : img->colorspace;
243 
244   while (width > 0)
245   {
246     ib = get_tile(img, x, y);
247 
248     if (ib == NULL)
249       return (-1);
250 
251     count = CUPS_TILE_SIZE - (x & (CUPS_TILE_SIZE - 1));
252     if (count > width)
253       count = width;
254     memcpy(pixels, ib, count * bpp);
255     pixels += count * bpp;
256     x      += count;
257     width  -= count;
258   }
259 
260   return (0);
261 }
262 
263 
264 /*
265  * 'cupsImageGetWidth()' - Get the width of an image.
266  */
267 
268 unsigned				/* O - Width in pixels */
cupsImageGetWidth(cups_image_t * img)269 cupsImageGetWidth(cups_image_t *img)	/* I - Image */
270 {
271   return (img->xsize);
272 }
273 
274 
275 /*
276  * 'cupsImageGetXPPI()' - Get the horizontal resolution of an image.
277  */
278 
279 unsigned				/* O - Horizontal PPI */
cupsImageGetXPPI(cups_image_t * img)280 cupsImageGetXPPI(cups_image_t *img)	/* I - Image */
281 {
282   return (img->xppi);
283 }
284 
285 
286 /*
287  * 'cupsImageGetYPPI()' - Get the vertical resolution of an image.
288  */
289 
290 unsigned				/* O - Vertical PPI */
cupsImageGetYPPI(cups_image_t * img)291 cupsImageGetYPPI(cups_image_t *img)	/* I - Image */
292 {
293   return (img->yppi);
294 }
295 
296 
297 /*
298  * 'cupsImageOpen()' - Open an image file and read it into memory.
299  */
300 
301 cups_image_t *				/* O - New image */
cupsImageOpen(const char * filename,cups_icspace_t primary,cups_icspace_t secondary,int saturation,int hue,const cups_ib_t * lut)302 cupsImageOpen(
303     const char      *filename,		/* I - Filename of image */
304     cups_icspace_t  primary,		/* I - Primary colorspace needed */
305     cups_icspace_t  secondary,		/* I - Secondary colorspace if primary no good */
306     int             saturation,		/* I - Color saturation level */
307     int             hue,		/* I - Color hue adjustment */
308     const cups_ib_t *lut)		/* I - RGB gamma/brightness LUT */
309 {
310   FILE		*fp;			/* File pointer */
311   unsigned char	header[16],		/* First 16 bytes of file */
312 		header2[16];		/* Bytes 2048-2064 (PhotoCD) */
313   cups_image_t	*img;			/* New image buffer */
314   int		status;			/* Status of load... */
315 
316 
317   DEBUG_printf(("cupsImageOpen(\"%s\", %d, %d, %d, %d, %p)\n",
318         	filename ? filename : "(null)", primary, secondary,
319 		saturation, hue, lut));
320 
321  /*
322   * Figure out the file type...
323   */
324 
325   if ((fp = fopen(filename, "r")) == NULL)
326     return (NULL);
327 
328   if (fread(header, 1, sizeof(header), fp) == 0)
329   {
330     fclose(fp);
331     return (NULL);
332   }
333 
334   fseek(fp, 2048, SEEK_SET);
335   memset(header2, 0, sizeof(header2));
336   if (fread(header2, 1, sizeof(header2), fp) == 0 && ferror(fp))
337     DEBUG_printf(("Error reading file!"));
338   fseek(fp, 0, SEEK_SET);
339 
340  /*
341   * Allocate memory...
342   */
343 
344   img = calloc(sizeof(cups_image_t), 1);
345 
346   if (img == NULL)
347   {
348     fclose(fp);
349     return (NULL);
350   }
351 
352  /*
353   * Load the image as appropriate...
354   */
355 
356   img->cachefile = -1;
357   img->max_ics   = CUPS_TILE_MINIMUM;
358   img->xppi      = 200;
359   img->yppi      = 200;
360 
361   if (!memcmp(header, "GIF87a", 6) || !memcmp(header, "GIF89a", 6))
362     status = _cupsImageReadGIF(img, fp, primary, secondary, saturation, hue,
363                                lut);
364   else if (!memcmp(header, "BM", 2))
365     status = _cupsImageReadBMP(img, fp, primary, secondary, saturation, hue,
366                                lut);
367   else if (header[0] == 0x01 && header[1] == 0xda)
368     status = _cupsImageReadSGI(img, fp, primary, secondary, saturation, hue,
369                                lut);
370   else if (header[0] == 0x59 && header[1] == 0xa6 &&
371            header[2] == 0x6a && header[3] == 0x95)
372     status = _cupsImageReadSunRaster(img, fp, primary, secondary, saturation,
373                                      hue, lut);
374   else if (header[0] == 'P' && header[1] >= '1' && header[1] <= '6')
375     status = _cupsImageReadPNM(img, fp, primary, secondary, saturation, hue,
376                                lut);
377   else if (!memcmp(header2, "PCD_IPI", 7))
378     status = _cupsImageReadPhotoCD(img, fp, primary, secondary, saturation,
379                                    hue, lut);
380   else if (!memcmp(header + 8, "\000\010", 2) ||
381            !memcmp(header + 8, "\000\030", 2))
382     status = _cupsImageReadPIX(img, fp, primary, secondary, saturation, hue,
383                                lut);
384 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
385   else if (!memcmp(header, "\211PNG", 4))
386     status = _cupsImageReadPNG(img, fp, primary, secondary, saturation, hue,
387                                lut);
388 #endif /* HAVE_LIBPNG && HAVE_LIBZ */
389 #ifdef HAVE_LIBJPEG
390   else if (!memcmp(header, "\377\330\377", 3) &&	/* Start-of-Image */
391 	   header[3] >= 0xe0 && header[3] <= 0xef)	/* APPn */
392     status = _cupsImageReadJPEG(img, fp, primary, secondary, saturation, hue,
393                                 lut);
394 #endif /* HAVE_LIBJPEG */
395 #ifdef HAVE_LIBTIFF
396   else if (!memcmp(header, "MM\000\052", 4) ||
397            !memcmp(header, "II\052\000", 4))
398     status = _cupsImageReadTIFF(img, fp, primary, secondary, saturation, hue,
399                                 lut);
400 #endif /* HAVE_LIBTIFF */
401   else
402   {
403     fclose(fp);
404     status = -1;
405   }
406 
407   if (status)
408   {
409     free(img);
410     return (NULL);
411   }
412   else
413     return (img);
414 }
415 
416 
417 /*
418  * '_cupsImagePutCol()' - Put a column of pixels to an image.
419  */
420 
421 int					/* O - -1 on error, 0 on success */
_cupsImagePutCol(cups_image_t * img,int x,int y,int height,const cups_ib_t * pixels)422 _cupsImagePutCol(
423     cups_image_t    *img,		/* I - Image */
424     int             x,			/* I - Column */
425     int             y,			/* I - Start row */
426     int             height,		/* I - Column height */
427     const cups_ib_t *pixels)		/* I - Pixels to put */
428 {
429   int		bpp,			/* Bytes per pixel */
430 		twidth,			/* Width of tile */
431 		count;			/* Number of pixels to put */
432   int		tilex,			/* Column within tile */
433 		tiley;			/* Row within tile */
434   cups_ib_t	*ib;			/* Pointer to pixels in tile */
435 
436 
437   if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize)
438     return (-1);
439 
440   if (y < 0)
441   {
442     height += y;
443     y = 0;
444   }
445 
446   if ((y + height) > img->ysize)
447     height = img->ysize - y;
448 
449   if (height < 1)
450     return (-1);
451 
452   bpp    = cupsImageGetDepth(img);
453   twidth = bpp * (CUPS_TILE_SIZE - 1);
454   tilex  = x / CUPS_TILE_SIZE;
455   tiley  = y / CUPS_TILE_SIZE;
456 
457   while (height > 0)
458   {
459     ib = get_tile(img, x, y);
460 
461     if (ib == NULL)
462       return (-1);
463 
464     img->tiles[tiley][tilex].dirty = 1;
465     tiley ++;
466 
467     count = CUPS_TILE_SIZE - (y & (CUPS_TILE_SIZE - 1));
468     if (count > height)
469       count = height;
470 
471     y      += count;
472     height -= count;
473 
474     for (; count > 0; count --, ib += twidth)
475       switch (bpp)
476       {
477         case 4 :
478             *ib++ = *pixels++;
479         case 3 :
480             *ib++ = *pixels++;
481             *ib++ = *pixels++;
482         case 1 :
483             *ib++ = *pixels++;
484             break;
485       }
486   }
487 
488   return (0);
489 }
490 
491 
492 /*
493  * '_cupsImagePutRow()' - Put a row of pixels to an image.
494  */
495 
496 int					/* O - -1 on error, 0 on success */
_cupsImagePutRow(cups_image_t * img,int x,int y,int width,const cups_ib_t * pixels)497 _cupsImagePutRow(
498     cups_image_t    *img,		/* I - Image */
499     int             x,			/* I - Start column */
500     int             y,			/* I - Row */
501     int             width,		/* I - Row width */
502     const cups_ib_t *pixels)		/* I - Pixel data */
503 {
504   int		bpp,			/* Bytes per pixel */
505 		count;			/* Number of pixels to put */
506   int		tilex,			/* Column within tile */
507 		tiley;			/* Row within tile */
508   cups_ib_t	*ib;			/* Pointer to pixels in tile */
509 
510 
511   if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize)
512     return (-1);
513 
514   if (x < 0)
515   {
516     width += x;
517     x = 0;
518   }
519 
520   if ((x + width) > img->xsize)
521     width = img->xsize - x;
522 
523   if (width < 1)
524     return (-1);
525 
526   bpp   = img->colorspace < 0 ? -img->colorspace : img->colorspace;
527   tilex = x / CUPS_TILE_SIZE;
528   tiley = y / CUPS_TILE_SIZE;
529 
530   while (width > 0)
531   {
532     ib = get_tile(img, x, y);
533 
534     if (ib == NULL)
535       return (-1);
536 
537     img->tiles[tiley][tilex].dirty = 1;
538 
539     count = CUPS_TILE_SIZE - (x & (CUPS_TILE_SIZE - 1));
540     if (count > width)
541       count = width;
542     memcpy(ib, pixels, count * bpp);
543     pixels += count * bpp;
544     x      += count;
545     width  -= count;
546     tilex  ++;
547   }
548 
549   return (0);
550 }
551 
552 
553 /*
554  * 'cupsImageSetMaxTiles()' - Set the maximum number of tiles to cache.
555  *
556  * If the "max_tiles" argument is 0 then the maximum number of tiles is
557  * computed from the image size or the RIP_CACHE environment variable.
558  */
559 
560 void
cupsImageSetMaxTiles(cups_image_t * img,int max_tiles)561 cupsImageSetMaxTiles(
562     cups_image_t *img,			/* I - Image to set */
563     int          max_tiles)		/* I - Number of tiles to cache */
564 {
565   int	cache_size,			/* Size of tile cache in bytes */
566 	min_tiles,			/* Minimum number of tiles to cache */
567 	max_size;			/* Maximum cache size in bytes */
568   char	*cache_env,			/* Cache size environment variable */
569 	cache_units[255];		/* Cache size units */
570 
571 
572   min_tiles = max(CUPS_TILE_MINIMUM,
573                   1 + max((img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE,
574                           (img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE));
575 
576   if (max_tiles == 0)
577     max_tiles = ((img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE) *
578                 ((img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE);
579 
580   cache_size = max_tiles * CUPS_TILE_SIZE * CUPS_TILE_SIZE *
581                cupsImageGetDepth(img);
582 
583   if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL)
584   {
585     switch (sscanf(cache_env, "%d%254s", &max_size, cache_units))
586     {
587       case 0 :
588           max_size = 32 * 1024 * 1024;
589 	  break;
590       case 1 :
591           max_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
592 	  break;
593       case 2 :
594           if (tolower(cache_units[0] & 255) == 'g')
595 	    max_size *= 1024 * 1024 * 1024;
596           else if (tolower(cache_units[0] & 255) == 'm')
597 	    max_size *= 1024 * 1024;
598 	  else if (tolower(cache_units[0] & 255) == 'k')
599 	    max_size *= 1024;
600 	  else if (tolower(cache_units[0] & 255) == 't')
601 	    max_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
602 	  break;
603     }
604   }
605   else
606     max_size = 32 * 1024 * 1024;
607 
608   if (cache_size > max_size)
609     max_tiles = max_size / CUPS_TILE_SIZE / CUPS_TILE_SIZE /
610                 cupsImageGetDepth(img);
611 
612   if (max_tiles < min_tiles)
613     max_tiles = min_tiles;
614 
615   img->max_ics = max_tiles;
616 
617   DEBUG_printf(("max_ics=%d...\n", img->max_ics));
618 }
619 
620 
621 /*
622  * 'flush_tile()' - Flush the least-recently-used tile in the cache.
623  */
624 
625 static int
flush_tile(cups_image_t * img)626 flush_tile(cups_image_t *img)		/* I - Image */
627 {
628   int		bpp;			/* Bytes per pixel */
629   cups_itile_t	*tile;			/* Pointer to tile */
630 
631 
632   bpp  = cupsImageGetDepth(img);
633   if(img==NULL||img->first==NULL||img->first->tile==NULL)
634   {
635     return -1;
636   }
637   tile = img->first->tile;
638 
639   if (!tile->dirty)
640   {
641     tile->ic = NULL;
642     return 0;
643   }
644 
645   if (img->cachefile < 0)
646   {
647     if ((img->cachefile = cupsTempFd(img->cachename,
648                                      sizeof(img->cachename))) < 0)
649     {
650       tile->ic    = NULL;
651       tile->dirty = 0;
652       return 0;
653     }
654 
655     DEBUG_printf(("Created swap file \"%s\"...\n", img->cachename));
656   }
657 
658   if (tile->pos >= 0)
659   {
660     if (lseek(img->cachefile, tile->pos, SEEK_SET) != tile->pos)
661     {
662       tile->ic    = NULL;
663       tile->dirty = 0;
664       return 0;
665     }
666   }
667   else
668   {
669     if ((tile->pos = lseek(img->cachefile, 0, SEEK_END)) < 0)
670     {
671       tile->ic    = NULL;
672       tile->dirty = 0;
673       return 0;
674     }
675   }
676 
677   if (write(img->cachefile, tile->ic->pixels,
678 	    bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE) == -1)
679     DEBUG_printf(("Error writing cache tile!"));
680 
681   tile->ic    = NULL;
682   tile->dirty = 0;
683   return 0;
684 }
685 
686 
687 /*
688  * 'get_tile()' - Get a cached tile.
689  */
690 
691 static cups_ib_t *			/* O - Pointer to tile or NULL */
get_tile(cups_image_t * img,int x,int y)692 get_tile(cups_image_t *img,		/* I - Image */
693          int          x,		/* I - Column in image */
694          int          y)		/* I - Row in image */
695 {
696   int		bpp,			/* Bytes per pixel */
697 		tilex,			/* Column within tile */
698 		tiley,			/* Row within tile */
699 		xtiles,			/* Number of tiles horizontally */
700 		ytiles;			/* Number of tiles vertically */
701   cups_ic_t	*ic;			/* Cache pointer */
702   cups_itile_t	*tile;			/* Tile pointer */
703 
704 
705   if (img->tiles == NULL)
706   {
707     xtiles = (img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE;
708     ytiles = (img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE;
709 
710     DEBUG_printf(("Creating tile array (%dx%d)\n", xtiles, ytiles));
711 
712     if ((img->tiles = calloc(sizeof(cups_itile_t *), ytiles)) == NULL)
713       return (NULL);
714 
715     if ((tile = calloc(xtiles * sizeof(cups_itile_t), ytiles)) == NULL)
716       return (NULL);
717 
718     for (tiley = 0; tiley < ytiles; tiley ++)
719     {
720       img->tiles[tiley] = tile;
721       for (tilex = xtiles; tilex > 0; tilex --, tile ++)
722         tile->pos = -1;
723     }
724   }
725 
726   bpp   = cupsImageGetDepth(img);
727   tilex = x / CUPS_TILE_SIZE;
728   tiley = y / CUPS_TILE_SIZE;
729   tile  = img->tiles[tiley] + tilex;
730   x     &= (CUPS_TILE_SIZE - 1);
731   y     &= (CUPS_TILE_SIZE - 1);
732 
733   if ((ic = tile->ic) == NULL)
734   {
735     if (img->num_ics < img->max_ics)
736     {
737       if ((ic = calloc(sizeof(cups_ic_t) +
738                        bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE, 1)) == NULL)
739       {
740         if (img->num_ics == 0)
741 	  return (NULL);
742 
743         flush_tile(img);
744 	ic = img->first;
745       }
746       else
747       {
748 	ic->pixels = ((cups_ib_t *)ic) + sizeof(cups_ic_t);
749 
750 	img->num_ics ++;
751 
752 	DEBUG_printf(("Allocated cache tile %d (%p)...\n", img->num_ics, ic));
753       }
754     }
755     else
756     {
757       DEBUG_printf(("Flushing old cache tile (%p)...\n", img->first));
758 
759       int res = flush_tile(img);
760       if(res)
761       {
762         return NULL;
763       }
764       ic = img->first;
765     }
766 
767     ic->tile = tile;
768     tile->ic = ic;
769 
770     if (tile->pos >= 0)
771     {
772       DEBUG_printf(("Loading cache tile from file position " CUPS_LLFMT "...\n",
773                     CUPS_LLCAST tile->pos));
774 
775       lseek(img->cachefile, tile->pos, SEEK_SET);
776       if (read(img->cachefile, ic->pixels,
777 	       bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE) == -1)
778 	DEBUG_printf(("Error reading cache tile!"));
779     }
780     else
781     {
782       DEBUG_puts("Clearing cache tile...");
783 
784       memset(ic->pixels, 0, bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE);
785     }
786   }
787 
788   if (ic == img->first)
789   {
790     if (ic->next != NULL)
791       ic->next->prev = NULL;
792 
793     img->first = ic->next;
794     ic->next   = NULL;
795     ic->prev   = NULL;
796   }
797   else if (img->first == NULL)
798     img->first = ic;
799 
800   if (ic != img->last)
801   {
802    /*
803     * Remove the cache entry from the list...
804     */
805 
806     if (ic->prev != NULL)
807       ic->prev->next = ic->next;
808     if (ic->next != NULL)
809       ic->next->prev = ic->prev;
810 
811    /*
812     * And add it to the end...
813     */
814 
815     if (img->last != NULL)
816       img->last->next = ic;
817 
818     ic->prev  = img->last;
819     img->last = ic;
820   }
821 
822   ic->next = NULL;
823 
824   return (ic->pixels + bpp * (y * CUPS_TILE_SIZE + x));
825 }
826 
827 /*
828  * Crop a image.
829  * (posw,posh): Position of left corner
830  * (width,height): width and height of required image.
831  */
cupsImageCrop(cups_image_t * img,int posw,int posh,int width,int height)832 cups_image_t* cupsImageCrop(cups_image_t* img,int posw,int posh,int width,int height)
833 {
834   int image_width = cupsImageGetWidth(img);
835   cups_image_t* temp=calloc(sizeof(cups_image_t),1);
836   cups_ib_t *pixels=(cups_ib_t*)malloc(img->xsize*cupsImageGetDepth(img));
837   temp->cachefile = -1;
838   temp->max_ics = CUPS_TILE_MINIMUM;
839   temp->colorspace=img->colorspace;
840   temp->xppi = img->xppi;
841   temp->yppi = img->yppi;
842   temp->num_ics = 0;
843   temp->first =temp->last = NULL;
844   temp->tiles = NULL;
845   temp->xsize = width;
846   temp->ysize = height;
847   for(int i=posh;i<min(cupsImageGetHeight(img),posh+height);i++){
848     cupsImageGetRow(img,posw,i,min(width,image_width-posw),pixels);
849     _cupsImagePutRow(temp,0,i-posh,min(width,image_width-posw),pixels);
850   }
851   free(pixels);
852   return temp;
853 }
854 
855 #ifdef HAVE_EXIF
856 /*
857   helper function required by EXIF read function
858   */
859 
trim_spaces(char * buf)860 static void trim_spaces(char *buf)
861 {
862   char *s = buf - 1;
863   for (; *buf; ++buf)
864   {
865     if (*buf != ' ')
866       s = buf;
867   }
868   *++s = 0; /* null terminate the string on the first of the final spaces */
869 }
870 
871 /*
872   implementation for EXIF read function
873   */
874 
875 /*
876   helper function to extract bytes from image files
877   */
878 
find_bytes(FILE * fp,long int * size)879 static unsigned char *find_bytes(FILE *fp, long int *size)
880 {
881   unsigned char *buf;
882 
883   long int originalOffset = ftell(fp);
884   fseek(fp, 0L, SEEK_END);
885 
886   // calculating the size of the file
887   long int res = ftell(fp);
888 
889   buf = (unsigned char *)malloc(res * sizeof(unsigned char) + 1);
890   fseek(fp, 0, SEEK_SET);
891 
892   if (fread(buf, 1, res, fp) < res)
893   {
894     free(buf);
895     buf = NULL;
896     *size = 0;
897   }
898   else
899     *size = res + 1;
900 
901   fseek(fp, originalOffset, SEEK_SET);
902 
903   return buf;
904 }
905 
_cupsImageReadEXIF(cups_image_t * img,FILE * fp)906 int _cupsImageReadEXIF(cups_image_t *img, FILE *fp)
907 {
908 
909   if (fp == NULL)
910   {
911     return -1;
912   }
913 
914   long int bufSize = 0;
915 
916   unsigned char *buf = find_bytes(fp, &bufSize);
917 
918   ExifData *ed = NULL;
919 
920   if (buf == NULL || bufSize <= 0 ||
921       (ed = exif_data_new_from_data(buf, bufSize)) == NULL)
922   {
923     DEBUG_printf(("DEBUG: No EXIF data found"));
924     return 2;
925   }
926 
927   ExifIfd ifd = EXIF_IFD_0;
928   ExifTag tagX = EXIF_TAG_X_RESOLUTION;
929   ExifTag tagY = EXIF_TAG_Y_RESOLUTION;
930 
931   ExifEntry *entryX = exif_content_get_entry(ed->ifd[ifd], tagX);
932 
933   ExifEntry *entryY = exif_content_get_entry(ed->ifd[ifd], tagY);
934 
935   if (entryX == NULL || entryY == NULL)
936   {
937     DEBUG_printf(("DEBUG: No EXIF data found"));
938     return 2;
939   }
940 
941   if (entryX)
942   {
943     char buf1[1024];
944 
945     exif_entry_get_value(entryX, buf1, sizeof(buf1));
946 
947     trim_spaces(buf1);
948 
949     if (*buf1)
950     {
951       int xRes;
952       sscanf(buf1, "%d", &xRes);
953       img->xppi = xRes;
954     }
955     else{
956       free(buf);
957       return 2;
958     }
959   }
960 
961   if (entryY)
962   {
963     char buf2[1024];
964 
965     exif_entry_get_value(entryY, buf2, sizeof(buf2));
966     trim_spaces(buf2);
967 
968     if (*buf2)
969     {
970       int yRes;
971       sscanf(buf2, "%d", &yRes);
972       img->yppi = yRes;
973     }
974     else{
975       free(buf);
976       return 2;
977     }
978   }
979 
980   free(buf);
981   return 1;
982 }
983 #endif
984