Leptonica 1.68
C Image Processing Library

tiffio.c

Go to the documentation of this file.
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 /* --------------------------------------------*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines