]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/image.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / image.c
CommitLineData
ef416fc2 1/*
bc44d920 2 * "$Id: image.c 6649 2007-07-11 21:46:42Z mike $"
ef416fc2 3 *
4 * Base image support for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 by Apple Inc.
ef416fc2 7 * Copyright 1993-2005 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 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
47static void flush_tile(cups_image_t *img);
48static cups_ib_t *get_tile(cups_image_t *img, int x, int y);
49
50
51/*
52 * 'cupsImageClose()' - Close an image file.
53 */
54
55void
56cupsImageClose(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 != NULL)
67 {
68 DEBUG_printf(("Closing/removing swap file \"%s\"...\n", img->cachename));
69
70 fclose(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
111int /* O - -1 on error, 0 on success */
112cupsImageGetCol(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
178cups_icspace_t /* O - Colorspace */
179cupsImageGetColorSpace(
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
190int /* O - Bytes per pixel */
191cupsImageGetDepth(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
201unsigned /* O - Height in pixels */
202cupsImageGetHeight(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
212int /* O - -1 on error, 0 on success */
213cupsImageGetRow(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
265unsigned /* O - Width in pixels */
266cupsImageGetWidth(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
276unsigned /* O - Horizontal PPI */
277cupsImageGetXPPI(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
287unsigned /* O - Vertical PPI */
288cupsImageGetYPPI(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
298cups_image_t * /* O - New image */
299cupsImageOpen(
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 {
324/* perror("ERROR: Unable to open image file");
325*/ return (NULL);
326 }
327
328 if (fread(header, 1, sizeof(header), fp) == 0)
329 {
330/* perror("ERROR: Unable to read image file header");
331*/
332 fclose(fp);
333 return (NULL);
334 }
335
336 fseek(fp, 2048, SEEK_SET);
337 memset(header2, 0, sizeof(header2));
338 fread(header2, 1, sizeof(header2), fp);
339 fseek(fp, 0, SEEK_SET);
340
341 /*
342 * Allocate memory...
343 */
344
345 img = calloc(sizeof(cups_image_t), 1);
346
347 if (img == NULL)
348 {
349/* perror("ERROR: Unable to allocate memory for image file");
350*/ fclose(fp);
351 return (NULL);
352 }
353
354 /*
355 * Load the image as appropriate...
356 */
357
358 img->max_ics = CUPS_TILE_MINIMUM;
359 img->xppi = 128;
360 img->yppi = 128;
361
362 if (!memcmp(header, "GIF87a", 6) || !memcmp(header, "GIF89a", 6))
363 status = _cupsImageReadGIF(img, fp, primary, secondary, saturation, hue,
364 lut);
365 else if (!memcmp(header, "BM", 2))
366 status = _cupsImageReadBMP(img, fp, primary, secondary, saturation, hue,
367 lut);
368 else if (header[0] == 0x01 && header[1] == 0xda)
369 status = _cupsImageReadSGI(img, fp, primary, secondary, saturation, hue,
370 lut);
371 else if (header[0] == 0x59 && header[1] == 0xa6 &&
372 header[2] == 0x6a && header[3] == 0x95)
373 status = _cupsImageReadSunRaster(img, fp, primary, secondary, saturation,
374 hue, lut);
375 else if (header[0] == 'P' && header[1] >= '1' && header[1] <= '6')
376 status = _cupsImageReadPNM(img, fp, primary, secondary, saturation, hue,
377 lut);
378 else if (!memcmp(header2, "PCD_IPI", 7))
379 status = _cupsImageReadPhotoCD(img, fp, primary, secondary, saturation,
380 hue, lut);
381 else if (!memcmp(header + 8, "\000\010", 2) ||
382 !memcmp(header + 8, "\000\030", 2))
383 status = _cupsImageReadPIX(img, fp, primary, secondary, saturation, hue,
384 lut);
385#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
386 else if (!memcmp(header, "\211PNG", 4))
387 status = _cupsImageReadPNG(img, fp, primary, secondary, saturation, hue,
388 lut);
389#endif /* HAVE_LIBPNG && HAVE_LIBZ */
390#ifdef HAVE_LIBJPEG
391 else if (!memcmp(header, "\377\330\377", 3) && /* Start-of-Image */
392 header[3] >= 0xe0 && header[3] <= 0xef) /* APPn */
393 status = _cupsImageReadJPEG(img, fp, primary, secondary, saturation, hue,
394 lut);
395#endif /* HAVE_LIBJPEG */
396#ifdef HAVE_LIBTIFF
397 else if (!memcmp(header, "MM\000\052", 4) ||
398 !memcmp(header, "II\052\000", 4))
399 status = _cupsImageReadTIFF(img, fp, primary, secondary, saturation, hue,
400 lut);
401#endif /* HAVE_LIBTIFF */
402 else
403 {
404/* fputs("ERROR: Unknown image file format!");
405*/ fclose(fp);
406 status = -1;
407 }
408
409 if (status)
410 {
411 free(img);
412 return (NULL);
413 }
414 else
415 return (img);
416}
417
418
419/*
420 * '_cupsImagePutCol()' - Put a column of pixels to an image.
421 */
422
423int /* O - -1 on error, 0 on success */
424_cupsImagePutCol(
425 cups_image_t *img, /* I - Image */
426 int x, /* I - Column */
427 int y, /* I - Start row */
428 int height, /* I - Column height */
429 const cups_ib_t *pixels) /* I - Pixels to put */
430{
431 int bpp, /* Bytes per pixel */
432 twidth, /* Width of tile */
433 count; /* Number of pixels to put */
434 int tilex, /* Column within tile */
435 tiley; /* Row within tile */
436 cups_ib_t *ib; /* Pointer to pixels in tile */
437
438
439 if (img == NULL || x < 0 || x >= img->xsize || y >= img->ysize)
440 return (-1);
441
442 if (y < 0)
443 {
444 height += y;
445 y = 0;
446 }
447
448 if ((y + height) > img->ysize)
449 height = img->ysize - y;
450
451 if (height < 1)
452 return (-1);
453
454 bpp = cupsImageGetDepth(img);
455 twidth = bpp * (CUPS_TILE_SIZE - 1);
456 tilex = x / CUPS_TILE_SIZE;
457 tiley = y / CUPS_TILE_SIZE;
458
459 while (height > 0)
460 {
461 ib = get_tile(img, x, y);
462
463 if (ib == NULL)
464 return (-1);
465
466 img->tiles[tiley][tilex].dirty = 1;
467 tiley ++;
468
469 count = CUPS_TILE_SIZE - (y & (CUPS_TILE_SIZE - 1));
470 if (count > height)
471 count = height;
472
473 y += count;
474 height -= count;
475
476 for (; count > 0; count --, ib += twidth)
477 switch (bpp)
478 {
479 case 4 :
480 *ib++ = *pixels++;
481 case 3 :
482 *ib++ = *pixels++;
483 *ib++ = *pixels++;
484 case 1 :
485 *ib++ = *pixels++;
486 break;
487 }
488 }
489
490 return (0);
491}
492
493
494/*
495 * '_cupsImagePutRow()' - Put a row of pixels to an image.
496 */
497
498int /* O - -1 on error, 0 on success */
499_cupsImagePutRow(
500 cups_image_t *img, /* I - Image */
501 int x, /* I - Start column */
502 int y, /* I - Row */
503 int width, /* I - Row width */
504 const cups_ib_t *pixels) /* I - Pixel data */
505{
506 int bpp, /* Bytes per pixel */
507 count; /* Number of pixels to put */
508 int tilex, /* Column within tile */
509 tiley; /* Row within tile */
510 cups_ib_t *ib; /* Pointer to pixels in tile */
511
512
513 if (img == NULL || y < 0 || y >= img->ysize || x >= img->xsize)
514 return (-1);
515
516 if (x < 0)
517 {
518 width += x;
519 x = 0;
520 }
521
522 if ((x + width) > img->xsize)
523 width = img->xsize - x;
524
525 if (width < 1)
526 return (-1);
527
528 bpp = img->colorspace < 0 ? -img->colorspace : img->colorspace;
529 tilex = x / CUPS_TILE_SIZE;
530 tiley = y / CUPS_TILE_SIZE;
531
532 while (width > 0)
533 {
534 ib = get_tile(img, x, y);
535
536 if (ib == NULL)
537 return (-1);
538
539 img->tiles[tiley][tilex].dirty = 1;
540
541 count = CUPS_TILE_SIZE - (x & (CUPS_TILE_SIZE - 1));
542 if (count > width)
543 count = width;
544 memcpy(ib, pixels, count * bpp);
545 pixels += count * bpp;
546 x += count;
547 width -= count;
548 tilex ++;
549 }
550
551 return (0);
552}
553
554
555/*
556 * 'cupsImageSetMaxTiles()' - Set the maximum number of tiles to cache.
557 *
558 * If the "max_tiles" argument is 0 then the maximum number of tiles is
559 * computed from the image size or the RIP_CACHE environment variable.
560 */
561
562void
563cupsImageSetMaxTiles(
564 cups_image_t *img, /* I - Image to set */
565 int max_tiles) /* I - Number of tiles to cache */
566{
567 int cache_size, /* Size of tile cache in bytes */
568 min_tiles, /* Minimum number of tiles to cache */
569 max_size; /* Maximum cache size in bytes */
570 char *cache_env, /* Cache size environment variable */
571 cache_units[255]; /* Cache size units */
572
573
574 min_tiles = max(CUPS_TILE_MINIMUM,
575 1 + max((img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE,
576 (img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE));
577
578 if (max_tiles == 0)
579 max_tiles = ((img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE) *
580 ((img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE);
581
582 cache_size = max_tiles * CUPS_TILE_SIZE * CUPS_TILE_SIZE *
583 cupsImageGetDepth(img);
584
585 if ((cache_env = getenv("RIP_MAX_CACHE")) != NULL)
586 {
587 switch (sscanf(cache_env, "%d%254s", &max_size, cache_units))
588 {
589 case 0 :
590 max_size = 32 * 1024 * 1024;
591 break;
592 case 1 :
593 max_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
594 break;
595 case 2 :
596 if (tolower(cache_units[0] & 255) == 'g')
597 max_size *= 1024 * 1024 * 1024;
598 else if (tolower(cache_units[0] & 255) == 'm')
599 max_size *= 1024 * 1024;
600 else if (tolower(cache_units[0] & 255) == 'k')
601 max_size *= 1024;
602 else if (tolower(cache_units[0] & 255) == 't')
603 max_size *= 4 * CUPS_TILE_SIZE * CUPS_TILE_SIZE;
604 break;
605 }
606 }
607 else
608 max_size = 32 * 1024 * 1024;
609
610 if (cache_size > max_size)
611 max_tiles = max_size / CUPS_TILE_SIZE / CUPS_TILE_SIZE /
612 cupsImageGetDepth(img);
613
614 if (max_tiles < min_tiles)
615 max_tiles = min_tiles;
616
617 img->max_ics = max_tiles;
618
619 DEBUG_printf(("max_ics=%d...\n", img->max_ics));
620}
621
622
623/*
624 * 'flush_tile()' - Flush the least-recently-used tile in the cache.
625 */
626
627static void
628flush_tile(cups_image_t *img) /* I - Image */
629{
630 int fd; /* Cache file descriptor */
631 int bpp; /* Bytes per pixel */
632 cups_itile_t *tile; /* Pointer to tile */
633
634
635 bpp = cupsImageGetDepth(img);
636 tile = img->first->tile;
637
638 if (!tile->dirty)
639 {
640 tile->ic = NULL;
641 return;
642 }
643
644 if (img->cachefile == NULL)
645 {
646 if ((fd = cupsTempFd(img->cachename, sizeof(img->cachename))) < 0)
647 {
648/* perror("ERROR: Unable to create image swap file");
649*/ tile->ic = NULL;
650 tile->dirty = 0;
651 return;
652 }
653
654 DEBUG_printf(("Created swap file \"%s\"...\n", img->cachename));
655
656 if ((img->cachefile = fdopen(fd, "wb+")) == NULL)
657 {
658/* perror("ERROR: Unable to create image swap file");
659*/ close(fd);
660 unlink(img->cachename);
661 tile->ic = NULL;
662 tile->dirty = 0;
663 return;
664 }
665 }
666
667 if (tile->pos >= 0)
668 {
669 if (ftell(img->cachefile) != tile->pos)
670 if (fseek(img->cachefile, tile->pos, SEEK_SET))
671 {
672/* perror("ERROR: Unable to seek in swap file");
673*/ tile->ic = NULL;
674 tile->dirty = 0;
675 return;
676 }
677 }
678 else
679 {
680 if (fseek(img->cachefile, 0, SEEK_END))
681 {
682/* perror("ERROR: Unable to append to swap file");
683*/ tile->ic = NULL;
684 tile->dirty = 0;
685 return;
686 }
687
688 tile->pos = ftell(img->cachefile);
689 }
690
691
692/* if (fwrite(tile->ic->pixels, bpp, CUPS_TILE_SIZE * CUPS_TILE_SIZE,
693 img->cachefile) < 1)
694 perror("ERROR: Unable to write tile to swap file");
695 else
696 DEBUG_printf(("Wrote tile at position %ld...\n", tile->pos));
697*/
698
699 fwrite(tile->ic->pixels, bpp, CUPS_TILE_SIZE * CUPS_TILE_SIZE,
700 img->cachefile);
701
702 tile->ic = NULL;
703 tile->dirty = 0;
704}
705
706
707/*
708 * 'get_tile()' - Get a cached tile.
709 */
710
711static cups_ib_t * /* O - Pointer to tile or NULL */
712get_tile(cups_image_t *img, /* I - Image */
713 int x, /* I - Column in image */
714 int y) /* I - Row in image */
715{
716 int bpp, /* Bytes per pixel */
717 tilex, /* Column within tile */
718 tiley, /* Row within tile */
719 xtiles, /* Number of tiles horizontally */
720 ytiles; /* Number of tiles vertically */
721 cups_ic_t *ic; /* Cache pointer */
722 cups_itile_t *tile; /* Tile pointer */
723
724
725 if (img->tiles == NULL)
726 {
727 xtiles = (img->xsize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE;
728 ytiles = (img->ysize + CUPS_TILE_SIZE - 1) / CUPS_TILE_SIZE;
729
730 DEBUG_printf(("Creating tile array (%dx%d)\n", xtiles, ytiles));
731
732 img->tiles = calloc(sizeof(cups_itile_t *), ytiles);
733 tile = calloc(sizeof(cups_itile_t), xtiles * ytiles);
734
735 for (tiley = 0; tiley < ytiles; tiley ++)
736 {
737 img->tiles[tiley] = tile;
738 for (tilex = xtiles; tilex > 0; tilex --, tile ++)
739 tile->pos = -1;
740 }
741 }
742
743 bpp = cupsImageGetDepth(img);
744 tilex = x / CUPS_TILE_SIZE;
745 tiley = y / CUPS_TILE_SIZE;
746 tile = img->tiles[tiley] + tilex;
747 x &= (CUPS_TILE_SIZE - 1);
748 y &= (CUPS_TILE_SIZE - 1);
749
750 if ((ic = tile->ic) == NULL)
751 {
752 if (img->num_ics < img->max_ics)
753 {
754 ic = calloc(sizeof(cups_ic_t) + bpp * CUPS_TILE_SIZE *
755 CUPS_TILE_SIZE, 1);
756 ic->pixels = ((cups_ib_t *)ic) + sizeof(cups_ic_t);
757
758 img->num_ics ++;
759
760 DEBUG_printf(("Allocated cache tile %d (%p)...\n", img->num_ics, ic));
761 }
762 else
763 {
764 DEBUG_printf(("Flushing old cache tile (%p)...\n", img->first));
765
766 flush_tile(img);
767 ic = img->first;
768 }
769
770 ic->tile = tile;
771 tile->ic = ic;
772
773 if (tile->pos >= 0)
774 {
775 DEBUG_printf(("Loading cache tile from file position %ld...\n",
776 tile->pos));
777
778 if (ftell(img->cachefile) != tile->pos)
779 fseek(img->cachefile, tile->pos, SEEK_SET);
780/* if (fseek(img->cachefile, tile->pos, SEEK_SET))
781 perror("get_tile:");
782*/
783
784 fread(ic->pixels, bpp, CUPS_TILE_SIZE * CUPS_TILE_SIZE, img->cachefile);
785 }
786 else
787 {
788 DEBUG_puts("Clearing cache tile...");
789
790 memset(ic->pixels, 0, bpp * CUPS_TILE_SIZE * CUPS_TILE_SIZE);
791 }
792 }
793
794 if (ic == img->first)
795 {
796 if (ic->next != NULL)
797 ic->next->prev = NULL;
798
799 img->first = ic->next;
800 ic->next = NULL;
801 ic->prev = NULL;
802 }
803 else if (img->first == NULL)
804 img->first = ic;
805
806 if (ic != img->last)
807 {
808 /*
809 * Remove the cache entry from the list...
810 */
811
812 if (ic->prev != NULL)
813 ic->prev->next = ic->next;
814 if (ic->next != NULL)
815 ic->next->prev = ic->prev;
816
817 /*
818 * And add it to the end...
819 */
820
821 if (img->last != NULL)
822 img->last->next = ic;
823
824 ic->prev = img->last;
825 img->last = ic;
826 }
827
828 ic->next = NULL;
829
830 return (ic->pixels + bpp * (y * CUPS_TILE_SIZE + x));
831}
832
833
834/*
bc44d920 835 * End of "$Id: image.c 6649 2007-07-11 21:46:42Z mike $".
ef416fc2 836 */