Leptonica 1.68
C Image Processing Library
|
00001 /*====================================================================* 00002 - Copyright (C) 2001 Leptonica. All rights reserved. 00003 - This software is distributed in the hope that it will be 00004 - useful, but with NO WARRANTY OF ANY KIND. 00005 - No author or distributor accepts responsibility to anyone for the 00006 - consequences of using this software, or for whether it serves any 00007 - particular purpose or works at all, unless he or she says so in 00008 - writing. Everyone is granted permission to copy, modify and 00009 - redistribute this source code, for commercial or non-commercial 00010 - purposes, with the following restrictions: (1) the origin of this 00011 - source code must not be misrepresented; (2) modified versions must 00012 - be plainly marked as such; and (3) this notice may not be removed 00013 - or altered from any source or modified source distribution. 00014 *====================================================================*/ 00015 00016 /* 00017 * tiffio.c 00018 * 00019 * Reading tiff: 00020 * PIX *pixReadTiff() [ special top level ] 00021 * PIX *pixReadStreamTiff() 00022 * static PIX *pixReadFromTiffStream() 00023 * 00024 * Writing tiff: 00025 * l_int32 pixWriteTiff() [ special top level ] 00026 * l_int32 pixWriteTiffCustom() [ special top level ] 00027 * l_int32 pixWriteStreamTiff() 00028 * static l_int32 pixWriteToTiffStream() 00029 * static l_int32 writeCustomTiffTags() 00030 * 00031 * Reading and writing multipage tiff 00032 * PIXA pixaReadMultipageTiff() 00033 * l_int32 writeMultipageTiff() [ special top level ] 00034 * l_int32 writeMultipageTiffSA() 00035 * 00036 * Information about tiff file 00037 * l_int32 fprintTiffInfo() 00038 * l_int32 tiffGetCount() 00039 * l_int32 getTiffResolution() 00040 * static l_int32 getTiffStreamResolution() 00041 * l_int32 readHeaderTiff() 00042 * l_int32 freadHeaderTiff() 00043 * l_int32 readHeaderMemTiff() 00044 * static l_int32 tiffReadHeaderTiff() 00045 * l_int32 findTiffCompression() 00046 * static l_int32 getTiffCompressedFormat() 00047 * 00048 * Extraction of tiff g4 data: 00049 * l_int32 extractG4DataFromFile() 00050 * 00051 * Open tiff stream from file stream 00052 * static TIFF *fopenTiff() 00053 * 00054 * Wrapper for TIFFOpen: 00055 * static TIFF *openTiff() 00056 * 00057 * Memory I/O: reading memory --> pix and writing pix --> memory 00058 * [10 static helper functions] 00059 * l_int32 pixReadMemTiff(); 00060 * l_int32 pixWriteMemTiff(); 00061 * l_int32 pixWriteMemTiffCustom(); 00062 * 00063 * Note: You should be using version 3.7.4 of libtiff to be certain 00064 * that all the necessary functions are included. 00065 */ 00066 00067 #include <string.h> 00068 #include <sys/types.h> 00069 #ifndef _MSC_VER 00070 #include <unistd.h> 00071 #else /* _MSC_VER */ 00072 #include <io.h> 00073 #define seek _seek; 00074 #endif /* _MSC_VER */ 00075 #include <fcntl.h> 00076 #include "allheaders.h" 00077 00078 #ifdef HAVE_CONFIG_H 00079 #include "config_auto.h" 00080 #endif /* HAVE_CONFIG_H */ 00081 00082 /* --------------------------------------------*/ 00083 #if HAVE_LIBTIFF /* defined in environ.h */ 00084 /* --------------------------------------------*/ 00085 00086 #include "tiff.h" 00087 #include "tiffio.h" 00088 00089 static const l_int32 DEFAULT_RESOLUTION = 300; /* ppi */ 00090 static const l_int32 MAX_PAGES_IN_TIFF_FILE = 3000; /* should be enough */ 00091 00092 00093 /* All functions with TIFF interfaces are static. */ 00094 static PIX *pixReadFromTiffStream(TIFF *tif); 00095 static l_int32 getTiffStreamResolution(TIFF *tif, l_int32 *pxres, 00096 l_int32 *pyres); 00097 static l_int32 tiffReadHeaderTiff(TIFF *tif, l_int32 *pwidth, 00098 l_int32 *pheight, l_int32 *pbps, 00099 l_int32 *pspp, l_int32 *pres, 00100 l_int32 *pcmap, l_int32 *pformat); 00101 static l_int32 writeCustomTiffTags(TIFF *tif, NUMA *natags, 00102 SARRAY *savals, SARRAY *satypes, 00103 NUMA *nasizes); 00104 static l_int32 pixWriteToTiffStream(TIFF *tif, PIX *pix, l_int32 comptype, 00105 NUMA *natags, SARRAY *savals, 00106 SARRAY *satypes, NUMA *nasizes); 00107 static TIFF *fopenTiff(FILE *fp, const char *modestring); 00108 static TIFF *openTiff(const char *filename, const char *modestring); 00109 00110 /* Static helper for tiff compression type */ 00111 static l_int32 getTiffCompressedFormat(l_uint16 tiffcomp); 00112 00113 /* Static function for memory I/O */ 00114 static TIFF *fopenTiffMemstream(const char *filename, const char *operation, 00115 l_uint8 **pdata, size_t *pdatasize); 00116 00117 /* This structure defines a transform to be performed on a TIFF image 00118 * (note that the same transformation can be represented in 00119 * several different ways using this structure since 00120 * vflip + hflip + counterclockwise == clockwise). */ 00121 struct tiff_transform { 00122 int vflip; /* if non-zero, image needs a vertical fip */ 00123 int hflip; /* if non-zero, image needs a horizontal flip */ 00124 int rotate; /* -1 -> counterclockwise 90-degree rotation, 00125 0 -> no rotation 00126 1 -> clockwise 90-degree rotation */ 00127 }; 00128 00129 /* This describes the transformations needed for a given orientation 00130 * tag. The tag values start at 1, so you need to subtract 1 to get a 00131 * valid index into this array. */ 00132 static struct tiff_transform tiff_orientation_transforms[] = { 00133 {0, 0, 0}, 00134 {0, 1, 0}, 00135 {1, 1, 0}, 00136 {1, 0, 0}, 00137 {0, 1, -1}, 00138 {0, 0, 1}, 00139 {0, 1, 1}, 00140 {0, 0, -1} 00141 }; 00142 00143 00144 00145 /*--------------------------------------------------------------* 00146 * Reading from file * 00147 *--------------------------------------------------------------*/ 00148 /*! 00149 * pixReadTiff() 00150 * 00151 * Input: filename 00152 * page number (0 based) 00153 * Return: pix, or null on error 00154 * 00155 * Notes: 00156 * (1) This is a version of pixRead(), specialized for tiff 00157 * files, that allows specification of the page to be returned 00158 */ 00159 PIX * 00160 pixReadTiff(const char *filename, 00161 l_int32 n) 00162 { 00163 FILE *fp; 00164 PIX *pix; 00165 00166 PROCNAME("pixReadTiff"); 00167 00168 if (!filename) 00169 return (PIX *)ERROR_PTR("filename not defined", procName, NULL); 00170 00171 if ((fp = fopenReadStream(filename)) == NULL) 00172 return (PIX *)ERROR_PTR("image file not found", procName, NULL); 00173 if ((pix = pixReadStreamTiff(fp, n)) == NULL) { 00174 fclose(fp); 00175 return (PIX *)ERROR_PTR("pix not read", procName, NULL); 00176 } 00177 fclose(fp); 00178 00179 return pix; 00180 } 00181 00182 00183 /*--------------------------------------------------------------* 00184 * Reading from stream * 00185 *--------------------------------------------------------------*/ 00186 /*! 00187 * pixReadStreamTiff() 00188 * 00189 * Input: stream 00190 * n (page number: 0 based) 00191 * Return: pix, or null on error (e.g., if the page number is invalid) 00192 */ 00193 PIX * 00194 pixReadStreamTiff(FILE *fp, 00195 l_int32 n) 00196 { 00197 l_int32 i, pagefound; 00198 PIX *pix; 00199 TIFF *tif; 00200 00201 PROCNAME("pixReadStreamTiff"); 00202 00203 if (!fp) 00204 return (PIX *)ERROR_PTR("stream not defined", procName, NULL); 00205 00206 if ((tif = fopenTiff(fp, "rb")) == NULL) 00207 return (PIX *)ERROR_PTR("tif not opened", procName, NULL); 00208 00209 pagefound = FALSE; 00210 pix = NULL; 00211 for (i = 0; i < MAX_PAGES_IN_TIFF_FILE; i++) { 00212 if (i == n) { 00213 pagefound = TRUE; 00214 if ((pix = pixReadFromTiffStream(tif)) == NULL) { 00215 TIFFCleanup(tif); 00216 return (PIX *)ERROR_PTR("pix not read", procName, NULL); 00217 } 00218 break; 00219 } 00220 if (TIFFReadDirectory(tif) == 0) 00221 break; 00222 } 00223 00224 if (pagefound == FALSE) { 00225 L_WARNING_INT("tiff page %d not found", procName, n); 00226 TIFFCleanup(tif); 00227 return NULL; 00228 } 00229 00230 TIFFCleanup(tif); 00231 return pix; 00232 } 00233 00234 00235 /*! 00236 * pixReadFromTiffStream() 00237 * 00238 * Input: stream 00239 * Return: pix, or null on error 00240 * 00241 * Quoting the libtiff documenation at http://libtiff.maptools.org/libtiff.html 00242 * 00243 * libtiff provides a high-level interface for reading image data from 00244 * a TIFF file. This interface handles the details of data 00245 * organization and format for a wide variety of TIFF files; at least 00246 * the large majority of those files that one would normally 00247 * encounter. Image data is, by default, returned as ABGR pixels 00248 * packed into 32-bit words (8 bits per sample). Rectangular rasters 00249 * can be read or data can be intercepted at an intermediate level and 00250 * packed into memory in a format more suitable to the 00251 * application. The library handles all the details of the format of 00252 * data stored on disk and, in most cases, if any colorspace 00253 * conversions are required: bilevel to RGB, greyscale to RGB, CMYK to 00254 * RGB, YCbCr to RGB, 16-bit samples to 8-bit samples, 00255 * associated/unassociated alpha, etc. 00256 */ 00257 static PIX * 00258 pixReadFromTiffStream(TIFF *tif) 00259 { 00260 l_uint8 *linebuf, *data; 00261 l_uint16 spp, bps, bpp, tiffbpl, photometry, tiffcomp, orientation; 00262 l_uint16 *redmap, *greenmap, *bluemap; 00263 l_int32 d, wpl, bpl, comptype, i, j, k, ncolors, rval, gval, bval; 00264 l_int32 xres, yres; 00265 l_uint32 w, h, tiffword; 00266 l_uint32 *line, *ppixel, *tiffdata; 00267 PIX *pix; 00268 PIXCMAP *cmap; 00269 00270 PROCNAME("pixReadFromTiffStream"); 00271 00272 if (!tif) 00273 return (PIX *)ERROR_PTR("tif not defined", procName, NULL); 00274 00275 /* Use default fields for bps and spp */ 00276 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps); 00277 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); 00278 bpp = bps * spp; 00279 if (bpp > 32) 00280 return (PIX *)ERROR_PTR("can't handle bpp > 32", procName, NULL); 00281 if (spp == 1) 00282 d = bps; 00283 else if (spp == 3 || spp == 4) 00284 d = 32; 00285 else 00286 return (PIX *)ERROR_PTR("spp not in set {1,3,4}", procName, NULL); 00287 00288 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); 00289 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 00290 tiffbpl = TIFFScanlineSize(tif); 00291 00292 if ((pix = pixCreate(w, h, d)) == NULL) 00293 return (PIX *)ERROR_PTR("pix not made", procName, NULL); 00294 data = (l_uint8 *)pixGetData(pix); 00295 wpl = pixGetWpl(pix); 00296 bpl = 4 * wpl; 00297 00298 /* Read the data */ 00299 if (spp == 1) { 00300 if ((linebuf = (l_uint8 *)CALLOC(tiffbpl + 1, sizeof(l_uint8))) == NULL) 00301 return (PIX *)ERROR_PTR("calloc fail for linebuf", procName, NULL); 00302 00303 for (i = 0 ; i < h ; i++) { 00304 if (TIFFReadScanline(tif, linebuf, i, 0) < 0) { 00305 FREE(linebuf); 00306 pixDestroy(&pix); 00307 return (PIX *)ERROR_PTR("line read fail", procName, NULL); 00308 } 00309 memcpy((char *)data, (char *)linebuf, tiffbpl); 00310 data += bpl; 00311 } 00312 if (bps <= 8) 00313 pixEndianByteSwap(pix); 00314 else /* bps == 16 */ 00315 pixEndianTwoByteSwap(pix); 00316 FREE(linebuf); 00317 } 00318 else { /* rgb */ 00319 if ((tiffdata = (l_uint32 *)CALLOC(w * h, sizeof(l_uint32))) == NULL) { 00320 pixDestroy(&pix); 00321 return (PIX *)ERROR_PTR("calloc fail for tiffdata", procName, NULL); 00322 } 00323 if (!TIFFReadRGBAImageOriented(tif, w, h, (uint32 *)tiffdata, 00324 ORIENTATION_TOPLEFT, 0)) { 00325 FREE(tiffdata); 00326 pixDestroy(&pix); 00327 return (PIX *)ERROR_PTR("failed to read tiffdata", procName, NULL); 00328 } 00329 00330 line = pixGetData(pix); 00331 for (i = 0 ; i < h ; i++, line += wpl) { 00332 for (j = 0, k = 0, ppixel = line; j < w; j++) { 00333 /* TIFFGet* are macros */ 00334 tiffword = tiffdata[i * w + j]; 00335 rval = TIFFGetR(tiffword); 00336 gval = TIFFGetG(tiffword); 00337 bval = TIFFGetB(tiffword); 00338 composeRGBPixel(rval, gval, bval, ppixel); 00339 ppixel++; 00340 } 00341 } 00342 FREE(tiffdata); 00343 } 00344 00345 if (getTiffStreamResolution(tif, &xres, &yres) == 0) { 00346 pixSetXRes(pix, xres); 00347 pixSetYRes(pix, yres); 00348 } 00349 00350 /* Find and save the compression type */ 00351 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp); 00352 comptype = getTiffCompressedFormat(tiffcomp); 00353 pixSetInputFormat(pix, comptype); 00354 00355 if (TIFFGetField(tif, TIFFTAG_COLORMAP, &redmap, &greenmap, &bluemap)) { 00356 /* Save the colormap as a pix cmap. Because the 00357 * tiff colormap components are 16 bit unsigned, 00358 * and go from black (0) to white (0xffff), the 00359 * the pix cmap takes the most significant byte. */ 00360 if ((cmap = pixcmapCreate(bps)) == NULL) { 00361 pixDestroy(&pix); 00362 return (PIX *)ERROR_PTR("cmap not made", procName, NULL); 00363 } 00364 ncolors = 1 << bps; 00365 for (i = 0; i < ncolors; i++) 00366 pixcmapAddColor(cmap, redmap[i] >> 8, greenmap[i] >> 8, 00367 bluemap[i] >> 8); 00368 pixSetColormap(pix, cmap); 00369 } 00370 else { /* No colormap: check photometry and invert if necessary */ 00371 if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometry)) { 00372 /* Guess default photometry setting. Assume min_is_white 00373 * if compressed 1 bpp; min_is_black otherwise. */ 00374 if (tiffcomp == COMPRESSION_CCITTFAX3 || 00375 tiffcomp == COMPRESSION_CCITTFAX4 || 00376 tiffcomp == COMPRESSION_CCITTRLE || 00377 tiffcomp == COMPRESSION_CCITTRLEW) { 00378 photometry = PHOTOMETRIC_MINISWHITE; 00379 } 00380 else 00381 photometry = PHOTOMETRIC_MINISBLACK; 00382 } 00383 if ((d == 1 && photometry == PHOTOMETRIC_MINISBLACK) || 00384 (d == 8 && photometry == PHOTOMETRIC_MINISWHITE)) 00385 pixInvert(pix, pix); 00386 } 00387 00388 if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation)) { 00389 if (orientation >= 1 && orientation <= 8) { 00390 struct tiff_transform *transform = 00391 &tiff_orientation_transforms[orientation - 1]; 00392 if (transform->vflip) pixFlipTB(pix, pix); 00393 if (transform->hflip) pixFlipLR(pix, pix); 00394 if (transform->rotate) { 00395 PIX *oldpix = pix; 00396 pix = pixRotate90(oldpix, transform->rotate); 00397 pixDestroy(&oldpix); 00398 } 00399 } 00400 } 00401 00402 return pix; 00403 } 00404 00405 00406 /*--------------------------------------------------------------* 00407 * Writing to file * 00408 *--------------------------------------------------------------*/ 00409 /*! 00410 * pixWriteTiff() 00411 * 00412 * Input: filename (to write to) 00413 * pix 00414 * comptype (IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS, 00415 * IFF_TIFF_G3, IFF_TIFF_G4, 00416 * IFF_TIFF_LZW, IFF_TIFF_ZIP) 00417 * modestring ("a" or "w") 00418 * Return: 0 if OK, 1 on error 00419 * 00420 * Notes: 00421 * (1) For multi-page tiff, write the first pix with mode "w" and 00422 * all subsequent pix with mode "a". 00423 */ 00424 l_int32 00425 pixWriteTiff(const char *filename, 00426 PIX *pix, 00427 l_int32 comptype, 00428 const char *modestring) 00429 { 00430 return pixWriteTiffCustom(filename, pix, comptype, modestring, 00431 NULL, NULL, NULL, NULL); 00432 } 00433 00434 00435 /*! 00436 * pixWriteTiffCustom() 00437 * 00438 * Input: filename (to write to) 00439 * pix 00440 * comptype (IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS, 00441 * IFF_TIFF_G3, IFF_TIFF_G4) 00442 * IFF_TIFF_LZW, IFF_TIFF_ZIP) 00443 * modestring ("a" or "w") 00444 * natags (<optional> NUMA of custom tiff tags) 00445 * savals (<optional> SARRAY of values) 00446 * satypes (<optional> SARRAY of types) 00447 * nasizes (<optional> NUMA of sizes) 00448 * Return: 0 if OK, 1 on error 00449 * 00450 * Usage: 00451 * (1) This writes a page image to a tiff file, with optional 00452 * extra tags defined in tiff.h 00453 * (2) For multi-page tiff, write the first pix with mode "w" and 00454 * all subsequent pix with mode "a". 00455 * (3) For the custom tiff tags: 00456 * (a) The three arrays {natags, savals, satypes} must all be 00457 * either NULL or defined and of equal size. 00458 * (b) If they are defined, the tags are an array of integers, 00459 * the vals are an array of values in string format, and 00460 * the types are an array of types in string format. 00461 * (c) All valid tags are definined in tiff.h. 00462 * (d) The types allowed are the set of strings: 00463 * "char*" 00464 * "l_uint8*" 00465 * "l_uint16" 00466 * "l_uint32" 00467 * "l_int32" 00468 * "l_float64" 00469 * "l_uint16-l_uint16" (note the dash; use it between the 00470 * two l_uint16 vals in the val string) 00471 * Of these, "char*" and "l_uint16" are the most commonly used. 00472 * (e) The last array, nasizes, is also optional. It is for 00473 * tags that take an array of bytes for a value, a number of 00474 * elements in the array, and a type that is either "char*" 00475 * or "l_uint8*" (probably either will work). 00476 * Use NULL if there are no such tags. 00477 * (f) VERY IMPORTANT: if there are any tags that require the 00478 * extra size value, stored in nasizes, they must be 00479 * written first! 00480 */ 00481 l_int32 00482 pixWriteTiffCustom(const char *filename, 00483 PIX *pix, 00484 l_int32 comptype, 00485 const char *modestring, 00486 NUMA *natags, 00487 SARRAY *savals, 00488 SARRAY *satypes, 00489 NUMA *nasizes) 00490 { 00491 l_int32 ret; 00492 TIFF *tif; 00493 00494 PROCNAME("pixWriteTiffCustom"); 00495 00496 if (!filename) 00497 return ERROR_INT("filename not defined", procName, 1); 00498 if (!pix) 00499 return ERROR_INT("pix not defined", procName, 1); 00500 00501 if ((tif = openTiff(filename, modestring)) == NULL) 00502 return ERROR_INT("tif not opened", procName, 1); 00503 ret = pixWriteToTiffStream(tif, pix, comptype, natags, savals, 00504 satypes, nasizes); 00505 TIFFClose(tif); 00506 00507 return ret; 00508 } 00509 00510 00511 /*--------------------------------------------------------------* 00512 * Writing to stream * 00513 *--------------------------------------------------------------*/ 00514 /*! 00515 * pixWriteStreamTiff() 00516 * 00517 * Input: stream (opened for append or write) 00518 * pix 00519 * comptype (IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS, 00520 * IFF_TIFF_G3, IFF_TIFF_G4, 00521 * IFF_TIFF_LZW, IFF_TIFF_ZIP) 00522 * Return: 0 if OK, 1 on error 00523 * 00524 * Notes: 00525 * (1) For images with bpp > 1, this resets the comptype, if 00526 * necessary, to write uncompressed data. 00527 * (2) G3 and G4 are only defined for 1 bpp. 00528 * (3) We only allow PACKBITS for bpp = 1, because for bpp > 1 00529 * it typically expands images that are not synthetically generated. 00530 * (4) G4 compression is typically about twice as good as G3. 00531 * G4 is excellent for binary compression of text/line-art, 00532 * but terrible for halftones and dithered patterns. (In 00533 * fact, G4 on halftones can give a file that is larger 00534 * than uncompressed!) If a binary image has dithered 00535 * regions, it is usually better to compress with png. 00536 */ 00537 l_int32 00538 pixWriteStreamTiff(FILE *fp, 00539 PIX *pix, 00540 l_int32 comptype) 00541 { 00542 TIFF *tif; 00543 00544 PROCNAME("pixWriteStreamTiff"); 00545 00546 if (!fp) 00547 return ERROR_INT("stream not defined", procName, 1 ); 00548 if (!pix) 00549 return ERROR_INT("pix not defined", procName, 1 ); 00550 00551 if (pixGetDepth(pix) != 1 && comptype != IFF_TIFF && 00552 comptype != IFF_TIFF_LZW && comptype != IFF_TIFF_ZIP) { 00553 L_WARNING("invalid compression type for image with bpp > 1", procName); 00554 comptype = IFF_TIFF_ZIP; 00555 } 00556 00557 if ((tif = fopenTiff(fp, "wb")) == NULL) 00558 return ERROR_INT("tif not opened", procName, 1); 00559 00560 if (pixWriteToTiffStream(tif, pix, comptype, NULL, NULL, NULL, NULL)) { 00561 TIFFCleanup(tif); 00562 return ERROR_INT("tif write error", procName, 1); 00563 } 00564 00565 TIFFCleanup(tif); 00566 return 0; 00567 } 00568 00569 00570 /*! 00571 * pixWriteToTiffStream() 00572 * 00573 * Input: tif (data structure, opened to a file) 00574 * pix 00575 * comptype (IFF_TIFF: for any image; no compression 00576 * IFF_TIFF_RLE, IFF_TIFF_PACKBITS: for 1 bpp only 00577 * IFF_TIFF_G4 and IFF_TIFF_G3: for 1 bpp only 00578 * IFF_TIFF_LZW, IFF_TIFF_ZIP: for any image 00579 * natags (<optional> NUMA of custom tiff tags) 00580 * savals (<optional> SARRAY of values) 00581 * satypes (<optional> SARRAY of types) 00582 * nasizes (<optional> NUMA of sizes) 00583 * Return: 0 if OK, 1 on error 00584 * 00585 * Notes: 00586 * (1) This static function should only be called through higher 00587 * level functions in this file; namely, pixWriteTiffCustom(), 00588 * pixWriteTiff(), pixWriteStreamTiff(), pixWriteMemTiff() 00589 * and pixWriteMemTiffCustom(). 00590 * (2) We only allow PACKBITS for bpp = 1, because for bpp > 1 00591 * it typically expands images that are not synthetically generated. 00592 * (3) See pixWriteTiffCustom() for details on how to use 00593 * the last four parameters for customized tiff tags. 00594 * (4) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16 00595 * and 32. However, it is possible, and in some cases desirable, 00596 * to write out a tiff file using an rgb pix that has 24 bpp. 00597 * This can be created by appending the raster data for a 24 bpp 00598 * image (with proper scanline padding) directly to a 24 bpp 00599 * pix that was created without a data array. See note in 00600 * pixWriteStreamPng() for an example. 00601 */ 00602 static l_int32 00603 pixWriteToTiffStream(TIFF *tif, 00604 PIX *pix, 00605 l_int32 comptype, 00606 NUMA *natags, 00607 SARRAY *savals, 00608 SARRAY *satypes, 00609 NUMA *nasizes) 00610 { 00611 l_uint8 *linebuf, *data; 00612 l_uint16 redmap[256], greenmap[256], bluemap[256]; 00613 l_int32 w, h, d, i, j, k, wpl, bpl, tiffbpl, ncolors, cmapsize; 00614 l_int32 *rmap, *gmap, *bmap; 00615 l_int32 xres, yres; 00616 l_uint32 *line, *ppixel; 00617 PIX *pixt; 00618 PIXCMAP *cmap; 00619 char *text; 00620 00621 PROCNAME("pixWriteToTiffStream"); 00622 00623 if (!tif) 00624 return ERROR_INT("tif stream not defined", procName, 1); 00625 if (!pix) 00626 return ERROR_INT( "pix not defined", procName, 1 ); 00627 00628 pixGetDimensions(pix, &w, &h, &d); 00629 xres = pixGetXRes(pix); 00630 yres = pixGetYRes(pix); 00631 if (xres == 0) xres = DEFAULT_RESOLUTION; 00632 if (yres == 0) yres = DEFAULT_RESOLUTION; 00633 00634 /* ------------------ Write out the header ------------- */ 00635 TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (l_uint32)RESUNIT_INCH); 00636 TIFFSetField(tif, TIFFTAG_XRESOLUTION, (l_float64)xres); 00637 TIFFSetField(tif, TIFFTAG_YRESOLUTION, (l_float64)yres); 00638 00639 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (l_uint32)w); 00640 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (l_uint32)h); 00641 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); 00642 00643 if ((text = pixGetText(pix)) != NULL) 00644 TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, text); 00645 00646 if (d == 1) 00647 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); 00648 else if (d == 32 || d == 24) { 00649 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); 00650 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 00651 (l_uint16)8, (l_uint16)8, (l_uint16)8); 00652 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)3); 00653 } 00654 else if ((cmap = pixGetColormap(pix)) == NULL) 00655 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); 00656 else { /* Save colormap in the tiff; not more than 256 colors */ 00657 pixcmapToArrays(cmap, &rmap, &gmap, &bmap); 00658 ncolors = pixcmapGetCount(cmap); 00659 ncolors = L_MIN(256, ncolors); /* max 256 */ 00660 cmapsize = 1 << d; 00661 cmapsize = L_MIN(256, cmapsize); /* power of 2; max 256 */ 00662 if (ncolors > cmapsize) { 00663 L_WARNING("too many colors in cmap for tiff; truncating", procName); 00664 ncolors = cmapsize; 00665 } 00666 for (i = 0; i < ncolors; i++) { 00667 redmap[i] = (rmap[i] << 8) | rmap[i]; 00668 greenmap[i] = (gmap[i] << 8) | gmap[i]; 00669 bluemap[i] = (bmap[i] << 8) | bmap[i]; 00670 } 00671 for (i = ncolors; i < cmapsize; i++) /* init, even though not used */ 00672 redmap[i] = greenmap[i] = bluemap[i] = 0; 00673 FREE(rmap); 00674 FREE(gmap); 00675 FREE(bmap); 00676 00677 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE); 00678 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)1); 00679 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (l_uint16)d); 00680 TIFFSetField(tif, TIFFTAG_COLORMAP, redmap, greenmap, bluemap); 00681 } 00682 00683 if (d != 24 && d != 32) { 00684 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (l_uint16)d); 00685 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)1); 00686 } 00687 00688 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); 00689 if (comptype == IFF_TIFF) /* no compression */ 00690 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); 00691 else if (comptype == IFF_TIFF_G4) 00692 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); 00693 else if (comptype == IFF_TIFF_G3) 00694 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3); 00695 else if (comptype == IFF_TIFF_RLE) 00696 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTRLE); 00697 else if (comptype == IFF_TIFF_PACKBITS) 00698 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); 00699 else if (comptype == IFF_TIFF_LZW) 00700 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); 00701 else if (comptype == IFF_TIFF_ZIP) 00702 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE); 00703 else { 00704 L_WARNING("unknown tiff compression; using none", procName); 00705 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); 00706 } 00707 00708 /* This is a no-op if arrays are NULL */ 00709 writeCustomTiffTags(tif, natags, savals, satypes, nasizes); 00710 00711 /* ------------- Write out the image data ------------- */ 00712 tiffbpl = TIFFScanlineSize(tif); 00713 wpl = pixGetWpl(pix); 00714 bpl = 4 * wpl; 00715 if (tiffbpl > bpl) 00716 fprintf(stderr, "Big trouble: tiffbpl = %d, bpl = %d\n", tiffbpl, bpl); 00717 if ((linebuf = (l_uint8 *)CALLOC(1, bpl)) == NULL) 00718 return ERROR_INT("calloc fail for linebuf", procName, 1); 00719 00720 /* Use single strip for image */ 00721 TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, h); 00722 00723 if (d != 24 && d != 32) { 00724 if (d == 16) 00725 pixt = pixEndianTwoByteSwapNew(pix); 00726 else 00727 pixt = pixEndianByteSwapNew(pix); 00728 data = (l_uint8 *)pixGetData(pixt); 00729 for (i = 0; i < h; i++, data += bpl) { 00730 memcpy((char *)linebuf, (char *)data, tiffbpl); 00731 if (TIFFWriteScanline(tif, linebuf, i, 0) < 0) 00732 break; 00733 } 00734 pixDestroy(&pixt); 00735 } 00736 else if (d == 24) { /* See note 4 above: special case of 24 bpp rgb */ 00737 for (i = 0; i < h; i++) { 00738 line = pixGetData(pix) + i * wpl; 00739 if (TIFFWriteScanline(tif, (l_uint8 *)line, i, 0) < 0) 00740 break; 00741 } 00742 } 00743 else { /* standard 32 bpp rgb */ 00744 for (i = 0; i < h; i++) { 00745 line = pixGetData(pix) + i * wpl; 00746 for (j = 0, k = 0, ppixel = line; j < w; j++) { 00747 linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_RED); 00748 linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN); 00749 linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE); 00750 ppixel++; 00751 } 00752 if (TIFFWriteScanline(tif, linebuf, i, 0) < 0) 00753 break; 00754 } 00755 } 00756 00757 /* TIFFWriteDirectory(tif); */ 00758 FREE(linebuf); 00759 00760 return 0; 00761 } 00762 00763 00764 /*! 00765 * writeCustomTiffTags() 00766 * 00767 * Input: tif 00768 * natags (<optional> NUMA of custom tiff tags) 00769 * savals (<optional> SARRAY of values) 00770 * satypes (<optional> SARRAY of types) 00771 * nasizes (<optional> NUMA of sizes) 00772 * Return: 0 if OK, 1 on error 00773 * 00774 * Notes: 00775 * (1) This static function should be called indirectly through 00776 * higher level functions, such as pixWriteTiffCustom(), 00777 * which call pixWriteToTiffStream(). See details in 00778 * pixWriteTiffCustom() for using the 4 input arrays. 00779 * (2) This is a no-op if the first 3 arrays are all NULL. 00780 * (3) Otherwise, the first 3 arrays must be defined and all 00781 * of equal size. 00782 * (4) The fourth array is always optional. 00783 * (5) The most commonly used types are "char*" and "u_int16". 00784 * See tiff.h for a full listing of the tiff tags. 00785 * Note that many of these tags, in particular the bit tags, 00786 * are intended to be private, and cannot be set by this function. 00787 * Examples are the STRIPOFFSETS and STRIPBYTECOUNTS tags, 00788 * which are bit tags that are automatically set in the header, 00789 * and can be extracted using tiffdump. 00790 */ 00791 static l_int32 00792 writeCustomTiffTags(TIFF *tif, 00793 NUMA *natags, 00794 SARRAY *savals, 00795 SARRAY *satypes, 00796 NUMA *nasizes) 00797 { 00798 char *sval, *type; 00799 l_int32 i, n, ns, size, tagval, val; 00800 l_float64 dval; 00801 l_uint32 uval, uval2; 00802 00803 PROCNAME("writeCustomTiffTags"); 00804 00805 if (!tif) 00806 return ERROR_INT("tif stream not defined", procName, 1); 00807 if (!natags && !savals && !satypes) 00808 return 0; 00809 if (!natags || !savals || !satypes) 00810 return ERROR_INT("not all arrays defined", procName, 1); 00811 n = numaGetCount(natags); 00812 if ((sarrayGetCount(savals) != n) || (sarrayGetCount(satypes) != n)) 00813 return ERROR_INT("not all sa the same size", procName, 1); 00814 00815 /* The sized arrays (4 args to TIFFSetField) are written first */ 00816 if (nasizes) { 00817 ns = numaGetCount(nasizes); 00818 if (ns > n) 00819 return ERROR_INT("too many 4-arg tag calls", procName, 1); 00820 for (i = 0; i < ns; i++) { 00821 numaGetIValue(natags, i, &tagval); 00822 sval = sarrayGetString(savals, i, 0); 00823 type = sarrayGetString(satypes, i, 0); 00824 numaGetIValue(nasizes, i, &size); 00825 if (strcmp(type, "char*") && strcmp(type, "l_uint8*")) 00826 L_WARNING("array type not char* or l_uint8*; ignore", procName); 00827 TIFFSetField(tif, tagval, size, sval); 00828 } 00829 } 00830 else 00831 ns = 0; 00832 00833 /* The typical tags (3 args to TIFFSetField) are now written */ 00834 for (i = ns; i < n; i++) { 00835 numaGetIValue(natags, i, &tagval); 00836 sval = sarrayGetString(savals, i, 0); 00837 type = sarrayGetString(satypes, i, 0); 00838 if (!strcmp(type, "char*")) { 00839 TIFFSetField(tif, tagval, sval); 00840 } 00841 else if (!strcmp(type, "l_uint16")) { 00842 if (sscanf(sval, "%u", &uval) == 1) { 00843 TIFFSetField(tif, tagval, (l_uint16)uval); 00844 } 00845 else { 00846 fprintf(stderr, "val %s not of type %s\n", sval, type); 00847 return ERROR_INT("custom tag(s) not written", procName, 1); 00848 } 00849 } 00850 else if (!strcmp(type, "l_uint32")) { 00851 if (sscanf(sval, "%u", &uval) == 1) { 00852 TIFFSetField(tif, tagval, uval); 00853 } 00854 else { 00855 fprintf(stderr, "val %s not of type %s\n", sval, type); 00856 return ERROR_INT("custom tag(s) not written", procName, 1); 00857 } 00858 } 00859 else if (!strcmp(type, "l_int32")) { 00860 if (sscanf(sval, "%d", &val) == 1) { 00861 TIFFSetField(tif, tagval, val); 00862 } 00863 else { 00864 fprintf(stderr, "val %s not of type %s\n", sval, type); 00865 return ERROR_INT("custom tag(s) not written", procName, 1); 00866 } 00867 } 00868 else if (!strcmp(type, "l_float64")) { 00869 if (sscanf(sval, "%lf", &dval) == 1) { 00870 TIFFSetField(tif, tagval, dval); 00871 } 00872 else { 00873 fprintf(stderr, "val %s not of type %s\n", sval, type); 00874 return ERROR_INT("custom tag(s) not written", procName, 1); 00875 } 00876 } 00877 else if (!strcmp(type, "l_uint16-l_uint16")) { 00878 if (sscanf(sval, "%u-%u", &uval, &uval2) == 2) { 00879 TIFFSetField(tif, tagval, (l_uint16)uval, (l_uint16)uval2); 00880 } 00881 else { 00882 fprintf(stderr, "val %s not of type %s\n", sval, type); 00883 return ERROR_INT("custom tag(s) not written", procName, 1); 00884 } 00885 } 00886 else 00887 return ERROR_INT("unknown type; tag(s) not written", procName, 1); 00888 } 00889 return 0; 00890 } 00891 00892 00893 /*--------------------------------------------------------------* 00894 * Reading and writing multipage tiff * 00895 *--------------------------------------------------------------*/ 00896 /* 00897 * pixaReadMultipageTiff() 00898 * 00899 * Input: filename (input tiff file) 00900 * Return: pixa (of page images), or null on error 00901 */ 00902 PIXA * 00903 pixaReadMultipageTiff(const char *filename) 00904 { 00905 l_int32 i, npages; 00906 FILE *fp; 00907 PIX *pix; 00908 PIXA *pixa; 00909 00910 PROCNAME("pixaReadMultipageTiff"); 00911 00912 if (!filename) 00913 return (PIXA *)ERROR_PTR("filename not defined", procName, NULL); 00914 00915 if ((fp = fopenReadStream(filename)) == NULL) 00916 return (PIXA *)ERROR_PTR("stream not opened", procName, NULL); 00917 if (fileFormatIsTiff(fp)) { 00918 tiffGetCount(fp, &npages); 00919 L_INFO_INT(" Tiff: %d pages\n", procName, npages); 00920 } 00921 else 00922 return (PIXA *)ERROR_PTR("file not tiff", procName, NULL); 00923 fclose(fp); 00924 00925 pixa = pixaCreate(npages); 00926 for (i = 0; i < npages; i++) { 00927 pix = pixReadTiff(filename, i); 00928 if (!pix) { 00929 L_WARNING_INT("pix not read for page %d", procName, i); 00930 continue; 00931 } 00932 pixaAddPix(pixa, pix, L_INSERT); 00933 } 00934 00935 return pixa; 00936 } 00937 00938 00939 /* 00940 * writeMultipageTiff() 00941 * 00942 * Input: dirin (input directory) 00943 * substr (<optional> substring filter on filenames; can be NULL) 00944 * fileout (output ps file) 00945 * Return: 0 if OK, 1 on error 00946 * 00947 * Notes: 00948 * (1) This writes a set of image files in a directory out 00949 * as a multipage tiff file. The images can be in any 00950 * initial file format. 00951 * (2) Images with a colormap have the colormap removed before 00952 * re-encoding as tiff. 00953 * (3) All images are encoded losslessly. Those with 1 bpp are 00954 * encoded 'g4'. The rest are encoded as 'zip' (flate encoding). 00955 * Because it is lossless, this is an expensive method for 00956 * saving most rgb images. 00957 */ 00958 l_int32 00959 writeMultipageTiff(const char *dirin, 00960 const char *substr, 00961 const char *fileout) 00962 { 00963 SARRAY *sa; 00964 00965 PROCNAME("writeMultipageTiff"); 00966 00967 if (!dirin) 00968 return ERROR_INT("dirin not defined", procName, 1); 00969 if (!fileout) 00970 return ERROR_INT("fileout not defined", procName, 1); 00971 00972 /* Get all filtered and sorted full pathnames. */ 00973 sa = getSortedPathnamesInDirectory(dirin, substr, 0, 0); 00974 00975 /* Generate the tiff file */ 00976 writeMultipageTiffSA(sa, fileout); 00977 sarrayDestroy(&sa); 00978 return 0; 00979 } 00980 00981 00982 /* 00983 * writeMultipageTiffSA() 00984 * 00985 * Input: sarray (of full path names) 00986 * fileout (output ps file) 00987 * Return: 0 if OK, 1 on error 00988 * 00989 * Notes: 00990 * (1) See writeMultipageTiff() 00991 */ 00992 l_int32 00993 writeMultipageTiffSA(SARRAY *sa, 00994 const char *fileout) 00995 { 00996 char *fname; 00997 const char *op; 00998 l_int32 i, nfiles, firstfile, format; 00999 PIX *pix, *pixt; 01000 01001 PROCNAME("writeMultipageTiffSA"); 01002 01003 if (!sa) 01004 return ERROR_INT("sa not defined", procName, 1); 01005 if (!fileout) 01006 return ERROR_INT("fileout not defined", procName, 1); 01007 01008 nfiles = sarrayGetCount(sa); 01009 firstfile = TRUE; 01010 for (i = 0; i < nfiles; i++) { 01011 op = (firstfile) ? "w" : "a"; 01012 fname = sarrayGetString(sa, i, L_NOCOPY); 01013 findFileFormat(fname, &format); 01014 if (format == IFF_UNKNOWN) { 01015 L_INFO_STRING("format of %s not known", procName, fname); 01016 continue; 01017 } 01018 01019 if ((pix = pixRead(fname)) == NULL) { 01020 L_WARNING_STRING("pix not made for file: %s", procName, fname); 01021 continue; 01022 } 01023 if (pixGetDepth(pix) == 1) 01024 pixWriteTiff(fileout, pix, IFF_TIFF_G4, op); 01025 else { 01026 if (pixGetColormap(pix)) 01027 pixt = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC); 01028 else 01029 pixt = pixClone(pix); 01030 pixWriteTiff(fileout, pixt, IFF_TIFF_ZIP, op); 01031 pixDestroy(&pixt); 01032 } 01033 firstfile = FALSE; 01034 pixDestroy(&pix); 01035 } 01036 01037 return 0; 01038 } 01039 01040 01041 /*--------------------------------------------------------------* 01042 * Print info to stream * 01043 *--------------------------------------------------------------*/ 01044 /* 01045 * fprintTiffInfo() 01046 * 01047 * Input: stream (for output of tag data) 01048 * tiffile (input) 01049 * Return: 0 if OK; 1 on error 01050 */ 01051 l_int32 01052 fprintTiffInfo(FILE *fpout, 01053 const char *tiffile) 01054 { 01055 TIFF *tif; 01056 01057 PROCNAME("fprintTiffInfo"); 01058 01059 if (!tiffile) 01060 return ERROR_INT("tiffile not defined", procName, 1); 01061 if (!fpout) 01062 return ERROR_INT("stream out not defined", procName, 1); 01063 01064 if ((tif = openTiff(tiffile, "rb")) == NULL) 01065 return ERROR_INT("tif not open for read", procName, 1); 01066 01067 TIFFPrintDirectory(tif, fpout, 0); 01068 TIFFClose(tif); 01069 01070 return 0; 01071 } 01072 01073 01074 /*--------------------------------------------------------------* 01075 * Get page count * 01076 *--------------------------------------------------------------*/ 01077 /* 01078 * tiffGetCount() 01079 * 01080 * Input: stream (opened for read) 01081 * &n (<return> number of images) 01082 * Return: 0 if OK; 1 on error 01083 */ 01084 l_int32 01085 tiffGetCount(FILE *fp, 01086 l_int32 *pn) 01087 { 01088 l_int32 i; 01089 TIFF *tif; 01090 01091 PROCNAME("tiffGetCount"); 01092 01093 if (!fp) 01094 return ERROR_INT("stream not defined", procName, 1); 01095 if (!pn) 01096 return ERROR_INT("&n not defined", procName, 1); 01097 *pn = 0; 01098 01099 if ((tif = fopenTiff(fp, "rb")) == NULL) 01100 return ERROR_INT("tif not open for read", procName, 1); 01101 01102 for (i = 1; i < MAX_PAGES_IN_TIFF_FILE; i++) { 01103 if (TIFFReadDirectory(tif) == 0) 01104 break; 01105 } 01106 *pn = i; 01107 TIFFCleanup(tif); 01108 return 0; 01109 } 01110 01111 01112 /*--------------------------------------------------------------* 01113 * Get resolution from tif * 01114 *--------------------------------------------------------------*/ 01115 /* 01116 * getTiffResolution() 01117 * 01118 * Input: stream (opened for read) 01119 * &xres, &yres (<return> resolution in ppi) 01120 * Return: 0 if OK; 1 on error 01121 * 01122 * Notes: 01123 * (1) If neither resolution field is set, this is not an error; 01124 * the returned resolution values are 0 (designating 'unknown'). 01125 */ 01126 l_int32 01127 getTiffResolution(FILE *fp, 01128 l_int32 *pxres, 01129 l_int32 *pyres) 01130 { 01131 TIFF *tif; 01132 01133 PROCNAME("getTiffResolution"); 01134 01135 if (!pxres || !pyres) 01136 return ERROR_INT("&xres and &yres not both defined", procName, 1); 01137 *pxres = *pyres = 0; 01138 if (!fp) 01139 return ERROR_INT("stream not opened", procName, 1); 01140 01141 if ((tif = fopenTiff(fp, "rb")) == NULL) 01142 return ERROR_INT("tif not open for read", procName, 1); 01143 getTiffStreamResolution(tif, pxres, pyres); 01144 TIFFCleanup(tif); 01145 return 0; 01146 } 01147 01148 01149 /* 01150 * getTiffStreamResolution() 01151 * 01152 * Input: tiff stream (opened for read) 01153 * &xres, &yres (<return> resolution in ppi) 01154 * Return: 0 if OK; 1 on error 01155 * 01156 * Notes: 01157 * (1) If neither resolution field is set, this is not an error; 01158 * the returned resolution values are 0 (designating 'unknown'). 01159 */ 01160 static l_int32 01161 getTiffStreamResolution(TIFF *tif, 01162 l_int32 *pxres, 01163 l_int32 *pyres) 01164 { 01165 l_uint16 resunit; 01166 l_int32 foundxres, foundyres; 01167 l_float32 fxres, fyres; 01168 01169 PROCNAME("getTiffStreamResolution"); 01170 01171 if (!tif) 01172 return ERROR_INT("tif not opened", procName, 1); 01173 if (!pxres || !pyres) 01174 return ERROR_INT("&xres and &yres not both defined", procName, 1); 01175 *pxres = *pyres = 0; 01176 01177 TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &resunit); 01178 foundxres = TIFFGetField(tif, TIFFTAG_XRESOLUTION, &fxres); 01179 foundyres = TIFFGetField(tif, TIFFTAG_YRESOLUTION, &fyres); 01180 if (!foundxres && !foundyres) return 1; 01181 if (!foundxres && foundyres) 01182 fxres = fyres; 01183 else if (foundxres && !foundyres) 01184 fyres = fxres; 01185 01186 if (resunit == RESUNIT_CENTIMETER) { /* convert to ppi */ 01187 *pxres = (l_int32)(2.54 * fxres + 0.5); 01188 *pyres = (l_int32)(2.54 * fyres + 0.5); 01189 } 01190 else { 01191 *pxres = (l_int32)fxres; 01192 *pyres = (l_int32)fyres; 01193 } 01194 01195 return 0; 01196 } 01197 01198 01199 /*--------------------------------------------------------------* 01200 * Get some tiff header information * 01201 *--------------------------------------------------------------*/ 01202 /*! 01203 * readHeaderTiff() 01204 * 01205 * Input: filename 01206 * n (page image number: 0-based) 01207 * &width (<return>) 01208 * &height (<return>) 01209 * &bps (<return> bits per sample -- 1, 2, 4 or 8) 01210 * &spp (<return>; samples per pixel -- 1 or 3) 01211 * &res (<optional return>; resolution in x dir; NULL to ignore) 01212 * &cmap (<optional return>; colormap exists; input NULL to ignore) 01213 * &format (<optional return>; tiff format; input NULL to ignore) 01214 * Return: 0 if OK, 1 on error 01215 * 01216 * Notes: 01217 * (1) If there is a colormap, cmap is returned as 1; else 0. 01218 * (2) If @n is equal to or greater than the number of images, returns 1. 01219 */ 01220 l_int32 01221 readHeaderTiff(const char *filename, 01222 l_int32 n, 01223 l_int32 *pwidth, 01224 l_int32 *pheight, 01225 l_int32 *pbps, 01226 l_int32 *pspp, 01227 l_int32 *pres, 01228 l_int32 *pcmap, 01229 l_int32 *pformat) 01230 { 01231 l_int32 ret; 01232 FILE *fp; 01233 01234 PROCNAME("readHeaderTiff"); 01235 01236 if (!filename) 01237 return ERROR_INT("filename not defined", procName, 1); 01238 if (!pwidth || !pheight || !pbps || !pspp) 01239 return ERROR_INT("input ptr(s) not all defined", procName, 1); 01240 *pwidth = *pheight = *pbps = *pspp = 0; 01241 if (pres) *pres = 0; 01242 if (pcmap) *pcmap = 0; 01243 01244 if ((fp = fopenReadStream(filename)) == NULL) 01245 return ERROR_INT("image file not found", procName, 1); 01246 ret = freadHeaderTiff(fp, n, pwidth, pheight, pbps, pspp, 01247 pres, pcmap, pformat); 01248 fclose(fp); 01249 return ret; 01250 } 01251 01252 01253 /*! 01254 * freadHeaderTiff() 01255 * 01256 * Input: stream 01257 * n (page image number: 0-based) 01258 * &width (<return>) 01259 * &height (<return>) 01260 * &bps (<return> bits per sample -- 1, 2, 4 or 8) 01261 * &spp (<return>; samples per pixel -- 1 or 3) 01262 * &res (<optional return>; resolution in x dir; NULL to ignore) 01263 * &cmap (<optional return>; colormap exists; input NULL to ignore) 01264 * &format (<optional return>; tiff format; input NULL to ignore) 01265 * Return: 0 if OK, 1 on error 01266 * 01267 * Notes: 01268 * (1) If there is a colormap, cmap is returned as 1; else 0. 01269 * (2) If @n is equal to or greater than the number of images, returns 1. 01270 */ 01271 l_int32 01272 freadHeaderTiff(FILE *fp, 01273 l_int32 n, 01274 l_int32 *pwidth, 01275 l_int32 *pheight, 01276 l_int32 *pbps, 01277 l_int32 *pspp, 01278 l_int32 *pres, 01279 l_int32 *pcmap, 01280 l_int32 *pformat) 01281 { 01282 l_int32 i, ret, format; 01283 TIFF *tif; 01284 01285 PROCNAME("freadHeaderTiff"); 01286 01287 if (!fp) 01288 return ERROR_INT("stream not defined", procName, 1); 01289 if (n < 0) 01290 return ERROR_INT("image index must be >= 0", procName, 1); 01291 if (!pwidth || !pheight || !pbps || !pspp) 01292 return ERROR_INT("input ptr(s) not all defined", procName, 1); 01293 *pwidth = *pheight = *pbps = *pspp = 0; 01294 if (pres) *pres = 0; 01295 if (pcmap) *pcmap = 0; 01296 if (pformat) *pformat = 0; 01297 01298 findFileFormatStream(fp, &format); 01299 if (format != IFF_TIFF && 01300 format != IFF_TIFF_G3 && format != IFF_TIFF_G4 && 01301 format != IFF_TIFF_RLE && format != IFF_TIFF_PACKBITS && 01302 format != IFF_TIFF_LZW && format != IFF_TIFF_ZIP) 01303 return ERROR_INT("file not tiff format", procName, 1); 01304 01305 if ((tif = fopenTiff(fp, "rb")) == NULL) 01306 return ERROR_INT("tif not open for read", procName, 1); 01307 01308 for (i = 0; i < n; i++) { 01309 if (TIFFReadDirectory(tif) == 0) 01310 return ERROR_INT("image n not found in file", procName, 1); 01311 } 01312 01313 ret = tiffReadHeaderTiff(tif, pwidth, pheight, pbps, pspp, 01314 pres, pcmap, pformat); 01315 TIFFCleanup(tif); 01316 return ret; 01317 } 01318 01319 01320 /*! 01321 * readHeaderMemTiff() 01322 * 01323 * Input: cdata (const; tiff-encoded) 01324 * size (size of data) 01325 * n (page image number: 0-based) 01326 * &width (<return>) 01327 * &height (<return>) 01328 * &bps (<return> bits per sample -- 1, 2, 4 or 8) 01329 * &spp (<return>; samples per pixel -- 1 or 3) 01330 * &res (<optional return>; resolution in x dir; NULL to ignore) 01331 * &cmap (<optional return>; colormap exists; input NULL to ignore) 01332 * &format (<optional return>; tiff format; input NULL to ignore) 01333 * Return: 0 if OK, 1 on error 01334 * 01335 * Notes: 01336 * (1) Use TIFFClose(); TIFFCleanup() doesn't free internal memstream. 01337 */ 01338 l_int32 01339 readHeaderMemTiff(const l_uint8 *cdata, 01340 size_t size, 01341 l_int32 n, 01342 l_int32 *pwidth, 01343 l_int32 *pheight, 01344 l_int32 *pbps, 01345 l_int32 *pspp, 01346 l_int32 *pres, 01347 l_int32 *pcmap, 01348 l_int32 *pformat) 01349 { 01350 l_uint8 *data; 01351 l_int32 i, ret; 01352 TIFF *tif; 01353 01354 PROCNAME("readHeaderMemTiff"); 01355 01356 if (!cdata) 01357 return ERROR_INT("cdata not defined", procName, 1); 01358 if (!pwidth || !pheight || !pbps || !pspp) 01359 return ERROR_INT("input ptr(s) not all defined", procName, 1); 01360 *pwidth = *pheight = *pbps = *pspp = 0; 01361 if (pres) *pres = 0; 01362 if (pcmap) *pcmap = 0; 01363 if (pformat) *pformat = 0; 01364 01365 /* Open a tiff stream to memory */ 01366 data = (l_uint8 *)cdata; /* we're really not going to change this */ 01367 if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL) 01368 return ERROR_INT("tiff stream not opened", procName, 1); 01369 01370 for (i = 0; i < n; i++) { 01371 if (TIFFReadDirectory(tif) == 0) { 01372 TIFFClose(tif); 01373 return ERROR_INT("image n not found in file", procName, 1); 01374 } 01375 } 01376 01377 ret = tiffReadHeaderTiff(tif, pwidth, pheight, pbps, pspp, 01378 pres, pcmap, pformat); 01379 TIFFClose(tif); 01380 return ret; 01381 } 01382 01383 01384 /*! 01385 * tiffReadHeaderTiff() 01386 * 01387 * Input: tif 01388 * &width (<return>) 01389 * &height (<return>) 01390 * &bps (<return> bits per sample -- 1, 2, 4 or 8) 01391 * &spp (<return>; samples per pixel -- 1 or 3) 01392 * &res (<optional return>; resolution in x dir; NULL to ignore) 01393 * &cmap (<optional return>; cmap exists; input NULL to ignore) 01394 * &format (<optional return>; tiff format; input NULL to ignore) 01395 * Return: 0 if OK, 1 on error 01396 */ 01397 static l_int32 01398 tiffReadHeaderTiff(TIFF *tif, 01399 l_int32 *pwidth, 01400 l_int32 *pheight, 01401 l_int32 *pbps, 01402 l_int32 *pspp, 01403 l_int32 *pres, 01404 l_int32 *pcmap, 01405 l_int32 *pformat) 01406 { 01407 l_uint16 tiffcomp; 01408 l_uint16 bps, spp; 01409 l_uint16 *rmap, *gmap, *bmap; 01410 l_int32 xres, yres; 01411 l_uint32 w, h; 01412 01413 PROCNAME("tiffReadHeaderTiff"); 01414 01415 if (!tif) 01416 return ERROR_INT("tif not opened", procName, 1); 01417 01418 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); 01419 *pwidth = w; 01420 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 01421 *pheight = h; 01422 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps); 01423 *pbps = bps; 01424 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); 01425 *pspp = spp; 01426 01427 if (pres) { 01428 *pres = 300; /* default ppi */ 01429 if (getTiffStreamResolution(tif, &xres, &yres) == 0) 01430 *pres = (l_int32)xres; 01431 } 01432 01433 if (pcmap) { 01434 *pcmap = 0; 01435 if (TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap)) 01436 *pcmap = 1; 01437 } 01438 01439 if (pformat) { 01440 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp); 01441 *pformat = getTiffCompressedFormat(tiffcomp); 01442 } 01443 return 0; 01444 } 01445 01446 01447 /*! 01448 * findTiffCompression() 01449 * 01450 * Input: stream (must be rewound to BOF) 01451 * &comptype (<return> compression type) 01452 * Return: 0 if OK, 1 on error 01453 * 01454 * Notes: 01455 * (1) The returned compression type is that defined in 01456 * the enum in imageio.h. It is not the tiff flag value. 01457 * (2) The compression type is initialized to IFF_UNKNOWN. 01458 * If it is not one of the specified types, the returned 01459 * type is IFF_TIFF, which indicates no compression. 01460 * (3) When this function is called, the stream must be at BOF. 01461 * If the opened stream is to be used again to read the 01462 * file, it must be rewound to BOF after calling this function. 01463 */ 01464 l_int32 01465 findTiffCompression(FILE *fp, 01466 l_int32 *pcomptype) 01467 { 01468 l_uint16 tiffcomp; 01469 TIFF *tif; 01470 01471 PROCNAME("findTiffCompression"); 01472 01473 if (!pcomptype) 01474 return ERROR_INT("&comptype not defined", procName, 1); 01475 *pcomptype = IFF_UNKNOWN; /* init */ 01476 if (!fp) 01477 return ERROR_INT("stream not defined", procName, 1); 01478 01479 if ((tif = fopenTiff(fp, "rb")) == NULL) 01480 return ERROR_INT("tif not opened", procName, 1); 01481 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp); 01482 *pcomptype = getTiffCompressedFormat(tiffcomp); 01483 TIFFCleanup(tif); 01484 return 0; 01485 } 01486 01487 01488 /*! 01489 * getTiffCompressedFormat() 01490 * 01491 * Input: tiffcomp (defined in tiff.h) 01492 * Return: compression format (defined in imageio.h) 01493 * 01494 * Notes: 01495 * (1) The input must be the actual tiff compression type 01496 * returned by a tiff library call. It should always be 01497 * a valid tiff type. 01498 * (2) The return type is defined in the enum in imageio.h. 01499 */ 01500 static l_int32 01501 getTiffCompressedFormat(l_uint16 tiffcomp) 01502 { 01503 l_int32 comptype; 01504 01505 switch (tiffcomp) 01506 { 01507 case COMPRESSION_CCITTFAX4: 01508 comptype = IFF_TIFF_G4; 01509 break; 01510 case COMPRESSION_CCITTFAX3: 01511 comptype = IFF_TIFF_G3; 01512 break; 01513 case COMPRESSION_CCITTRLE: 01514 comptype = IFF_TIFF_RLE; 01515 break; 01516 case COMPRESSION_PACKBITS: 01517 comptype = IFF_TIFF_PACKBITS; 01518 break; 01519 case COMPRESSION_LZW: 01520 comptype = IFF_TIFF_LZW; 01521 break; 01522 case COMPRESSION_ADOBE_DEFLATE: 01523 comptype = IFF_TIFF_ZIP; 01524 break; 01525 default: 01526 comptype = IFF_TIFF; 01527 break; 01528 } 01529 return comptype; 01530 } 01531 01532 01533 /*--------------------------------------------------------------* 01534 * Extraction of tiff g4 data * 01535 *--------------------------------------------------------------*/ 01536 /*! 01537 * extractG4DataFromFile() 01538 * 01539 * Input: filein 01540 * &data (<return> binary data of ccitt g4 encoded stream) 01541 * &nbytes (<return> size of binary data) 01542 * &w (<return optional> image width) 01543 * &h (<return optional> image height) 01544 * &minisblack (<return optional> boolean) 01545 * Return: 0 if OK, 1 on error 01546 */ 01547 l_int32 01548 extractG4DataFromFile(const char *filein, 01549 l_uint8 **pdata, 01550 size_t *pnbytes, 01551 l_int32 *pw, 01552 l_int32 *ph, 01553 l_int32 *pminisblack) 01554 { 01555 l_uint8 *inarray, *data; 01556 l_uint16 minisblack, comptype; /* accessors require l_uint16 */ 01557 l_int32 istiff; 01558 l_uint32 w, h, rowsperstrip; /* accessors require l_uint32 */ 01559 l_uint32 diroff; 01560 size_t fbytes, nbytes; 01561 FILE *fpin; 01562 TIFF *tif; 01563 01564 PROCNAME("extractG4DataFromFile"); 01565 01566 if (!pdata) 01567 return ERROR_INT("&data not defined", procName, 1); 01568 if (!pnbytes) 01569 return ERROR_INT("&nbytes not defined", procName, 1); 01570 if (!pw && !ph && !pminisblack) 01571 return ERROR_INT("no output data requested", procName, 1); 01572 *pdata = NULL; 01573 *pnbytes = 0; 01574 01575 if ((fpin = fopenReadStream(filein)) == NULL) 01576 return ERROR_INT("stream not opened to file", procName, 1); 01577 istiff = fileFormatIsTiff(fpin); 01578 fclose(fpin); 01579 if (!istiff) 01580 return ERROR_INT("filein not tiff", procName, 1); 01581 01582 if ((inarray = l_binaryRead(filein, &fbytes)) == NULL) 01583 return ERROR_INT("inarray not made", procName, 1); 01584 01585 /* Get metadata about the image */ 01586 if ((tif = openTiff(filein, "rb")) == NULL) 01587 return ERROR_INT("tif not open for read", procName, 1); 01588 TIFFGetField(tif, TIFFTAG_COMPRESSION, &comptype); 01589 if (comptype != COMPRESSION_CCITTFAX4) { 01590 FREE(inarray); 01591 TIFFClose(tif); 01592 return ERROR_INT("filein is not g4 compressed", procName, 1); 01593 } 01594 01595 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); 01596 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 01597 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 01598 if (h != rowsperstrip) 01599 L_WARNING("more than 1 strip", procName); 01600 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &minisblack); /* for 1 bpp */ 01601 /* TIFFPrintDirectory(tif, stderr, 0); */ 01602 TIFFClose(tif); 01603 if (pw) *pw = (l_int32)w; 01604 if (ph) *ph = (l_int32)h; 01605 if (pminisblack) *pminisblack = (l_int32)minisblack; 01606 01607 /* The header has 8 bytes: the first 2 are the magic number, 01608 * the next 2 are the version, and the last 4 are the 01609 * offset to the first directory. That's what we want here. 01610 * We have to test the byte order before decoding 4 bytes! */ 01611 if (inarray[0] == 0x4d) { /* big-endian */ 01612 diroff = (inarray[4] << 24) | (inarray[5] << 16) | 01613 (inarray[6] << 8) | inarray[7]; 01614 } 01615 else { /* inarray[0] == 0x49 : little-endian */ 01616 diroff = (inarray[7] << 24) | (inarray[6] << 16) | 01617 (inarray[5] << 8) | inarray[4]; 01618 } 01619 /* fprintf(stderr, " diroff = %d, %x\n", diroff, diroff); */ 01620 01621 /* Extract the ccittg4 encoded data from the tiff file. 01622 * We skip the 8 byte header and take nbytes of data, 01623 * up to the beginning of the directory (at diroff) */ 01624 nbytes = diroff - 8; 01625 *pnbytes = nbytes; 01626 if ((data = (l_uint8 *)CALLOC(nbytes, sizeof(l_uint8))) == NULL) { 01627 FREE(inarray); 01628 return ERROR_INT("data not allocated", procName, 1); 01629 } 01630 *pdata = data; 01631 memcpy(data, inarray + 8, nbytes); 01632 FREE(inarray); 01633 01634 return 0; 01635 } 01636 01637 01638 /*--------------------------------------------------------------* 01639 * Open tiff stream from file stream * 01640 *--------------------------------------------------------------*/ 01641 /*! 01642 * fopenTiff() 01643 * 01644 * Input: stream 01645 * modestring ("r", "w", ...) 01646 * Return: tiff (data structure, opened for a file descriptor) 01647 * 01648 * Notes: 01649 * (1) Why is this here? Leffler did not provide a function that 01650 * takes a stream and gives a TIFF. He only gave one that 01651 * generates a TIFF starting with a file descriptor. So we 01652 * need to make it here, because it is useful to have functions 01653 * that take a stream as input. 01654 * (2) Requires lseek to rewind to BOF; fseek won't hack it. 01655 * (3) When linking with windows, suggest you use tif_unix.c 01656 * instead of tif_win32.c, because it has been reported that 01657 * the file descriptor returned from fileno() does not work 01658 * with TIFFFdOpen() in tif_win32.c. (win32 requires a 01659 * "handle", which is an integer returned by _get_osfhandle(fd).) 01660 */ 01661 static TIFF * 01662 fopenTiff(FILE *fp, 01663 const char *modestring) 01664 { 01665 l_int32 fd; 01666 01667 PROCNAME("fopenTiff"); 01668 01669 if (!fp) 01670 return (TIFF *)ERROR_PTR("stream not opened", procName, NULL); 01671 if (!modestring) 01672 return (TIFF *)ERROR_PTR("modestring not defined", procName, NULL); 01673 01674 if ((fd = fileno(fp)) < 0) 01675 return (TIFF *)ERROR_PTR("invalid file descriptor", procName, NULL); 01676 lseek(fd, 0, SEEK_SET); 01677 01678 return TIFFFdOpen(fd, "TIFFstream", modestring); 01679 } 01680 01681 01682 /*--------------------------------------------------------------* 01683 * Wrapper for TIFFOpen * 01684 *--------------------------------------------------------------*/ 01685 /*! 01686 * openTiff() 01687 * 01688 * Input: filename 01689 * modestring ("r", "w", ...) 01690 * Return: tiff (data structure) 01691 * 01692 * Notes: 01693 * (1) This handles multi-platform file naming. 01694 */ 01695 static TIFF * 01696 openTiff(const char *filename, 01697 const char *modestring) 01698 { 01699 char *fname; 01700 TIFF *tif; 01701 01702 PROCNAME("openTiff"); 01703 01704 if (!filename) 01705 return (TIFF *)ERROR_PTR("filename not defined", procName, NULL); 01706 if (!modestring) 01707 return (TIFF *)ERROR_PTR("modestring not defined", procName, NULL); 01708 01709 fname = genPathname(filename, NULL); 01710 tif = TIFFOpen(fname, modestring); 01711 FREE(fname); 01712 return tif; 01713 } 01714 01715 01716 /*----------------------------------------------------------------------* 01717 * Memory I/O: reading memory --> pix and writing pix --> memory * 01718 *----------------------------------------------------------------------*/ 01719 /* It would be nice to use open_memstream() and fmemopen() 01720 * for writing and reading to memory, rsp. These functions manage 01721 * memory for writes and reads that use a file streams interface. 01722 * Unfortunately, the tiff library only has an interface for reading 01723 * and writing to file descriptors, not to file streams. The tiff 01724 * library procedure is to open a "tiff stream" and read/write to it. 01725 * The library provides a client interface for managing the I/O 01726 * from memory, which requires seven callbacks. See the TIFFClientOpen 01727 * man page for callback signatures. Adam Langley provided the code 01728 * to do this. */ 01729 01730 /* 01731 * The L_Memstram @buffer has different functions in writing and reading. 01732 * 01733 * * In reading, it is assigned to the data and read from as 01734 * the tiff library uncompresses the data and generates the pix. 01735 * The @offset points to the current read position in the data, 01736 * and the @hw always gives the number of bytes of data. 01737 * The @outdata and @outsize ptrs are not used. 01738 * When finished, tiffCloseCallback() simply frees the L_Memstream. 01739 * 01740 * * In writing, it accepts the data that the tiff library 01741 * produces when a pix is compressed. the buffer points to a 01742 * malloced area of @bufsize bytes. The current writing position 01743 * in the buffer is @offset and the most ever written is @hw. 01744 * The buffer is expanded as necessary. When finished, 01745 * tiffCloseCallback() assigns the @outdata and @outsize ptrs 01746 * to the @buffer and @bufsize results, and frees the L_Memstream. 01747 */ 01748 struct L_Memstream 01749 { 01750 l_uint8 *buffer; /* expands to hold data when written to; */ 01751 /* fixed size when read from. */ 01752 size_t bufsize; /* current size allocated when written to; */ 01753 /* fixed size of input data when read from. */ 01754 size_t offset; /* byte offset from beginning of buffer. */ 01755 size_t hw; /* high-water mark; max bytes in buffer. */ 01756 l_uint8 **poutdata; /* input param for writing; data goes here. */ 01757 size_t *poutsize; /* input param for writing; data size goes here. */ 01758 }; 01759 typedef struct L_Memstream L_MEMSTREAM; 01760 01761 01762 /* These are static functions for memory I/O */ 01763 static L_MEMSTREAM *memstreamCreateForRead(l_uint8 *indata, size_t pinsize); 01764 static L_MEMSTREAM *memstreamCreateForWrite(l_uint8 **poutdata, 01765 size_t *poutsize); 01766 static tsize_t tiffReadCallback(thandle_t handle, tdata_t data, tsize_t length); 01767 static tsize_t tiffWriteCallback(thandle_t handle, tdata_t data, 01768 tsize_t length); 01769 static toff_t tiffSeekCallback(thandle_t handle, toff_t offset, l_int32 whence); 01770 static l_int32 tiffCloseCallback(thandle_t handle); 01771 static toff_t tiffSizeCallback(thandle_t handle); 01772 static l_int32 tiffMapCallback(thandle_t handle, tdata_t *data, toff_t *length); 01773 static void tiffUnmapCallback(thandle_t handle, tdata_t data, toff_t length); 01774 01775 01776 static L_MEMSTREAM * 01777 memstreamCreateForRead(l_uint8 *indata, 01778 size_t insize) 01779 { 01780 L_MEMSTREAM *mstream; 01781 01782 mstream = (L_MEMSTREAM *)CALLOC(1, sizeof(L_MEMSTREAM)); 01783 mstream->buffer = indata; /* handle to input data array */ 01784 mstream->bufsize = insize; /* amount of input data */ 01785 mstream->hw = insize; /* high-water mark fixed at input data size */ 01786 mstream->offset = 0; /* offset always starts at 0 */ 01787 return mstream; 01788 } 01789 01790 01791 static L_MEMSTREAM * 01792 memstreamCreateForWrite(l_uint8 **poutdata, 01793 size_t *poutsize) 01794 { 01795 L_MEMSTREAM *mstream; 01796 01797 mstream = (L_MEMSTREAM *)CALLOC(1, sizeof(L_MEMSTREAM)); 01798 mstream->buffer = (l_uint8 *)CALLOC(8 * 1024, 1); 01799 mstream->bufsize = 8 * 1024; 01800 mstream->poutdata = poutdata; /* used only at end of write */ 01801 mstream->poutsize = poutsize; /* ditto */ 01802 mstream->hw = mstream->offset = 0; 01803 return mstream; 01804 } 01805 01806 01807 static tsize_t 01808 tiffReadCallback(thandle_t handle, 01809 tdata_t data, 01810 tsize_t length) 01811 { 01812 L_MEMSTREAM *mstream; 01813 size_t amount; 01814 01815 mstream = (L_MEMSTREAM *)handle; 01816 amount = L_MIN((size_t)length, mstream->hw - mstream->offset); 01817 memcpy(data, mstream->buffer + mstream->offset, amount); 01818 mstream->offset += amount; 01819 return amount; 01820 } 01821 01822 01823 static tsize_t 01824 tiffWriteCallback(thandle_t handle, 01825 tdata_t data, 01826 tsize_t length) 01827 { 01828 L_MEMSTREAM *mstream; 01829 size_t newsize; 01830 01831 /* reallocNew() uses calloc to initialize the array. 01832 * If malloc is used instead, for some of the encoding methods, 01833 * not all the data in 'bufsize' bytes in the buffer will 01834 * have been initialized by the end of the compression. */ 01835 mstream = (L_MEMSTREAM *)handle; 01836 if (mstream->offset + length > mstream->bufsize) { 01837 newsize = 2 * (mstream->offset + length); 01838 mstream->buffer = (l_uint8 *)reallocNew((void **)&mstream->buffer, 01839 mstream->offset, newsize); 01840 mstream->bufsize = newsize; 01841 } 01842 01843 memcpy(mstream->buffer + mstream->offset, data, length); 01844 mstream->offset += length; 01845 mstream->hw = L_MAX(mstream->offset, mstream->hw); 01846 return length; 01847 } 01848 01849 01850 static toff_t 01851 tiffSeekCallback(thandle_t handle, 01852 toff_t offset, 01853 l_int32 whence) 01854 { 01855 L_MEMSTREAM *mstream; 01856 01857 PROCNAME("tiffSeekCallback"); 01858 mstream = (L_MEMSTREAM *)handle; 01859 switch (whence) { 01860 case SEEK_SET: 01861 /* fprintf(stderr, "seek_set: offset = %d\n", offset); */ 01862 mstream->offset = offset; 01863 break; 01864 case SEEK_CUR: 01865 /* fprintf(stderr, "seek_cur: offset = %d\n", offset); */ 01866 mstream->offset += offset; 01867 break; 01868 case SEEK_END: 01869 /* fprintf(stderr, "seek end: hw = %d, offset = %d\n", 01870 mstream->hw, offset); */ 01871 mstream->offset = mstream->hw - offset; /* offset >= 0 */ 01872 break; 01873 default: 01874 return (toff_t)ERROR_INT("bad whence value", procName, 01875 mstream->offset); 01876 } 01877 01878 return mstream->offset; 01879 } 01880 01881 01882 static l_int32 01883 tiffCloseCallback(thandle_t handle) 01884 { 01885 L_MEMSTREAM *mstream; 01886 01887 mstream = (L_MEMSTREAM *)handle; 01888 if (mstream->poutdata) { /* writing: save the output data */ 01889 *mstream->poutdata = mstream->buffer; 01890 *mstream->poutsize = mstream->hw; 01891 } 01892 FREE(mstream); /* never free the buffer! */ 01893 return 0; 01894 } 01895 01896 01897 static toff_t 01898 tiffSizeCallback(thandle_t handle) 01899 { 01900 L_MEMSTREAM *mstream; 01901 01902 mstream = (L_MEMSTREAM *)handle; 01903 return mstream->hw; 01904 } 01905 01906 01907 static l_int32 01908 tiffMapCallback(thandle_t handle, 01909 tdata_t *data, 01910 toff_t *length) 01911 { 01912 L_MEMSTREAM *mstream; 01913 01914 mstream = (L_MEMSTREAM *)handle; 01915 *data = mstream->buffer; 01916 *length = mstream->hw; 01917 return 0; 01918 } 01919 01920 01921 static void 01922 tiffUnmapCallback(thandle_t handle, 01923 tdata_t data, 01924 toff_t length) 01925 { 01926 return; 01927 } 01928 01929 01930 /*! 01931 * fopenTiffMemstream() 01932 * 01933 * Input: filename (for error output; can be "") 01934 * operation ("w" for write, "r" for read) 01935 * &data (<return> written data) 01936 * &datasize (<return> size of written data) 01937 * Return: tiff (data structure, opened for write to memory) 01938 * 01939 * Notes: 01940 * (1) This wraps up a number of callbacks for either: 01941 * * reading from tiff in memory buffer --> pix 01942 * * writing from pix --> tiff in memory buffer 01943 * (2) After use, the memstream is automatically destroyed when 01944 * TIFFClose() is called. TIFFCleanup() doesn't free the memstream. 01945 */ 01946 static TIFF * 01947 fopenTiffMemstream(const char *filename, 01948 const char *operation, 01949 l_uint8 **pdata, 01950 size_t *pdatasize) 01951 { 01952 L_MEMSTREAM *mstream; 01953 01954 PROCNAME("fopenTiffMemstream"); 01955 01956 if (!filename) 01957 return (TIFF *)ERROR_PTR("filename not defined", procName, NULL); 01958 if (!operation) 01959 return (TIFF *)ERROR_PTR("operation not defined", procName, NULL); 01960 if (!pdata) 01961 return (TIFF *)ERROR_PTR("&data not defined", procName, NULL); 01962 if (!pdatasize) 01963 return (TIFF *)ERROR_PTR("&datasize not defined", procName, NULL); 01964 if (!strcmp(operation, "r") && !strcmp(operation, "w")) 01965 return (TIFF *)ERROR_PTR("operation not 'r' or 'w'}", procName, NULL); 01966 01967 if (!strcmp(operation, "r")) 01968 mstream = memstreamCreateForRead(*pdata, *pdatasize); 01969 else 01970 mstream = memstreamCreateForWrite(pdata, pdatasize); 01971 01972 return TIFFClientOpen(filename, operation, mstream, 01973 tiffReadCallback, tiffWriteCallback, 01974 tiffSeekCallback, tiffCloseCallback, 01975 tiffSizeCallback, tiffMapCallback, 01976 tiffUnmapCallback); 01977 } 01978 01979 01980 /*! 01981 * pixReadMemTiff() 01982 * 01983 * Input: data (const; tiff-encoded) 01984 * datasize (size of data) 01985 * n (page image number: 0-based) 01986 * Return: pix, or null on error 01987 * 01988 * Notes: 01989 * (1) This is a version of pixReadTiff(), where the data is read 01990 * from a memory buffer and uncompressed. 01991 * (2) Use TIFFClose(); TIFFCleanup() doesn't free internal memstream. 01992 */ 01993 PIX * 01994 pixReadMemTiff(const l_uint8 *cdata, 01995 size_t size, 01996 l_int32 n) 01997 { 01998 l_uint8 *data; 01999 l_int32 i, pagefound; 02000 PIX *pix; 02001 TIFF *tif; 02002 02003 PROCNAME("pixReadMemTiff"); 02004 02005 if (!cdata) 02006 return (PIX *)ERROR_PTR("cdata not defined", procName, NULL); 02007 02008 data = (l_uint8 *)cdata; /* we're really not going to change this */ 02009 if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL) 02010 return (PIX *)ERROR_PTR("tiff stream not opened", procName, NULL); 02011 02012 pagefound = FALSE; 02013 pix = NULL; 02014 for (i = 0; i < MAX_PAGES_IN_TIFF_FILE; i++) { 02015 if (i == n) { 02016 pagefound = TRUE; 02017 if ((pix = pixReadFromTiffStream(tif)) == NULL) { 02018 TIFFClose(tif); 02019 return (PIX *)ERROR_PTR("pix not read", procName, NULL); 02020 } 02021 pixSetInputFormat(pix, IFF_TIFF); 02022 break; 02023 } 02024 if (TIFFReadDirectory(tif) == 0) 02025 break; 02026 } 02027 02028 if (pagefound == FALSE) 02029 L_WARNING_INT("tiff page %d not found", procName, n); 02030 02031 TIFFClose(tif); 02032 return pix; 02033 } 02034 02035 02036 /*! 02037 * pixWriteMemTiff() 02038 * 02039 * Input: &data (<return> data of tiff compressed image) 02040 * &size (<return> size of returned data) 02041 * pix 02042 * comptype (IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS, 02043 * IFF_TIFF_G3, IFF_TIFF_G4, 02044 * IFF_TIFF_LZW, IFF_TIFF_ZIP) 02045 * Return: 0 if OK, 1 on error 02046 * 02047 * Usage: 02048 * (1) See pixWriteTiff(). This version writes to 02049 * memory instead of to a file. 02050 */ 02051 l_int32 02052 pixWriteMemTiff(l_uint8 **pdata, 02053 size_t *psize, 02054 PIX *pix, 02055 l_int32 comptype) 02056 { 02057 return pixWriteMemTiffCustom(pdata, psize, pix, comptype, 02058 NULL, NULL, NULL, NULL); 02059 } 02060 02061 02062 /*! 02063 * pixWriteMemTiffCustom() 02064 * 02065 * Input: &data (<return> data of tiff compressed image) 02066 * &size (<return> size of returned data) 02067 * pix 02068 * comptype (IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS, 02069 * IFF_TIFF_G3, IFF_TIFF_G4, 02070 * IFF_TIFF_LZW, IFF_TIFF_ZIP) 02071 * natags (<optional> NUMA of custom tiff tags) 02072 * savals (<optional> SARRAY of values) 02073 * satypes (<optional> SARRAY of types) 02074 * nasizes (<optional> NUMA of sizes) 02075 * Return: 0 if OK, 1 on error 02076 * 02077 * Usage: 02078 * (1) See pixWriteTiffCustom(). This version writes to 02079 * memory instead of to a file. 02080 * (2) Use TIFFClose(); TIFFCleanup() doesn't free internal memstream. 02081 */ 02082 l_int32 02083 pixWriteMemTiffCustom(l_uint8 **pdata, 02084 size_t *psize, 02085 PIX *pix, 02086 l_int32 comptype, 02087 NUMA *natags, 02088 SARRAY *savals, 02089 SARRAY *satypes, 02090 NUMA *nasizes) 02091 { 02092 l_int32 ret; 02093 TIFF *tif; 02094 02095 PROCNAME("pixWriteMemTiffCustom"); 02096 02097 if (!pdata) 02098 return ERROR_INT("&data not defined", procName, 1); 02099 if (!psize) 02100 return ERROR_INT("&size not defined", procName, 1); 02101 if (!pix) 02102 return ERROR_INT("&pix not defined", procName, 1); 02103 if (pixGetDepth(pix) != 1 && comptype != IFF_TIFF && 02104 comptype != IFF_TIFF_LZW && comptype != IFF_TIFF_ZIP) { 02105 L_WARNING("invalid compression type for image with bpp > 1", procName); 02106 comptype = IFF_TIFF_ZIP; 02107 } 02108 02109 if ((tif = fopenTiffMemstream("tifferror", "w", pdata, psize)) == NULL) 02110 return ERROR_INT("tiff stream not opened", procName, 1); 02111 ret = pixWriteToTiffStream(tif, pix, comptype, natags, savals, 02112 satypes, nasizes); 02113 02114 TIFFClose(tif); 02115 return ret; 02116 } 02117 02118 /* --------------------------------------------*/ 02119 #endif /* HAVE_LIBTIFF */ 02120 /* --------------------------------------------*/