1 #ifndef lint
2 static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_getimage.c,v 1.8 92/03/11 09:19:10 sam Exp $";
3 #endif
4
5 /*
6 * Copyright (c) 1991, 1992 Sam Leffler
7 * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
8 *
9 * Permission to use, copy, modify, distribute, and sell this software and
10 * its documentation for any purpose is hereby granted without fee, provided
11 * that (i) the above copyright notices and this permission notice appear in
12 * all copies of the software and related documentation, and (ii) the names of
13 * Sam Leffler and Silicon Graphics may not be used in any advertising or
14 * publicity relating to the software without the specific, prior written
15 * permission of Sam Leffler and Silicon Graphics.
16 *
17 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
19 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
22 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
23 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
25 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 * OF THIS SOFTWARE.
27 */
28
29 /*
30 * TIFF Library
31 *
32 * Read and return a packed RGBA image.
33 */
34 #include "tiffio.h"
35 #include "tiffcompat.h"
36 #include "prototypes.h"
37
38 typedef u_char RGBvalue;
39
40 static u_long width, height; /* image width & height */
41 static u_short bitspersample;
42 static u_short samplesperpixel;
43 static u_short photometric;
44 static u_short orientation;
45 /* colormap for pallete images */
46 static u_short *redcmap, *greencmap, *bluecmap;
47 static int stoponerr; /* stop on read error */
48 static char *filename;
49 /* YCbCr support */
50 static u_short YCbCrHorizSampling;
51 static u_short YCbCrVertSampling;
52 static float *YCbCrCoeffs;
53 static float *refBlackWhite;
54
55 static u_long **BWmap;
56 static u_long **PALmap;
57
58 static int gt();
59
TIFFReadRGBAImage(tif,rwidth,rheight,raster,stop)60 TIFFReadRGBAImage(tif, rwidth, rheight, raster, stop)
61 TIFF *tif;
62 u_long rwidth, rheight;
63 u_long *raster;
64 int stop;
65 {
66 int ok;
67 u_long width, height;
68
69 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
70 switch (bitspersample) {
71 case 1: case 2: case 4:
72 case 8: case 16:
73 break;
74 default:
75 TIFFError(TIFFFileName(tif),
76 "Sorry, can not handle %d-bit pictures", bitspersample);
77 return (0);
78 }
79 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
80 switch (samplesperpixel) {
81 case 1: case 3: case 4:
82 break;
83 default:
84 TIFFError(TIFFFileName(tif),
85 "Sorry, can not handle %d-channel images", samplesperpixel);
86 return (0);
87 }
88 if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
89 switch (samplesperpixel) {
90 case 1:
91 photometric = PHOTOMETRIC_MINISBLACK;
92 break;
93 case 3: case 4:
94 photometric = PHOTOMETRIC_RGB;
95 break;
96 default:
97 TIFFError(TIFFFileName(tif),
98 "Missing needed \"PhotometricInterpretation\" tag");
99 return (0);
100 }
101 TIFFError(TIFFFileName(tif),
102 "No \"PhotometricInterpretation\" tag, assuming %s\n",
103 photometric == PHOTOMETRIC_RGB ? "RGB" : "min-is-black");
104 }
105 /* XXX maybe should check photometric? */
106 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
107 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
108 /* XXX verify rwidth and rheight against width and height */
109 stoponerr = stop;
110 BWmap = NULL;
111 PALmap = NULL;
112 ok = gt(tif, rwidth, height, raster + (rheight-height)*rwidth);
113 if (BWmap)
114 free((char *)BWmap);
115 if (PALmap)
116 free((char *)PALmap);
117 return (ok);
118 }
119
120 static int
checkcmap(n,r,g,b)121 checkcmap(n, r, g, b)
122 int n;
123 u_short *r, *g, *b;
124 {
125 while (n-- > 0)
126 if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
127 return (16);
128 TIFFWarning(filename, "Assuming 8-bit colormap");
129 return (8);
130 }
131
132 static gtTileContig();
133 static gtTileSeparate();
134 static gtStripContig();
135 static gtStripSeparate();
136 static void initYCbCrConversion();
137
138 static
gt(tif,w,h,raster)139 gt(tif, w, h, raster)
140 TIFF *tif;
141 int w, h;
142 u_long *raster;
143 {
144 u_short minsamplevalue, maxsamplevalue, planarconfig;
145 RGBvalue *Map;
146 int e;
147
148 TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue);
149 TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue);
150 Map = NULL;
151 switch (photometric) {
152 case PHOTOMETRIC_YCBCR:
153 TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRCOEFFICIENTS,
154 &YCbCrCoeffs);
155 TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING,
156 &YCbCrHorizSampling, &YCbCrVertSampling);
157 TIFFGetFieldDefaulted(tif, TIFFTAG_REFERENCEBLACKWHITE,
158 &refBlackWhite);
159 initYCbCrConversion();
160 /* fall thru... */
161 case PHOTOMETRIC_RGB:
162 if (minsamplevalue == 0 && maxsamplevalue == 255)
163 break;
164 /* fall thru... */
165 case PHOTOMETRIC_MINISBLACK:
166 case PHOTOMETRIC_MINISWHITE: {
167 register int x, range;
168
169 range = maxsamplevalue - minsamplevalue;
170 Map = (RGBvalue *)malloc((range + 1) * sizeof (RGBvalue));
171 if (Map == NULL) {
172 TIFFError(filename,
173 "No space for photometric conversion table");
174 return (0);
175 }
176 if (photometric == PHOTOMETRIC_MINISWHITE) {
177 for (x = 0; x <= range; x++)
178 Map[x] = ((range - x) * 255) / range;
179 } else {
180 for (x = 0; x <= range; x++)
181 Map[x] = (x * 255) / range;
182 }
183 if (photometric != PHOTOMETRIC_RGB && bitspersample <= 8) {
184 /*
185 * Use photometric mapping table to construct
186 * unpacking tables for samples <= 8 bits.
187 */
188 if (!makebwmap(Map))
189 return (0);
190 /* no longer need Map, free it */
191 free((char *)Map);
192 Map = NULL;
193 }
194 break;
195 }
196 case PHOTOMETRIC_PALETTE:
197 if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
198 &redcmap, &greencmap, &bluecmap)) {
199 TIFFError(filename,
200 "Missing required \"Colormap\" tag");
201 return (0);
202 }
203 /*
204 * Convert 16-bit colormap to 8-bit (unless it looks
205 * like an old-style 8-bit colormap).
206 */
207 if (checkcmap(1<<bitspersample, redcmap, greencmap, bluecmap) == 16) {
208 int i;
209 for (i = (1<<bitspersample)-1; i > 0; i--) {
210 #define CVT(x) (((x) * 255) / ((1L<<16)-1))
211 redcmap[i] = CVT(redcmap[i]);
212 greencmap[i] = CVT(greencmap[i]);
213 bluecmap[i] = CVT(bluecmap[i]);
214 }
215 }
216 if (bitspersample <= 8) {
217 /*
218 * Use mapping table and colormap to construct
219 * unpacking tables for samples < 8 bits.
220 */
221 if (!makecmap(redcmap, greencmap, bluecmap))
222 return (0);
223 }
224 break;
225 }
226 TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
227 if (planarconfig == PLANARCONFIG_SEPARATE && samplesperpixel > 1) {
228 e = TIFFIsTiled(tif) ?
229 gtTileSeparate(tif, raster, Map, h, w) :
230 gtStripSeparate(tif, raster, Map, h, w);
231 } else {
232 e = TIFFIsTiled(tif) ?
233 gtTileContig(tif, raster, Map, h, w) :
234 gtStripContig(tif, raster, Map, h, w);
235 }
236 if (Map)
237 free((char *)Map);
238 return (e);
239 }
240
241 u_long
setorientation(tif,h)242 setorientation(tif, h)
243 TIFF *tif;
244 u_long h;
245 {
246 u_long y;
247
248 TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &orientation);
249 switch (orientation) {
250 case ORIENTATION_BOTRIGHT:
251 case ORIENTATION_RIGHTBOT: /* XXX */
252 case ORIENTATION_LEFTBOT: /* XXX */
253 TIFFWarning(filename, "using bottom-left orientation");
254 orientation = ORIENTATION_BOTLEFT;
255 /* fall thru... */
256 case ORIENTATION_BOTLEFT:
257 y = 0;
258 break;
259 case ORIENTATION_TOPRIGHT:
260 case ORIENTATION_RIGHTTOP: /* XXX */
261 case ORIENTATION_LEFTTOP: /* XXX */
262 default:
263 TIFFWarning(filename, "using top-left orientation");
264 orientation = ORIENTATION_TOPLEFT;
265 /* fall thru... */
266 case ORIENTATION_TOPLEFT:
267 y = h-1;
268 break;
269 }
270 return (y);
271 }
272
273 #if USE_PROTOTYPES
274 typedef void (*tileContigRoutine)
275 (u_long*, u_char*, RGBvalue*, u_long, u_long, int, int);
276 static tileContigRoutine pickTileContigCase(RGBvalue*);
277 #else
278 typedef void (*tileContigRoutine)();
279 static tileContigRoutine pickTileContigCase();
280 #endif
281
282 /*
283 * Get an tile-organized image that has
284 * PlanarConfiguration contiguous if SamplesPerPixel > 1
285 * or
286 * SamplesPerPixel == 1
287 */
288 static
gtTileContig(tif,raster,Map,h,w)289 gtTileContig(tif, raster, Map, h, w)
290 TIFF *tif;
291 u_long *raster;
292 RGBvalue *Map;
293 u_long h, w;
294 {
295 u_long col, row, y;
296 u_long tw, th;
297 u_char *buf;
298 int fromskew, toskew;
299 u_int nrow;
300 tileContigRoutine put;
301
302 put = pickTileContigCase(Map);
303 if (put == 0)
304 return (0);
305 buf = (u_char *)malloc(TIFFTileSize(tif));
306 if (buf == 0) {
307 TIFFError(filename, "No space for tile buffer");
308 return (0);
309 }
310 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
311 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
312 y = setorientation(tif, h);
313 toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
314 for (row = 0; row < h; row += th) {
315 nrow = (row + th > h ? h - row : th);
316 for (col = 0; col < w; col += tw) {
317 if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0 &&
318 stoponerr)
319 break;
320 if (col + tw > w) {
321 /*
322 * Tile is clipped horizontally. Calculate
323 * visible portion and skewing factors.
324 */
325 u_long npix = w - col;
326 fromskew = tw - npix;
327 (*put)(raster + y*w + col, buf, Map,
328 npix, nrow, fromskew, toskew + fromskew);
329 } else
330 (*put)(raster + y*w + col, buf, Map,
331 tw, nrow, 0, toskew);
332 }
333 y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
334 }
335 free(buf);
336 return (1);
337 }
338
339 #if USE_PROTOTYPES
340 typedef void (*tileSeparateRoutine)
341 (u_long*, u_char*, u_char*, u_char*, RGBvalue*, u_long, u_long, int, int);
342 static tileSeparateRoutine pickTileSeparateCase(RGBvalue*);
343 #else
344 typedef void (*tileSeparateRoutine)();
345 static tileSeparateRoutine pickTileSeparateCase();
346 #endif
347
348 /*
349 * Get an tile-organized image that has
350 * SamplesPerPixel > 1
351 * PlanarConfiguration separated
352 * We assume that all such images are RGB.
353 */
354 static
gtTileSeparate(tif,raster,Map,h,w)355 gtTileSeparate(tif, raster, Map, h, w)
356 TIFF *tif;
357 u_long *raster;
358 RGBvalue *Map;
359 u_long h, w;
360 {
361 u_long col, row, y;
362 u_long tw, th;
363 u_char *buf;
364 u_char *r, *g, *b;
365 int tilesize;
366 int fromskew, toskew;
367 u_int nrow;
368 tileSeparateRoutine put;
369
370 put = pickTileSeparateCase(Map);
371 if (put == 0)
372 return (0);
373 tilesize = TIFFTileSize(tif);
374 buf = (u_char *)malloc(3*tilesize);
375 if (buf == 0) {
376 TIFFError(filename, "No space for tile buffer");
377 return (0);
378 }
379 r = buf;
380 g = r + tilesize;
381 b = g + tilesize;
382 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
383 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
384 y = setorientation(tif, h);
385 toskew = (orientation == ORIENTATION_TOPLEFT ? -tw + -w : -tw + w);
386 for (row = 0; row < h; row += th) {
387 nrow = (row + th > h ? h - row : th);
388 for (col = 0; col < w; col += tw) {
389 if (TIFFReadTile(tif, r, col, row,0,0) < 0 && stoponerr)
390 break;
391 if (TIFFReadTile(tif, g, col, row,0,1) < 0 && stoponerr)
392 break;
393 if (TIFFReadTile(tif, b, col, row,0,2) < 0 && stoponerr)
394 break;
395 if (col + tw > w) {
396 /*
397 * Tile is clipped horizontally. Calculate
398 * visible portion and skewing factors.
399 */
400 u_long npix = w - col;
401 fromskew = tw - npix;
402 (*put)(raster + y*w + col, r, g, b, Map,
403 npix, nrow, fromskew, toskew + fromskew);
404 } else
405 (*put)(raster + y*w + col, r, g, b, Map,
406 tw, nrow, 0, toskew);
407 }
408 y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
409 }
410 free(buf);
411 return (1);
412 }
413
414 /*
415 * Get a strip-organized image that has
416 * PlanarConfiguration contiguous if SamplesPerPixel > 1
417 * or
418 * SamplesPerPixel == 1
419 */
420 static
gtStripContig(tif,raster,Map,h,w)421 gtStripContig(tif, raster, Map, h, w)
422 TIFF *tif;
423 u_long *raster;
424 RGBvalue *Map;
425 u_long h, w;
426 {
427 u_long row, y, nrow;
428 u_char *buf;
429 tileContigRoutine put;
430 u_long rowsperstrip;
431 u_long imagewidth;
432 int scanline;
433 int fromskew, toskew;
434
435 put = pickTileContigCase(Map);
436 if (put == 0)
437 return (0);
438 buf = (u_char *)malloc(TIFFStripSize(tif));
439 if (buf == 0) {
440 TIFFError(filename, "No space for strip buffer");
441 return (0);
442 }
443 y = setorientation(tif, h);
444 toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
445 TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
446 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
447 scanline = TIFFScanlineSize(tif);
448 fromskew = (w < imagewidth ? imagewidth - w : 0);
449 for (row = 0; row < h; row += rowsperstrip) {
450 nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
451 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
452 buf, nrow*scanline) < 0 && stoponerr)
453 break;
454 (*put)(raster + y*w, buf, Map, w, nrow, fromskew, toskew);
455 y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
456 }
457 free(buf);
458 return (1);
459 }
460
461 /*
462 * Get a strip-organized image with
463 * SamplesPerPixel > 1
464 * PlanarConfiguration separated
465 * We assume that all such images are RGB.
466 */
467 static
gtStripSeparate(tif,raster,Map,h,w)468 gtStripSeparate(tif, raster, Map, h, w)
469 TIFF *tif;
470 u_long *raster;
471 register RGBvalue *Map;
472 u_long h, w;
473 {
474 u_char *buf;
475 u_char *r, *g, *b;
476 u_long row, y, nrow;
477 int scanline;
478 tileSeparateRoutine put;
479 u_long rowsperstrip;
480 u_long imagewidth;
481 u_int stripsize;
482 int fromskew, toskew;
483
484 stripsize = TIFFStripSize(tif);
485 r = buf = (u_char *)malloc(3*stripsize);
486 if (buf == 0)
487 return (0);
488 g = r + stripsize;
489 b = g + stripsize;
490 put = pickTileSeparateCase(Map);
491 if (put == 0) {
492 TIFFError(filename, "Can not handle format");
493 return (0);
494 }
495 y = setorientation(tif, h);
496 toskew = (orientation == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
497 TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
498 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imagewidth);
499 scanline = TIFFScanlineSize(tif);
500 fromskew = (w < imagewidth ? imagewidth - w : 0);
501 for (row = 0; row < h; row += rowsperstrip) {
502 nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
503 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
504 r, nrow*scanline) < 0 && stoponerr)
505 break;
506 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
507 g, nrow*scanline) < 0 && stoponerr)
508 break;
509 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
510 b, nrow*scanline) < 0 && stoponerr)
511 break;
512 (*put)(raster + y*w, r, g, b, Map, w, nrow, fromskew, toskew);
513 y += (orientation == ORIENTATION_TOPLEFT ? -nrow : nrow);
514 }
515 free(buf);
516 return (1);
517 }
518
519 #define PACK(r,g,b) ((u_long)(r)|((u_long)(g)<<8)|((u_long)(b)<<16))
520
521 /*
522 * Greyscale images with less than 8 bits/sample are handled
523 * with a table to avoid lots of shifts and masks. The table
524 * is setup so that put*bwtile (below) can retrieve 8/bitspersample
525 * pixel values simply by indexing into the table with one
526 * number.
527 */
makebwmap(Map)528 makebwmap(Map)
529 RGBvalue *Map;
530 {
531 register int i;
532 int nsamples = 8 / bitspersample;
533 register u_long *p;
534
535 BWmap = (u_long **)malloc(
536 256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)));
537 if (BWmap == NULL) {
538 TIFFError(filename, "No space for B&W mapping table");
539 return (0);
540 }
541 p = (u_long *)(BWmap + 256);
542 for (i = 0; i < 256; i++) {
543 BWmap[i] = p;
544 switch (bitspersample) {
545 register RGBvalue c;
546 #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c);
547 case 1:
548 GREY(i>>7);
549 GREY((i>>6)&1);
550 GREY((i>>5)&1);
551 GREY((i>>4)&1);
552 GREY((i>>3)&1);
553 GREY((i>>2)&1);
554 GREY((i>>1)&1);
555 GREY(i&1);
556 break;
557 case 2:
558 GREY(i>>6);
559 GREY((i>>4)&3);
560 GREY((i>>2)&3);
561 GREY(i&3);
562 break;
563 case 4:
564 GREY(i>>4);
565 GREY(i&0xf);
566 break;
567 case 8:
568 GREY(i);
569 break;
570 }
571 #undef GREY
572 }
573 return (1);
574 }
575
576 /*
577 * Palette images with <= 8 bits/sample are handled
578 * with a table to avoid lots of shifts and masks. The table
579 * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
580 * pixel values simply by indexing into the table with one
581 * number.
582 */
makecmap(rmap,gmap,bmap)583 makecmap(rmap, gmap, bmap)
584 u_short *rmap, *gmap, *bmap;
585 {
586 register int i;
587 int nsamples = 8 / bitspersample;
588 register u_long *p;
589
590 PALmap = (u_long **)malloc(
591 256*sizeof (u_long *)+(256*nsamples*sizeof(u_long)));
592 if (PALmap == NULL) {
593 TIFFError(filename, "No space for Palette mapping table");
594 return (0);
595 }
596 p = (u_long *)(PALmap + 256);
597 for (i = 0; i < 256; i++) {
598 PALmap[i] = p;
599 #define CMAP(x) \
600 c = x; *p++ = PACK(rmap[c]&0xff, gmap[c]&0xff, bmap[c]&0xff);
601 switch (bitspersample) {
602 register RGBvalue c;
603 case 1:
604 CMAP(i>>7);
605 CMAP((i>>6)&1);
606 CMAP((i>>5)&1);
607 CMAP((i>>4)&1);
608 CMAP((i>>3)&1);
609 CMAP((i>>2)&1);
610 CMAP((i>>1)&1);
611 CMAP(i&1);
612 break;
613 case 2:
614 CMAP(i>>6);
615 CMAP((i>>4)&3);
616 CMAP((i>>2)&3);
617 CMAP(i&3);
618 break;
619 case 4:
620 CMAP(i>>4);
621 CMAP(i&0xf);
622 break;
623 case 8:
624 CMAP(i);
625 break;
626 }
627 #undef CMAP
628 }
629 return (1);
630 }
631
632 /*
633 * The following routines move decoded data returned
634 * from the TIFF library into rasters filled with packed
635 * ABGR pixels (i.e. suitable for passing to lrecwrite.)
636 *
637 * The routines have been created according to the most
638 * important cases and optimized. pickTileContigCase and
639 * pickTileSeparateCase analyze the parameters and select
640 * the appropriate "put" routine to use.
641 */
642 #define REPEAT8(op) REPEAT4(op); REPEAT4(op)
643 #define REPEAT4(op) REPEAT2(op); REPEAT2(op)
644 #define REPEAT2(op) op; op
645 #define CASE8(x,op) \
646 switch (x) { \
647 case 7: op; case 6: op; case 5: op; \
648 case 4: op; case 3: op; case 2: op; \
649 case 1: op; \
650 }
651 #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; }
652
653 #define UNROLL8(w, op1, op2) { \
654 register u_long x; \
655 for (x = w; x >= 8; x -= 8) { \
656 op1; \
657 REPEAT8(op2); \
658 } \
659 if (x > 0) { \
660 op1; \
661 CASE8(x,op2); \
662 } \
663 }
664 #define UNROLL4(w, op1, op2) { \
665 register u_long x; \
666 for (x = w; x >= 4; x -= 4) { \
667 op1; \
668 REPEAT4(op2); \
669 } \
670 if (x > 0) { \
671 op1; \
672 CASE4(x,op2); \
673 } \
674 }
675 #define UNROLL2(w, op1, op2) { \
676 register u_long x; \
677 for (x = w; x >= 2; x -= 2) { \
678 op1; \
679 REPEAT2(op2); \
680 } \
681 if (x) { \
682 op1; \
683 op2; \
684 } \
685 }
686
687
688 #define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; }
689
690 /*
691 * 8-bit palette => colormap/RGB
692 */
693 static void
put8bitcmaptile(cp,pp,Map,w,h,fromskew,toskew)694 put8bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
695 register u_long *cp;
696 register u_char *pp;
697 RGBvalue *Map;
698 u_long w, h;
699 int fromskew, toskew;
700 {
701 while (h-- > 0) {
702 UNROLL8(w,, *cp++ = PALmap[*pp++][0]);
703 cp += toskew;
704 pp += fromskew;
705 }
706 }
707
708 /*
709 * 4-bit palette => colormap/RGB
710 */
711 static void
put4bitcmaptile(cp,pp,Map,w,h,fromskew,toskew)712 put4bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
713 register u_long *cp;
714 register u_char *pp;
715 register RGBvalue *Map;
716 u_long w, h;
717 int fromskew, toskew;
718 {
719 register u_long *bw;
720
721 fromskew /= 2;
722 while (h-- > 0) {
723 UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
724 cp += toskew;
725 pp += fromskew;
726 }
727 }
728
729 /*
730 * 2-bit palette => colormap/RGB
731 */
732 static void
put2bitcmaptile(cp,pp,Map,w,h,fromskew,toskew)733 put2bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
734 register u_long *cp;
735 register u_char *pp;
736 register RGBvalue *Map;
737 u_long w, h;
738 int fromskew, toskew;
739 {
740 register u_long *bw;
741
742 fromskew /= 4;
743 while (h-- > 0) {
744 UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
745 cp += toskew;
746 pp += fromskew;
747 }
748 }
749
750 /*
751 * 1-bit palette => colormap/RGB
752 */
753 static void
put1bitcmaptile(cp,pp,Map,w,h,fromskew,toskew)754 put1bitcmaptile(cp, pp, Map, w, h, fromskew, toskew)
755 register u_long *cp;
756 register u_char *pp;
757 register RGBvalue *Map;
758 u_long w, h;
759 int fromskew, toskew;
760 {
761 register u_long *bw;
762
763 fromskew /= 8;
764 while (h-- > 0) {
765 UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
766 cp += toskew;
767 pp += fromskew;
768 }
769 }
770
771 /*
772 * 8-bit greyscale => colormap/RGB
773 */
774 static void
putgreytile(cp,pp,Map,w,h,fromskew,toskew)775 putgreytile(cp, pp, Map, w, h, fromskew, toskew)
776 register u_long *cp;
777 register u_char *pp;
778 RGBvalue *Map;
779 u_long w, h;
780 int fromskew, toskew;
781 {
782 while (h-- > 0) {
783 register u_long x;
784 for (x = w; x-- > 0;)
785 *cp++ = BWmap[*pp++][0];
786 cp += toskew;
787 pp += fromskew;
788 }
789 }
790
791 /*
792 * 1-bit bilevel => colormap/RGB
793 */
794 static void
put1bitbwtile(cp,pp,Map,w,h,fromskew,toskew)795 put1bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
796 u_long *cp;
797 u_char *pp;
798 RGBvalue *Map;
799 u_long w, h;
800 int fromskew, toskew;
801 {
802 register u_long *bw;
803
804 fromskew /= 8;
805 while (h-- > 0) {
806 UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
807 cp += toskew;
808 pp += fromskew;
809 }
810 }
811
812 /*
813 * 2-bit greyscale => colormap/RGB
814 */
815 static void
put2bitbwtile(cp,pp,Map,w,h,fromskew,toskew)816 put2bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
817 u_long *cp;
818 u_char *pp;
819 RGBvalue *Map;
820 u_long w, h;
821 int fromskew, toskew;
822 {
823 register u_long *bw;
824
825 fromskew /= 4;
826 while (h-- > 0) {
827 UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
828 cp += toskew;
829 pp += fromskew;
830 }
831 }
832
833 /*
834 * 4-bit greyscale => colormap/RGB
835 */
836 static void
put4bitbwtile(cp,pp,Map,w,h,fromskew,toskew)837 put4bitbwtile(cp, pp, Map, w, h, fromskew, toskew)
838 u_long *cp;
839 u_char *pp;
840 RGBvalue *Map;
841 u_long w, h;
842 int fromskew, toskew;
843 {
844 register u_long *bw;
845
846 fromskew /= 2;
847 while (h-- > 0) {
848 UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
849 cp += toskew;
850 pp += fromskew;
851 }
852 }
853
854 /*
855 * 8-bit packed samples => RGB
856 */
857 static void
putRGBcontig8bittile(cp,pp,Map,w,h,fromskew,toskew)858 putRGBcontig8bittile(cp, pp, Map, w, h, fromskew, toskew)
859 register u_long *cp;
860 register u_char *pp;
861 register RGBvalue *Map;
862 u_long w, h;
863 int fromskew, toskew;
864 {
865 fromskew *= samplesperpixel;
866 if (Map) {
867 while (h-- > 0) {
868 register u_long x;
869 for (x = w; x-- > 0;) {
870 *cp++ = PACK(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
871 pp += samplesperpixel;
872 }
873 pp += fromskew;
874 cp += toskew;
875 }
876 } else {
877 while (h-- > 0) {
878 UNROLL8(w,,
879 *cp++ = PACK(pp[0], pp[1], pp[2]);
880 pp += samplesperpixel);
881 cp += toskew;
882 pp += fromskew;
883 }
884 }
885 }
886
887 /*
888 * 16-bit packed samples => RGB
889 */
890 static void
putRGBcontig16bittile(cp,pp,Map,w,h,fromskew,toskew)891 putRGBcontig16bittile(cp, pp, Map, w, h, fromskew, toskew)
892 register u_long *cp;
893 u_char *pp;
894 register RGBvalue *Map;
895 u_long w, h;
896 int fromskew, toskew;
897 {
898 register u_short *wp = (u_short *)pp;
899 register u_int x;
900
901 fromskew *= samplesperpixel;
902 if (Map) {
903 while (h-- > 0) {
904 for (x = w; x-- > 0;) {
905 *cp++ = PACK(Map[wp[0]], Map[wp[1]], Map[wp[2]]);
906 wp += samplesperpixel;
907 }
908 cp += toskew;
909 wp += fromskew;
910 }
911 } else {
912 while (h-- > 0) {
913 for (x = w; x-- > 0;) {
914 *cp++ = PACK(wp[0], wp[1], wp[2]);
915 wp += samplesperpixel;
916 }
917 cp += toskew;
918 wp += fromskew;
919 }
920 }
921 }
922
923 /*
924 * 8-bit unpacked samples => RGB
925 */
926 static void
putRGBseparate8bittile(cp,r,g,b,Map,w,h,fromskew,toskew)927 putRGBseparate8bittile(cp, r, g, b, Map, w, h, fromskew, toskew)
928 register u_long *cp;
929 register u_char *r, *g, *b;
930 register RGBvalue *Map;
931 u_long w, h;
932 int fromskew, toskew;
933
934 {
935 if (Map) {
936 while (h-- > 0) {
937 register u_long x;
938 for (x = w; x > 0; x--)
939 *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
940 SKEW(r, g, b, fromskew);
941 cp += toskew;
942 }
943 } else {
944 while (h-- > 0) {
945 UNROLL8(w,, *cp++ = PACK(*r++, *g++, *b++));
946 SKEW(r, g, b, fromskew);
947 cp += toskew;
948 }
949 }
950 }
951
952 /*
953 * 16-bit unpacked samples => RGB
954 */
955 static void
putRGBseparate16bittile(cp,br,bg,bb,Map,w,h,fromskew,toskew)956 putRGBseparate16bittile(cp, br, bg, bb, Map, w, h, fromskew, toskew)
957 register u_long *cp;
958 u_char *br, *bg, *bb;
959 register RGBvalue *Map;
960 u_long w, h;
961 int fromskew, toskew;
962 {
963 register u_short *r = (u_short *)br;
964 register u_short *g = (u_short *)bg;
965 register u_short *b = (u_short *)bb;
966 register u_long x;
967
968 if (Map) {
969 while (h-- > 0) {
970 for (x = w; x > 0; x--)
971 *cp++ = PACK(Map[*r++], Map[*g++], Map[*b++]);
972 SKEW(r, g, b, fromskew);
973 cp += toskew;
974 }
975 } else {
976 while (h-- > 0) {
977 for (x = 0; x < w; x++)
978 *cp++ = PACK(*r++, *g++, *b++);
979 SKEW(r, g, b, fromskew);
980 cp += toskew;
981 }
982 }
983 }
984
985 #define Code2V(c, RB, RW, CR) ((((c)-RB)*(float)CR)/(float)(RW-RB))
986 #define CLAMP(f,min,max) \
987 (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
988
989 #define LumaRed YCbCrCoeffs[0]
990 #define LumaGreen YCbCrCoeffs[1]
991 #define LumaBlue YCbCrCoeffs[2]
992
993 static float D1, D2;
994 static float D3, D4;
995
996 static void
initYCbCrConversion()997 initYCbCrConversion()
998 {
999 D1 = 2 - 2*LumaRed;
1000 D2 = D1*LumaRed / LumaGreen;
1001 D3 = 2 - 2*LumaBlue;
1002 D4 = D2*LumaBlue / LumaGreen;
1003 }
1004
1005 static void
putRGBContigYCbCrClump(cp,pp,cw,ch,w,n,fromskew,toskew)1006 putRGBContigYCbCrClump(cp, pp, cw, ch, w, n, fromskew, toskew)
1007 register u_long *cp;
1008 register u_char *pp;
1009 int cw, ch;
1010 u_long w;
1011 int n, fromskew, toskew;
1012 {
1013 float Cb, Cr;
1014 int j, k;
1015
1016 Cb = Code2V(pp[n], refBlackWhite[2], refBlackWhite[3], 127);
1017 Cr = Code2V(pp[n+1], refBlackWhite[4], refBlackWhite[5], 127);
1018 for (j = 0; j < ch; j++) {
1019 for (k = 0; k < cw; k++) {
1020 float Y, R, G, B;
1021 Y = Code2V(*pp++,
1022 refBlackWhite[0], refBlackWhite[1], 255);
1023 R = Y + Cr*D1;
1024 B = Y + Cb*D3;
1025 G = Y - Cb*D4 - Cr*D2;
1026 cp[k] = PACK(CLAMP(R,0,255),
1027 CLAMP(G,0,255),
1028 CLAMP(B,0,255));
1029 }
1030 cp += w+toskew;
1031 pp += fromskew;
1032 }
1033 }
1034 #undef LumaBlue
1035 #undef LumaGreen
1036 #undef LumaRed
1037 #undef CLAMP
1038 #undef Code2V
1039
1040 /*
1041 * 8-bit packed YCbCr samples => RGB
1042 */
1043 static void
putcontig8bitYCbCrtile(cp,pp,Map,w,h,fromskew,toskew)1044 putcontig8bitYCbCrtile(cp, pp, Map, w, h, fromskew, toskew)
1045 register u_long *cp;
1046 register u_char *pp;
1047 register RGBvalue *Map;
1048 u_long w, h;
1049 int fromskew, toskew;
1050 {
1051 u_int Coff = YCbCrVertSampling * YCbCrHorizSampling;
1052 u_long *tp;
1053 u_long x;
1054
1055 /* XXX adjust fromskew */
1056 while (h >= YCbCrVertSampling) {
1057 tp = cp;
1058 for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
1059 putRGBContigYCbCrClump(tp, pp,
1060 YCbCrHorizSampling, YCbCrVertSampling,
1061 w, Coff, 0, toskew);
1062 tp += YCbCrHorizSampling;
1063 pp += Coff+2;
1064 }
1065 if (x > 0) {
1066 putRGBContigYCbCrClump(tp, pp,
1067 x, YCbCrVertSampling,
1068 w, Coff, YCbCrHorizSampling - x, toskew);
1069 pp += Coff+2;
1070 }
1071 cp += YCbCrVertSampling*(w + toskew);
1072 pp += fromskew;
1073 h -= YCbCrVertSampling;
1074 }
1075 if (h > 0) {
1076 tp = cp;
1077 for (x = w; x >= YCbCrHorizSampling; x -= YCbCrHorizSampling) {
1078 putRGBContigYCbCrClump(tp, pp, YCbCrHorizSampling, h,
1079 w, Coff, 0, toskew);
1080 tp += YCbCrHorizSampling;
1081 pp += Coff+2;
1082 }
1083 if (x > 0)
1084 putRGBContigYCbCrClump(tp, pp, x, h,
1085 w, Coff, YCbCrHorizSampling - x, toskew);
1086 }
1087 }
1088
1089 /*
1090 * Select the appropriate conversion routine for packed data.
1091 */
1092 static tileContigRoutine
DECLARE1(pickTileContigCase,RGBvalue *,Map)1093 DECLARE1(pickTileContigCase, RGBvalue*, Map)
1094 {
1095 tileContigRoutine put = 0;
1096
1097 switch (photometric) {
1098 case PHOTOMETRIC_RGB:
1099 put = (bitspersample == 8 ?
1100 putRGBcontig8bittile : putRGBcontig16bittile);
1101 break;
1102 case PHOTOMETRIC_PALETTE:
1103 switch (bitspersample) {
1104 case 8: put = put8bitcmaptile; break;
1105 case 4: put = put4bitcmaptile; break;
1106 case 2: put = put2bitcmaptile; break;
1107 case 1: put = put1bitcmaptile; break;
1108 }
1109 break;
1110 case PHOTOMETRIC_MINISWHITE:
1111 case PHOTOMETRIC_MINISBLACK:
1112 switch (bitspersample) {
1113 case 8: put = putgreytile; break;
1114 case 4: put = put4bitbwtile; break;
1115 case 2: put = put2bitbwtile; break;
1116 case 1: put = put1bitbwtile; break;
1117 }
1118 break;
1119 case PHOTOMETRIC_YCBCR:
1120 switch (bitspersample) {
1121 case 8: put = putcontig8bitYCbCrtile; break;
1122 }
1123 break;
1124 }
1125 if (put == 0)
1126 TIFFError(filename, "Can not handle format");
1127 return (put);
1128 }
1129
1130 /*
1131 * Select the appropriate conversion routine for unpacked data.
1132 *
1133 * NB: we assume that unpacked single channel data is directed
1134 * to the "packed routines.
1135 */
1136 static tileSeparateRoutine
DECLARE1(pickTileSeparateCase,RGBvalue *,Map)1137 DECLARE1(pickTileSeparateCase, RGBvalue*, Map)
1138 {
1139 tileSeparateRoutine put = 0;
1140
1141 switch (photometric) {
1142 case PHOTOMETRIC_RGB:
1143 put = (bitspersample == 8 ?
1144 putRGBseparate8bittile : putRGBseparate16bittile);
1145 break;
1146 }
1147 if (put == 0)
1148 TIFFError(filename, "Can not handle format");
1149 return (put);
1150 }
1151