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