Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentif_getimage.c
Go to the documentation of this file.
00001 /* $Id: tif_getimage.c,v 1.63.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ 00002 00003 /* 00004 * Copyright (c) 1991-1997 Sam Leffler 00005 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 00006 * 00007 * Permission to use, copy, modify, distribute, and sell this software and 00008 * its documentation for any purpose is hereby granted without fee, provided 00009 * that (i) the above copyright notices and this permission notice appear in 00010 * all copies of the software and related documentation, and (ii) the names of 00011 * Sam Leffler and Silicon Graphics may not be used in any advertising or 00012 * publicity relating to the software without the specific, prior written 00013 * permission of Sam Leffler and Silicon Graphics. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 00016 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 00017 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 00018 * 00019 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 00020 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 00021 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00022 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 00023 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 00024 * OF THIS SOFTWARE. 00025 */ 00026 00027 /* 00028 * TIFF Library 00029 * 00030 * Read and return a packed RGBA image. 00031 */ 00032 #include "tiffiop.h" 00033 #include <stdio.h> 00034 00035 static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32); 00036 static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); 00037 static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32); 00038 static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32); 00039 static int PickContigCase(TIFFRGBAImage*); 00040 static int PickSeparateCase(TIFFRGBAImage*); 00041 static const char photoTag[] = "PhotometricInterpretation"; 00042 00043 /* 00044 * Helper constants used in Orientation tag handling 00045 */ 00046 #define FLIP_VERTICALLY 0x01 00047 #define FLIP_HORIZONTALLY 0x02 00048 00049 /* 00050 * Color conversion constants. We will define display types here. 00051 */ 00052 00053 TIFFDisplay display_sRGB = { 00054 { /* XYZ -> luminance matrix */ 00055 { 3.2410F, -1.5374F, -0.4986F }, 00056 { -0.9692F, 1.8760F, 0.0416F }, 00057 { 0.0556F, -0.2040F, 1.0570F } 00058 }, 00059 100.0F, 100.0F, 100.0F, /* Light o/p for reference white */ 00060 255, 255, 255, /* Pixel values for ref. white */ 00061 1.0F, 1.0F, 1.0F, /* Residual light o/p for black pixel */ 00062 2.4F, 2.4F, 2.4F, /* Gamma values for the three guns */ 00063 }; 00064 00065 /* 00066 * Check the image to see if TIFFReadRGBAImage can deal with it. 00067 * 1/0 is returned according to whether or not the image can 00068 * be handled. If 0 is returned, emsg contains the reason 00069 * why it is being rejected. 00070 */ 00071 int 00072 TIFFRGBAImageOK(TIFF* tif, char emsg[1024]) 00073 { 00074 TIFFDirectory* td = &tif->tif_dir; 00075 uint16 photometric; 00076 int colorchannels; 00077 00078 if (!tif->tif_decodestatus) { 00079 sprintf(emsg, "Sorry, requested compression method is not configured"); 00080 return (0); 00081 } 00082 switch (td->td_bitspersample) { 00083 case 1: 00084 case 2: 00085 case 4: 00086 case 8: 00087 case 16: 00088 break; 00089 default: 00090 sprintf(emsg, "Sorry, can not handle images with %d-bit samples", 00091 td->td_bitspersample); 00092 return (0); 00093 } 00094 colorchannels = td->td_samplesperpixel - td->td_extrasamples; 00095 if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) { 00096 switch (colorchannels) { 00097 case 1: 00098 photometric = PHOTOMETRIC_MINISBLACK; 00099 break; 00100 case 3: 00101 photometric = PHOTOMETRIC_RGB; 00102 break; 00103 default: 00104 sprintf(emsg, "Missing needed %s tag", photoTag); 00105 return (0); 00106 } 00107 } 00108 switch (photometric) { 00109 case PHOTOMETRIC_MINISWHITE: 00110 case PHOTOMETRIC_MINISBLACK: 00111 case PHOTOMETRIC_PALETTE: 00112 if (td->td_planarconfig == PLANARCONFIG_CONTIG 00113 && td->td_samplesperpixel != 1 00114 && td->td_bitspersample < 8 ) { 00115 sprintf(emsg, 00116 "Sorry, can not handle contiguous data with %s=%d, " 00117 "and %s=%d and Bits/Sample=%d", 00118 photoTag, photometric, 00119 "Samples/pixel", td->td_samplesperpixel, 00120 td->td_bitspersample); 00121 return (0); 00122 } 00123 /* 00124 * We should likely validate that any extra samples are either 00125 * to be ignored, or are alpha, and if alpha we should try to use 00126 * them. But for now we won't bother with this. 00127 */ 00128 break; 00129 case PHOTOMETRIC_YCBCR: 00130 /* 00131 * TODO: if at all meaningful and useful, make more complete 00132 * support check here, or better still, refactor to let supporting 00133 * code decide whether there is support and what meaningfull 00134 * error to return 00135 */ 00136 break; 00137 case PHOTOMETRIC_RGB: 00138 if (colorchannels < 3) { 00139 sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", 00140 "Color channels", colorchannels); 00141 return (0); 00142 } 00143 break; 00144 case PHOTOMETRIC_SEPARATED: 00145 { 00146 uint16 inkset; 00147 TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); 00148 if (inkset != INKSET_CMYK) { 00149 sprintf(emsg, 00150 "Sorry, can not handle separated image with %s=%d", 00151 "InkSet", inkset); 00152 return 0; 00153 } 00154 if (td->td_samplesperpixel < 4) { 00155 sprintf(emsg, 00156 "Sorry, can not handle separated image with %s=%d", 00157 "Samples/pixel", td->td_samplesperpixel); 00158 return 0; 00159 } 00160 break; 00161 } 00162 case PHOTOMETRIC_LOGL: 00163 if (td->td_compression != COMPRESSION_SGILOG) { 00164 sprintf(emsg, "Sorry, LogL data must have %s=%d", 00165 "Compression", COMPRESSION_SGILOG); 00166 return (0); 00167 } 00168 break; 00169 case PHOTOMETRIC_LOGLUV: 00170 if (td->td_compression != COMPRESSION_SGILOG && 00171 td->td_compression != COMPRESSION_SGILOG24) { 00172 sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", 00173 "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); 00174 return (0); 00175 } 00176 if (td->td_planarconfig != PLANARCONFIG_CONTIG) { 00177 sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", 00178 "Planarconfiguration", td->td_planarconfig); 00179 return (0); 00180 } 00181 break; 00182 case PHOTOMETRIC_CIELAB: 00183 break; 00184 default: 00185 sprintf(emsg, "Sorry, can not handle image with %s=%d", 00186 photoTag, photometric); 00187 return (0); 00188 } 00189 return (1); 00190 } 00191 00192 void 00193 TIFFRGBAImageEnd(TIFFRGBAImage* img) 00194 { 00195 if (img->Map) 00196 _TIFFfree(img->Map), img->Map = NULL; 00197 if (img->BWmap) 00198 _TIFFfree(img->BWmap), img->BWmap = NULL; 00199 if (img->PALmap) 00200 _TIFFfree(img->PALmap), img->PALmap = NULL; 00201 if (img->ycbcr) 00202 _TIFFfree(img->ycbcr), img->ycbcr = NULL; 00203 if (img->cielab) 00204 _TIFFfree(img->cielab), img->cielab = NULL; 00205 if( img->redcmap ) { 00206 _TIFFfree( img->redcmap ); 00207 _TIFFfree( img->greencmap ); 00208 _TIFFfree( img->bluecmap ); 00209 } 00210 } 00211 00212 static int 00213 isCCITTCompression(TIFF* tif) 00214 { 00215 uint16 compress; 00216 TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress); 00217 return (compress == COMPRESSION_CCITTFAX3 || 00218 compress == COMPRESSION_CCITTFAX4 || 00219 compress == COMPRESSION_CCITTRLE || 00220 compress == COMPRESSION_CCITTRLEW); 00221 } 00222 00223 int 00224 TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024]) 00225 { 00226 uint16* sampleinfo; 00227 uint16 extrasamples; 00228 uint16 planarconfig; 00229 uint16 compress; 00230 int colorchannels; 00231 uint16 *red_orig, *green_orig, *blue_orig; 00232 int n_color; 00233 00234 /* Initialize to normal values */ 00235 img->row_offset = 0; 00236 img->col_offset = 0; 00237 img->redcmap = NULL; 00238 img->greencmap = NULL; 00239 img->bluecmap = NULL; 00240 img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */ 00241 00242 img->tif = tif; 00243 img->stoponerr = stop; 00244 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample); 00245 switch (img->bitspersample) { 00246 case 1: 00247 case 2: 00248 case 4: 00249 case 8: 00250 case 16: 00251 break; 00252 default: 00253 sprintf(emsg, "Sorry, can not handle images with %d-bit samples", 00254 img->bitspersample); 00255 return (0); 00256 } 00257 img->alpha = 0; 00258 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel); 00259 TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, 00260 &extrasamples, &sampleinfo); 00261 if (extrasamples >= 1) 00262 { 00263 switch (sampleinfo[0]) { 00264 case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without */ 00265 if (img->samplesperpixel > 3) /* correct info about alpha channel */ 00266 img->alpha = EXTRASAMPLE_ASSOCALPHA; 00267 break; 00268 case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */ 00269 case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */ 00270 img->alpha = sampleinfo[0]; 00271 break; 00272 } 00273 } 00274 00275 #ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA 00276 if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) 00277 img->photometric = PHOTOMETRIC_MINISWHITE; 00278 00279 if( extrasamples == 0 00280 && img->samplesperpixel == 4 00281 && img->photometric == PHOTOMETRIC_RGB ) 00282 { 00283 img->alpha = EXTRASAMPLE_ASSOCALPHA; 00284 extrasamples = 1; 00285 } 00286 #endif 00287 00288 colorchannels = img->samplesperpixel - extrasamples; 00289 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress); 00290 TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig); 00291 if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) { 00292 switch (colorchannels) { 00293 case 1: 00294 if (isCCITTCompression(tif)) 00295 img->photometric = PHOTOMETRIC_MINISWHITE; 00296 else 00297 img->photometric = PHOTOMETRIC_MINISBLACK; 00298 break; 00299 case 3: 00300 img->photometric = PHOTOMETRIC_RGB; 00301 break; 00302 default: 00303 sprintf(emsg, "Missing needed %s tag", photoTag); 00304 return (0); 00305 } 00306 } 00307 switch (img->photometric) { 00308 case PHOTOMETRIC_PALETTE: 00309 if (!TIFFGetField(tif, TIFFTAG_COLORMAP, 00310 &red_orig, &green_orig, &blue_orig)) { 00311 sprintf(emsg, "Missing required \"Colormap\" tag"); 00312 return (0); 00313 } 00314 00315 /* copy the colormaps so we can modify them */ 00316 n_color = (1L << img->bitspersample); 00317 img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); 00318 img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); 00319 img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color); 00320 if( !img->redcmap || !img->greencmap || !img->bluecmap ) { 00321 sprintf(emsg, "Out of memory for colormap copy"); 00322 return (0); 00323 } 00324 00325 _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 ); 00326 _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 ); 00327 _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 ); 00328 00329 /* fall thru... */ 00330 case PHOTOMETRIC_MINISWHITE: 00331 case PHOTOMETRIC_MINISBLACK: 00332 if (planarconfig == PLANARCONFIG_CONTIG 00333 && img->samplesperpixel != 1 00334 && img->bitspersample < 8 ) { 00335 sprintf(emsg, 00336 "Sorry, can not handle contiguous data with %s=%d, " 00337 "and %s=%d and Bits/Sample=%d", 00338 photoTag, img->photometric, 00339 "Samples/pixel", img->samplesperpixel, 00340 img->bitspersample); 00341 return (0); 00342 } 00343 break; 00344 case PHOTOMETRIC_YCBCR: 00345 /* It would probably be nice to have a reality check here. */ 00346 if (planarconfig == PLANARCONFIG_CONTIG) 00347 /* can rely on libjpeg to convert to RGB */ 00348 /* XXX should restore current state on exit */ 00349 switch (compress) { 00350 case COMPRESSION_JPEG: 00351 /* 00352 * TODO: when complete tests verify complete desubsampling 00353 * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in 00354 * favor of tif_getimage.c native handling 00355 */ 00356 TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); 00357 img->photometric = PHOTOMETRIC_RGB; 00358 break; 00359 default: 00360 /* do nothing */; 00361 break; 00362 } 00363 /* 00364 * TODO: if at all meaningful and useful, make more complete 00365 * support check here, or better still, refactor to let supporting 00366 * code decide whether there is support and what meaningfull 00367 * error to return 00368 */ 00369 break; 00370 case PHOTOMETRIC_RGB: 00371 if (colorchannels < 3) { 00372 sprintf(emsg, "Sorry, can not handle RGB image with %s=%d", 00373 "Color channels", colorchannels); 00374 return (0); 00375 } 00376 break; 00377 case PHOTOMETRIC_SEPARATED: 00378 { 00379 uint16 inkset; 00380 TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset); 00381 if (inkset != INKSET_CMYK) { 00382 sprintf(emsg, "Sorry, can not handle separated image with %s=%d", 00383 "InkSet", inkset); 00384 return (0); 00385 } 00386 if (img->samplesperpixel < 4) { 00387 sprintf(emsg, "Sorry, can not handle separated image with %s=%d", 00388 "Samples/pixel", img->samplesperpixel); 00389 return (0); 00390 } 00391 } 00392 break; 00393 case PHOTOMETRIC_LOGL: 00394 if (compress != COMPRESSION_SGILOG) { 00395 sprintf(emsg, "Sorry, LogL data must have %s=%d", 00396 "Compression", COMPRESSION_SGILOG); 00397 return (0); 00398 } 00399 TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); 00400 img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */ 00401 img->bitspersample = 8; 00402 break; 00403 case PHOTOMETRIC_LOGLUV: 00404 if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) { 00405 sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d", 00406 "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24); 00407 return (0); 00408 } 00409 if (planarconfig != PLANARCONFIG_CONTIG) { 00410 sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d", 00411 "Planarconfiguration", planarconfig); 00412 return (0); 00413 } 00414 TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT); 00415 img->photometric = PHOTOMETRIC_RGB; /* little white lie */ 00416 img->bitspersample = 8; 00417 break; 00418 case PHOTOMETRIC_CIELAB: 00419 break; 00420 default: 00421 sprintf(emsg, "Sorry, can not handle image with %s=%d", 00422 photoTag, img->photometric); 00423 return (0); 00424 } 00425 img->Map = NULL; 00426 img->BWmap = NULL; 00427 img->PALmap = NULL; 00428 img->ycbcr = NULL; 00429 img->cielab = NULL; 00430 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width); 00431 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height); 00432 TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation); 00433 img->isContig = 00434 !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1); 00435 if (img->isContig) { 00436 if (!PickContigCase(img)) { 00437 sprintf(emsg, "Sorry, can not handle image"); 00438 return 0; 00439 } 00440 } else { 00441 if (!PickSeparateCase(img)) { 00442 sprintf(emsg, "Sorry, can not handle image"); 00443 return 0; 00444 } 00445 } 00446 return 1; 00447 } 00448 00449 int 00450 TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) 00451 { 00452 if (img->get == NULL) { 00453 TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup"); 00454 return (0); 00455 } 00456 if (img->put.any == NULL) { 00457 TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), 00458 "No \"put\" routine setupl; probably can not handle image format"); 00459 return (0); 00460 } 00461 return (*img->get)(img, raster, w, h); 00462 } 00463 00464 /* 00465 * Read the specified image into an ABGR-format rastertaking in account 00466 * specified orientation. 00467 */ 00468 int 00469 TIFFReadRGBAImageOriented(TIFF* tif, 00470 uint32 rwidth, uint32 rheight, uint32* raster, 00471 int orientation, int stop) 00472 { 00473 char emsg[1024] = ""; 00474 TIFFRGBAImage img; 00475 int ok; 00476 00477 if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) { 00478 img.req_orientation = orientation; 00479 /* XXX verify rwidth and rheight against width and height */ 00480 ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth, 00481 rwidth, img.height); 00482 TIFFRGBAImageEnd(&img); 00483 } else { 00484 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); 00485 ok = 0; 00486 } 00487 return (ok); 00488 } 00489 00490 /* 00491 * Read the specified image into an ABGR-format raster. Use bottom left 00492 * origin for raster by default. 00493 */ 00494 int 00495 TIFFReadRGBAImage(TIFF* tif, 00496 uint32 rwidth, uint32 rheight, uint32* raster, int stop) 00497 { 00498 return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster, 00499 ORIENTATION_BOTLEFT, stop); 00500 } 00501 00502 static int 00503 setorientation(TIFFRGBAImage* img) 00504 { 00505 switch (img->orientation) { 00506 case ORIENTATION_TOPLEFT: 00507 case ORIENTATION_LEFTTOP: 00508 if (img->req_orientation == ORIENTATION_TOPRIGHT || 00509 img->req_orientation == ORIENTATION_RIGHTTOP) 00510 return FLIP_HORIZONTALLY; 00511 else if (img->req_orientation == ORIENTATION_BOTRIGHT || 00512 img->req_orientation == ORIENTATION_RIGHTBOT) 00513 return FLIP_HORIZONTALLY | FLIP_VERTICALLY; 00514 else if (img->req_orientation == ORIENTATION_BOTLEFT || 00515 img->req_orientation == ORIENTATION_LEFTBOT) 00516 return FLIP_VERTICALLY; 00517 else 00518 return 0; 00519 case ORIENTATION_TOPRIGHT: 00520 case ORIENTATION_RIGHTTOP: 00521 if (img->req_orientation == ORIENTATION_TOPLEFT || 00522 img->req_orientation == ORIENTATION_LEFTTOP) 00523 return FLIP_HORIZONTALLY; 00524 else if (img->req_orientation == ORIENTATION_BOTRIGHT || 00525 img->req_orientation == ORIENTATION_RIGHTBOT) 00526 return FLIP_VERTICALLY; 00527 else if (img->req_orientation == ORIENTATION_BOTLEFT || 00528 img->req_orientation == ORIENTATION_LEFTBOT) 00529 return FLIP_HORIZONTALLY | FLIP_VERTICALLY; 00530 else 00531 return 0; 00532 case ORIENTATION_BOTRIGHT: 00533 case ORIENTATION_RIGHTBOT: 00534 if (img->req_orientation == ORIENTATION_TOPLEFT || 00535 img->req_orientation == ORIENTATION_LEFTTOP) 00536 return FLIP_HORIZONTALLY | FLIP_VERTICALLY; 00537 else if (img->req_orientation == ORIENTATION_TOPRIGHT || 00538 img->req_orientation == ORIENTATION_RIGHTTOP) 00539 return FLIP_VERTICALLY; 00540 else if (img->req_orientation == ORIENTATION_BOTLEFT || 00541 img->req_orientation == ORIENTATION_LEFTBOT) 00542 return FLIP_HORIZONTALLY; 00543 else 00544 return 0; 00545 case ORIENTATION_BOTLEFT: 00546 case ORIENTATION_LEFTBOT: 00547 if (img->req_orientation == ORIENTATION_TOPLEFT || 00548 img->req_orientation == ORIENTATION_LEFTTOP) 00549 return FLIP_VERTICALLY; 00550 else if (img->req_orientation == ORIENTATION_TOPRIGHT || 00551 img->req_orientation == ORIENTATION_RIGHTTOP) 00552 return FLIP_HORIZONTALLY | FLIP_VERTICALLY; 00553 else if (img->req_orientation == ORIENTATION_BOTRIGHT || 00554 img->req_orientation == ORIENTATION_RIGHTBOT) 00555 return FLIP_HORIZONTALLY; 00556 else 00557 return 0; 00558 default: /* NOTREACHED */ 00559 return 0; 00560 } 00561 } 00562 00563 /* 00564 * Get an tile-organized image that has 00565 * PlanarConfiguration contiguous if SamplesPerPixel > 1 00566 * or 00567 * SamplesPerPixel == 1 00568 */ 00569 static int 00570 gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) 00571 { 00572 TIFF* tif = img->tif; 00573 tileContigRoutine put = img->put.contig; 00574 uint32 col, row, y, rowstoread; 00575 uint32 pos; 00576 uint32 tw, th; 00577 unsigned char* buf; 00578 int32 fromskew, toskew; 00579 uint32 nrow; 00580 int ret = 1, flip; 00581 00582 buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif)); 00583 if (buf == 0) { 00584 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); 00585 return (0); 00586 } 00587 _TIFFmemset(buf, 0, TIFFTileSize(tif)); 00588 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); 00589 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); 00590 00591 flip = setorientation(img); 00592 if (flip & FLIP_VERTICALLY) { 00593 y = h - 1; 00594 toskew = -(int32)(tw + w); 00595 } 00596 else { 00597 y = 0; 00598 toskew = -(int32)(tw - w); 00599 } 00600 00601 for (row = 0; row < h; row += nrow) 00602 { 00603 rowstoread = th - (row + img->row_offset) % th; 00604 nrow = (row + rowstoread > h ? h - row : rowstoread); 00605 for (col = 0; col < w; col += tw) 00606 { 00607 if (TIFFReadTile(tif, buf, col+img->col_offset, 00608 row+img->row_offset, 0, 0) < 0 && img->stoponerr) 00609 { 00610 ret = 0; 00611 break; 00612 } 00613 00614 pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); 00615 00616 if (col + tw > w) 00617 { 00618 /* 00619 * Tile is clipped horizontally. Calculate 00620 * visible portion and skewing factors. 00621 */ 00622 uint32 npix = w - col; 00623 fromskew = tw - npix; 00624 (*put)(img, raster+y*w+col, col, y, 00625 npix, nrow, fromskew, toskew + fromskew, buf + pos); 00626 } 00627 else 00628 { 00629 (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos); 00630 } 00631 } 00632 00633 y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); 00634 } 00635 _TIFFfree(buf); 00636 00637 if (flip & FLIP_HORIZONTALLY) { 00638 uint32 line; 00639 00640 for (line = 0; line < h; line++) { 00641 uint32 *left = raster + (line * w); 00642 uint32 *right = left + w - 1; 00643 00644 while ( left < right ) { 00645 uint32 temp = *left; 00646 *left = *right; 00647 *right = temp; 00648 left++, right--; 00649 } 00650 } 00651 } 00652 00653 return (ret); 00654 } 00655 00656 /* 00657 * Get an tile-organized image that has 00658 * SamplesPerPixel > 1 00659 * PlanarConfiguration separated 00660 * We assume that all such images are RGB. 00661 */ 00662 static int 00663 gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) 00664 { 00665 TIFF* tif = img->tif; 00666 tileSeparateRoutine put = img->put.separate; 00667 uint32 col, row, y, rowstoread; 00668 uint32 pos; 00669 uint32 tw, th; 00670 unsigned char* buf; 00671 unsigned char* p0; 00672 unsigned char* p1; 00673 unsigned char* p2; 00674 unsigned char* pa; 00675 tsize_t tilesize; 00676 int32 fromskew, toskew; 00677 int alpha = img->alpha; 00678 uint32 nrow; 00679 int ret = 1, flip; 00680 00681 tilesize = TIFFTileSize(tif); 00682 buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize); 00683 if (buf == 0) { 00684 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); 00685 return (0); 00686 } 00687 _TIFFmemset(buf, 0, (alpha?4:3)*tilesize); 00688 p0 = buf; 00689 p1 = p0 + tilesize; 00690 p2 = p1 + tilesize; 00691 pa = (alpha?(p2+tilesize):NULL); 00692 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); 00693 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); 00694 00695 flip = setorientation(img); 00696 if (flip & FLIP_VERTICALLY) { 00697 y = h - 1; 00698 toskew = -(int32)(tw + w); 00699 } 00700 else { 00701 y = 0; 00702 toskew = -(int32)(tw - w); 00703 } 00704 00705 for (row = 0; row < h; row += nrow) 00706 { 00707 rowstoread = th - (row + img->row_offset) % th; 00708 nrow = (row + rowstoread > h ? h - row : rowstoread); 00709 for (col = 0; col < w; col += tw) 00710 { 00711 if (TIFFReadTile(tif, p0, col+img->col_offset, 00712 row+img->row_offset,0,0) < 0 && img->stoponerr) 00713 { 00714 ret = 0; 00715 break; 00716 } 00717 if (TIFFReadTile(tif, p1, col+img->col_offset, 00718 row+img->row_offset,0,1) < 0 && img->stoponerr) 00719 { 00720 ret = 0; 00721 break; 00722 } 00723 if (TIFFReadTile(tif, p2, col+img->col_offset, 00724 row+img->row_offset,0,2) < 0 && img->stoponerr) 00725 { 00726 ret = 0; 00727 break; 00728 } 00729 if (alpha) 00730 { 00731 if (TIFFReadTile(tif,pa,col+img->col_offset, 00732 row+img->row_offset,0,3) < 0 && img->stoponerr) 00733 { 00734 ret = 0; 00735 break; 00736 } 00737 } 00738 00739 pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif); 00740 00741 if (col + tw > w) 00742 { 00743 /* 00744 * Tile is clipped horizontally. Calculate 00745 * visible portion and skewing factors. 00746 */ 00747 uint32 npix = w - col; 00748 fromskew = tw - npix; 00749 (*put)(img, raster+y*w+col, col, y, 00750 npix, nrow, fromskew, toskew + fromskew, 00751 p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); 00752 } else { 00753 (*put)(img, raster+y*w+col, col, y, 00754 tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL)); 00755 } 00756 } 00757 00758 y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow); 00759 } 00760 00761 if (flip & FLIP_HORIZONTALLY) { 00762 uint32 line; 00763 00764 for (line = 0; line < h; line++) { 00765 uint32 *left = raster + (line * w); 00766 uint32 *right = left + w - 1; 00767 00768 while ( left < right ) { 00769 uint32 temp = *left; 00770 *left = *right; 00771 *right = temp; 00772 left++, right--; 00773 } 00774 } 00775 } 00776 00777 _TIFFfree(buf); 00778 return (ret); 00779 } 00780 00781 /* 00782 * Get a strip-organized image that has 00783 * PlanarConfiguration contiguous if SamplesPerPixel > 1 00784 * or 00785 * SamplesPerPixel == 1 00786 */ 00787 static int 00788 gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) 00789 { 00790 TIFF* tif = img->tif; 00791 tileContigRoutine put = img->put.contig; 00792 uint32 row, y, nrow, nrowsub, rowstoread; 00793 uint32 pos; 00794 unsigned char* buf; 00795 uint32 rowsperstrip; 00796 uint16 subsamplinghor,subsamplingver; 00797 uint32 imagewidth = img->width; 00798 tsize_t scanline; 00799 int32 fromskew, toskew; 00800 int ret = 1, flip; 00801 00802 buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif)); 00803 if (buf == 0) { 00804 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); 00805 return (0); 00806 } 00807 _TIFFmemset(buf, 0, TIFFStripSize(tif)); 00808 00809 flip = setorientation(img); 00810 if (flip & FLIP_VERTICALLY) { 00811 y = h - 1; 00812 toskew = -(int32)(w + w); 00813 } else { 00814 y = 0; 00815 toskew = -(int32)(w - w); 00816 } 00817 00818 TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 00819 TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver); 00820 scanline = TIFFNewScanlineSize(tif); 00821 fromskew = (w < imagewidth ? imagewidth - w : 0); 00822 for (row = 0; row < h; row += nrow) 00823 { 00824 rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; 00825 nrow = (row + rowstoread > h ? h - row : rowstoread); 00826 nrowsub = nrow; 00827 if ((nrowsub%subsamplingver)!=0) 00828 nrowsub+=subsamplingver-nrowsub%subsamplingver; 00829 if (TIFFReadEncodedStrip(tif, 00830 TIFFComputeStrip(tif,row+img->row_offset, 0), 00831 buf, 00832 ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0 00833 && img->stoponerr) 00834 { 00835 ret = 0; 00836 break; 00837 } 00838 00839 pos = ((row + img->row_offset) % rowsperstrip) * scanline; 00840 (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos); 00841 y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); 00842 } 00843 00844 if (flip & FLIP_HORIZONTALLY) { 00845 uint32 line; 00846 00847 for (line = 0; line < h; line++) { 00848 uint32 *left = raster + (line * w); 00849 uint32 *right = left + w - 1; 00850 00851 while ( left < right ) { 00852 uint32 temp = *left; 00853 *left = *right; 00854 *right = temp; 00855 left++, right--; 00856 } 00857 } 00858 } 00859 00860 _TIFFfree(buf); 00861 return (ret); 00862 } 00863 00864 /* 00865 * Get a strip-organized image with 00866 * SamplesPerPixel > 1 00867 * PlanarConfiguration separated 00868 * We assume that all such images are RGB. 00869 */ 00870 static int 00871 gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) 00872 { 00873 TIFF* tif = img->tif; 00874 tileSeparateRoutine put = img->put.separate; 00875 unsigned char *buf; 00876 unsigned char *p0, *p1, *p2, *pa; 00877 uint32 row, y, nrow, rowstoread; 00878 uint32 pos; 00879 tsize_t scanline; 00880 uint32 rowsperstrip, offset_row; 00881 uint32 imagewidth = img->width; 00882 tsize_t stripsize; 00883 int32 fromskew, toskew; 00884 int alpha = img->alpha; 00885 int ret = 1, flip; 00886 00887 stripsize = TIFFStripSize(tif); 00888 p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize); 00889 if (buf == 0) { 00890 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer"); 00891 return (0); 00892 } 00893 _TIFFmemset(buf, 0, (alpha?4:3)*stripsize); 00894 p1 = p0 + stripsize; 00895 p2 = p1 + stripsize; 00896 pa = (alpha?(p2+stripsize):NULL); 00897 00898 flip = setorientation(img); 00899 if (flip & FLIP_VERTICALLY) { 00900 y = h - 1; 00901 toskew = -(int32)(w + w); 00902 } 00903 else { 00904 y = 0; 00905 toskew = -(int32)(w - w); 00906 } 00907 00908 TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 00909 scanline = TIFFScanlineSize(tif); 00910 fromskew = (w < imagewidth ? imagewidth - w : 0); 00911 for (row = 0; row < h; row += nrow) 00912 { 00913 rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; 00914 nrow = (row + rowstoread > h ? h - row : rowstoread); 00915 offset_row = row + img->row_offset; 00916 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), 00917 p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 00918 && img->stoponerr) 00919 { 00920 ret = 0; 00921 break; 00922 } 00923 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), 00924 p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 00925 && img->stoponerr) 00926 { 00927 ret = 0; 00928 break; 00929 } 00930 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), 00931 p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 00932 && img->stoponerr) 00933 { 00934 ret = 0; 00935 break; 00936 } 00937 if (alpha) 00938 { 00939 if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3), 00940 pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0 00941 && img->stoponerr) 00942 { 00943 ret = 0; 00944 break; 00945 } 00946 } 00947 00948 pos = ((row + img->row_offset) % rowsperstrip) * scanline; 00949 (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos, 00950 p2 + pos, (alpha?(pa+pos):NULL)); 00951 y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow); 00952 } 00953 00954 if (flip & FLIP_HORIZONTALLY) { 00955 uint32 line; 00956 00957 for (line = 0; line < h; line++) { 00958 uint32 *left = raster + (line * w); 00959 uint32 *right = left + w - 1; 00960 00961 while ( left < right ) { 00962 uint32 temp = *left; 00963 *left = *right; 00964 *right = temp; 00965 left++, right--; 00966 } 00967 } 00968 } 00969 00970 _TIFFfree(buf); 00971 return (ret); 00972 } 00973 00974 /* 00975 * The following routines move decoded data returned 00976 * from the TIFF library into rasters filled with packed 00977 * ABGR pixels (i.e. suitable for passing to lrecwrite.) 00978 * 00979 * The routines have been created according to the most 00980 * important cases and optimized. PickContigCase and 00981 * PickSeparateCase analyze the parameters and select 00982 * the appropriate "get" and "put" routine to use. 00983 */ 00984 #define REPEAT8(op) REPEAT4(op); REPEAT4(op) 00985 #define REPEAT4(op) REPEAT2(op); REPEAT2(op) 00986 #define REPEAT2(op) op; op 00987 #define CASE8(x,op) \ 00988 switch (x) { \ 00989 case 7: op; case 6: op; case 5: op; \ 00990 case 4: op; case 3: op; case 2: op; \ 00991 case 1: op; \ 00992 } 00993 #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } 00994 #define NOP 00995 00996 #define UNROLL8(w, op1, op2) { \ 00997 uint32 _x; \ 00998 for (_x = w; _x >= 8; _x -= 8) { \ 00999 op1; \ 01000 REPEAT8(op2); \ 01001 } \ 01002 if (_x > 0) { \ 01003 op1; \ 01004 CASE8(_x,op2); \ 01005 } \ 01006 } 01007 #define UNROLL4(w, op1, op2) { \ 01008 uint32 _x; \ 01009 for (_x = w; _x >= 4; _x -= 4) { \ 01010 op1; \ 01011 REPEAT4(op2); \ 01012 } \ 01013 if (_x > 0) { \ 01014 op1; \ 01015 CASE4(_x,op2); \ 01016 } \ 01017 } 01018 #define UNROLL2(w, op1, op2) { \ 01019 uint32 _x; \ 01020 for (_x = w; _x >= 2; _x -= 2) { \ 01021 op1; \ 01022 REPEAT2(op2); \ 01023 } \ 01024 if (_x) { \ 01025 op1; \ 01026 op2; \ 01027 } \ 01028 } 01029 01030 #define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; } 01031 #define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; } 01032 01033 #define A1 (((uint32)0xffL)<<24) 01034 #define PACK(r,g,b) \ 01035 ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1) 01036 #define PACK4(r,g,b,a) \ 01037 ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24)) 01038 #define W2B(v) (((v)>>8)&0xff) 01039 #define PACKW(r,g,b) \ 01040 ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1) 01041 #define PACKW4(r,g,b,a) \ 01042 ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24)) 01043 01044 #define DECLAREContigPutFunc(name) \ 01045 static void name(\ 01046 TIFFRGBAImage* img, \ 01047 uint32* cp, \ 01048 uint32 x, uint32 y, \ 01049 uint32 w, uint32 h, \ 01050 int32 fromskew, int32 toskew, \ 01051 unsigned char* pp \ 01052 ) 01053 01054 /* 01055 * 8-bit palette => colormap/RGB 01056 */ 01057 DECLAREContigPutFunc(put8bitcmaptile) 01058 { 01059 uint32** PALmap = img->PALmap; 01060 int samplesperpixel = img->samplesperpixel; 01061 01062 (void) y; 01063 while (h-- > 0) { 01064 for (x = w; x-- > 0;) 01065 { 01066 *cp++ = PALmap[*pp][0]; 01067 pp += samplesperpixel; 01068 } 01069 cp += toskew; 01070 pp += fromskew; 01071 } 01072 } 01073 01074 /* 01075 * 4-bit palette => colormap/RGB 01076 */ 01077 DECLAREContigPutFunc(put4bitcmaptile) 01078 { 01079 uint32** PALmap = img->PALmap; 01080 01081 (void) x; (void) y; 01082 fromskew /= 2; 01083 while (h-- > 0) { 01084 uint32* bw; 01085 UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++); 01086 cp += toskew; 01087 pp += fromskew; 01088 } 01089 } 01090 01091 /* 01092 * 2-bit palette => colormap/RGB 01093 */ 01094 DECLAREContigPutFunc(put2bitcmaptile) 01095 { 01096 uint32** PALmap = img->PALmap; 01097 01098 (void) x; (void) y; 01099 fromskew /= 4; 01100 while (h-- > 0) { 01101 uint32* bw; 01102 UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++); 01103 cp += toskew; 01104 pp += fromskew; 01105 } 01106 } 01107 01108 /* 01109 * 1-bit palette => colormap/RGB 01110 */ 01111 DECLAREContigPutFunc(put1bitcmaptile) 01112 { 01113 uint32** PALmap = img->PALmap; 01114 01115 (void) x; (void) y; 01116 fromskew /= 8; 01117 while (h-- > 0) { 01118 uint32* bw; 01119 UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++); 01120 cp += toskew; 01121 pp += fromskew; 01122 } 01123 } 01124 01125 /* 01126 * 8-bit greyscale => colormap/RGB 01127 */ 01128 DECLAREContigPutFunc(putgreytile) 01129 { 01130 int samplesperpixel = img->samplesperpixel; 01131 uint32** BWmap = img->BWmap; 01132 01133 (void) y; 01134 while (h-- > 0) { 01135 for (x = w; x-- > 0;) 01136 { 01137 *cp++ = BWmap[*pp][0]; 01138 pp += samplesperpixel; 01139 } 01140 cp += toskew; 01141 pp += fromskew; 01142 } 01143 } 01144 01145 /* 01146 * 16-bit greyscale => colormap/RGB 01147 */ 01148 DECLAREContigPutFunc(put16bitbwtile) 01149 { 01150 int samplesperpixel = img->samplesperpixel; 01151 uint32** BWmap = img->BWmap; 01152 01153 (void) y; 01154 while (h-- > 0) { 01155 uint16 *wp = (uint16 *) pp; 01156 01157 for (x = w; x-- > 0;) 01158 { 01159 /* use high order byte of 16bit value */ 01160 01161 *cp++ = BWmap[*wp >> 8][0]; 01162 pp += 2 * samplesperpixel; 01163 wp += samplesperpixel; 01164 } 01165 cp += toskew; 01166 pp += fromskew; 01167 } 01168 } 01169 01170 /* 01171 * 1-bit bilevel => colormap/RGB 01172 */ 01173 DECLAREContigPutFunc(put1bitbwtile) 01174 { 01175 uint32** BWmap = img->BWmap; 01176 01177 (void) x; (void) y; 01178 fromskew /= 8; 01179 while (h-- > 0) { 01180 uint32* bw; 01181 UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++); 01182 cp += toskew; 01183 pp += fromskew; 01184 } 01185 } 01186 01187 /* 01188 * 2-bit greyscale => colormap/RGB 01189 */ 01190 DECLAREContigPutFunc(put2bitbwtile) 01191 { 01192 uint32** BWmap = img->BWmap; 01193 01194 (void) x; (void) y; 01195 fromskew /= 4; 01196 while (h-- > 0) { 01197 uint32* bw; 01198 UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++); 01199 cp += toskew; 01200 pp += fromskew; 01201 } 01202 } 01203 01204 /* 01205 * 4-bit greyscale => colormap/RGB 01206 */ 01207 DECLAREContigPutFunc(put4bitbwtile) 01208 { 01209 uint32** BWmap = img->BWmap; 01210 01211 (void) x; (void) y; 01212 fromskew /= 2; 01213 while (h-- > 0) { 01214 uint32* bw; 01215 UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++); 01216 cp += toskew; 01217 pp += fromskew; 01218 } 01219 } 01220 01221 /* 01222 * 8-bit packed samples, no Map => RGB 01223 */ 01224 DECLAREContigPutFunc(putRGBcontig8bittile) 01225 { 01226 int samplesperpixel = img->samplesperpixel; 01227 01228 (void) x; (void) y; 01229 fromskew *= samplesperpixel; 01230 while (h-- > 0) { 01231 UNROLL8(w, NOP, 01232 *cp++ = PACK(pp[0], pp[1], pp[2]); 01233 pp += samplesperpixel); 01234 cp += toskew; 01235 pp += fromskew; 01236 } 01237 } 01238 01239 /* 01240 * 8-bit packed samples => RGBA w/ associated alpha 01241 * (known to have Map == NULL) 01242 */ 01243 DECLAREContigPutFunc(putRGBAAcontig8bittile) 01244 { 01245 int samplesperpixel = img->samplesperpixel; 01246 01247 (void) x; (void) y; 01248 fromskew *= samplesperpixel; 01249 while (h-- > 0) { 01250 UNROLL8(w, NOP, 01251 *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]); 01252 pp += samplesperpixel); 01253 cp += toskew; 01254 pp += fromskew; 01255 } 01256 } 01257 01258 /* 01259 * 8-bit packed samples => RGBA w/ unassociated alpha 01260 * (known to have Map == NULL) 01261 */ 01262 DECLAREContigPutFunc(putRGBUAcontig8bittile) 01263 { 01264 int samplesperpixel = img->samplesperpixel; 01265 (void) y; 01266 fromskew *= samplesperpixel; 01267 while (h-- > 0) { 01268 uint32 r, g, b, a; 01269 for (x = w; x-- > 0;) { 01270 a = pp[3]; 01271 r = (a*pp[0] + 127) / 255; 01272 g = (a*pp[1] + 127) / 255; 01273 b = (a*pp[2] + 127) / 255; 01274 *cp++ = PACK4(r,g,b,a); 01275 pp += samplesperpixel; 01276 } 01277 cp += toskew; 01278 pp += fromskew; 01279 } 01280 } 01281 01282 /* 01283 * 16-bit packed samples => RGB 01284 */ 01285 DECLAREContigPutFunc(putRGBcontig16bittile) 01286 { 01287 int samplesperpixel = img->samplesperpixel; 01288 uint16 *wp = (uint16 *)pp; 01289 (void) y; 01290 fromskew *= samplesperpixel; 01291 while (h-- > 0) { 01292 for (x = w; x-- > 0;) { 01293 *cp++ = PACKW(wp[0],wp[1],wp[2]); 01294 wp += samplesperpixel; 01295 } 01296 cp += toskew; 01297 wp += fromskew; 01298 } 01299 } 01300 01301 /* 01302 * 16-bit packed samples => RGBA w/ associated alpha 01303 * (known to have Map == NULL) 01304 */ 01305 DECLAREContigPutFunc(putRGBAAcontig16bittile) 01306 { 01307 int samplesperpixel = img->samplesperpixel; 01308 uint16 *wp = (uint16 *)pp; 01309 (void) y; 01310 fromskew *= samplesperpixel; 01311 while (h-- > 0) { 01312 for (x = w; x-- > 0;) { 01313 *cp++ = PACKW4(wp[0],wp[1],wp[2],wp[3]); 01314 wp += samplesperpixel; 01315 } 01316 cp += toskew; 01317 wp += fromskew; 01318 } 01319 } 01320 01321 /* 01322 * 16-bit packed samples => RGBA w/ unassociated alpha 01323 * (known to have Map == NULL) 01324 */ 01325 DECLAREContigPutFunc(putRGBUAcontig16bittile) 01326 { 01327 int samplesperpixel = img->samplesperpixel; 01328 uint16 *wp = (uint16 *)pp; 01329 (void) y; 01330 fromskew *= samplesperpixel; 01331 while (h-- > 0) { 01332 uint32 r,g,b,a; 01333 for (x = w; x-- > 0;) { 01334 a = W2B(wp[3]); 01335 r = (a*W2B(wp[0]) + 127) / 255; 01336 g = (a*W2B(wp[1]) + 127) / 255; 01337 b = (a*W2B(wp[2]) + 127) / 255; 01338 *cp++ = PACK4(r,g,b,a); 01339 wp += samplesperpixel; 01340 } 01341 cp += toskew; 01342 wp += fromskew; 01343 } 01344 } 01345 01346 /* 01347 * 8-bit packed CMYK samples w/o Map => RGB 01348 * 01349 * NB: The conversion of CMYK->RGB is *very* crude. 01350 */ 01351 DECLAREContigPutFunc(putRGBcontig8bitCMYKtile) 01352 { 01353 int samplesperpixel = img->samplesperpixel; 01354 uint16 r, g, b, k; 01355 01356 (void) x; (void) y; 01357 fromskew *= samplesperpixel; 01358 while (h-- > 0) { 01359 UNROLL8(w, NOP, 01360 k = 255 - pp[3]; 01361 r = (k*(255-pp[0]))/255; 01362 g = (k*(255-pp[1]))/255; 01363 b = (k*(255-pp[2]))/255; 01364 *cp++ = PACK(r, g, b); 01365 pp += samplesperpixel); 01366 cp += toskew; 01367 pp += fromskew; 01368 } 01369 } 01370 01371 /* 01372 * 8-bit packed CMYK samples w/Map => RGB 01373 * 01374 * NB: The conversion of CMYK->RGB is *very* crude. 01375 */ 01376 DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile) 01377 { 01378 int samplesperpixel = img->samplesperpixel; 01379 TIFFRGBValue* Map = img->Map; 01380 uint16 r, g, b, k; 01381 01382 (void) y; 01383 fromskew *= samplesperpixel; 01384 while (h-- > 0) { 01385 for (x = w; x-- > 0;) { 01386 k = 255 - pp[3]; 01387 r = (k*(255-pp[0]))/255; 01388 g = (k*(255-pp[1]))/255; 01389 b = (k*(255-pp[2]))/255; 01390 *cp++ = PACK(Map[r], Map[g], Map[b]); 01391 pp += samplesperpixel; 01392 } 01393 pp += fromskew; 01394 cp += toskew; 01395 } 01396 } 01397 01398 #define DECLARESepPutFunc(name) \ 01399 static void name(\ 01400 TIFFRGBAImage* img,\ 01401 uint32* cp,\ 01402 uint32 x, uint32 y, \ 01403 uint32 w, uint32 h,\ 01404 int32 fromskew, int32 toskew,\ 01405 unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a\ 01406 ) 01407 01408 /* 01409 * 8-bit unpacked samples => RGB 01410 */ 01411 DECLARESepPutFunc(putRGBseparate8bittile) 01412 { 01413 (void) img; (void) x; (void) y; (void) a; 01414 while (h-- > 0) { 01415 UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++)); 01416 SKEW(r, g, b, fromskew); 01417 cp += toskew; 01418 } 01419 } 01420 01421 /* 01422 * 8-bit unpacked samples => RGBA w/ associated alpha 01423 */ 01424 DECLARESepPutFunc(putRGBAAseparate8bittile) 01425 { 01426 (void) img; (void) x; (void) y; 01427 while (h-- > 0) { 01428 UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++)); 01429 SKEW4(r, g, b, a, fromskew); 01430 cp += toskew; 01431 } 01432 } 01433 01434 /* 01435 * 8-bit unpacked samples => RGBA w/ unassociated alpha 01436 */ 01437 DECLARESepPutFunc(putRGBUAseparate8bittile) 01438 { 01439 (void) img; (void) y; 01440 while (h-- > 0) { 01441 uint32 rv, gv, bv, av; 01442 for (x = w; x-- > 0;) { 01443 av = *a++; 01444 rv = (av* *r++ + 127) / 255; 01445 gv = (av* *g++ + 127) / 255; 01446 bv = (av* *b++ + 127) / 255; 01447 *cp++ = PACK4(rv,gv,bv,av); 01448 } 01449 SKEW4(r, g, b, a, fromskew); 01450 cp += toskew; 01451 } 01452 } 01453 01454 /* 01455 * 16-bit unpacked samples => RGB 01456 */ 01457 DECLARESepPutFunc(putRGBseparate16bittile) 01458 { 01459 uint16 *wr = (uint16*) r; 01460 uint16 *wg = (uint16*) g; 01461 uint16 *wb = (uint16*) b; 01462 (void) img; (void) y; (void) a; 01463 while (h-- > 0) { 01464 for (x = 0; x < w; x++) 01465 *cp++ = PACKW(*wr++,*wg++,*wb++); 01466 SKEW(wr, wg, wb, fromskew); 01467 cp += toskew; 01468 } 01469 } 01470 01471 /* 01472 * 16-bit unpacked samples => RGBA w/ associated alpha 01473 */ 01474 DECLARESepPutFunc(putRGBAAseparate16bittile) 01475 { 01476 uint16 *wr = (uint16*) r; 01477 uint16 *wg = (uint16*) g; 01478 uint16 *wb = (uint16*) b; 01479 uint16 *wa = (uint16*) a; 01480 (void) img; (void) y; 01481 while (h-- > 0) { 01482 for (x = 0; x < w; x++) 01483 *cp++ = PACKW4(*wr++,*wg++,*wb++,*wa++); 01484 SKEW4(wr, wg, wb, wa, fromskew); 01485 cp += toskew; 01486 } 01487 } 01488 01489 /* 01490 * 16-bit unpacked samples => RGBA w/ unassociated alpha 01491 */ 01492 DECLARESepPutFunc(putRGBUAseparate16bittile) 01493 { 01494 uint16 *wr = (uint16*) r; 01495 uint16 *wg = (uint16*) g; 01496 uint16 *wb = (uint16*) b; 01497 uint16 *wa = (uint16*) a; 01498 (void) img; (void) y; 01499 while (h-- > 0) { 01500 uint32 r,g,b,a; 01501 for (x = w; x-- > 0;) { 01502 a = W2B(*wa++); 01503 r = (a*W2B(*wr++) + 127) / 255; 01504 g = (a*W2B(*wg++) + 127) / 255; 01505 b = (a*W2B(*wb++) + 127) / 255; 01506 *cp++ = PACK4(r,g,b,a); 01507 } 01508 SKEW4(wr, wg, wb, wa, fromskew); 01509 cp += toskew; 01510 } 01511 } 01512 01513 /* 01514 * 8-bit packed CIE L*a*b 1976 samples => RGB 01515 */ 01516 DECLAREContigPutFunc(putcontig8bitCIELab) 01517 { 01518 float X, Y, Z; 01519 uint32 r, g, b; 01520 (void) y; 01521 fromskew *= 3; 01522 while (h-- > 0) { 01523 for (x = w; x-- > 0;) { 01524 TIFFCIELabToXYZ(img->cielab, 01525 (unsigned char)pp[0], 01526 (signed char)pp[1], 01527 (signed char)pp[2], 01528 &X, &Y, &Z); 01529 TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b); 01530 *cp++ = PACK(r, g, b); 01531 pp += 3; 01532 } 01533 cp += toskew; 01534 pp += fromskew; 01535 } 01536 } 01537 01538 /* 01539 * YCbCr -> RGB conversion and packing routines. 01540 */ 01541 01542 #define YCbCrtoRGB(dst, Y) { \ 01543 uint32 r, g, b; \ 01544 TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b); \ 01545 dst = PACK(r, g, b); \ 01546 } 01547 01548 /* 01549 * 8-bit packed YCbCr samples => RGB 01550 * This function is generic for different sampling sizes, 01551 * and can handle blocks sizes that aren't multiples of the 01552 * sampling size. However, it is substantially less optimized 01553 * than the specific sampling cases. It is used as a fallback 01554 * for difficult blocks. 01555 */ 01556 #ifdef notdef 01557 static void putcontig8bitYCbCrGenericTile( 01558 TIFFRGBAImage* img, 01559 uint32* cp, 01560 uint32 x, uint32 y, 01561 uint32 w, uint32 h, 01562 int32 fromskew, int32 toskew, 01563 unsigned char* pp, 01564 int h_group, 01565 int v_group ) 01566 01567 { 01568 uint32* cp1 = cp+w+toskew; 01569 uint32* cp2 = cp1+w+toskew; 01570 uint32* cp3 = cp2+w+toskew; 01571 int32 incr = 3*w+4*toskew; 01572 int32 Cb, Cr; 01573 int group_size = v_group * h_group + 2; 01574 01575 (void) y; 01576 fromskew = (fromskew * group_size) / h_group; 01577 01578 for( yy = 0; yy < h; yy++ ) 01579 { 01580 unsigned char *pp_line; 01581 int y_line_group = yy / v_group; 01582 int y_remainder = yy - y_line_group * v_group; 01583 01584 pp_line = pp + v_line_group * 01585 01586 01587 for( xx = 0; xx < w; xx++ ) 01588 { 01589 Cb = pp 01590 } 01591 } 01592 for (; h >= 4; h -= 4) { 01593 x = w>>2; 01594 do { 01595 Cb = pp[16]; 01596 Cr = pp[17]; 01597 01598 YCbCrtoRGB(cp [0], pp[ 0]); 01599 YCbCrtoRGB(cp [1], pp[ 1]); 01600 YCbCrtoRGB(cp [2], pp[ 2]); 01601 YCbCrtoRGB(cp [3], pp[ 3]); 01602 YCbCrtoRGB(cp1[0], pp[ 4]); 01603 YCbCrtoRGB(cp1[1], pp[ 5]); 01604 YCbCrtoRGB(cp1[2], pp[ 6]); 01605 YCbCrtoRGB(cp1[3], pp[ 7]); 01606 YCbCrtoRGB(cp2[0], pp[ 8]); 01607 YCbCrtoRGB(cp2[1], pp[ 9]); 01608 YCbCrtoRGB(cp2[2], pp[10]); 01609 YCbCrtoRGB(cp2[3], pp[11]); 01610 YCbCrtoRGB(cp3[0], pp[12]); 01611 YCbCrtoRGB(cp3[1], pp[13]); 01612 YCbCrtoRGB(cp3[2], pp[14]); 01613 YCbCrtoRGB(cp3[3], pp[15]); 01614 01615 cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; 01616 pp += 18; 01617 } while (--x); 01618 cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; 01619 pp += fromskew; 01620 } 01621 } 01622 #endif 01623 01624 /* 01625 * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB 01626 */ 01627 DECLAREContigPutFunc(putcontig8bitYCbCr44tile) 01628 { 01629 uint32* cp1 = cp+w+toskew; 01630 uint32* cp2 = cp1+w+toskew; 01631 uint32* cp3 = cp2+w+toskew; 01632 int32 incr = 3*w+4*toskew; 01633 01634 (void) y; 01635 /* adjust fromskew */ 01636 fromskew = (fromskew * 18) / 4; 01637 if ((h & 3) == 0 && (w & 3) == 0) { 01638 for (; h >= 4; h -= 4) { 01639 x = w>>2; 01640 do { 01641 int32 Cb = pp[16]; 01642 int32 Cr = pp[17]; 01643 01644 YCbCrtoRGB(cp [0], pp[ 0]); 01645 YCbCrtoRGB(cp [1], pp[ 1]); 01646 YCbCrtoRGB(cp [2], pp[ 2]); 01647 YCbCrtoRGB(cp [3], pp[ 3]); 01648 YCbCrtoRGB(cp1[0], pp[ 4]); 01649 YCbCrtoRGB(cp1[1], pp[ 5]); 01650 YCbCrtoRGB(cp1[2], pp[ 6]); 01651 YCbCrtoRGB(cp1[3], pp[ 7]); 01652 YCbCrtoRGB(cp2[0], pp[ 8]); 01653 YCbCrtoRGB(cp2[1], pp[ 9]); 01654 YCbCrtoRGB(cp2[2], pp[10]); 01655 YCbCrtoRGB(cp2[3], pp[11]); 01656 YCbCrtoRGB(cp3[0], pp[12]); 01657 YCbCrtoRGB(cp3[1], pp[13]); 01658 YCbCrtoRGB(cp3[2], pp[14]); 01659 YCbCrtoRGB(cp3[3], pp[15]); 01660 01661 cp += 4, cp1 += 4, cp2 += 4, cp3 += 4; 01662 pp += 18; 01663 } while (--x); 01664 cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; 01665 pp += fromskew; 01666 } 01667 } else { 01668 while (h > 0) { 01669 for (x = w; x > 0;) { 01670 int32 Cb = pp[16]; 01671 int32 Cr = pp[17]; 01672 switch (x) { 01673 default: 01674 switch (h) { 01675 default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */ 01676 case 3: YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */ 01677 case 2: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ 01678 case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ 01679 } /* FALLTHROUGH */ 01680 case 3: 01681 switch (h) { 01682 default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */ 01683 case 3: YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */ 01684 case 2: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ 01685 case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ 01686 } /* FALLTHROUGH */ 01687 case 2: 01688 switch (h) { 01689 default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */ 01690 case 3: YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */ 01691 case 2: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ 01692 case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ 01693 } /* FALLTHROUGH */ 01694 case 1: 01695 switch (h) { 01696 default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */ 01697 case 3: YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */ 01698 case 2: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ 01699 case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ 01700 } /* FALLTHROUGH */ 01701 } 01702 if (x < 4) { 01703 cp += x; cp1 += x; cp2 += x; cp3 += x; 01704 x = 0; 01705 } 01706 else { 01707 cp += 4; cp1 += 4; cp2 += 4; cp3 += 4; 01708 x -= 4; 01709 } 01710 pp += 18; 01711 } 01712 if (h <= 4) 01713 break; 01714 h -= 4; 01715 cp += incr, cp1 += incr, cp2 += incr, cp3 += incr; 01716 pp += fromskew; 01717 } 01718 } 01719 } 01720 01721 /* 01722 * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB 01723 */ 01724 DECLAREContigPutFunc(putcontig8bitYCbCr42tile) 01725 { 01726 uint32* cp1 = cp+w+toskew; 01727 int32 incr = 2*toskew+w; 01728 01729 (void) y; 01730 fromskew = (fromskew * 10) / 4; 01731 if ((h & 3) == 0 && (w & 1) == 0) { 01732 for (; h >= 2; h -= 2) { 01733 x = w>>2; 01734 do { 01735 int32 Cb = pp[8]; 01736 int32 Cr = pp[9]; 01737 01738 YCbCrtoRGB(cp [0], pp[0]); 01739 YCbCrtoRGB(cp [1], pp[1]); 01740 YCbCrtoRGB(cp [2], pp[2]); 01741 YCbCrtoRGB(cp [3], pp[3]); 01742 YCbCrtoRGB(cp1[0], pp[4]); 01743 YCbCrtoRGB(cp1[1], pp[5]); 01744 YCbCrtoRGB(cp1[2], pp[6]); 01745 YCbCrtoRGB(cp1[3], pp[7]); 01746 01747 cp += 4, cp1 += 4; 01748 pp += 10; 01749 } while (--x); 01750 cp += incr, cp1 += incr; 01751 pp += fromskew; 01752 } 01753 } else { 01754 while (h > 0) { 01755 for (x = w; x > 0;) { 01756 int32 Cb = pp[8]; 01757 int32 Cr = pp[9]; 01758 switch (x) { 01759 default: 01760 switch (h) { 01761 default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */ 01762 case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */ 01763 } /* FALLTHROUGH */ 01764 case 3: 01765 switch (h) { 01766 default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */ 01767 case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */ 01768 } /* FALLTHROUGH */ 01769 case 2: 01770 switch (h) { 01771 default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */ 01772 case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */ 01773 } /* FALLTHROUGH */ 01774 case 1: 01775 switch (h) { 01776 default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */ 01777 case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */ 01778 } /* FALLTHROUGH */ 01779 } 01780 if (x < 4) { 01781 cp += x; cp1 += x; 01782 x = 0; 01783 } 01784 else { 01785 cp += 4; cp1 += 4; 01786 x -= 4; 01787 } 01788 pp += 10; 01789 } 01790 if (h <= 2) 01791 break; 01792 h -= 2; 01793 cp += incr, cp1 += incr; 01794 pp += fromskew; 01795 } 01796 } 01797 } 01798 01799 /* 01800 * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB 01801 */ 01802 DECLAREContigPutFunc(putcontig8bitYCbCr41tile) 01803 { 01804 (void) y; 01805 /* XXX adjust fromskew */ 01806 do { 01807 x = w>>2; 01808 do { 01809 int32 Cb = pp[4]; 01810 int32 Cr = pp[5]; 01811 01812 YCbCrtoRGB(cp [0], pp[0]); 01813 YCbCrtoRGB(cp [1], pp[1]); 01814 YCbCrtoRGB(cp [2], pp[2]); 01815 YCbCrtoRGB(cp [3], pp[3]); 01816 01817 cp += 4; 01818 pp += 6; 01819 } while (--x); 01820 01821 if( (w&3) != 0 ) 01822 { 01823 int32 Cb = pp[4]; 01824 int32 Cr = pp[5]; 01825 01826 switch( (w&3) ) { 01827 case 3: YCbCrtoRGB(cp [2], pp[2]); 01828 case 2: YCbCrtoRGB(cp [1], pp[1]); 01829 case 1: YCbCrtoRGB(cp [0], pp[0]); 01830 case 0: break; 01831 } 01832 01833 cp += (w&3); 01834 pp += 6; 01835 } 01836 01837 cp += toskew; 01838 pp += fromskew; 01839 } while (--h); 01840 01841 } 01842 01843 /* 01844 * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB 01845 */ 01846 DECLAREContigPutFunc(putcontig8bitYCbCr22tile) 01847 { 01848 uint32* cp2; 01849 (void) y; 01850 fromskew = (fromskew / 2) * 6; 01851 cp2 = cp+w+toskew; 01852 while (h>=2) { 01853 x = w; 01854 while (x>=2) { 01855 uint32 Cb = pp[4]; 01856 uint32 Cr = pp[5]; 01857 YCbCrtoRGB(cp[0], pp[0]); 01858 YCbCrtoRGB(cp[1], pp[1]); 01859 YCbCrtoRGB(cp2[0], pp[2]); 01860 YCbCrtoRGB(cp2[1], pp[3]); 01861 cp += 2; 01862 cp2 += 2; 01863 pp += 6; 01864 x -= 2; 01865 } 01866 if (x==1) { 01867 uint32 Cb = pp[4]; 01868 uint32 Cr = pp[5]; 01869 YCbCrtoRGB(cp[0], pp[0]); 01870 YCbCrtoRGB(cp2[0], pp[2]); 01871 cp ++ ; 01872 cp2 ++ ; 01873 pp += 6; 01874 } 01875 cp += toskew*2+w; 01876 cp2 += toskew*2+w; 01877 pp += fromskew; 01878 h-=2; 01879 } 01880 if (h==1) { 01881 x = w; 01882 while (x>=2) { 01883 uint32 Cb = pp[4]; 01884 uint32 Cr = pp[5]; 01885 YCbCrtoRGB(cp[0], pp[0]); 01886 YCbCrtoRGB(cp[1], pp[1]); 01887 cp += 2; 01888 cp2 += 2; 01889 pp += 6; 01890 x -= 2; 01891 } 01892 if (x==1) { 01893 uint32 Cb = pp[4]; 01894 uint32 Cr = pp[5]; 01895 YCbCrtoRGB(cp[0], pp[0]); 01896 } 01897 } 01898 } 01899 01900 /* 01901 * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB 01902 */ 01903 DECLAREContigPutFunc(putcontig8bitYCbCr21tile) 01904 { 01905 (void) y; 01906 fromskew = (fromskew * 4) / 2; 01907 do { 01908 x = w>>1; 01909 do { 01910 int32 Cb = pp[2]; 01911 int32 Cr = pp[3]; 01912 01913 YCbCrtoRGB(cp[0], pp[0]); 01914 YCbCrtoRGB(cp[1], pp[1]); 01915 01916 cp += 2; 01917 pp += 4; 01918 } while (--x); 01919 01920 if( (w&1) != 0 ) 01921 { 01922 int32 Cb = pp[2]; 01923 int32 Cr = pp[3]; 01924 01925 YCbCrtoRGB(cp[0], pp[0]); 01926 01927 cp += 1; 01928 pp += 4; 01929 } 01930 01931 cp += toskew; 01932 pp += fromskew; 01933 } while (--h); 01934 } 01935 01936 /* 01937 * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB 01938 */ 01939 DECLAREContigPutFunc(putcontig8bitYCbCr12tile) 01940 { 01941 uint32* cp2; 01942 (void) y; 01943 fromskew = (fromskew / 2) * 4; 01944 cp2 = cp+w+toskew; 01945 while (h>=2) { 01946 x = w; 01947 do { 01948 uint32 Cb = pp[2]; 01949 uint32 Cr = pp[3]; 01950 YCbCrtoRGB(cp[0], pp[0]); 01951 YCbCrtoRGB(cp2[0], pp[1]); 01952 cp ++; 01953 cp2 ++; 01954 pp += 4; 01955 } while (--x); 01956 cp += toskew*2+w; 01957 cp2 += toskew*2+w; 01958 pp += fromskew; 01959 h-=2; 01960 } 01961 if (h==1) { 01962 x = w; 01963 do { 01964 uint32 Cb = pp[2]; 01965 uint32 Cr = pp[3]; 01966 YCbCrtoRGB(cp[0], pp[0]); 01967 cp ++; 01968 pp += 4; 01969 } while (--x); 01970 } 01971 } 01972 01973 /* 01974 * 8-bit packed YCbCr samples w/ no subsampling => RGB 01975 */ 01976 DECLAREContigPutFunc(putcontig8bitYCbCr11tile) 01977 { 01978 (void) y; 01979 fromskew *= 3; 01980 do { 01981 x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */ 01982 do { 01983 int32 Cb = pp[1]; 01984 int32 Cr = pp[2]; 01985 01986 YCbCrtoRGB(*cp++, pp[0]); 01987 01988 pp += 3; 01989 } while (--x); 01990 cp += toskew; 01991 pp += fromskew; 01992 } while (--h); 01993 } 01994 01995 /* 01996 * 8-bit packed YCbCr samples w/ no subsampling => RGB 01997 */ 01998 DECLARESepPutFunc(putseparate8bitYCbCr11tile) 01999 { 02000 (void) y; 02001 (void) a; 02002 /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */ 02003 while (h-- > 0) { 02004 x = w; 02005 do { 02006 uint32 dr, dg, db; 02007 TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db); 02008 *cp++ = PACK(dr,dg,db); 02009 } while (--x); 02010 SKEW(r, g, b, fromskew); 02011 cp += toskew; 02012 } 02013 } 02014 #undef YCbCrtoRGB 02015 02016 static int 02017 initYCbCrConversion(TIFFRGBAImage* img) 02018 { 02019 static char module[] = "initYCbCrConversion"; 02020 02021 float *luma, *refBlackWhite; 02022 02023 if (img->ycbcr == NULL) { 02024 img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc( 02025 TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)) 02026 + 4*256*sizeof (TIFFRGBValue) 02027 + 2*256*sizeof (int) 02028 + 3*256*sizeof (int32) 02029 ); 02030 if (img->ycbcr == NULL) { 02031 TIFFErrorExt(img->tif->tif_clientdata, module, 02032 "No space for YCbCr->RGB conversion state"); 02033 return (0); 02034 } 02035 } 02036 02037 TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma); 02038 TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE, 02039 &refBlackWhite); 02040 if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0) 02041 return(0); 02042 return (1); 02043 } 02044 02045 static tileContigRoutine 02046 initCIELabConversion(TIFFRGBAImage* img) 02047 { 02048 static char module[] = "initCIELabConversion"; 02049 02050 float *whitePoint; 02051 float refWhite[3]; 02052 02053 if (!img->cielab) { 02054 img->cielab = (TIFFCIELabToRGB *) 02055 _TIFFmalloc(sizeof(TIFFCIELabToRGB)); 02056 if (!img->cielab) { 02057 TIFFErrorExt(img->tif->tif_clientdata, module, 02058 "No space for CIE L*a*b*->RGB conversion state."); 02059 return NULL; 02060 } 02061 } 02062 02063 TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint); 02064 refWhite[1] = 100.0F; 02065 refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1]; 02066 refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1]) 02067 / whitePoint[1] * refWhite[1]; 02068 if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) { 02069 TIFFErrorExt(img->tif->tif_clientdata, module, 02070 "Failed to initialize CIE L*a*b*->RGB conversion state."); 02071 _TIFFfree(img->cielab); 02072 return NULL; 02073 } 02074 02075 return putcontig8bitCIELab; 02076 } 02077 02078 /* 02079 * Greyscale images with less than 8 bits/sample are handled 02080 * with a table to avoid lots of shifts and masks. The table 02081 * is setup so that put*bwtile (below) can retrieve 8/bitspersample 02082 * pixel values simply by indexing into the table with one 02083 * number. 02084 */ 02085 static int 02086 makebwmap(TIFFRGBAImage* img) 02087 { 02088 TIFFRGBValue* Map = img->Map; 02089 int bitspersample = img->bitspersample; 02090 int nsamples = 8 / bitspersample; 02091 int i; 02092 uint32* p; 02093 02094 if( nsamples == 0 ) 02095 nsamples = 1; 02096 02097 img->BWmap = (uint32**) _TIFFmalloc( 02098 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); 02099 if (img->BWmap == NULL) { 02100 TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table"); 02101 return (0); 02102 } 02103 p = (uint32*)(img->BWmap + 256); 02104 for (i = 0; i < 256; i++) { 02105 TIFFRGBValue c; 02106 img->BWmap[i] = p; 02107 switch (bitspersample) { 02108 #define GREY(x) c = Map[x]; *p++ = PACK(c,c,c); 02109 case 1: 02110 GREY(i>>7); 02111 GREY((i>>6)&1); 02112 GREY((i>>5)&1); 02113 GREY((i>>4)&1); 02114 GREY((i>>3)&1); 02115 GREY((i>>2)&1); 02116 GREY((i>>1)&1); 02117 GREY(i&1); 02118 break; 02119 case 2: 02120 GREY(i>>6); 02121 GREY((i>>4)&3); 02122 GREY((i>>2)&3); 02123 GREY(i&3); 02124 break; 02125 case 4: 02126 GREY(i>>4); 02127 GREY(i&0xf); 02128 break; 02129 case 8: 02130 case 16: 02131 GREY(i); 02132 break; 02133 } 02134 #undef GREY 02135 } 02136 return (1); 02137 } 02138 02139 /* 02140 * Construct a mapping table to convert from the range 02141 * of the data samples to [0,255] --for display. This 02142 * process also handles inverting B&W images when needed. 02143 */ 02144 static int 02145 setupMap(TIFFRGBAImage* img) 02146 { 02147 int32 x, range; 02148 02149 range = (int32)((1L<<img->bitspersample)-1); 02150 02151 /* treat 16 bit the same as eight bit */ 02152 if( img->bitspersample == 16 ) 02153 range = (int32) 255; 02154 02155 img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue)); 02156 if (img->Map == NULL) { 02157 TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), 02158 "No space for photometric conversion table"); 02159 return (0); 02160 } 02161 if (img->photometric == PHOTOMETRIC_MINISWHITE) { 02162 for (x = 0; x <= range; x++) 02163 img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range); 02164 } else { 02165 for (x = 0; x <= range; x++) 02166 img->Map[x] = (TIFFRGBValue) ((x * 255) / range); 02167 } 02168 if (img->bitspersample <= 16 && 02169 (img->photometric == PHOTOMETRIC_MINISBLACK || 02170 img->photometric == PHOTOMETRIC_MINISWHITE)) { 02171 /* 02172 * Use photometric mapping table to construct 02173 * unpacking tables for samples <= 8 bits. 02174 */ 02175 if (!makebwmap(img)) 02176 return (0); 02177 /* no longer need Map, free it */ 02178 _TIFFfree(img->Map), img->Map = NULL; 02179 } 02180 return (1); 02181 } 02182 02183 static int 02184 checkcmap(TIFFRGBAImage* img) 02185 { 02186 uint16* r = img->redcmap; 02187 uint16* g = img->greencmap; 02188 uint16* b = img->bluecmap; 02189 long n = 1L<<img->bitspersample; 02190 02191 while (n-- > 0) 02192 if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) 02193 return (16); 02194 return (8); 02195 } 02196 02197 static void 02198 cvtcmap(TIFFRGBAImage* img) 02199 { 02200 uint16* r = img->redcmap; 02201 uint16* g = img->greencmap; 02202 uint16* b = img->bluecmap; 02203 long i; 02204 02205 for (i = (1L<<img->bitspersample)-1; i >= 0; i--) { 02206 #define CVT(x) ((uint16)((x)>>8)) 02207 r[i] = CVT(r[i]); 02208 g[i] = CVT(g[i]); 02209 b[i] = CVT(b[i]); 02210 #undef CVT 02211 } 02212 } 02213 02214 /* 02215 * Palette images with <= 8 bits/sample are handled 02216 * with a table to avoid lots of shifts and masks. The table 02217 * is setup so that put*cmaptile (below) can retrieve 8/bitspersample 02218 * pixel values simply by indexing into the table with one 02219 * number. 02220 */ 02221 static int 02222 makecmap(TIFFRGBAImage* img) 02223 { 02224 int bitspersample = img->bitspersample; 02225 int nsamples = 8 / bitspersample; 02226 uint16* r = img->redcmap; 02227 uint16* g = img->greencmap; 02228 uint16* b = img->bluecmap; 02229 uint32 *p; 02230 int i; 02231 02232 img->PALmap = (uint32**) _TIFFmalloc( 02233 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32))); 02234 if (img->PALmap == NULL) { 02235 TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table"); 02236 return (0); 02237 } 02238 p = (uint32*)(img->PALmap + 256); 02239 for (i = 0; i < 256; i++) { 02240 TIFFRGBValue c; 02241 img->PALmap[i] = p; 02242 #define CMAP(x) c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff); 02243 switch (bitspersample) { 02244 case 1: 02245 CMAP(i>>7); 02246 CMAP((i>>6)&1); 02247 CMAP((i>>5)&1); 02248 CMAP((i>>4)&1); 02249 CMAP((i>>3)&1); 02250 CMAP((i>>2)&1); 02251 CMAP((i>>1)&1); 02252 CMAP(i&1); 02253 break; 02254 case 2: 02255 CMAP(i>>6); 02256 CMAP((i>>4)&3); 02257 CMAP((i>>2)&3); 02258 CMAP(i&3); 02259 break; 02260 case 4: 02261 CMAP(i>>4); 02262 CMAP(i&0xf); 02263 break; 02264 case 8: 02265 CMAP(i); 02266 break; 02267 } 02268 #undef CMAP 02269 } 02270 return (1); 02271 } 02272 02273 /* 02274 * Construct any mapping table used 02275 * by the associated put routine. 02276 */ 02277 static int 02278 buildMap(TIFFRGBAImage* img) 02279 { 02280 switch (img->photometric) { 02281 case PHOTOMETRIC_RGB: 02282 case PHOTOMETRIC_YCBCR: 02283 case PHOTOMETRIC_SEPARATED: 02284 if (img->bitspersample == 8) 02285 break; 02286 /* fall thru... */ 02287 case PHOTOMETRIC_MINISBLACK: 02288 case PHOTOMETRIC_MINISWHITE: 02289 if (!setupMap(img)) 02290 return (0); 02291 break; 02292 case PHOTOMETRIC_PALETTE: 02293 /* 02294 * Convert 16-bit colormap to 8-bit (unless it looks 02295 * like an old-style 8-bit colormap). 02296 */ 02297 if (checkcmap(img) == 16) 02298 cvtcmap(img); 02299 else 02300 TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap"); 02301 /* 02302 * Use mapping table and colormap to construct 02303 * unpacking tables for samples < 8 bits. 02304 */ 02305 if (img->bitspersample <= 8 && !makecmap(img)) 02306 return (0); 02307 break; 02308 } 02309 return (1); 02310 } 02311 02312 /* 02313 * Select the appropriate conversion routine for packed data. 02314 */ 02315 static int 02316 PickContigCase(TIFFRGBAImage* img) 02317 { 02318 img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig; 02319 img->put.contig = NULL; 02320 switch (img->photometric) { 02321 case PHOTOMETRIC_RGB: 02322 switch (img->bitspersample) { 02323 case 8: 02324 if (img->alpha == EXTRASAMPLE_ASSOCALPHA) 02325 img->put.contig = putRGBAAcontig8bittile; 02326 else if (img->alpha == EXTRASAMPLE_UNASSALPHA) 02327 { 02328 img->put.contig = putRGBUAcontig8bittile; 02329 } 02330 else 02331 img->put.contig = putRGBcontig8bittile; 02332 break; 02333 case 16: 02334 if (img->alpha == EXTRASAMPLE_ASSOCALPHA) 02335 { 02336 img->put.contig = putRGBAAcontig16bittile; 02337 } 02338 else if (img->alpha == EXTRASAMPLE_UNASSALPHA) 02339 { 02340 img->put.contig = putRGBUAcontig16bittile; 02341 } 02342 else 02343 { 02344 img->put.contig = putRGBcontig16bittile; 02345 } 02346 break; 02347 } 02348 break; 02349 case PHOTOMETRIC_SEPARATED: 02350 if (buildMap(img)) { 02351 if (img->bitspersample == 8) { 02352 if (!img->Map) 02353 img->put.contig = putRGBcontig8bitCMYKtile; 02354 else 02355 img->put.contig = putRGBcontig8bitCMYKMaptile; 02356 } 02357 } 02358 break; 02359 case PHOTOMETRIC_PALETTE: 02360 if (buildMap(img)) { 02361 switch (img->bitspersample) { 02362 case 8: 02363 img->put.contig = put8bitcmaptile; 02364 break; 02365 case 4: 02366 img->put.contig = put4bitcmaptile; 02367 break; 02368 case 2: 02369 img->put.contig = put2bitcmaptile; 02370 break; 02371 case 1: 02372 img->put.contig = put1bitcmaptile; 02373 break; 02374 } 02375 } 02376 break; 02377 case PHOTOMETRIC_MINISWHITE: 02378 case PHOTOMETRIC_MINISBLACK: 02379 if (buildMap(img)) { 02380 switch (img->bitspersample) { 02381 case 16: 02382 img->put.contig = put16bitbwtile; 02383 break; 02384 case 8: 02385 img->put.contig = putgreytile; 02386 break; 02387 case 4: 02388 img->put.contig = put4bitbwtile; 02389 break; 02390 case 2: 02391 img->put.contig = put2bitbwtile; 02392 break; 02393 case 1: 02394 img->put.contig = put1bitbwtile; 02395 break; 02396 } 02397 } 02398 break; 02399 case PHOTOMETRIC_YCBCR: 02400 if (img->bitspersample == 8) 02401 { 02402 if (initYCbCrConversion(img)!=0) 02403 { 02404 /* 02405 * The 6.0 spec says that subsampling must be 02406 * one of 1, 2, or 4, and that vertical subsampling 02407 * must always be <= horizontal subsampling; so 02408 * there are only a few possibilities and we just 02409 * enumerate the cases. 02410 * Joris: added support for the [1,2] case, nonetheless, to accomodate 02411 * some OJPEG files 02412 */ 02413 uint16 SubsamplingHor; 02414 uint16 SubsamplingVer; 02415 TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer); 02416 switch ((SubsamplingHor<<4)|SubsamplingVer) { 02417 case 0x44: 02418 img->put.contig = putcontig8bitYCbCr44tile; 02419 break; 02420 case 0x42: 02421 img->put.contig = putcontig8bitYCbCr42tile; 02422 break; 02423 case 0x41: 02424 img->put.contig = putcontig8bitYCbCr41tile; 02425 break; 02426 case 0x22: 02427 img->put.contig = putcontig8bitYCbCr22tile; 02428 break; 02429 case 0x21: 02430 img->put.contig = putcontig8bitYCbCr21tile; 02431 break; 02432 case 0x12: 02433 img->put.contig = putcontig8bitYCbCr12tile; 02434 break; 02435 case 0x11: 02436 img->put.contig = putcontig8bitYCbCr11tile; 02437 break; 02438 } 02439 } 02440 } 02441 break; 02442 case PHOTOMETRIC_CIELAB: 02443 if (buildMap(img)) { 02444 if (img->bitspersample == 8) 02445 img->put.contig = initCIELabConversion(img); 02446 break; 02447 } 02448 } 02449 return ((img->get!=NULL) && (img->put.contig!=NULL)); 02450 } 02451 02452 /* 02453 * Select the appropriate conversion routine for unpacked data. 02454 * 02455 * NB: we assume that unpacked single channel data is directed 02456 * to the "packed routines. 02457 */ 02458 static int 02459 PickSeparateCase(TIFFRGBAImage* img) 02460 { 02461 img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate; 02462 img->put.separate = NULL; 02463 switch (img->photometric) { 02464 case PHOTOMETRIC_RGB: 02465 switch (img->bitspersample) { 02466 case 8: 02467 if (img->alpha == EXTRASAMPLE_ASSOCALPHA) 02468 img->put.separate = putRGBAAseparate8bittile; 02469 else if (img->alpha == EXTRASAMPLE_UNASSALPHA) 02470 { 02471 img->put.separate = putRGBUAseparate8bittile; 02472 } 02473 else 02474 img->put.separate = putRGBseparate8bittile; 02475 break; 02476 case 16: 02477 if (img->alpha == EXTRASAMPLE_ASSOCALPHA) 02478 { 02479 img->put.separate = putRGBAAseparate16bittile; 02480 } 02481 else if (img->alpha == EXTRASAMPLE_UNASSALPHA) 02482 { 02483 img->put.separate = putRGBUAseparate16bittile; 02484 } 02485 else 02486 { 02487 img->put.separate = putRGBseparate16bittile; 02488 } 02489 break; 02490 } 02491 break; 02492 case PHOTOMETRIC_YCBCR: 02493 if ((img->bitspersample==8) && (img->samplesperpixel==3)) 02494 { 02495 if (initYCbCrConversion(img)!=0) 02496 { 02497 uint16 hs, vs; 02498 TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs); 02499 switch ((hs<<4)|vs) { 02500 case 0x11: 02501 img->put.separate = putseparate8bitYCbCr11tile; 02502 break; 02503 /* TODO: add other cases here */ 02504 } 02505 } 02506 } 02507 break; 02508 } 02509 return ((img->get!=NULL) && (img->put.separate!=NULL)); 02510 } 02511 02512 /* 02513 * Read a whole strip off data from the file, and convert to RGBA form. 02514 * If this is the last strip, then it will only contain the portion of 02515 * the strip that is actually within the image space. The result is 02516 * organized in bottom to top form. 02517 */ 02518 02519 02520 int 02521 TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster ) 02522 02523 { 02524 char emsg[1024] = ""; 02525 TIFFRGBAImage img; 02526 int ok; 02527 uint32 rowsperstrip, rows_to_read; 02528 02529 if( TIFFIsTiled( tif ) ) 02530 { 02531 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), 02532 "Can't use TIFFReadRGBAStrip() with tiled file."); 02533 return (0); 02534 } 02535 02536 TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 02537 if( (row % rowsperstrip) != 0 ) 02538 { 02539 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), 02540 "Row passed to TIFFReadRGBAStrip() must be first in a strip."); 02541 return (0); 02542 } 02543 02544 if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) { 02545 02546 img.row_offset = row; 02547 img.col_offset = 0; 02548 02549 if( row + rowsperstrip > img.height ) 02550 rows_to_read = img.height - row; 02551 else 02552 rows_to_read = rowsperstrip; 02553 02554 ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read ); 02555 02556 TIFFRGBAImageEnd(&img); 02557 } else { 02558 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); 02559 ok = 0; 02560 } 02561 02562 return (ok); 02563 } 02564 02565 /* 02566 * Read a whole tile off data from the file, and convert to RGBA form. 02567 * The returned RGBA data is organized from bottom to top of tile, 02568 * and may include zeroed areas if the tile extends off the image. 02569 */ 02570 02571 int 02572 TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster) 02573 02574 { 02575 char emsg[1024] = ""; 02576 TIFFRGBAImage img; 02577 int ok; 02578 uint32 tile_xsize, tile_ysize; 02579 uint32 read_xsize, read_ysize; 02580 uint32 i_row; 02581 02582 /* 02583 * Verify that our request is legal - on a tile file, and on a 02584 * tile boundary. 02585 */ 02586 02587 if( !TIFFIsTiled( tif ) ) 02588 { 02589 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), 02590 "Can't use TIFFReadRGBATile() with stripped file."); 02591 return (0); 02592 } 02593 02594 TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize); 02595 TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); 02596 if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 ) 02597 { 02598 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), 02599 "Row/col passed to TIFFReadRGBATile() must be top" 02600 "left corner of a tile."); 02601 return (0); 02602 } 02603 02604 /* 02605 * Setup the RGBA reader. 02606 */ 02607 02608 if (!TIFFRGBAImageOK(tif, emsg) 02609 || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) { 02610 TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg); 02611 return( 0 ); 02612 } 02613 02614 /* 02615 * The TIFFRGBAImageGet() function doesn't allow us to get off the 02616 * edge of the image, even to fill an otherwise valid tile. So we 02617 * figure out how much we can read, and fix up the tile buffer to 02618 * a full tile configuration afterwards. 02619 */ 02620 02621 if( row + tile_ysize > img.height ) 02622 read_ysize = img.height - row; 02623 else 02624 read_ysize = tile_ysize; 02625 02626 if( col + tile_xsize > img.width ) 02627 read_xsize = img.width - col; 02628 else 02629 read_xsize = tile_xsize; 02630 02631 /* 02632 * Read the chunk of imagery. 02633 */ 02634 02635 img.row_offset = row; 02636 img.col_offset = col; 02637 02638 ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize ); 02639 02640 TIFFRGBAImageEnd(&img); 02641 02642 /* 02643 * If our read was incomplete we will need to fix up the tile by 02644 * shifting the data around as if a full tile of data is being returned. 02645 * 02646 * This is all the more complicated because the image is organized in 02647 * bottom to top format. 02648 */ 02649 02650 if( read_xsize == tile_xsize && read_ysize == tile_ysize ) 02651 return( ok ); 02652 02653 for( i_row = 0; i_row < read_ysize; i_row++ ) { 02654 memmove( raster + (tile_ysize - i_row - 1) * tile_xsize, 02655 raster + (read_ysize - i_row - 1) * read_xsize, 02656 read_xsize * sizeof(uint32) ); 02657 _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize, 02658 0, sizeof(uint32) * (tile_xsize - read_xsize) ); 02659 } 02660 02661 for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) { 02662 _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize, 02663 0, sizeof(uint32) * tile_xsize ); 02664 } 02665 02666 return (ok); 02667 } 02668 02669 /* vim: set ts=8 sts=8 sw=8 noet: */ 02670 /* 02671 * Local Variables: 02672 * mode: c 02673 * c-basic-offset: 8 02674 * fill-column: 78 02675 * End: 02676 */ Generated on Sun May 27 2012 04:19:34 for ReactOS by
1.7.6.1
|