Coverage Report

Created: 2026-10-28 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/leptonica/src/tiffio.c
Line
Count
Source
1
/*====================================================================*
2
 -  Copyright (C) 2001 Leptonica.  All rights reserved.
3
 -
4
 -  Redistribution and use in source and binary forms, with or without
5
 -  modification, are permitted provided that the following conditions
6
 -  are met:
7
 -  1. Redistributions of source code must retain the above copyright
8
 -     notice, this list of conditions and the following disclaimer.
9
 -  2. Redistributions in binary form must reproduce the above
10
 -     copyright notice, this list of conditions and the following
11
 -     disclaimer in the documentation and/or other materials
12
 -     provided with the distribution.
13
 -
14
 -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15
 -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
 -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
 -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
18
 -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19
 -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20
 -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21
 -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22
 -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23
 -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
 -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 *====================================================================*/
26
27
/*!
28
 * \file tiffio.c
29
 * <pre>
30
 *
31
 *     TIFFClientOpen() wrappers for FILE*:
32
 *      static tsize_t    lept_read_proc()
33
 *      static tsize_t    lept_write_proc()
34
 *      static toff_t     lept_seek_proc()
35
 *      static int        lept_close_proc()
36
 *      static toff_t     lept_size_proc()
37
 *
38
 *     Reading tiff:
39
 *             PIX       *pixReadTiff()             [ special top level ]
40
 *             PIX       *pixReadStreamTiff()
41
 *      static PIX       *pixReadFromTiffStream()
42
 *
43
 *     Writing tiff:
44
 *             l_int32    pixWriteTiff()            [ special top level ]
45
 *             l_int32    pixWriteTiffCustom()      [ special top level ]
46
 *             l_int32    pixWriteStreamTiff()
47
 *             l_int32    pixWriteStreamTiffWA()
48
 *      static l_int32    pixWriteToTiffStream()
49
 *      static l_int32    writeCustomTiffTags()
50
 *
51
 *     Reading and writing multipage tiff
52
 *             PIX       *pixReadFromMultipageTiff()
53
 *             PIXA      *pixaReadMultipageTiff()   [ special top level ]
54
 *             l_int32    pixaWriteMultipageTiff()  [ special top level ]
55
 *             l_int32    writeMultipageTiff()      [ special top level ]
56
 *             l_int32    writeMultipageTiffSA()
57
 *
58
 *     Information about tiff file
59
 *             l_int32    fprintTiffInfo()
60
 *             l_int32    tiffGetCount()
61
 *             l_int32    getTiffResolution()
62
 *      static l_int32    getTiffStreamResolution()
63
 *             l_int32    readHeaderTiff()
64
 *             l_int32    freadHeaderTiff()
65
 *             l_int32    readHeaderMemTiff()
66
 *      static l_int32    tiffReadHeaderTiff()
67
 *             l_int32    findTiffCompression()
68
 *      static l_int32    getTiffCompressedFormat()
69
 *
70
 *     Extraction of tiff g4 data:
71
 *             l_int32    extractG4DataFromFile()
72
 *
73
 *     Open tiff stream from file stream
74
 *      static TIFF      *fopenTiff()
75
 *
76
 *     Wrapper for TIFFOpen:
77
 *      static TIFF      *openTiff()
78
 *
79
 *     Memory I/O: reading memory --> pix and writing pix --> memory
80
 *        Ten static low-level memstream functions
81
 *           static L_MEMSTREAM  *memstreamCreateForRead()
82
 *           static L_MEMSTREAM  *memstreamCreateForWrite()
83
 *           static tsize_t       tiffReadCallback()
84
 *           static tsize_t       tiffWriteCallback()
85
 *           static toff_t        tiffSeekCallback()
86
 *           static l_int32       tiffCloseCallback()
87
 *           static toff_t        tiffSizeCallback()
88
 *           static l_int32       tiffMapCallback()
89
 *           static void          tiffUnmapCallback()
90
 *           static TIFF         *fopenTiffMemstream()
91
 *
92
 *           PIX       *pixReadMemTiff();
93
 *           PIX       *pixReadMemFromMultipageTiff();
94
 *           PIXA      *pixaReadMemMultipageTiff()    [ special top level ]
95
 *           l_int32    pixaWriteMemMultipageTiff()   [ special top level ]
96
 *           l_int32    pixWriteMemTiff();
97
 *           l_int32    pixWriteMemTiffCustom();
98
 *
99
 *  Note 1: To include all necessary functions, use libtiff version 3.7.4
100
 *          (from 2005) or later.
101
 *  Note 2: What compression methods in tiff are supported?
102
 *          * We support most methods that are fully implemented in the
103
 *            tiff library, such as G3, G4, RLE and LZW.
104
 *          * The exception is the old-style jpeg tiff format (OJPEG), which
105
 *            is not supported.
106
 *          * We support two formats requiring external libraries: ZIP and JPEG
107
 *            All computers should have the zip library.
108
 *          * At present we do not support WEBP in tiff, which uses
109
 *            libwebp and was added in tifflib 4.1.0 in 2019.
110
 *  Note 3: We set the pad bits to 0 before writing in pixWriteToTiffStream().
111
 *          Although they don't affect the raster image after decompression,
112
 *          it is sometimes convenient to use a golden file with a
113
 *          byte-by-byte check to verify invariance.  The issue came up
114
 *          on Windows for 2 and 4 bpp images.
115
 * </pre>
116
 */
117
118
#ifdef HAVE_CONFIG_H
119
#include <config_auto.h>
120
#endif  /* HAVE_CONFIG_H */
121
122
#include <string.h>
123
#include <math.h>   /* for isnan */
124
#include <sys/types.h>
125
#ifndef _MSC_VER
126
#include <unistd.h>
127
#else  /* _MSC_VER */
128
#include <io.h>
129
#endif  /* _MSC_VER */
130
#include <fcntl.h>
131
#include "allheaders.h"
132
133
/* ---------------------------------------------------------*/
134
#if  HAVE_LIBTIFF && HAVE_LIBJPEG   /* defined in environ.h */
135
/* ---------------------------------------------------------*/
136
137
#include "tiff.h"
138
#include "tiffio.h"
139
140
static const l_int32  DefaultResolution = 300;   /* ppi */
141
static const l_int32  ManyPagesInTiffFile = 3000;  /* warn if big */
142
143
    /* Verified that tiflib makes valid g4 files of this size */
144
static const l_int32  MaxTiffWidth = 1 << 20;  /* 1M pixels */
145
static const l_int32  MaxTiffHeight = 1 << 20;  /* 1M pixels */
146
147
    /* Check g4 data size */
148
static const size_t  MaxNumTiffBytes = (1 << 28) - 1;  /* 256 MB */
149
150
    /* All functions with TIFF interfaces are static. */
151
static PIX      *pixReadFromTiffStream(TIFF *tif);
152
static l_int32   getTiffStreamResolution(TIFF *tif, l_int32 *pxres,
153
                                         l_int32 *pyres);
154
static l_int32   tiffReadHeaderTiff(TIFF *tif, l_int32 *pwidth,
155
                                    l_int32 *pheight, l_int32 *pbps,
156
                                    l_int32 *pspp, l_int32 *pres,
157
                                    l_int32 *pcmap, l_int32 *pformat);
158
static l_int32   writeCustomTiffTags(TIFF *tif, NUMA *natags,
159
                                     SARRAY *savals, SARRAY  *satypes,
160
                                     NUMA *nasizes);
161
static l_int32   pixWriteToTiffStream(TIFF *tif, PIX *pix, l_int32 comptype,
162
                                      NUMA *natags, SARRAY *savals,
163
                                      SARRAY *satypes, NUMA *nasizes);
164
static TIFF     *fopenTiff(FILE *fp, const char *modestring);
165
static TIFF     *openTiff(const char *filename, const char *modestring);
166
167
    /* Static helper for tiff compression type */
168
static l_int32   getTiffCompressedFormat(l_uint16 tiffcomp);
169
170
    /* Static function for memory I/O */
171
static TIFF     *fopenTiffMemstream(const char *filename, const char *operation,
172
                                    l_uint8 **pdata, size_t *pdatasize);
173
174
    /* This structure defines a transform to be performed on a TIFF image
175
     * (note that the same transformation can be represented in
176
     * several different ways using this structure since
177
     * vflip + hflip + counterclockwise == clockwise). */
178
struct tiff_transform {
179
    int vflip;    /* if non-zero, image needs a vertical fip */
180
    int hflip;    /* if non-zero, image needs a horizontal flip */
181
    int rotate;   /* -1 -> counterclockwise 90-degree rotation,
182
                      0 -> no rotation
183
                      1 -> clockwise 90-degree rotation */
184
};
185
186
    /* This describes the transformations needed for a given orientation
187
     * tag.  The tag values start at 1, so you need to subtract 1 to get a
188
     * valid index into this array.  It is only valid when not using
189
     * TIFFReadRGBAImageOriented(). */
190
static struct tiff_transform tiff_orientation_transforms[] = {
191
    {0, 0, 0},
192
    {0, 1, 0},
193
    {1, 1, 0},
194
    {1, 0, 0},
195
    {0, 1, -1},
196
    {0, 0, 1},
197
    {0, 1, 1},
198
    {0, 0, -1}
199
};
200
201
    /* Same as above, except that test transformations are only valid
202
     * when using TIFFReadRGBAImageOriented().  Transformations
203
     * were determined empirically.  See the libtiff mailing list for
204
     * more discussion: http://www.asmail.be/msg0054683875.html  */
205
static struct tiff_transform tiff_partial_orientation_transforms[] = {
206
    {0, 0, 0},
207
    {0, 0, 0},
208
    {0, 0, 0},
209
    {0, 0, 0},
210
    {0, 1, -1},
211
    {0, 1, 1},
212
    {1, 0, 1},
213
    {0, 1, -1}
214
};
215
216
217
/*-----------------------------------------------------------------------*
218
 *             TIFFClientOpen() wrappers for FILE*                       *
219
 *             Provided by Jürgen Buchmüller                             *
220
 *                                                                       *
221
 *  We previously used TIFFFdOpen(), which used low-level file           *
222
 *  descriptors.  It had portability issues with Windows, along          *
223
 *  with other limitations from lack of stream control operations.       *
224
 *  These callbacks to TIFFClientOpen() avoid the problems.              *
225
 *                                                                       *
226
 *  Jürgen made the functions use 64 bit file operations where possible  *
227
 *  or required, namely for seek and size. On Windows there are specific *
228
 *  _fseeki64() and _ftelli64() functions.  On unix it is common to look *
229
 *  for a macro _LARGEFILE64_SOURCE being defined, which makes available *
230
 *  the off64_t type, and to use fseeko() and ftello() in this case.     *
231
 *-----------------------------------------------------------------------*/
232
static tsize_t
233
lept_read_proc(thandle_t  cookie,
234
               tdata_t    buff,
235
               tsize_t    size)
236
0
{
237
0
    FILE* fp = (FILE *)cookie;
238
0
    tsize_t done;
239
0
    if (!buff || !cookie || !fp)
240
0
        return (tsize_t)-1;
241
0
    done = fread(buff, 1, size, fp);
242
0
    return done;
243
0
}
244
245
static tsize_t
246
lept_write_proc(thandle_t  cookie,
247
                tdata_t    buff,
248
                tsize_t    size)
249
0
{
250
0
    FILE* fp = (FILE *)cookie;
251
0
    tsize_t done;
252
0
    if (!buff || !cookie || !fp)
253
0
        return (tsize_t)-1;
254
0
    done = fwrite(buff, 1, size, fp);
255
0
    return done;
256
0
}
257
258
static toff_t
259
lept_seek_proc(thandle_t  cookie,
260
               toff_t     offs,
261
               int        whence)
262
0
{
263
0
    FILE* fp = (FILE *)cookie;
264
#if defined(_MSC_VER)
265
    __int64 pos = 0;
266
    if (!cookie || !fp)
267
        return (tsize_t)-1;
268
    switch (whence) {
269
    case SEEK_SET:
270
        pos = 0;
271
        break;
272
    case SEEK_CUR:
273
        pos = ftell(fp);
274
        if (pos < 0)
275
            return (tsize_t)-1;
276
        break;
277
    case SEEK_END:
278
        if (_fseeki64(fp, 0, SEEK_END) != 0)
279
            return (tsize_t)-1;
280
        pos = _ftelli64(fp);
281
        if (pos < 0)
282
            return (tsize_t)-1;
283
        break;
284
    }
285
    pos = (__int64)(pos + offs);
286
    _fseeki64(fp, pos, SEEK_SET);
287
    if (pos == _ftelli64(fp))
288
        return (tsize_t)pos;
289
#elif defined(_LARGEFILE64_SOURCE)
290
    off64_t pos = 0;
291
    if (!cookie || !fp)
292
        return (tsize_t)-1;
293
    switch (whence) {
294
    case SEEK_SET:
295
        pos = 0;
296
        break;
297
    case SEEK_CUR:
298
        pos = ftello(fp);
299
        if (pos < 0)
300
            return (tsize_t)-1;
301
        break;
302
    case SEEK_END:
303
        if (fseeko(fp, 0, SEEK_END) != 0)
304
            return (tsize_t)-1;
305
        pos = ftello(fp);
306
        if (pos < 0)
307
            return (tsize_t)-1;
308
        break;
309
    }
310
    pos = (off64_t)(pos + offs);
311
    fseeko(fp, pos, SEEK_SET);
312
    if (pos == ftello(fp))
313
        return (tsize_t)pos;
314
#else
315
0
    off_t pos = 0;
316
0
    if (!cookie || !fp)
317
0
        return (tsize_t)-1;
318
0
    switch (whence) {
319
0
    case SEEK_SET:
320
0
        pos = 0;
321
0
        break;
322
0
    case SEEK_CUR:
323
0
        pos = ftell(fp);
324
0
        if (pos < 0)
325
0
            return (tsize_t)-1;
326
0
        break;
327
0
    case SEEK_END:
328
0
        if (fseek(fp, 0, SEEK_END) != 0)
329
0
            return (tsize_t)-1;
330
0
        pos = ftell(fp);
331
0
        if (pos < 0)
332
0
            return (tsize_t)-1;
333
0
        break;
334
0
    }
335
0
    pos = (off_t)(pos + offs);
336
0
    fseek(fp, pos, SEEK_SET);
337
0
    if (pos == ftell(fp))
338
0
        return (tsize_t)pos;
339
0
#endif
340
0
    return (tsize_t)-1;
341
0
}
342
343
static int
344
lept_close_proc(thandle_t  cookie)
345
0
{
346
0
    FILE* fp = (FILE *)cookie;
347
0
    if (!cookie || !fp)
348
0
        return 0;
349
0
    fseek(fp, 0, SEEK_SET);
350
0
    return 0;
351
0
}
352
353
static toff_t
354
lept_size_proc(thandle_t  cookie)
355
0
{
356
0
    FILE* fp = (FILE *)cookie;
357
#if defined(_MSC_VER)
358
    __int64 pos;
359
    __int64 size;
360
    if (!cookie || !fp)
361
        return (toff_t)-1;
362
    pos = _ftelli64(fp);
363
    if (pos < 0 || _fseeki64(fp, 0, SEEK_END) != 0)
364
        return (toff_t)-1;
365
    size = _ftelli64(fp);
366
    if (_fseeki64(fp, pos, SEEK_SET) != 0)
367
        return (toff_t)-1;
368
    if (size < 0)
369
        return (toff_t)-1;
370
#elif defined(_LARGEFILE64_SOURCE)
371
    off64_t pos;
372
    off64_t size;
373
    if (!fp)
374
        return (toff_t)-1;
375
    pos = ftello(fp);
376
    if (pos < 0 || fseeko(fp, 0, SEEK_END) != 0)
377
        return (toff_t)-1;
378
    size = ftello(fp);
379
    if (fseeko(fp, pos, SEEK_SET) != 0)
380
        return (toff_t)-1;
381
    if (size < 0)
382
        return (toff_t)-1;
383
#else
384
0
    off_t pos;
385
0
    off_t size;
386
0
    if (!cookie || !fp)
387
0
        return (toff_t)-1;
388
0
    pos = ftell(fp);
389
0
    if (pos < 0 || fseek(fp, 0, SEEK_END) != 0)
390
0
        return (toff_t)-1;
391
0
    size = ftell(fp);
392
0
    if (fseek(fp, pos, SEEK_SET) != 0)
393
0
        return (toff_t)-1;
394
0
    if (size < 0)
395
0
        return (toff_t)-1;
396
0
#endif
397
0
    return (toff_t)size;
398
0
}
399
400
401
/*--------------------------------------------------------------*
402
 *                      Reading from file                       *
403
 *--------------------------------------------------------------*/
404
/*!
405
 * \brief   pixReadTiff()
406
 *
407
 * \param[in]    filename
408
 * \param[in]    n           page number 0 based
409
 * \return  pix, or NULL on error
410
 *
411
 * <pre>
412
 * Notes:
413
 *      (1) This is a version of pixRead(), specialized for tiff
414
 *          files, that allows specification of the page to be returned
415
 *      (2) No warning messages on failure, because of how multi-page
416
 *          TIFF reading works. You are supposed to keep trying until
417
 *          it stops working.
418
 * </pre>
419
 */
420
PIX *
421
pixReadTiff(const char  *filename,
422
            l_int32      n)
423
0
{
424
0
FILE  *fp;
425
0
PIX   *pix;
426
427
0
    if (!filename)
428
0
        return (PIX *)ERROR_PTR("filename not defined", __func__, NULL);
429
430
0
    if ((fp = fopenReadStream(filename)) == NULL)
431
0
        return (PIX *)ERROR_PTR_1("image file not found",
432
0
                                  filename, __func__, NULL);
433
0
    pix = pixReadStreamTiff(fp, n);
434
0
    fclose(fp);
435
0
    return pix;
436
0
}
437
438
439
/*--------------------------------------------------------------*
440
 *                     Reading from stream                      *
441
 *--------------------------------------------------------------*/
442
/*!
443
 * \brief   pixReadStreamTiff()
444
 *
445
 * \param[in]    fp    file stream
446
 * \param[in]    n     page number: 0 based
447
 * \return  pix, or NULL on error or if there are no more images in the file
448
 *
449
 * <pre>
450
 * Notes:
451
 *      (1) No warning messages on failure, because of how multi-page
452
 *          TIFF reading works. You are supposed to keep trying until
453
 *          it stops working.
454
 * </pre>
455
 */
456
PIX *
457
pixReadStreamTiff(FILE    *fp,
458
                  l_int32  n)
459
0
{
460
0
PIX   *pix;
461
0
TIFF  *tif;
462
463
0
    if (!fp)
464
0
        return (PIX *)ERROR_PTR("stream not defined", __func__, NULL);
465
466
0
    if ((tif = fopenTiff(fp, "r")) == NULL)
467
0
        return (PIX *)ERROR_PTR("tif not opened", __func__, NULL);
468
469
0
    if (TIFFSetDirectory(tif, n) == 0) {
470
0
        TIFFCleanup(tif);
471
0
        return NULL;
472
0
    }
473
0
    if ((pix = pixReadFromTiffStream(tif)) == NULL) {
474
0
        TIFFCleanup(tif);
475
0
        return NULL;
476
0
    }
477
0
    TIFFCleanup(tif);
478
0
    return pix;
479
0
}
480
481
482
/*!
483
 * \brief   pixReadFromTiffStream()
484
 *
485
 * \param[in]    tif    TIFF handle
486
 * \return  pix, or NULL on error
487
 *
488
 * <pre>
489
 * Notes:
490
 *      (1) We can read the following images (up to 32 bits/pixel):
491
 *          1 spp (grayscale): 1, 2, 4, 8, 16 bps
492
 *          1 spp (colormapped): 1, 2, 4, 8 bps
493
 *          2 spp (gray+alpha): 8 bps
494
 *          3 spp (rgb) and 4 spp (rgba): 8 or 16 bps
495
 *          Note that 16 bps rgb and rgba are converted to 8 bps in the pix.
496
 *      (2) In particular, we do not support
497
 *             16 bps for spp == 2
498
 *              4 bps for spp == 3 or spp == 4.
499
 *      (3) We only support uint image data.
500
 *      (4) We do not support tiled format, old-style jpeg encoding,
501
 *          or webp encoded tiff.
502
 *      (5) 2 bpp gray+alpha are rasterized as 32 bit/pixel rgba, with
503
 *          the gray value replicated in r, g and b.
504
 *      (6) For colormapped images, we support 8 bits/color in the palette.
505
 *          Tiff colormaps have 16 bits/color, and we reduce them to 8.
506
 *      (7) Quoting the libtiff documentation at
507
 *               http://libtiff.maptools.org/libtiff.html
508
 *          "libtiff provides a high-level interface for reading image data
509
 *          from a TIFF file. This interface handles the details of data
510
 *          organization and format for a wide variety of TIFF files;
511
 *          at least the large majority of those files that one would
512
 *          normally encounter. Image data is, by default, returned as
513
 *          ABGR pixels packed into 32-bit words (8 bits per sample).
514
 *          Rectangular rasters can be read or data can be intercepted
515
 *          at an intermediate level and packed into memory in a format
516
 *          more suitable to the application. The library handles all
517
 *          the details of the format of data stored on disk and,
518
 *          in most cases, if any colorspace conversions are required:
519
 *          bilevel to RGB, greyscale to RGB, CMYK to RGB, YCbCr to RGB,
520
 *          16-bit samples to 8-bit samples, associated/unassociated alpha,
521
 *          etc."
522
 * </pre>
523
 */
524
static PIX *
525
pixReadFromTiffStream(TIFF  *tif)
526
4
{
527
4
char      *text;
528
4
l_uint8   *linebuf, *data, *rowptr;
529
4
l_uint16   spp, bps, photometry, tiffcomp, orientation, sample_fmt;
530
4
l_uint16  *redmap, *greenmap, *bluemap;
531
4
l_int32    d, wpl, bpl, comptype, i, j, k, ncolors, rval, gval, bval, aval;
532
4
l_int32    xres, yres, tiffbpl, packedbpl, half_size, twothirds_size;
533
4
l_uint32   w, h, tiffword, read_oriented;
534
4
l_uint32  *line, *ppixel, *tiffdata, *pixdata;
535
4
PIX       *pix, *pix1;
536
4
PIXCMAP   *cmap;
537
538
4
    if (!tif)
539
0
        return (PIX *)ERROR_PTR("tif not defined", __func__, NULL);
540
541
4
    read_oriented = 0;
542
543
        /* Only accept uint image data:
544
         *   SAMPLEFORMAT_UINT = 1;
545
         *   SAMPLEFORMAT_INT = 2;
546
         *   SAMPLEFORMAT_IEEEFP = 3;
547
         *   SAMPLEFORMAT_VOID = 4;   */
548
4
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sample_fmt);
549
4
    if (sample_fmt != SAMPLEFORMAT_UINT) {
550
0
        L_ERROR("sample format = %d is not uint\n", __func__, sample_fmt);
551
0
        return NULL;
552
0
    }
553
554
        /* Can't read tiff in tiled format. For what is involved, see, e.g:
555
         *   https://www.cs.rochester.edu/~nelson/courses/vision/\
556
         *     resources/tiff/libtiff.html#Tiles
557
         * A tiled tiff can be converted to a normal (strip) tif:
558
         *   tiffcp -s <input-tiled-tif> <output-strip-tif>    */
559
4
    if (TIFFIsTiled(tif)) {
560
0
        L_ERROR("tiled format is not supported\n", __func__);
561
0
        return NULL;
562
0
    }
563
564
        /* Old style jpeg is not supported.  We tried supporting 8 bpp.
565
         * TIFFReadScanline() fails on this format, so we used RGBA
566
         * reading, which generates a 4 spp image, and pulled out the
567
         * red component.  However, there were problems with double-frees
568
         * in cleanup.  For RGB, tiffbpl is exactly half the size that
569
         * you would expect for the raster data in a scanline, which
570
         * is 3 * w.  */
571
4
    TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp);
572
4
    if (tiffcomp == COMPRESSION_OJPEG) {
573
0
        L_ERROR("old style jpeg format is not supported\n", __func__);
574
0
        return NULL;
575
0
    }
576
577
        /* webp in tiff is in 4.1.0 and not yet supported in Adobe registry */
578
4
#if defined(COMPRESSION_WEBP)
579
4
    if (tiffcomp == COMPRESSION_WEBP) {
580
0
        L_ERROR("webp in tiff not generally supported yet\n", __func__);
581
0
        return NULL;
582
0
    }
583
4
#endif  /* COMPRESSION_WEBP */
584
585
        /* Use default fields for bps and spp */
586
4
    TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps);
587
4
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
588
4
    if (bps != 1 && bps != 2 && bps != 4 && bps != 8 && bps != 16) {
589
0
        L_ERROR("invalid bps = %d\n", __func__, bps);
590
0
        return NULL;
591
0
    }
592
4
    if (spp == 2 && bps != 8) {
593
0
        L_ERROR("for 2 spp, only handle 8 bps; this is %d bps\n",
594
0
                __func__, bps);
595
0
        return NULL;
596
0
    }
597
4
    if ((spp == 3 || spp == 4) && bps < 8) {
598
0
        L_ERROR("for 3 and 4 spp, only handle 8 and 16 bps; this is %d bps\n",
599
0
                __func__, bps);
600
0
        return NULL;
601
0
    }
602
4
    if (spp == 1) {
603
4
        d = bps;
604
4
    } else if (spp == 2) {  /* gray plus alpha */
605
0
        d = 32;  /* will convert to RGBA */
606
0
    } else if (spp == 3 || spp == 4) {
607
0
        d = 32;
608
0
    } else {
609
0
        L_ERROR("spp = %d; not in {1,2,3,4}\n", __func__, spp);
610
0
        return NULL;
611
0
    }
612
613
4
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
614
4
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
615
4
    if (w > MaxTiffWidth) {
616
0
        L_ERROR("width = %d pixels; too large\n", __func__, w);
617
0
        return NULL;
618
0
    }
619
4
    if (h > MaxTiffHeight) {
620
0
        L_ERROR("height = %d pixels; too large\n", __func__, h);
621
0
        return NULL;
622
0
    }
623
624
        /* The relation between the size of a byte buffer required to hold
625
           a raster of image pixels (packedbpl) and the size of the tiff
626
           buffer (tiffbuf) is either 1:1 or approximately 1.5:1 or 2:1,
627
           depending on how the data is stored and subsampled.  For security,
628
           we test this relation between tiffbuf and the image parameters
629
           w, spp and bps. */
630
4
    tiffbpl = TIFFScanlineSize(tif);
631
4
    packedbpl = (bps * spp * w + 7) / 8;
632
4
    half_size = (L_ABS(2 * tiffbpl - packedbpl) <= 8);
633
4
    twothirds_size = (L_ABS(3 * tiffbpl - 2 * packedbpl) <= 8);
634
#if 0
635
    if (half_size)
636
        L_INFO("half_size: packedbpl = %d is approx. twice tiffbpl = %d\n",
637
               __func__, packedbpl, tiffbpl);
638
    if (twothirds_size)
639
        L_INFO("twothirds_size: packedbpl = %d is approx. 1.5 tiffbpl = %d\n",
640
               __func__, packedbpl, tiffbpl);
641
    lept_stderr("tiffbpl = %d, packedbpl = %d, bps = %d, spp = %d, w = %d\n",
642
                tiffbpl, packedbpl, bps, spp, w);
643
#endif
644
4
    if (tiffbpl != packedbpl && !half_size && !twothirds_size) {
645
0
        L_ERROR("invalid tiffbpl: tiffbpl = %d, packedbpl = %d, "
646
0
                "bps = %d, spp = %d, w = %d\n",
647
0
                __func__, tiffbpl, packedbpl, bps, spp, w);
648
0
        return NULL;
649
0
    }
650
651
        /* Use a linebuf that will hold all the pixels generated
652
           by tiff when reading (decompressing) a scanline. */
653
4
    if ((pix = pixCreate(w, h, d)) == NULL)
654
0
        return (PIX *)ERROR_PTR("pix not made", __func__, NULL);
655
4
    pixSetInputFormat(pix, IFF_TIFF);
656
4
    data = (l_uint8 *)pixGetData(pix);
657
4
    wpl = pixGetWpl(pix);
658
4
    bpl = 4 * wpl;
659
4
    if (spp == 1) {
660
4
        linebuf = (l_uint8 *)LEPT_CALLOC(4 * wpl, sizeof(l_uint8));
661
2.34k
        for (i = 0; i < h; i++) {
662
2.34k
            if (TIFFReadScanline(tif, linebuf, i, 0) < 0) {
663
0
                LEPT_FREE(linebuf);
664
0
                pixDestroy(&pix);
665
0
                L_ERROR("spp = 1, read fail at line %d\n", __func__, i);
666
0
                return NULL;
667
0
            }
668
2.34k
            memcpy(data, linebuf, tiffbpl);
669
2.34k
            data += bpl;
670
2.34k
        }
671
4
        if (bps <= 8)
672
4
            pixEndianByteSwap(pix);
673
0
        else   /* bps == 16 */
674
0
            pixEndianTwoByteSwap(pix);
675
4
        LEPT_FREE(linebuf);
676
4
    } else if (spp == 2 && bps == 8) {  /* gray plus alpha */
677
0
        L_INFO("gray+alpha is not supported; converting to RGBA\n", __func__);
678
0
        pixSetSpp(pix, 4);
679
0
        linebuf = (l_uint8 *)LEPT_CALLOC(4 * wpl, sizeof(l_uint8));
680
0
        pixdata = pixGetData(pix);
681
0
        for (i = 0; i < h; i++) {
682
0
            if (TIFFReadScanline(tif, linebuf, i, 0) < 0) {
683
0
                LEPT_FREE(linebuf);
684
0
                pixDestroy(&pix);
685
0
                L_ERROR("spp = 2, read fail at line %d\n", __func__, i);
686
0
                return NULL;
687
0
            }
688
0
            rowptr = linebuf;
689
0
            ppixel = pixdata + i * wpl;
690
0
            for (j = k = 0; j < w; j++) {
691
                    /* Copy gray value into r, g and b */
692
0
                SET_DATA_BYTE(ppixel, COLOR_RED, rowptr[k]);
693
0
                SET_DATA_BYTE(ppixel, COLOR_GREEN, rowptr[k]);
694
0
                SET_DATA_BYTE(ppixel, COLOR_BLUE, rowptr[k++]);
695
0
                SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL, rowptr[k++]);
696
0
                ppixel++;
697
0
            }
698
0
        }
699
0
        LEPT_FREE(linebuf);
700
0
    } else {  /* rgb and rgba */
701
0
        if ((tiffdata = (l_uint32 *)LEPT_CALLOC((size_t)w * h,
702
0
                                                 sizeof(l_uint32))) == NULL) {
703
0
            pixDestroy(&pix);
704
0
            return (PIX *)ERROR_PTR("calloc fail for tiffdata", __func__, NULL);
705
0
        }
706
            /* TIFFReadRGBAImageOriented() converts to 8 bps */
707
0
        if (!TIFFReadRGBAImageOriented(tif, w, h, tiffdata,
708
0
                                       ORIENTATION_TOPLEFT, 0)) {
709
0
            LEPT_FREE(tiffdata);
710
0
            pixDestroy(&pix);
711
0
            return (PIX *)ERROR_PTR("failed to read tiffdata", __func__, NULL);
712
0
        } else {
713
0
            read_oriented = 1;
714
0
        }
715
716
0
        if (spp == 4) pixSetSpp(pix, 4);
717
0
        line = pixGetData(pix);
718
0
        for (i = 0; i < h; i++, line += wpl) {
719
0
            for (j = 0, ppixel = line; j < w; j++) {
720
                    /* TIFFGet* are macros */
721
0
                tiffword = tiffdata[i * w + j];
722
0
                rval = TIFFGetR(tiffword);
723
0
                gval = TIFFGetG(tiffword);
724
0
                bval = TIFFGetB(tiffword);
725
0
                if (spp == 3) {
726
0
                    composeRGBPixel(rval, gval, bval, ppixel);
727
0
                } else {  /* spp == 4 */
728
0
                    aval = TIFFGetA(tiffword);
729
0
                    composeRGBAPixel(rval, gval, bval, aval, ppixel);
730
0
                }
731
0
                ppixel++;
732
0
            }
733
0
        }
734
0
        LEPT_FREE(tiffdata);
735
0
    }
736
737
4
    if (getTiffStreamResolution(tif, &xres, &yres) == 0) {
738
4
        pixSetXRes(pix, xres);
739
4
        pixSetYRes(pix, yres);
740
4
    }
741
742
        /* Find and save the compression type */
743
4
    comptype = getTiffCompressedFormat(tiffcomp);
744
4
    pixSetInputFormat(pix, comptype);
745
746
4
    if (TIFFGetField(tif, TIFFTAG_COLORMAP, &redmap, &greenmap, &bluemap)) {
747
            /* Save the colormap as a pix cmap.  Because the
748
             * tiff colormap components are 16 bit unsigned,
749
             * and go from black (0) to white (0xffff), the
750
             * the pix cmap takes the most significant byte. */
751
0
        if (bps > 8) {
752
0
            pixDestroy(&pix);
753
0
            return (PIX *)ERROR_PTR("colormap size > 256", __func__, NULL);
754
0
        }
755
0
        if ((cmap = pixcmapCreate(bps)) == NULL) {
756
0
            pixDestroy(&pix);
757
0
            return (PIX *)ERROR_PTR("colormap not made", __func__, NULL);
758
0
        }
759
0
        ncolors = 1 << bps;
760
0
        for (i = 0; i < ncolors; i++)
761
0
            pixcmapAddColor(cmap, redmap[i] >> 8, greenmap[i] >> 8,
762
0
                            bluemap[i] >> 8);
763
0
        if (pixSetColormap(pix, cmap)) {
764
0
            pixDestroy(&pix);
765
0
            return (PIX *)ERROR_PTR("invalid colormap", __func__, NULL);
766
0
        }
767
768
            /* Remove the colormap for 1 bpp. */
769
0
        if (bps == 1) {
770
0
            pix1 = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC);
771
0
            pixDestroy(&pix);
772
0
            pix = pix1;
773
0
        }
774
4
    } else {   /* No colormap: check photometry and invert if necessary */
775
4
        if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometry)) {
776
                /* Guess default photometry setting.  Assume min_is_white
777
                 * if compressed 1 bpp; min_is_black otherwise. */
778
0
            if (tiffcomp == COMPRESSION_CCITTFAX3 ||
779
0
                tiffcomp == COMPRESSION_CCITTFAX4 ||
780
0
                tiffcomp == COMPRESSION_CCITTRLE ||
781
0
                tiffcomp == COMPRESSION_CCITTRLEW) {
782
0
                photometry = PHOTOMETRIC_MINISWHITE;
783
0
            } else {
784
0
                photometry = PHOTOMETRIC_MINISBLACK;
785
0
            }
786
0
        }
787
4
        if ((d == 1 && photometry == PHOTOMETRIC_MINISBLACK) ||
788
0
            (d == 8 && photometry == PHOTOMETRIC_MINISWHITE))
789
4
            pixInvert(pix, pix);
790
4
    }
791
792
4
    if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation)) {
793
4
        if (orientation >= 1 && orientation <= 8) {
794
4
            struct tiff_transform *transform = (read_oriented) ?
795
0
                &tiff_partial_orientation_transforms[orientation - 1] :
796
4
                &tiff_orientation_transforms[orientation - 1];
797
4
            if (transform->vflip) pixFlipTB(pix, pix);
798
4
            if (transform->hflip) pixFlipLR(pix, pix);
799
4
            if (transform->rotate) {
800
0
                PIX *oldpix = pix;
801
0
                pix = pixRotate90(oldpix, transform->rotate);
802
0
                pixDestroy(&oldpix);
803
0
            }
804
4
        }
805
4
    }
806
807
4
    text = NULL;
808
4
    TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &text);
809
4
    if (text) pixSetText(pix, text);
810
4
    return pix;
811
4
}
812
813
814
/*--------------------------------------------------------------*
815
 *                       Writing to file                        *
816
 *--------------------------------------------------------------*/
817
/*!
818
 * \brief   pixWriteTiff()
819
 *
820
 * \param[in]    filename   to write to
821
 * \param[in]    pix        any depth, colormap will be removed
822
 * \param[in]    comptype   IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS,
823
 *                          IFF_TIFF_G3, IFF_TIFF_G4,
824
 *                          IFF_TIFF_LZW, IFF_TIFF_ZIP, IFF_TIFF_JPEG
825
 * \param[in]    modestr    "a" or "w"
826
 * \return  0 if OK, 1 on error
827
 *
828
 * <pre>
829
 * Notes:
830
 *      (1) For multipage tiff, write the first pix with mode "w" and
831
 *          all subsequent pix with mode "a".
832
 *      (2) For multipage tiff, there is considerable overhead in the
833
 *          machinery to append an image and add the directory entry,
834
 *          and the time required for each image increases linearly
835
 *          with the number of images in the file.
836
 * </pre>
837
 */
838
l_ok
839
pixWriteTiff(const char  *filename,
840
             PIX         *pix,
841
             l_int32      comptype,
842
             const char  *modestr)
843
0
{
844
0
    return pixWriteTiffCustom(filename, pix, comptype, modestr,
845
0
                              NULL, NULL, NULL, NULL);
846
0
}
847
848
849
/*!
850
 * \brief   pixWriteTiffCustom()
851
 *
852
 * \param[in]    filename   to write to
853
 * \param[in]    pix
854
 * \param[in]    comptype   IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS,
855
 *                          IFF_TIFF_G3, IFF_TIFF_G4,
856
 *                          IFF_TIFF_LZW, IFF_TIFF_ZIP, IFF_TIFF_JPEG
857
 * \param[in]    modestr    "a" or "w"
858
 * \param[in]    natags [optional] NUMA of custom tiff tags
859
 * \param[in]    savals [optional] SARRAY of values
860
 * \param[in]    satypes [optional] SARRAY of types
861
 * \param[in]    nasizes [optional] NUMA of sizes
862
 * \return  0 if OK, 1 on error
863
 *
864
 *  Usage:
865
 *      1 This writes a page image to a tiff file, with optional
866
 *          extra tags defined in tiff.h
867
 *      2 For multipage tiff, write the first pix with mode "w" and
868
 *          all subsequent pix with mode "a".
869
 *      3 For the custom tiff tags:
870
 *          a The three arrays {natags, savals, satypes} must all be
871
 *              either NULL or defined and of equal size.
872
 *          b If they are defined, the tags are an array of integers,
873
 *              the vals are an array of values in string format, and
874
 *              the types are an array of types in string format.
875
 *          c All valid tags are definined in tiff.h.
876
 *          d The types allowed are the set of strings:
877
 *                "char*"
878
 *                "l_uint8*"
879
 *                "l_uint16"
880
 *                "l_uint32"
881
 *                "l_int32"
882
 *                "l_float64"
883
 *                "l_uint16-l_uint16" note the dash; use it between the
884
 *                                    two l_uint16 vals in the val string
885
 *              Of these, "char*" and "l_uint16" are the most commonly used.
886
 *          e The last array, nasizes, is also optional.  It is for
887
 *              tags that take an array of bytes for a value, a number of
888
 *              elements in the array, and a type that is either "char*"
889
 *              or "l_uint8*" probably either will work.
890
 *              Use NULL if there are no such tags.
891
 *          f VERY IMPORTANT: if there are any tags that require the
892
 *              extra size value, stored in nasizes, they must be
893
 *              written first!
894
 */
895
l_ok
896
pixWriteTiffCustom(const char  *filename,
897
                   PIX         *pix,
898
                   l_int32      comptype,
899
                   const char  *modestr,
900
                   NUMA        *natags,
901
                   SARRAY      *savals,
902
                   SARRAY      *satypes,
903
                   NUMA        *nasizes)
904
0
{
905
0
l_int32  ret;
906
0
TIFF    *tif;
907
908
0
    if (!filename)
909
0
        return ERROR_INT("filename not defined", __func__, 1);
910
0
    if (!pix)
911
0
        return ERROR_INT("pix not defined", __func__, 1);
912
913
0
    if ((tif = openTiff(filename, modestr)) == NULL)
914
0
        return ERROR_INT("tif not opened", __func__, 1);
915
0
    ret = pixWriteToTiffStream(tif, pix, comptype, natags, savals,
916
0
                               satypes, nasizes);
917
0
    TIFFClose(tif);
918
0
    return ret;
919
0
}
920
921
922
/*--------------------------------------------------------------*
923
 *                       Writing to stream                      *
924
 *--------------------------------------------------------------*/
925
/*!
926
 * \brief   pixWriteStreamTiff()
927
 *
928
 * \param[in]    fp       file stream
929
 * \param[in]    pix
930
 * \param[in]    comptype IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS,
931
 *                        IFF_TIFF_G3, IFF_TIFF_G4,
932
 *                        IFF_TIFF_LZW, IFF_TIFF_ZIP, IFF_TIFF_JPEG
933
 * \return  0 if OK, 1 on error
934
 *
935
 * <pre>
936
 * Notes:
937
 *      (1) This writes a single image to a file stream opened for writing.
938
 *      (2) If the pix has a colormap, it is preserved in the output file.
939
 *      (3) For images with bpp > 1, this resets the comptype, if
940
 *          necessary, to write uncompressed data.
941
 *      (4) G3 and G4 are only defined for 1 bpp.
942
 *      (5) We only allow PACKBITS for bpp = 1, because for bpp > 1
943
 *          it typically expands images that are not synthetically generated.
944
 *      (6) G4 compression is typically about twice as good as G3.
945
 *          G4 is excellent for binary compression of text/line-art,
946
 *          but terrible for halftones and dithered patterns.  (In
947
 *          fact, G4 on halftones can give a file that is larger
948
 *          than uncompressed!)  If a binary image has dithered
949
 *          regions, it is usually better to compress with png.
950
 * </pre>
951
 */
952
l_ok
953
pixWriteStreamTiff(FILE    *fp,
954
                   PIX     *pix,
955
                   l_int32  comptype)
956
0
{
957
0
    return pixWriteStreamTiffWA(fp, pix, comptype, "w");
958
0
}
959
960
961
/*!
962
 * \brief   pixWriteStreamTiffWA()
963
 *
964
 * \param[in]    fp       file stream opened for append or write
965
 * \param[in]    pix
966
 * \param[in]    comptype IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS,
967
 *                        IFF_TIFF_G3, IFF_TIFF_G4,
968
 *                        IFF_TIFF_LZW, IFF_TIFF_ZIP, IFF_TIFF_JPEG
969
 * \param[in]    modestr  "w" or "a"
970
 * \return  0 if OK, 1 on error
971
 *
972
 * <pre>
973
 * Notes:
974
 *      (1) See pixWriteStreamTiff()
975
 * </pre>
976
 */
977
l_ok
978
pixWriteStreamTiffWA(FILE        *fp,
979
                     PIX         *pix,
980
                     l_int32      comptype,
981
                     const char  *modestr)
982
0
{
983
0
TIFF  *tif;
984
985
0
    if (!fp)
986
0
        return ERROR_INT("stream not defined", __func__, 1 );
987
0
    if (!pix)
988
0
        return ERROR_INT("pix not defined", __func__, 1 );
989
0
    if (strcmp(modestr, "w") && strcmp(modestr, "a")) {
990
0
        L_ERROR("modestr = %s; not 'w' or 'a'\n", __func__, modestr);
991
0
        return 1;
992
0
    }
993
994
0
    if (pixGetDepth(pix) != 1 && comptype != IFF_TIFF &&
995
0
        comptype != IFF_TIFF_LZW && comptype != IFF_TIFF_ZIP &&
996
0
        comptype != IFF_TIFF_JPEG) {
997
0
        L_WARNING("invalid compression type %d for bpp > 1; using TIFF_ZIP\n",
998
0
                  __func__, comptype);
999
0
        comptype = IFF_TIFF_ZIP;
1000
0
    }
1001
1002
0
    if ((tif = fopenTiff(fp, modestr)) == NULL)
1003
0
        return ERROR_INT("tif not opened", __func__, 1);
1004
1005
0
    if (pixWriteToTiffStream(tif, pix, comptype, NULL, NULL, NULL, NULL)) {
1006
0
        TIFFCleanup(tif);
1007
0
        return ERROR_INT("tif write error", __func__, 1);
1008
0
    }
1009
1010
0
    TIFFCleanup(tif);
1011
0
    return 0;
1012
0
}
1013
1014
1015
/*!
1016
 * \brief   pixWriteToTiffStream()
1017
 *
1018
 * \param[in]    tif       data structure, opened to a file
1019
 * \param[in]    pix
1020
 * \param[in]    comptype  IFF_TIFF: for any image; no compression
1021
 *                         IFF_TIFF_RLE, IFF_TIFF_PACKBITS: for 1 bpp only
1022
 *                         IFF_TIFF_G4 and IFF_TIFF_G3: for 1 bpp only
1023
 *                         IFF_TIFF_LZW, IFF_TIFF_ZIP: lossless for any image
1024
 *                         IFF_TIFF_JPEG: lossy 8 bpp gray or rgb
1025
 * \param[in]    natags    [optional] NUMA of custom tiff tags
1026
 * \param[in]    savals    [optional] SARRAY of values
1027
 * \param[in]    satypes   [optional] SARRAY of types
1028
 * \param[in]    nasizes   [optional] NUMA of sizes
1029
 * \return  0 if OK, 1 on error
1030
 *
1031
 * <pre>
1032
 * Notes:
1033
 *      (1) This static function should only be called through higher
1034
 *          level functions in this file; namely, pixWriteTiffCustom(),
1035
 *          pixWriteTiff(), pixWriteStreamTiff(), pixWriteMemTiff()
1036
 *          and pixWriteMemTiffCustom().
1037
 *      (2) We only allow PACKBITS for bpp = 1, because for bpp > 1
1038
 *          it typically expands images that are not synthetically generated.
1039
 *      (3) See pixWriteTiffCustom() for details on how to use
1040
 *          the last four parameters for customized tiff tags.
1041
 *      (4) The only valid pixel depths in leptonica are 1, 2, 4, 8, 16
1042
 *          and 32.  However, it is possible, and in some cases desirable,
1043
 *          to write out a tiff file using an rgb pix that has 24 bpp.
1044
 *          This can be created by appending the raster data for a 24 bpp
1045
 *          image (with proper scanline padding) directly to a 24 bpp
1046
 *          pix that was created without a data array.  See note in
1047
 *          pixWriteStreamPng() for an example.
1048
 * </pre>
1049
 */
1050
static l_int32
1051
pixWriteToTiffStream(TIFF    *tif,
1052
                     PIX     *pix,
1053
                     l_int32  comptype,
1054
                     NUMA    *natags,
1055
                     SARRAY  *savals,
1056
                     SARRAY  *satypes,
1057
                     NUMA    *nasizes)
1058
0
{
1059
0
l_uint8   *linebuf, *data;
1060
0
l_uint16   redmap[256], greenmap[256], bluemap[256];
1061
0
l_int32    w, h, d, spp, i, j, k, wpl, bpl, tiffbpl, ncolors, cmapsize;
1062
0
l_int32   *rmap, *gmap, *bmap;
1063
0
l_int32    xres, yres;
1064
0
l_uint32  *line, *ppixel;
1065
0
PIX       *pixt;
1066
0
PIXCMAP   *cmap;
1067
0
char      *text;
1068
1069
0
    if (!tif)
1070
0
        return ERROR_INT("tif stream not defined", __func__, 1);
1071
0
    if (!pix)
1072
0
        return ERROR_INT( "pix not defined", __func__, 1 );
1073
1074
0
    pixSetPadBits(pix, 0);
1075
0
    pixGetDimensions(pix, &w, &h, &d);
1076
0
    spp = pixGetSpp(pix);
1077
0
    xres = pixGetXRes(pix);
1078
0
    yres = pixGetYRes(pix);
1079
0
    if (xres == 0) xres = DefaultResolution;
1080
0
    if (yres == 0) yres = DefaultResolution;
1081
1082
        /* ------------------ Write out the header -------------  */
1083
0
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (l_uint32)RESUNIT_INCH);
1084
0
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, (l_float64)xres);
1085
0
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, (l_float64)yres);
1086
1087
0
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (l_uint32)w);
1088
0
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (l_uint32)h);
1089
0
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1090
1091
0
    if ((text = pixGetText(pix)) != NULL)
1092
0
        TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, text);
1093
1094
0
    if (d == 1 && !pixGetColormap(pix)) {
1095
            /* If d == 1, preserve the colormap.  Note that when
1096
             * d == 1 pix with colormaps are read, the colormaps
1097
             * are removed.  The only pix in leptonica that have
1098
             * colormaps are made programmatically. */
1099
0
        TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
1100
0
    } else if ((d == 32 && spp == 3) || d == 24) {
1101
0
        TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1102
0
        TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)3);
1103
0
        TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,
1104
0
                       (l_uint16)8, (l_uint16)8, (l_uint16)8);
1105
0
    } else if (d == 32 && spp == 4) {
1106
0
        l_uint16  val[1];
1107
0
        val[0] = EXTRASAMPLE_ASSOCALPHA;
1108
0
        TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, (l_uint16)1, &val);
1109
0
        TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1110
0
        TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)4);
1111
0
        TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,
1112
0
                     (l_uint16)8, (l_uint16)8, (l_uint16)8, (l_uint16)8);
1113
0
    } else if (d == 16) {  /* we only support spp = 1, bps = 16 */
1114
0
        TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1115
0
    } else if ((cmap = pixGetColormap(pix)) == NULL) {
1116
0
        TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1117
0
    } else {  /* Save colormap in the tiff; not more than 256 colors */
1118
0
        if (d > 8) {
1119
0
            L_ERROR("d = %d > 8 with colormap!; reducing to 8\n", __func__, d);
1120
0
            d = 8;
1121
0
        }
1122
0
        pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL);
1123
0
        ncolors = pixcmapGetCount(cmap);
1124
0
        ncolors = L_MIN(256, ncolors);  /* max 256 */
1125
0
        cmapsize = 1 << d;
1126
0
        cmapsize = L_MIN(256, cmapsize);  /* power of 2; max 256 */
1127
0
        if (ncolors > cmapsize) {
1128
0
            L_WARNING("too many colors in cmap for tiff; truncating\n",
1129
0
                      __func__);
1130
0
            ncolors = cmapsize;
1131
0
        }
1132
0
        for (i = 0; i < ncolors; i++) {
1133
0
            redmap[i] = (rmap[i] << 8) | rmap[i];
1134
0
            greenmap[i] = (gmap[i] << 8) | gmap[i];
1135
0
            bluemap[i] = (bmap[i] << 8) | bmap[i];
1136
0
        }
1137
0
        for (i = ncolors; i < cmapsize; i++)  /* init, even though not used */
1138
0
            redmap[i] = greenmap[i] = bluemap[i] = 0;
1139
0
        LEPT_FREE(rmap);
1140
0
        LEPT_FREE(gmap);
1141
0
        LEPT_FREE(bmap);
1142
1143
0
        TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
1144
0
        TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)1);
1145
0
        TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (l_uint16)d);
1146
0
        TIFFSetField(tif, TIFFTAG_COLORMAP, redmap, greenmap, bluemap);
1147
0
    }
1148
1149
0
    if (d <= 16) {
1150
0
        TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (l_uint16)d);
1151
0
        TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)1);
1152
0
    }
1153
1154
0
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1155
0
    if (comptype == IFF_TIFF) {  /* no compression */
1156
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1157
0
    } else if (comptype == IFF_TIFF_G4) {
1158
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
1159
0
    } else if (comptype == IFF_TIFF_G3) {
1160
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3);
1161
0
    } else if (comptype == IFF_TIFF_RLE) {
1162
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTRLE);
1163
0
    } else if (comptype == IFF_TIFF_PACKBITS) {
1164
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
1165
0
    } else if (comptype == IFF_TIFF_LZW) {
1166
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
1167
0
    } else if (comptype == IFF_TIFF_ZIP) {
1168
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
1169
0
    } else if (comptype == IFF_TIFF_JPEG) {
1170
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
1171
0
    } else {
1172
0
        L_WARNING("unknown tiff compression; using none\n", __func__);
1173
0
        TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1174
0
    }
1175
1176
        /* This is a no-op if arrays are NULL */
1177
0
    writeCustomTiffTags(tif, natags, savals, satypes, nasizes);
1178
1179
        /* ------------- Write out the image data -------------  */
1180
0
    tiffbpl = TIFFScanlineSize(tif);
1181
0
    wpl = pixGetWpl(pix);
1182
0
    bpl = 4 * wpl;
1183
0
    if (tiffbpl > bpl)
1184
0
        lept_stderr("Big trouble: tiffbpl = %d, bpl = %d\n", tiffbpl, bpl);
1185
0
    if ((linebuf = (l_uint8 *)LEPT_CALLOC(1, bpl)) == NULL)
1186
0
        return ERROR_INT("calloc fail for linebuf", __func__, 1);
1187
1188
        /* Use single strip for image */
1189
0
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, h);
1190
1191
0
    if (d != 24 && d != 32) {
1192
0
        if (d == 16)
1193
0
            pixt = pixEndianTwoByteSwapNew(pix);
1194
0
        else
1195
0
            pixt = pixEndianByteSwapNew(pix);
1196
0
        data = (l_uint8 *)pixGetData(pixt);
1197
0
        for (i = 0; i < h; i++, data += bpl) {
1198
0
            memcpy(linebuf, data, tiffbpl);
1199
0
            if (TIFFWriteScanline(tif, linebuf, i, 0) < 0)
1200
0
                break;
1201
0
        }
1202
0
        pixDestroy(&pixt);
1203
0
    } else if (d == 24) {  /* See note 4 above: special case of 24 bpp rgb */
1204
0
        for (i = 0; i < h; i++) {
1205
0
            line = pixGetData(pix) + i * wpl;
1206
0
            if (TIFFWriteScanline(tif, (l_uint8 *)line, i, 0) < 0)
1207
0
                break;
1208
0
        }
1209
0
    } else {  /* 32 bpp rgb or rgba */
1210
0
        for (i = 0; i < h; i++) {
1211
0
            line = pixGetData(pix) + i * wpl;
1212
0
            for (j = 0, k = 0, ppixel = line; j < w; j++) {
1213
0
                linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
1214
0
                linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
1215
0
                linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
1216
0
                if (spp == 4)
1217
0
                    linebuf[k++] = GET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL);
1218
0
                ppixel++;
1219
0
            }
1220
0
            if (TIFFWriteScanline(tif, linebuf, i, 0) < 0)
1221
0
                break;
1222
0
        }
1223
0
    }
1224
1225
/*    TIFFWriteDirectory(tif); */
1226
0
    LEPT_FREE(linebuf);
1227
1228
0
    return 0;
1229
0
}
1230
1231
1232
/*!
1233
 * \brief   writeCustomTiffTags()
1234
 *
1235
 * \param[in]    tif
1236
 * \param[in]    natags   [optional] NUMA of custom tiff tags
1237
 * \param[in]    savals   [optional] SARRAY of values
1238
 * \param[in]    satypes  [optional] SARRAY of types
1239
 * \param[in]    nasizes  [optional] NUMA of sizes
1240
 * \return  0 if OK, 1 on error
1241
 *
1242
 * <pre>
1243
 * Notes:
1244
 *      (1) This static function should be called indirectly through
1245
 *          higher level functions, such as pixWriteTiffCustom(),
1246
 *          which call pixWriteToTiffStream().  See details in
1247
 *          pixWriteTiffCustom() for using the 4 input arrays.
1248
 *      (2) This is a no-op if the first 3 arrays are all NULL.
1249
 *      (3) Otherwise, the first 3 arrays must be defined and all
1250
 *          of equal size.
1251
 *      (4) The fourth array is always optional.
1252
 *      (5) The most commonly used types are "char*" and "u_int16".
1253
 *          See tiff.h for a full listing of the tiff tags.
1254
 *          Note that many of these tags, in particular the bit tags,
1255
 *          are intended to be private, and cannot be set by this function.
1256
 *          Examples are the STRIPOFFSETS and STRIPBYTECOUNTS tags,
1257
 *          which are bit tags that are automatically set in the header,
1258
 *          and can be extracted using tiffdump.
1259
 * </pre>
1260
 */
1261
static l_int32
1262
writeCustomTiffTags(TIFF    *tif,
1263
                    NUMA    *natags,
1264
                    SARRAY  *savals,
1265
                    SARRAY  *satypes,
1266
                    NUMA    *nasizes)
1267
0
{
1268
0
char      *sval, *type;
1269
0
l_int32    i, n, ns, size, tagval, val;
1270
0
l_float64  dval;
1271
0
l_uint32   uval, uval2;
1272
1273
0
    if (!tif)
1274
0
        return ERROR_INT("tif stream not defined", __func__, 1);
1275
0
    if (!natags && !savals && !satypes)
1276
0
        return 0;
1277
0
    if (!natags || !savals || !satypes)
1278
0
        return ERROR_INT("not all arrays defined", __func__, 1);
1279
0
    n = numaGetCount(natags);
1280
0
    if ((sarrayGetCount(savals) != n) || (sarrayGetCount(satypes) != n))
1281
0
        return ERROR_INT("not all sa the same size", __func__, 1);
1282
1283
        /* The sized arrays (4 args to TIFFSetField) are written first */
1284
0
    if (nasizes) {
1285
0
        ns = numaGetCount(nasizes);
1286
0
        if (ns > n)
1287
0
            return ERROR_INT("too many 4-arg tag calls", __func__, 1);
1288
0
        for (i = 0; i < ns; i++) {
1289
0
            numaGetIValue(natags, i, &tagval);
1290
0
            sval = sarrayGetString(savals, i, L_NOCOPY);
1291
0
            type = sarrayGetString(satypes, i, L_NOCOPY);
1292
0
            numaGetIValue(nasizes, i, &size);
1293
0
            if (strcmp(type, "char*") && strcmp(type, "l_uint8*"))
1294
0
                L_WARNING("array type not char* or l_uint8*; ignore\n",
1295
0
                          __func__);
1296
0
            TIFFSetField(tif, tagval, size, sval);
1297
0
        }
1298
0
    } else {
1299
0
        ns = 0;
1300
0
    }
1301
1302
        /* The typical tags (3 args to TIFFSetField) are now written */
1303
0
    for (i = ns; i < n; i++) {
1304
0
        numaGetIValue(natags, i, &tagval);
1305
0
        sval = sarrayGetString(savals, i, L_NOCOPY);
1306
0
        type = sarrayGetString(satypes, i, L_NOCOPY);
1307
0
        if (!strcmp(type, "char*") || !strcmp(type, "const char*")) {
1308
0
            TIFFSetField(tif, tagval, sval);
1309
0
        } else if (!strcmp(type, "l_uint16")) {
1310
0
            if (sscanf(sval, "%u", &uval) == 1) {
1311
0
                TIFFSetField(tif, tagval, (l_uint16)uval);
1312
0
            } else {
1313
0
                lept_stderr("val %s not of type %s\n", sval, type);
1314
0
                return ERROR_INT("custom tag(s) not written", __func__, 1);
1315
0
            }
1316
0
        } else if (!strcmp(type, "l_uint32")) {
1317
0
            if (sscanf(sval, "%u", &uval) == 1) {
1318
0
                TIFFSetField(tif, tagval, uval);
1319
0
            } else {
1320
0
                lept_stderr("val %s not of type %s\n", sval, type);
1321
0
                return ERROR_INT("custom tag(s) not written", __func__, 1);
1322
0
            }
1323
0
        } else if (!strcmp(type, "l_int32")) {
1324
0
            if (sscanf(sval, "%d", &val) == 1) {
1325
0
                TIFFSetField(tif, tagval, val);
1326
0
            } else {
1327
0
                lept_stderr("val %s not of type %s\n", sval, type);
1328
0
                return ERROR_INT("custom tag(s) not written", __func__, 1);
1329
0
            }
1330
0
        } else if (!strcmp(type, "l_float64")) {
1331
0
            if (sscanf(sval, "%lf", &dval) == 1) {
1332
0
                TIFFSetField(tif, tagval, dval);
1333
0
            } else {
1334
0
                lept_stderr("val %s not of type %s\n", sval, type);
1335
0
                return ERROR_INT("custom tag(s) not written", __func__, 1);
1336
0
            }
1337
0
        } else if (!strcmp(type, "l_uint16-l_uint16")) {
1338
0
            if (sscanf(sval, "%u-%u", &uval, &uval2) == 2) {
1339
0
                TIFFSetField(tif, tagval, (l_uint16)uval, (l_uint16)uval2);
1340
0
            } else {
1341
0
                lept_stderr("val %s not of type %s\n", sval, type);
1342
0
                return ERROR_INT("custom tag(s) not written", __func__, 1);
1343
0
            }
1344
0
        } else {
1345
0
            lept_stderr("unknown type %s\n",type);
1346
0
            return ERROR_INT("unknown type; tag(s) not written", __func__, 1);
1347
0
        }
1348
0
    }
1349
0
    return 0;
1350
0
}
1351
1352
1353
/*--------------------------------------------------------------*
1354
 *               Reading and writing multipage tiff             *
1355
 *--------------------------------------------------------------*/
1356
/*!
1357
 * \brief   pixReadFromMultipageTiff()
1358
 *
1359
 * \param[in]      fname     filename
1360
 * \param[in,out]  poffset   set offset to 0 for first image
1361
 * \return  pix, or NULL on error or if previous call returned the last image
1362
 *
1363
 * <pre>
1364
 * Notes:
1365
 *      (1) This allows overhead for traversal of a multipage tiff file
1366
 *          to be linear in the number of images.  This will also work
1367
 *          with a singlepage tiff file.
1368
 *      (2) No TIFF internal data structures are exposed to the caller
1369
 *          (thanks to Jeff Breidenbach).
1370
 *      (3) offset is the byte offset of a particular image in a multipage
1371
 *          tiff file. To get the first image in the file, input the
1372
 *          special offset value of 0.
1373
 *      (4) The offset is updated to point to the next image, for a
1374
 *          subsequent call.
1375
 *      (5) On the last image, the offset returned is 0.  Exit the loop
1376
 *          when the returned offset is 0.
1377
 *      (6) For reading a multipage tiff from a memory buffer, see
1378
 *            pixReadMemFromMultipageTiff()
1379
 *      (7) Example usage for reading all the images in the tif file:
1380
 *            size_t offset = 0;
1381
 *            do {
1382
 *                Pix *pix = pixReadFromMultipageTiff(filename, &offset);
1383
 *                // do something with pix
1384
 *            } while (offset != 0);
1385
 * </pre>
1386
 */
1387
PIX *
1388
pixReadFromMultipageTiff(const char  *fname,
1389
                         size_t      *poffset)
1390
0
{
1391
0
l_int32  retval;
1392
0
size_t   offset;
1393
0
PIX     *pix;
1394
0
TIFF    *tif;
1395
1396
0
    if (!fname)
1397
0
        return (PIX *)ERROR_PTR("fname not defined", __func__, NULL);
1398
0
    if (!poffset)
1399
0
        return (PIX *)ERROR_PTR("&offset not defined", __func__, NULL);
1400
1401
0
    if ((tif = openTiff(fname, "r")) == NULL) {
1402
0
        L_ERROR("tif open failed for %s\n", __func__, fname);
1403
0
        return NULL;
1404
0
    }
1405
1406
        /* Set ptrs in the TIFF to the beginning of the image */
1407
0
    offset = *poffset;
1408
0
    retval = (offset == 0) ? TIFFSetDirectory(tif, 0)
1409
0
                            : TIFFSetSubDirectory(tif, offset);
1410
0
    if (retval == 0) {
1411
0
        TIFFClose(tif);
1412
0
        return NULL;
1413
0
    }
1414
1415
0
    if ((pix = pixReadFromTiffStream(tif)) == NULL) {
1416
0
        TIFFClose(tif);
1417
0
        return NULL;
1418
0
    }
1419
1420
        /* Advance to the next image and return the new offset */
1421
0
    TIFFReadDirectory(tif);
1422
0
    *poffset = TIFFCurrentDirOffset(tif);
1423
0
    TIFFClose(tif);
1424
0
    return pix;
1425
0
}
1426
1427
1428
/*!
1429
 * \brief   pixaReadMultipageTiff()
1430
 *
1431
 * \param[in]    filename    input tiff file
1432
 * \return  pixa of page images, or NULL on error
1433
 */
1434
PIXA *
1435
pixaReadMultipageTiff(const char  *filename)
1436
0
{
1437
0
l_int32  i, npages;
1438
0
FILE    *fp;
1439
0
PIX     *pix;
1440
0
PIXA    *pixa;
1441
0
TIFF    *tif;
1442
1443
0
    if (!filename)
1444
0
        return (PIXA *)ERROR_PTR("filename not defined", __func__, NULL);
1445
1446
0
    if ((fp = fopenReadStream(filename)) == NULL)
1447
0
        return (PIXA *)ERROR_PTR_1("stream not opened",
1448
0
                                   filename, __func__, NULL);
1449
0
    if (fileFormatIsTiff(fp)) {
1450
0
        tiffGetCount(fp, &npages);
1451
0
        L_INFO(" Tiff: %d pages\n", __func__, npages);
1452
0
    } else {
1453
0
        return (PIXA *)ERROR_PTR_1("file is not tiff",
1454
0
                                   filename, __func__, NULL);
1455
0
    }
1456
1457
0
    if ((tif = fopenTiff(fp, "r")) == NULL)
1458
0
        return (PIXA *)ERROR_PTR_1("tif not opened",
1459
0
                                   filename, __func__, NULL);
1460
1461
0
    pixa = pixaCreate(npages);
1462
0
    pix = NULL;
1463
0
    for (i = 0; i < npages; i++) {
1464
0
        if ((pix = pixReadFromTiffStream(tif)) != NULL) {
1465
0
            pixaAddPix(pixa, pix, L_INSERT);
1466
0
        } else {
1467
0
            L_WARNING("pix not read for page %d\n", __func__, i);
1468
0
        }
1469
1470
            /* Advance to the next directory (i.e., the next image) */
1471
0
        if (TIFFReadDirectory(tif) == 0)
1472
0
            break;
1473
0
    }
1474
1475
0
    fclose(fp);
1476
0
    TIFFCleanup(tif);
1477
0
    return pixa;
1478
0
}
1479
1480
1481
/*!
1482
 * \brief   pixaWriteMultipageTiff()
1483
 *
1484
 * \param[in]    fname      input tiff file
1485
 * \param[in]    pixa       any depth; colormap will be removed
1486
 * \return  0 if OK, 1 on error
1487
 *
1488
 * <pre>
1489
 * Notes:
1490
 *      (1) The tiff directory overhead is O(n^2).  I have not been
1491
 *          able to reduce it to O(n).  The overhead for n = 2000 is
1492
 *          about 1 second.
1493
 * </pre>
1494
 */
1495
l_ok
1496
pixaWriteMultipageTiff(const char  *fname,
1497
                       const PIXA  *pixa)
1498
0
{
1499
0
const char  *modestr;
1500
0
l_int32      i, n;
1501
0
PIX         *pix1;
1502
1503
0
    if (!fname)
1504
0
        return ERROR_INT("fname not defined", __func__, 1);
1505
0
    if (!pixa)
1506
0
        return ERROR_INT("pixa not defined", __func__, 1);
1507
1508
0
    n = pixaGetCount(pixa);
1509
0
    for (i = 0; i < n; i++) {
1510
0
        modestr = (i == 0) ? "w" : "a";
1511
0
        pix1 = pixaGetPix(pixa, i, L_CLONE);
1512
0
        if (pixGetDepth(pix1) == 1)
1513
0
            pixWriteTiff(fname, pix1, IFF_TIFF_G4, modestr);
1514
0
        else
1515
0
            pixWriteTiff(fname, pix1, IFF_TIFF_ZIP, modestr);
1516
0
        pixDestroy(&pix1);
1517
0
    }
1518
1519
0
    return 0;
1520
0
}
1521
1522
1523
/*!
1524
 * \brief   writeMultipageTiff()
1525
 *
1526
 * \param[in]    dirin   input directory
1527
 * \param[in]    substr  [optional] substring filter on filenames; can be NULL
1528
 * \param[in]    fileout output multipage tiff file
1529
 * \return  0 if OK, 1 on error
1530
 *
1531
 * <pre>
1532
 * Notes:
1533
 *      (1) This writes a set of image files in a directory out
1534
 *          as a multipage tiff file.  The images can be in any
1535
 *          initial file format.
1536
 *      (2) Images with a colormap have the colormap removed before
1537
 *          re-encoding as tiff.
1538
 *      (3) All images are encoded losslessly.  Those with 1 bpp are
1539
 *          encoded 'g4'.  The rest are encoded as 'zip' (flate encoding).
1540
 *          Because it is lossless, this is an expensive method for
1541
 *          saving most rgb images.
1542
 *      (4) The tiff directory overhead is quadratic in the number of
1543
 *          images.  To avoid this for very large numbers of images to be
1544
 *          written, apply the method used in pixaWriteMultipageTiff().
1545
 * </pre>
1546
 */
1547
l_ok
1548
writeMultipageTiff(const char  *dirin,
1549
                   const char  *substr,
1550
                   const char  *fileout)
1551
0
{
1552
0
SARRAY  *sa;
1553
1554
0
    if (!dirin)
1555
0
        return ERROR_INT("dirin not defined", __func__, 1);
1556
0
    if (!fileout)
1557
0
        return ERROR_INT("fileout not defined", __func__, 1);
1558
1559
        /* Get all filtered and sorted full pathnames. */
1560
0
    sa = getSortedPathnamesInDirectory(dirin, substr, 0, 0);
1561
1562
        /* Generate the tiff file */
1563
0
    writeMultipageTiffSA(sa, fileout);
1564
0
    sarrayDestroy(&sa);
1565
0
    return 0;
1566
0
}
1567
1568
1569
/*!
1570
 * \brief   writeMultipageTiffSA()
1571
 *
1572
 * \param[in]    sa       string array of full path names
1573
 * \param[in]    fileout  output ps file
1574
 * \return  0 if OK, 1 on error
1575
 *
1576
 * <pre>
1577
 * Notes:
1578
 *      (1) See writeMultipageTiff()
1579
 * </pre>
1580
 */
1581
l_ok
1582
writeMultipageTiffSA(SARRAY      *sa,
1583
                     const char  *fileout)
1584
0
{
1585
0
char        *fname;
1586
0
const char  *op;
1587
0
l_int32      i, nfiles, firstfile, format;
1588
0
PIX         *pix;
1589
1590
0
    if (!sa)
1591
0
        return ERROR_INT("sa not defined", __func__, 1);
1592
0
    if (!fileout)
1593
0
        return ERROR_INT("fileout not defined", __func__, 1);
1594
1595
0
    nfiles = sarrayGetCount(sa);
1596
0
    firstfile = TRUE;
1597
0
    for (i = 0; i < nfiles; i++) {
1598
0
        op = (firstfile) ? "w" : "a";
1599
0
        fname = sarrayGetString(sa, i, L_NOCOPY);
1600
0
        findFileFormat(fname, &format);
1601
0
        if (format == IFF_UNKNOWN) {
1602
0
            L_INFO("format of %s not known\n", __func__, fname);
1603
0
            continue;
1604
0
        }
1605
1606
0
        if ((pix = pixRead(fname)) == NULL) {
1607
0
            L_WARNING("pix not made for file: %s\n", __func__, fname);
1608
0
            continue;
1609
0
        }
1610
0
        if (pixGetDepth(pix) == 1)
1611
0
            pixWriteTiff(fileout, pix, IFF_TIFF_G4, op);
1612
0
        else
1613
0
            pixWriteTiff(fileout, pix, IFF_TIFF_ZIP, op);
1614
0
        firstfile = FALSE;
1615
0
        pixDestroy(&pix);
1616
0
    }
1617
1618
0
    return 0;
1619
0
}
1620
1621
1622
/*--------------------------------------------------------------*
1623
 *                    Print info to stream                      *
1624
 *--------------------------------------------------------------*/
1625
/*!
1626
 * \brief   fprintTiffInfo()
1627
 *
1628
 * \param[in]    fpout    stream for output of tag data
1629
 * \param[in]    tiffile  input
1630
 * \return  0 if OK; 1 on error
1631
 */
1632
l_ok
1633
fprintTiffInfo(FILE        *fpout,
1634
               const char  *tiffile)
1635
0
{
1636
0
TIFF  *tif;
1637
1638
0
    if (!tiffile)
1639
0
        return ERROR_INT("tiffile not defined", __func__, 1);
1640
0
    if (!fpout)
1641
0
        return ERROR_INT("stream out not defined", __func__, 1);
1642
1643
0
    if ((tif = openTiff(tiffile, "rb")) == NULL)
1644
0
        return ERROR_INT("tif not open for read", __func__, 1);
1645
1646
0
    TIFFPrintDirectory(tif, fpout, 0);
1647
0
    TIFFClose(tif);
1648
1649
0
    return 0;
1650
0
}
1651
1652
1653
/*--------------------------------------------------------------*
1654
 *                        Get page count                        *
1655
 *--------------------------------------------------------------*/
1656
/*!
1657
 * \brief   tiffGetCount()
1658
 *
1659
 * \param[in]    fp   file stream opened for read
1660
 * \param[out]   pn   number of images
1661
 * \return  0 if OK; 1 on error
1662
 */
1663
l_ok
1664
tiffGetCount(FILE     *fp,
1665
             l_int32  *pn)
1666
0
{
1667
0
l_int32  i;
1668
0
TIFF    *tif;
1669
1670
0
    if (!fp)
1671
0
        return ERROR_INT("stream not defined", __func__, 1);
1672
0
    if (!pn)
1673
0
        return ERROR_INT("&n not defined", __func__, 1);
1674
0
    *pn = 0;
1675
1676
0
    if ((tif = fopenTiff(fp, "r")) == NULL)
1677
0
        return ERROR_INT("tif not open for read", __func__, 1);
1678
1679
0
    for (i = 1; ; i++) {
1680
0
        if (TIFFReadDirectory(tif) == 0)
1681
0
            break;
1682
0
        if (i == ManyPagesInTiffFile + 1) {
1683
0
            L_WARNING("big file: more than %d pages\n", __func__,
1684
0
                      ManyPagesInTiffFile);
1685
0
        }
1686
0
    }
1687
0
    *pn = i;
1688
0
    TIFFCleanup(tif);
1689
0
    return 0;
1690
0
}
1691
1692
1693
/*--------------------------------------------------------------*
1694
 *                   Get resolution from tif                    *
1695
 *--------------------------------------------------------------*/
1696
/*!
1697
 * \brief   getTiffResolution()
1698
 *
1699
 * \param[in]    fp            file stream opened for read
1700
 * \param[out]   pxres, pyres  resolution in ppi
1701
 * \return  0 if OK; 1 on error
1702
 *
1703
 * <pre>
1704
 * Notes:
1705
 *      (1) If neither resolution field is set, this is not an error;
1706
 *          the returned resolution values are 0 (designating 'unknown').
1707
 * </pre>
1708
 */
1709
l_ok
1710
getTiffResolution(FILE     *fp,
1711
                  l_int32  *pxres,
1712
                  l_int32  *pyres)
1713
0
{
1714
0
TIFF  *tif;
1715
1716
0
    if (!pxres || !pyres)
1717
0
        return ERROR_INT("&xres and &yres not both defined", __func__, 1);
1718
0
    *pxres = *pyres = 0;
1719
0
    if (!fp)
1720
0
        return ERROR_INT("stream not opened", __func__, 1);
1721
1722
0
    if ((tif = fopenTiff(fp, "r")) == NULL)
1723
0
        return ERROR_INT("tif not open for read", __func__, 1);
1724
0
    getTiffStreamResolution(tif, pxres, pyres);
1725
0
    TIFFCleanup(tif);
1726
0
    return 0;
1727
0
}
1728
1729
1730
/*!
1731
 * \brief   getTiffStreamResolution()
1732
 *
1733
 * \param[in]    tif            TIFF handle opened for read
1734
 * \param[out]   pxres, pyres   resolution in ppi
1735
 * \return  0 if OK; 1 on error
1736
 *
1737
 * <pre>
1738
 * Notes:
1739
 *      (1) If neither resolution field is set, this is not an error;
1740
 *          the returned resolution values are 0 (designating 'unknown').
1741
 * </pre>
1742
 */
1743
static l_int32
1744
getTiffStreamResolution(TIFF     *tif,
1745
                        l_int32  *pxres,
1746
                        l_int32  *pyres)
1747
4
{
1748
4
l_uint16   resunit;
1749
4
l_int32    foundxres, foundyres;
1750
4
l_float32  fxres, fyres;
1751
1752
4
    if (!tif)
1753
0
        return ERROR_INT("tif not opened", __func__, 1);
1754
4
    if (!pxres || !pyres)
1755
0
        return ERROR_INT("&xres and &yres not both defined", __func__, 1);
1756
4
    *pxres = *pyres = 0;
1757
1758
4
    TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
1759
4
    foundxres = TIFFGetField(tif, TIFFTAG_XRESOLUTION, &fxres);
1760
4
    foundyres = TIFFGetField(tif, TIFFTAG_YRESOLUTION, &fyres);
1761
4
    if (!foundxres && !foundyres) return 1;
1762
4
    if (isnan(fxres) || isnan(fyres)) return 1;
1763
4
    if (!foundxres && foundyres)
1764
0
        fxres = fyres;
1765
4
    else if (foundxres && !foundyres)
1766
0
        fyres = fxres;
1767
1768
        /* Avoid overflow into int32; set max fxres and fyres to 5 x 10^8 */
1769
4
    if (fxres < 0 || fxres > (1L << 29) || fyres < 0 || fyres > (1L << 29))
1770
0
        return ERROR_INT("fxres and/or fyres values are invalid", __func__, 1);
1771
1772
4
    if (resunit == RESUNIT_CENTIMETER) {  /* convert to ppi */
1773
0
        *pxres = (l_int32)(2.54 * fxres + 0.5);
1774
0
        *pyres = (l_int32)(2.54 * fyres + 0.5);
1775
4
    } else {
1776
4
        *pxres = (l_int32)(fxres + 0.5);
1777
4
        *pyres = (l_int32)(fyres + 0.5);
1778
4
    }
1779
1780
4
    return 0;
1781
4
}
1782
1783
1784
/*--------------------------------------------------------------*
1785
 *              Get some tiff header information                *
1786
 *--------------------------------------------------------------*/
1787
/*!
1788
 * \brief   readHeaderTiff()
1789
 *
1790
 * \param[in]    filename
1791
 * \param[in]    n          page image number: 0-based
1792
 * \param[out]   pw         [optional] width
1793
 * \param[out]   ph         [optional] height
1794
 * \param[out]   pbps       [optional] bits per sample -- 1, 2, 4 or 8
1795
 * \param[out]   pspp       [optional] samples per pixel -- 1 or 3
1796
 * \param[out]   pres       [optional] resolution in x dir; NULL to ignore
1797
 * \param[out]   pcmap      [optional] colormap exists; input NULL to ignore
1798
 * \param[out]   pformat    [optional] tiff format; input NULL to ignore
1799
 * \return  0 if OK, 1 on error
1800
 *
1801
 * <pre>
1802
 * Notes:
1803
 *      (1) If there is a colormap, cmap is returned as 1; else 0.
1804
 *      (2) If %n is equal to or greater than the number of images, returns 1.
1805
 * </pre>
1806
 */
1807
l_ok
1808
readHeaderTiff(const char *filename,
1809
               l_int32     n,
1810
               l_int32    *pw,
1811
               l_int32    *ph,
1812
               l_int32    *pbps,
1813
               l_int32    *pspp,
1814
               l_int32    *pres,
1815
               l_int32    *pcmap,
1816
               l_int32    *pformat)
1817
0
{
1818
0
l_int32  ret;
1819
0
FILE    *fp;
1820
1821
0
    if (pw) *pw = 0;
1822
0
    if (ph) *ph = 0;
1823
0
    if (pbps) *pbps = 0;
1824
0
    if (pspp) *pspp = 0;
1825
0
    if (pres) *pres = 0;
1826
0
    if (pcmap) *pcmap = 0;
1827
0
    if (pformat) *pformat = 0;
1828
0
    if (!filename)
1829
0
        return ERROR_INT("filename not defined", __func__, 1);
1830
0
    if (!pw && !ph && !pbps && !pspp && !pres && !pcmap && !pformat)
1831
0
        return ERROR_INT("no results requested", __func__, 1);
1832
1833
0
    if ((fp = fopenReadStream(filename)) == NULL)
1834
0
        return ERROR_INT_1("image file not found", filename, __func__, 1);
1835
0
    ret = freadHeaderTiff(fp, n, pw, ph, pbps, pspp, pres, pcmap, pformat);
1836
0
    fclose(fp);
1837
0
    return ret;
1838
0
}
1839
1840
1841
/*!
1842
 * \brief   freadHeaderTiff()
1843
 *
1844
 * \param[in]    fp       file stream
1845
 * \param[in]    n        page image number: 0-based
1846
 * \param[out]   pw       [optional] width
1847
 * \param[out]   ph       [optional] height
1848
 * \param[out]   pbps     [optional] bits per sample -- 1, 2, 4 or 8
1849
 * \param[out]   pspp     [optional] samples per pixel -- 1 or 3
1850
 * \param[out]   pres     [optional] resolution in x dir; NULL to ignore
1851
 * \param[out]   pcmap    [optional] colormap exists; input NULL to ignore
1852
 * \param[out]   pformat  [optional] tiff format; input NULL to ignore
1853
 * \return  0 if OK, 1 on error
1854
 *
1855
 * <pre>
1856
 * Notes:
1857
 *      (1) If there is a colormap, cmap is returned as 1; else 0.
1858
 *      (2) If %n is equal to or greater than the number of images, returns 1.
1859
 * </pre>
1860
 */
1861
l_ok
1862
freadHeaderTiff(FILE     *fp,
1863
                l_int32   n,
1864
                l_int32  *pw,
1865
                l_int32  *ph,
1866
                l_int32  *pbps,
1867
                l_int32  *pspp,
1868
                l_int32  *pres,
1869
                l_int32  *pcmap,
1870
                l_int32  *pformat)
1871
0
{
1872
0
l_int32  i, ret, format;
1873
0
TIFF    *tif;
1874
1875
0
    if (pw) *pw = 0;
1876
0
    if (ph) *ph = 0;
1877
0
    if (pbps) *pbps = 0;
1878
0
    if (pspp) *pspp = 0;
1879
0
    if (pres) *pres = 0;
1880
0
    if (pcmap) *pcmap = 0;
1881
0
    if (pformat) *pformat = 0;
1882
0
    if (!fp)
1883
0
        return ERROR_INT("stream not defined", __func__, 1);
1884
0
    if (n < 0)
1885
0
        return ERROR_INT("image index must be >= 0", __func__, 1);
1886
0
    if (!pw && !ph && !pbps && !pspp && !pres && !pcmap && !pformat)
1887
0
        return ERROR_INT("no results requested", __func__, 1);
1888
1889
0
    findFileFormatStream(fp, &format);
1890
0
    if (!L_FORMAT_IS_TIFF(format))
1891
0
        return ERROR_INT("file not tiff format", __func__, 1);
1892
1893
0
    if ((tif = fopenTiff(fp, "r")) == NULL)
1894
0
        return ERROR_INT("tif not open for read", __func__, 1);
1895
1896
0
    for (i = 0; i < n; i++) {
1897
0
        if (TIFFReadDirectory(tif) == 0)
1898
0
            return ERROR_INT("image n not found in file", __func__, 1);
1899
0
    }
1900
1901
0
    ret = tiffReadHeaderTiff(tif, pw, ph, pbps, pspp, pres, pcmap, pformat);
1902
0
    TIFFCleanup(tif);
1903
0
    return ret;
1904
0
}
1905
1906
1907
/*!
1908
 * \brief   readHeaderMemTiff()
1909
 *
1910
 * \param[in]    cdata     const; tiff-encoded
1911
 * \param[in]    size      size of data
1912
 * \param[in]    n         page image number: 0-based
1913
 * \param[out]   pw        [optional] width
1914
 * \param[out]   ph        [optional] height
1915
 * \param[out]   pbps      [optional] bits per sample -- 1, 2, 4 or 8
1916
 * \param[out]   pspp      [optional] samples per pixel -- 1 or 3
1917
 * \param[out]   pres      [optional] resolution in x dir; NULL to ignore
1918
 * \param[out]   pcmap     [optional] colormap exists; input NULL to ignore
1919
 * \param[out]   pformat   [optional] tiff format; input NULL to ignore
1920
 * \return  0 if OK, 1 on error
1921
 *
1922
 * <pre>
1923
 * Notes:
1924
 *      (1) Use TIFFClose(); TIFFCleanup() doesn't free internal memstream.
1925
 *      (2) Returns res = 0 if not set in the file.
1926
 * </pre>
1927
 */
1928
l_ok
1929
readHeaderMemTiff(const l_uint8  *cdata,
1930
                  size_t          size,
1931
                  l_int32         n,
1932
                  l_int32        *pw,
1933
                  l_int32        *ph,
1934
                  l_int32        *pbps,
1935
                  l_int32        *pspp,
1936
                  l_int32        *pres,
1937
                  l_int32        *pcmap,
1938
                  l_int32        *pformat)
1939
0
{
1940
0
l_uint8  *data;
1941
0
l_int32   i, ret;
1942
0
TIFF     *tif;
1943
1944
0
    if (pw) *pw = 0;
1945
0
    if (ph) *ph = 0;
1946
0
    if (pbps) *pbps = 0;
1947
0
    if (pspp) *pspp = 0;
1948
0
    if (pres) *pres = 0;
1949
0
    if (pcmap) *pcmap = 0;
1950
0
    if (pformat) *pformat = 0;
1951
0
    if (!pw && !ph && !pbps && !pspp && !pres && !pcmap && !pformat)
1952
0
        return ERROR_INT("no results requested", __func__, 1);
1953
0
    if (!cdata)
1954
0
        return ERROR_INT("cdata not defined", __func__, 1);
1955
1956
        /* Open a tiff stream to memory */
1957
0
    data = (l_uint8 *)cdata;  /* we're really not going to change this */
1958
0
    if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL)
1959
0
        return ERROR_INT("tiff stream not opened", __func__, 1);
1960
1961
0
    for (i = 0; i < n; i++) {
1962
0
        if (TIFFReadDirectory(tif) == 0) {
1963
0
            TIFFClose(tif);
1964
0
            return ERROR_INT("image n not found in file", __func__, 1);
1965
0
        }
1966
0
    }
1967
1968
0
    ret = tiffReadHeaderTiff(tif, pw, ph, pbps, pspp, pres, pcmap, pformat);
1969
0
    TIFFClose(tif);
1970
0
    return ret;
1971
0
}
1972
1973
1974
/*!
1975
 * \brief   tiffReadHeaderTiff()
1976
 *
1977
 * \param[in]    tif
1978
 * \param[out]   pw        [optional] width
1979
 * \param[out]   ph        [optional] height
1980
 * \param[out]   pbps      [optional] bits per sample -- 1, 2, 4 or 8
1981
 * \param[out]   pspp      [optional] samples per pixel -- 1 or 3
1982
 * \param[out]   pres      [optional] resolution in x dir; NULL to ignore
1983
 * \param[out]   pcmap     [optional] cmap exists; input NULL to ignore
1984
 * \param[out]   pformat   [optional] tiff format; input NULL to ignore
1985
 * \return  0 if OK, 1 on error
1986
 */
1987
static l_int32
1988
tiffReadHeaderTiff(TIFF     *tif,
1989
                   l_int32  *pw,
1990
                   l_int32  *ph,
1991
                   l_int32  *pbps,
1992
                   l_int32  *pspp,
1993
                   l_int32  *pres,
1994
                   l_int32  *pcmap,
1995
                   l_int32  *pformat)
1996
0
{
1997
0
l_uint16   tiffcomp;
1998
0
l_uint16   bps, spp;
1999
0
l_uint16  *rmap, *gmap, *bmap;
2000
0
l_int32    xres, yres;
2001
0
l_uint32   w, h;
2002
2003
0
    if (!tif)
2004
0
        return ERROR_INT("tif not opened", __func__, 1);
2005
2006
0
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
2007
0
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
2008
0
    TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps);
2009
0
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
2010
0
    if (w < 1 || h < 1)
2011
0
        return ERROR_INT("tif w and h not both > 0", __func__, 1);
2012
0
    if (bps != 1 && bps != 2 && bps != 4 && bps != 8 && bps != 16)
2013
0
        return ERROR_INT("bps not in set {1,2,4,8,16}", __func__, 1);
2014
0
    if (spp != 1 && spp != 2 && spp != 3 && spp != 4)
2015
0
        return ERROR_INT("spp not in set {1,2,3,4}", __func__, 1);
2016
0
    if (pw) *pw = w;
2017
0
    if (ph) *ph = h;
2018
0
    if (pbps) *pbps = bps;
2019
0
    if (pspp) *pspp = spp;
2020
0
    if (pres) {
2021
0
        if (getTiffStreamResolution(tif, &xres, &yres) == 0)
2022
0
            *pres = (l_int32)xres;
2023
0
    }
2024
0
    if (pcmap) {
2025
0
        if (TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap))
2026
0
            *pcmap = 1;
2027
0
    }
2028
0
    if (pformat) {
2029
0
        TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp);
2030
0
        *pformat = getTiffCompressedFormat(tiffcomp);
2031
0
    }
2032
0
    return 0;
2033
0
}
2034
2035
2036
/*!
2037
 * \brief   findTiffCompression()
2038
 *
2039
 * \param[in]    fp         file stream; must be rewound to BOF
2040
 * \param[out]   pcomptype  compression type
2041
 * \return  0 if OK, 1 on error
2042
 *
2043
 * <pre>
2044
 * Notes:
2045
 *      (1) The returned compression type is that defined in
2046
 *          the enum in imageio.h.  It is not the tiff flag value.
2047
 *      (2) The compression type is initialized to IFF_UNKNOWN.
2048
 *          If it is not one of the specified types, the returned
2049
 *          type is IFF_TIFF, which indicates no compression.
2050
 *      (3) When this function is called, the stream must be at BOF.
2051
 *          If the opened stream is to be used again to read the
2052
 *          file, it must be rewound to BOF after calling this function.
2053
 * </pre>
2054
 */
2055
l_ok
2056
findTiffCompression(FILE     *fp,
2057
                    l_int32  *pcomptype)
2058
0
{
2059
0
l_uint16  tiffcomp;
2060
0
TIFF     *tif;
2061
2062
0
    if (!pcomptype)
2063
0
        return ERROR_INT("&comptype not defined", __func__, 1);
2064
0
    *pcomptype = IFF_UNKNOWN;  /* init */
2065
0
    if (!fp)
2066
0
        return ERROR_INT("stream not defined", __func__, 1);
2067
2068
0
    if ((tif = fopenTiff(fp, "r")) == NULL)
2069
0
        return ERROR_INT("tif not opened", __func__, 1);
2070
0
    TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp);
2071
0
    *pcomptype = getTiffCompressedFormat(tiffcomp);
2072
0
    TIFFCleanup(tif);
2073
0
    return 0;
2074
0
}
2075
2076
2077
/*!
2078
 * \brief   getTiffCompressedFormat()
2079
 *
2080
 * \param[in]    tiffcomp    defined in tiff.h
2081
 * \return  compression format defined in imageio.h
2082
 *
2083
 * <pre>
2084
 * Notes:
2085
 *      (1) The input must be the actual tiff compression type
2086
 *          returned by a tiff library call.  It should always be
2087
 *          a valid tiff type.
2088
 *      (2) The return type is defined in the enum in imageio.h.
2089
 * </pre>
2090
 */
2091
static l_int32
2092
getTiffCompressedFormat(l_uint16  tiffcomp)
2093
4
{
2094
4
l_int32  comptype;
2095
2096
4
    switch (tiffcomp)
2097
4
    {
2098
4
    case COMPRESSION_CCITTFAX4:
2099
4
        comptype = IFF_TIFF_G4;
2100
4
        break;
2101
0
    case COMPRESSION_CCITTFAX3:
2102
0
        comptype = IFF_TIFF_G3;
2103
0
        break;
2104
0
    case COMPRESSION_CCITTRLE:
2105
0
        comptype = IFF_TIFF_RLE;
2106
0
        break;
2107
0
    case COMPRESSION_PACKBITS:
2108
0
        comptype = IFF_TIFF_PACKBITS;
2109
0
        break;
2110
0
    case COMPRESSION_LZW:
2111
0
        comptype = IFF_TIFF_LZW;
2112
0
        break;
2113
0
    case COMPRESSION_ADOBE_DEFLATE:
2114
0
        comptype = IFF_TIFF_ZIP;
2115
0
        break;
2116
0
    case COMPRESSION_JPEG:
2117
0
        comptype = IFF_TIFF_JPEG;
2118
0
        break;
2119
0
    default:
2120
0
        comptype = IFF_TIFF;
2121
0
        break;
2122
4
    }
2123
4
    return comptype;
2124
4
}
2125
2126
2127
/*--------------------------------------------------------------*
2128
 *                   Extraction of tiff g4 data                 *
2129
 *--------------------------------------------------------------*/
2130
/*!
2131
 * \brief   extractG4DataFromFile()
2132
 *
2133
 * \param[in]    filein
2134
 * \param[out]   pdata         binary data of ccitt g4 encoded stream
2135
 * \param[out]   pnbytes       size of binary data
2136
 * \param[out]   pw            [optional] image width
2137
 * \param[out]   ph            [optional] image height
2138
 * \param[out]   pminisblack   [optional] boolean
2139
 * \return  0 if OK, 1 on error
2140
 */
2141
l_ok
2142
extractG4DataFromFile(const char  *filein,
2143
                      l_uint8    **pdata,
2144
                      size_t      *pnbytes,
2145
                      l_int32     *pw,
2146
                      l_int32     *ph,
2147
                      l_int32     *pminisblack)
2148
0
{
2149
0
l_uint8  *inarray, *data;
2150
0
l_uint16  minisblack, comptype;  /* accessors require l_uint16 */
2151
0
l_int32   istiff;
2152
0
l_uint32  w, h, rowsperstrip;  /* accessors require l_uint32 */
2153
0
l_uint32  diroff;
2154
0
size_t    fbytes, nbytes;
2155
0
FILE     *fpin;
2156
0
TIFF     *tif;
2157
2158
0
    if (!pdata)
2159
0
        return ERROR_INT("&data not defined", __func__, 1);
2160
0
    if (!pnbytes)
2161
0
        return ERROR_INT("&nbytes not defined", __func__, 1);
2162
0
    if (!pw && !ph && !pminisblack)
2163
0
        return ERROR_INT("no output data requested", __func__, 1);
2164
0
    *pdata = NULL;
2165
0
    *pnbytes = 0;
2166
2167
0
    if ((fpin = fopenReadStream(filein)) == NULL)
2168
0
        return ERROR_INT_1("stream not opened to file", filein, __func__, 1);
2169
0
    istiff = fileFormatIsTiff(fpin);
2170
0
    fclose(fpin);
2171
0
    if (!istiff)
2172
0
        return ERROR_INT_1("filein not tiff", filein, __func__, 1);
2173
2174
0
    if ((inarray = l_binaryRead(filein, &fbytes)) == NULL)
2175
0
        return ERROR_INT_1("inarray not made", filein, __func__, 1);
2176
2177
        /* Get metadata about the image */
2178
0
    if ((tif = openTiff(filein, "rb")) == NULL) {
2179
0
        LEPT_FREE(inarray);
2180
0
        return ERROR_INT_1("tif not open for read", filein, __func__, 1);
2181
0
    }
2182
0
    TIFFGetField(tif, TIFFTAG_COMPRESSION, &comptype);
2183
0
    if (comptype != COMPRESSION_CCITTFAX4) {
2184
0
        LEPT_FREE(inarray);
2185
0
        TIFFClose(tif);
2186
0
        return ERROR_INT_1("filein is not g4 compressed", filein, __func__, 1);
2187
0
    }
2188
2189
0
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
2190
0
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
2191
0
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
2192
0
    if (h != rowsperstrip)
2193
0
        L_WARNING("more than 1 strip\n", __func__);
2194
        /* From the standard:
2195
             TIFFTAG_PHOTOMETRIC = 0 (false) -->  min value is white.
2196
             TIFFTAG_PHOTOMETRIC = 1 (true) -->  min value is black.
2197
           Most 1 bpp tiffs have the tag value 0 (black is 1),
2198
           because there are fewer black pixels than white pixels,
2199
           so it makes sense to encode runs of black pixels.  */
2200
0
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &minisblack);
2201
/*    TIFFPrintDirectory(tif, stderr, 0); */
2202
0
    TIFFClose(tif);
2203
0
    if (pw) *pw = (l_int32)w;
2204
0
    if (ph) *ph = (l_int32)h;
2205
0
    if (pminisblack) *pminisblack = (l_int32)minisblack;
2206
2207
        /* The header has 8 bytes: the first 2 are the magic number,
2208
         * the next 2 are the version, and the last 4 are the
2209
         * offset to the first directory.  That's what we want here.
2210
         * We have to test the byte order before decoding 4 bytes! */
2211
0
    if (inarray[0] == 0x4d) {  /* big-endian */
2212
0
        diroff = (inarray[4] << 24) | (inarray[5] << 16) |
2213
0
                 (inarray[6] << 8) | inarray[7];
2214
0
    } else  {   /* inarray[0] == 0x49 :  little-endian */
2215
0
        diroff = (inarray[7] << 24) | (inarray[6] << 16) |
2216
0
                 (inarray[5] << 8) | inarray[4];
2217
0
    }
2218
/*    lept_stderr(" diroff = %d, %x\n", diroff, diroff); */
2219
2220
        /* Extract the ccittg4 encoded data from the tiff file.
2221
         * We skip the 8 byte header and take nbytes of data,
2222
         * up to the beginning of the directory (at diroff)  */
2223
0
    nbytes = diroff - 8;
2224
0
    if (nbytes > MaxNumTiffBytes) {
2225
0
        LEPT_FREE(inarray);
2226
0
        L_ERROR("requesting %zu bytes > %zu\n", __func__,
2227
0
                nbytes, MaxNumTiffBytes);
2228
0
        return 1;
2229
0
    }
2230
0
    *pnbytes = nbytes;
2231
0
    if ((data = (l_uint8 *)LEPT_CALLOC(nbytes, sizeof(l_uint8))) == NULL) {
2232
0
        LEPT_FREE(inarray);
2233
0
        return ERROR_INT("data not allocated", __func__, 1);
2234
0
    }
2235
0
    *pdata = data;
2236
0
    memcpy(data, inarray + 8, nbytes);
2237
0
    LEPT_FREE(inarray);
2238
2239
0
    return 0;
2240
0
}
2241
2242
2243
/*--------------------------------------------------------------*
2244
 *               Open tiff stream from file stream              *
2245
 *--------------------------------------------------------------*/
2246
/*!
2247
 * \brief   fopenTiff()
2248
 *
2249
 * \param[in]    fp           file stream
2250
 * \param[in]    modestring   "r", "w", ...
2251
 * \return  tiff data structure, opened for a file descriptor
2252
 *
2253
 * <pre>
2254
 * Notes:
2255
 *      (1) Why is this here?  Leffler did not provide a function that
2256
 *          takes a stream and gives a TIFF.  He only gave one that
2257
 *          generates a TIFF starting with a file descriptor.  So we
2258
 *          need to make it here, because it is useful to have functions
2259
 *          that take a stream as input.
2260
 *      (2) We use TIFFClientOpen() together with a set of static wrapper
2261
 *          functions which map TIFF read, write, seek, close and size.
2262
 *          to functions expecting a cookie of type stream (i.e. FILE *).
2263
 *          This implementation was contributed by Jürgen Buchmüller.
2264
 * </pre>
2265
 */
2266
static TIFF *
2267
fopenTiff(FILE        *fp,
2268
          const char  *modestring)
2269
0
{
2270
0
    if (!fp)
2271
0
        return (TIFF *)ERROR_PTR("stream not opened", __func__, NULL);
2272
0
    if (!modestring)
2273
0
        return (TIFF *)ERROR_PTR("modestring not defined", __func__, NULL);
2274
2275
0
    TIFFSetWarningHandler(NULL);  /* disable warnings */
2276
0
    TIFFSetErrorHandler(NULL);  /* disable error messages */
2277
2278
0
    fseek(fp, 0, SEEK_SET);
2279
0
    return TIFFClientOpen("TIFFstream", modestring, (thandle_t)fp,
2280
0
                          lept_read_proc, lept_write_proc, lept_seek_proc,
2281
0
                          lept_close_proc, lept_size_proc, NULL, NULL);
2282
0
}
2283
2284
2285
/*--------------------------------------------------------------*
2286
 *                      Wrapper for TIFFOpen                    *
2287
 *--------------------------------------------------------------*/
2288
/*!
2289
 * \brief   openTiff()
2290
 *
2291
 * \param[in]    filename
2292
 * \param[in]    modestring   "r", "w", ...
2293
 * \return  tiff data structure
2294
 *
2295
 * <pre>
2296
 * Notes:
2297
 *      (1) This handles multi-platform file naming.
2298
 * </pre>
2299
 */
2300
static TIFF *
2301
openTiff(const char  *filename,
2302
         const char  *modestring)
2303
0
{
2304
0
char  *fname;
2305
0
TIFF  *tif;
2306
2307
0
    if (!filename)
2308
0
        return (TIFF *)ERROR_PTR("filename not defined", __func__, NULL);
2309
0
    if (!modestring)
2310
0
        return (TIFF *)ERROR_PTR("modestring not defined", __func__, NULL);
2311
2312
0
    TIFFSetWarningHandler(NULL);  /* disable warnings */
2313
0
    TIFFSetErrorHandler(NULL);  /* disable error messages */
2314
2315
0
    fname = genPathname(filename, NULL);
2316
0
    tif = TIFFOpen(fname, modestring);
2317
0
    LEPT_FREE(fname);
2318
0
    return tif;
2319
0
}
2320
2321
2322
/*----------------------------------------------------------------------*
2323
 *     Memory I/O: reading memory --> pix and writing pix --> memory    *
2324
 *----------------------------------------------------------------------*/
2325
/*  It would be nice to use open_memstream() and fmemopen()
2326
 *  for writing and reading to memory, rsp.  These functions manage
2327
 *  memory for writes and reads that use a file streams interface.
2328
 *  Unfortunately, the tiff library only has an interface for reading
2329
 *  and writing to file descriptors, not to file streams.  The tiff
2330
 *  library procedure is to open a "tiff stream" and read/write to it.
2331
 *  The library provides a client interface for managing the I/O
2332
 *  from memory, which requires seven callbacks.  See the TIFFClientOpen
2333
 *  man page for callback signatures.  Adam Langley provided the code
2334
 *  to do this.  */
2335
2336
/*!
2337
 * \brief   Memory stream buffer used with TIFFClientOpen()
2338
 *
2339
 *  The L_Memstram %buffer has different functions in writing and reading.
2340
 *
2341
 *     * In reading, it is assigned to the data and read from as
2342
 *       the tiff library uncompresses the data and generates the pix.
2343
 *       The %offset points to the current read position in the data,
2344
 *       and the %hw always gives the number of bytes of data.
2345
 *       The %outdata and %outsize ptrs are not used.
2346
 *       When finished, tiffCloseCallback() simply frees the L_Memstream.
2347
 *
2348
 *     * In writing, it accepts the data that the tiff library
2349
 *       produces when a pix is compressed.  the buffer points to a
2350
 *       malloced area of %bufsize bytes.  The current writing position
2351
 *       in the buffer is %offset and the most ever written is %hw.
2352
 *       The buffer is expanded as necessary.  When finished,
2353
 *       tiffCloseCallback() assigns the %outdata and %outsize ptrs
2354
 *       to the %buffer and %bufsize results, and frees the L_Memstream.
2355
 */
2356
struct L_Memstream
2357
{
2358
    l_uint8   *buffer;    /* expands to hold data when written to;         */
2359
                          /* fixed size when read from.                    */
2360
    size_t     bufsize;   /* current size allocated when written to;       */
2361
                          /* fixed size of input data when read from.      */
2362
    size_t     offset;    /* byte offset from beginning of buffer.         */
2363
    size_t     hw;        /* high-water mark; max bytes in buffer.         */
2364
    l_uint8  **poutdata;  /* input param for writing; data goes here.      */
2365
    size_t    *poutsize;  /* input param for writing; data size goes here. */
2366
};
2367
typedef struct L_Memstream  L_MEMSTREAM;
2368
2369
2370
    /* These are static functions for memory I/O */
2371
static L_MEMSTREAM *memstreamCreateForRead(l_uint8 *indata, size_t pinsize);
2372
static L_MEMSTREAM *memstreamCreateForWrite(l_uint8 **poutdata,
2373
                                            size_t *poutsize);
2374
static tsize_t tiffReadCallback(thandle_t handle, tdata_t data, tsize_t length);
2375
static tsize_t tiffWriteCallback(thandle_t handle, tdata_t data,
2376
                                 tsize_t length);
2377
static toff_t tiffSeekCallback(thandle_t handle, toff_t offset, l_int32 whence);
2378
static l_int32 tiffCloseCallback(thandle_t handle);
2379
static toff_t tiffSizeCallback(thandle_t handle);
2380
static l_int32 tiffMapCallback(thandle_t handle, tdata_t *data, toff_t *length);
2381
static void tiffUnmapCallback(thandle_t handle, tdata_t data, toff_t length);
2382
2383
2384
static L_MEMSTREAM *
2385
memstreamCreateForRead(l_uint8  *indata,
2386
                       size_t    insize)
2387
4
{
2388
4
L_MEMSTREAM  *mstream;
2389
2390
4
    mstream = (L_MEMSTREAM *)LEPT_CALLOC(1, sizeof(L_MEMSTREAM));
2391
4
    mstream->buffer = indata;   /* handle to input data array */
2392
4
    mstream->bufsize = insize;  /* amount of input data */
2393
4
    mstream->hw = insize;       /* high-water mark fixed at input data size */
2394
4
    mstream->offset = 0;        /* offset always starts at 0 */
2395
4
    return mstream;
2396
4
}
2397
2398
2399
static L_MEMSTREAM *
2400
memstreamCreateForWrite(l_uint8  **poutdata,
2401
                        size_t    *poutsize)
2402
0
{
2403
0
L_MEMSTREAM  *mstream;
2404
2405
0
    mstream = (L_MEMSTREAM *)LEPT_CALLOC(1, sizeof(L_MEMSTREAM));
2406
0
    mstream->buffer = (l_uint8 *)LEPT_CALLOC(8 * 1024, 1);
2407
0
    mstream->bufsize = 8 * 1024;
2408
0
    mstream->poutdata = poutdata;  /* used only at end of write */
2409
0
    mstream->poutsize = poutsize;  /* ditto  */
2410
0
    mstream->hw = mstream->offset = 0;
2411
0
    return mstream;
2412
0
}
2413
2414
2415
static tsize_t
2416
tiffReadCallback(thandle_t  handle,
2417
                 tdata_t    data,
2418
                 tsize_t    length)
2419
28
{
2420
28
L_MEMSTREAM  *mstream;
2421
28
size_t        amount;
2422
2423
28
    mstream = (L_MEMSTREAM *)handle;
2424
28
    amount = L_MIN((size_t)length, mstream->hw - mstream->offset);
2425
2426
        /* Fuzzed files can create this condition! */
2427
28
    if (mstream->offset + amount < amount ||  /* overflow */
2428
28
        mstream->offset + amount > mstream->hw) {
2429
0
        lept_stderr("Bad file: amount too big: %zu\n", amount);
2430
0
        return 0;
2431
0
    }
2432
2433
28
    memcpy(data, mstream->buffer + mstream->offset, amount);
2434
28
    mstream->offset += amount;
2435
28
    return amount;
2436
28
}
2437
2438
2439
static tsize_t
2440
tiffWriteCallback(thandle_t  handle,
2441
                  tdata_t    data,
2442
                  tsize_t    length)
2443
0
{
2444
0
L_MEMSTREAM  *mstream;
2445
0
size_t        newsize;
2446
2447
        /* reallocNew() uses calloc to initialize the array.
2448
         * If malloc is used instead, for some of the encoding methods,
2449
         * not all the data in 'bufsize' bytes in the buffer will
2450
         * have been initialized by the end of the compression. */
2451
0
    mstream = (L_MEMSTREAM *)handle;
2452
0
    if (mstream->offset + length > mstream->bufsize) {
2453
0
        newsize = 2 * (mstream->offset + length);
2454
0
        mstream->buffer = (l_uint8 *)reallocNew((void **)&mstream->buffer,
2455
0
                                                mstream->hw, newsize);
2456
0
        mstream->bufsize = newsize;
2457
0
    }
2458
2459
0
    memcpy(mstream->buffer + mstream->offset, data, length);
2460
0
    mstream->offset += length;
2461
0
    mstream->hw = L_MAX(mstream->offset, mstream->hw);
2462
0
    return length;
2463
0
}
2464
2465
2466
static toff_t
2467
tiffSeekCallback(thandle_t  handle,
2468
                 toff_t     offset,
2469
                 l_int32    whence)
2470
16
{
2471
16
L_MEMSTREAM  *mstream;
2472
2473
16
    mstream = (L_MEMSTREAM *)handle;
2474
16
    switch (whence) {
2475
16
        case SEEK_SET:
2476
/*            lept_stderr("seek_set: offset = %d\n", offset); */
2477
16
            if((size_t)offset != offset) {  /* size_t overflow on uint32 */
2478
0
                return (toff_t)ERROR_INT("too large offset value", __func__, 1);
2479
0
            }
2480
16
            mstream->offset = offset;
2481
16
            break;
2482
0
        case SEEK_CUR:
2483
/*            lept_stderr("seek_cur: offset = %d\n", offset); */
2484
0
            mstream->offset += offset;
2485
0
            break;
2486
0
        case SEEK_END:
2487
/*            lept_stderr("seek end: hw = %d, offset = %d\n",
2488
                    mstream->hw, offset); */
2489
0
            mstream->offset = mstream->hw - offset;  /* offset >= 0 */
2490
0
            break;
2491
0
        default:
2492
0
            return (toff_t)ERROR_INT("bad whence value", __func__,
2493
16
                                     mstream->offset);
2494
16
    }
2495
2496
16
    return mstream->offset;
2497
16
}
2498
2499
2500
static l_int32
2501
tiffCloseCallback(thandle_t  handle)
2502
4
{
2503
4
L_MEMSTREAM  *mstream;
2504
2505
4
    mstream = (L_MEMSTREAM *)handle;
2506
4
    if (mstream->poutdata) {   /* writing: save the output data */
2507
0
        *mstream->poutdata = mstream->buffer;
2508
0
        *mstream->poutsize = mstream->hw;
2509
0
    }
2510
4
    LEPT_FREE(mstream);  /* never free the buffer! */
2511
4
    return 0;
2512
4
}
2513
2514
2515
static toff_t
2516
tiffSizeCallback(thandle_t  handle)
2517
0
{
2518
0
L_MEMSTREAM  *mstream;
2519
2520
0
    mstream = (L_MEMSTREAM *)handle;
2521
0
    return mstream->hw;
2522
0
}
2523
2524
2525
static l_int32
2526
tiffMapCallback(thandle_t  handle,
2527
                tdata_t   *data,
2528
                toff_t    *length)
2529
4
{
2530
4
L_MEMSTREAM  *mstream;
2531
2532
4
    mstream = (L_MEMSTREAM *)handle;
2533
4
    *data = mstream->buffer;
2534
4
    *length = mstream->hw;
2535
4
    return 0;
2536
4
}
2537
2538
2539
static void
2540
tiffUnmapCallback(thandle_t  handle,
2541
                  tdata_t    data,
2542
                  toff_t     length)
2543
0
{
2544
0
    return;
2545
0
}
2546
2547
2548
/*!
2549
 * \brief   fopenTiffMemstream()
2550
 *
2551
 * \param[in]    filename    for error output; can be ""
2552
 * \param[in]    operation   "w" for write, "r" for read
2553
 * \param[out]   pdata       written data
2554
 * \param[out]   pdatasize   size of written data
2555
 * \return  tiff data structure, opened for write to memory
2556
 *
2557
 * <pre>
2558
 * Notes:
2559
 *      (1) This wraps up a number of callbacks for either:
2560
 *            * reading from tiff in memory buffer --> pix
2561
 *            * writing from pix --> tiff in memory buffer
2562
 *      (2) After use, the memstream is automatically destroyed when
2563
 *          TIFFClose() is called.  TIFFCleanup() doesn't free the memstream.
2564
 *      (3) This does not work in append mode, and in write mode it
2565
 *          does not append.
2566
 * </pre>
2567
 */
2568
static TIFF *
2569
fopenTiffMemstream(const char  *filename,
2570
                   const char  *operation,
2571
                   l_uint8    **pdata,
2572
                   size_t      *pdatasize)
2573
4
{
2574
4
L_MEMSTREAM  *mstream;
2575
4
TIFF         *tif;
2576
2577
4
    if (!filename)
2578
0
        return (TIFF *)ERROR_PTR("filename not defined", __func__, NULL);
2579
4
    if (!operation)
2580
0
        return (TIFF *)ERROR_PTR("operation not defined", __func__, NULL);
2581
4
    if (!pdata)
2582
0
        return (TIFF *)ERROR_PTR("&data not defined", __func__, NULL);
2583
4
    if (!pdatasize)
2584
0
        return (TIFF *)ERROR_PTR("&datasize not defined", __func__, NULL);
2585
4
    if (strcmp(operation, "r") && strcmp(operation, "w"))
2586
0
        return (TIFF *)ERROR_PTR("op not 'r' or 'w'", __func__, NULL);
2587
2588
4
    if (!strcmp(operation, "r"))
2589
4
        mstream = memstreamCreateForRead(*pdata, *pdatasize);
2590
0
    else
2591
0
        mstream = memstreamCreateForWrite(pdata, pdatasize);
2592
4
    if (!mstream)
2593
0
        return (TIFF *)ERROR_PTR("mstream not made", __func__, NULL);
2594
2595
4
    TIFFSetWarningHandler(NULL);  /* disable warnings */
2596
4
    TIFFSetErrorHandler(NULL);  /* disable error messages */
2597
2598
4
    tif = TIFFClientOpen(filename, operation, (thandle_t)mstream,
2599
4
                         tiffReadCallback, tiffWriteCallback,
2600
4
                         tiffSeekCallback, tiffCloseCallback,
2601
4
                         tiffSizeCallback, tiffMapCallback,
2602
4
                         tiffUnmapCallback);
2603
4
    if (!tif)
2604
0
        LEPT_FREE(mstream);
2605
4
    return tif;
2606
4
}
2607
2608
2609
/*!
2610
 * \brief   pixReadMemTiff()
2611
 *
2612
 * \param[in]    cdata    const; tiff-encoded
2613
 * \param[in]    size     size of cdata
2614
 * \param[in]    n        page image number: 0-based
2615
 * \return  pix, or NULL on error
2616
 *
2617
 * <pre>
2618
 * Notes:
2619
 *      (1) This is a version of pixReadTiff(), where the data is read
2620
 *          from a memory buffer and uncompressed.
2621
 *      (2) Use TIFFClose(); TIFFCleanup() doesn't free internal memstream.
2622
 *      (3) No warning messages on failure, because of how multi-page
2623
 *          TIFF reading works. You are supposed to keep trying until
2624
 *          it stops working.
2625
 *      (4) Tiff directory overhead is linear in the input page number.
2626
 *          If reading many images, use pixReadMemFromMultipageTiff().
2627
 * </pre>
2628
 */
2629
PIX *
2630
pixReadMemTiff(const l_uint8  *cdata,
2631
               size_t          size,
2632
               l_int32         n)
2633
4
{
2634
4
l_uint8  *data;
2635
4
l_int32   i;
2636
4
PIX      *pix;
2637
4
TIFF     *tif;
2638
2639
4
    if (!cdata)
2640
0
        return (PIX *)ERROR_PTR("cdata not defined", __func__, NULL);
2641
2642
4
    data = (l_uint8 *)cdata;  /* we're really not going to change this */
2643
4
    if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL)
2644
0
        return (PIX *)ERROR_PTR("tiff stream not opened", __func__, NULL);
2645
2646
4
    pix = NULL;
2647
4
    for (i = 0; ; i++) {
2648
4
        if (i == n) {
2649
4
            if ((pix = pixReadFromTiffStream(tif)) == NULL) {
2650
0
                TIFFClose(tif);
2651
0
                return NULL;
2652
0
            }
2653
4
            pixSetInputFormat(pix, IFF_TIFF);
2654
4
            break;
2655
4
        }
2656
0
        if (TIFFReadDirectory(tif) == 0)
2657
0
            break;
2658
0
        if (i == ManyPagesInTiffFile + 1) {
2659
0
            L_WARNING("big file: more than %d pages\n", __func__,
2660
0
                      ManyPagesInTiffFile);
2661
0
        }
2662
0
    }
2663
2664
4
    TIFFClose(tif);
2665
4
    return pix;
2666
4
}
2667
2668
2669
/*!
2670
 * \brief   pixReadMemFromMultipageTiff()
2671
 *
2672
 * \param[in]    cdata      const; tiff-encoded
2673
 * \param[in]    size       size of cdata
2674
 * \param[in,out]  poffset  set offset to 0 for first image
2675
 * \return  pix, or NULL on error or if previous call returned the last image
2676
 *
2677
 * <pre>
2678
 * Notes:
2679
 *      (1) This is a read-from-memory version of pixReadFromMultipageTiff().
2680
 *          See that function for usage.
2681
 *      (2) If reading sequentially from the tiff data, this is more
2682
 *          efficient than pixReadMemTiff(), which has an overhead
2683
 *          proportional to the image index n.
2684
 *      (3) Example usage for reading all the images:
2685
 *            size_t offset = 0;
2686
 *            do {
2687
 *                Pix *pix = pixReadMemFromMultipageTiff(data, size, &offset);
2688
 *                // do something with pix
2689
 *            } while (offset != 0);
2690
 * </pre>
2691
 */
2692
PIX *
2693
pixReadMemFromMultipageTiff(const l_uint8  *cdata,
2694
                            size_t          size,
2695
                            size_t         *poffset)
2696
0
{
2697
0
l_uint8  *data;
2698
0
l_int32   retval;
2699
0
size_t    offset;
2700
0
PIX      *pix;
2701
0
TIFF     *tif;
2702
2703
0
    if (!cdata)
2704
0
        return (PIX *)ERROR_PTR("cdata not defined", __func__, NULL);
2705
0
    if (!poffset)
2706
0
        return (PIX *)ERROR_PTR("&offset not defined", __func__, NULL);
2707
2708
0
    data = (l_uint8 *)cdata;  /* we're really not going to change this */
2709
0
    if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL)
2710
0
        return (PIX *)ERROR_PTR("tiff stream not opened", __func__, NULL);
2711
2712
        /* Set ptrs in the TIFF to the beginning of the image */
2713
0
    offset = *poffset;
2714
0
    retval = (offset == 0) ? TIFFSetDirectory(tif, 0)
2715
0
                           : TIFFSetSubDirectory(tif, offset);
2716
0
    if (retval == 0) {
2717
0
        TIFFClose(tif);
2718
0
        return NULL;
2719
0
    }
2720
2721
0
    if ((pix = pixReadFromTiffStream(tif)) == NULL) {
2722
0
        TIFFClose(tif);
2723
0
        return NULL;
2724
0
    }
2725
2726
        /* Advance to the next image and return the new offset */
2727
0
    TIFFReadDirectory(tif);
2728
0
    *poffset = TIFFCurrentDirOffset(tif);
2729
0
    TIFFClose(tif);
2730
0
    return pix;
2731
0
}
2732
2733
2734
/*!
2735
 * \brief   pixaReadMemMultipageTiff()
2736
 *
2737
 * \param[in]    data    const; multiple pages; tiff-encoded
2738
 * \param[in]    size    size of cdata
2739
 * \return  pixa, or NULL on error
2740
 *
2741
 * <pre>
2742
 * Notes:
2743
 *      (1) This is an O(n) read-from-memory version of pixaReadMultipageTiff().
2744
 *      (2) Failure to read any page results in NULL return.
2745
 * </pre>
2746
 */
2747
PIXA *
2748
pixaReadMemMultipageTiff(const l_uint8  *data,
2749
                         size_t          size)
2750
0
{
2751
0
size_t  offset;
2752
0
PIX    *pix;
2753
0
PIXA   *pixa;
2754
2755
0
    if (!data)
2756
0
        return (PIXA *)ERROR_PTR("data not defined", __func__, NULL);
2757
2758
0
    offset = 0;
2759
0
    pixa = pixaCreate(0);
2760
0
    do {
2761
0
        if ((pix = pixReadMemFromMultipageTiff(data, size, &offset)) == NULL) {
2762
0
            L_ERROR("reading tiff fails at offset %zu\n", __func__, offset);
2763
0
            pixaDestroy(&pixa);
2764
0
            return NULL;
2765
0
        }
2766
0
        pixaAddPix(pixa, pix, L_INSERT);
2767
0
    } while (offset != 0);
2768
0
    return pixa;
2769
0
}
2770
2771
2772
/*!
2773
 * \brief   pixaWriteMemMultipageTiff()
2774
 *
2775
 * \param[out]    pdata   const; tiff-encoded
2776
 * \param[out]    psize   size of data
2777
 * \param[in]     pixa    any depth; colormap will be removed
2778
 * \return  0 if OK, 1 on error
2779
 *
2780
 * <pre>
2781
 * Notes:
2782
 *      (1) fopenTiffMemstream() does not work in append mode, so we
2783
 *          must work-around with a temporary file.
2784
 *      (2) Getting a file stream from
2785
 *            open_memstream((char **)pdata, psize)
2786
 *          does not work with the tiff directory.
2787
 * </pre>
2788
 */
2789
l_ok
2790
pixaWriteMemMultipageTiff(l_uint8    **pdata,
2791
                          size_t      *psize,
2792
                          const PIXA  *pixa)
2793
0
{
2794
0
const char  *modestr;
2795
0
l_int32      i, n;
2796
0
FILE        *fp;
2797
0
PIX         *pix1;
2798
2799
0
    if (pdata) *pdata = NULL;
2800
0
    if (!pdata)
2801
0
        return ERROR_INT("pdata not defined", __func__, 1);
2802
0
    if (!pixa)
2803
0
        return ERROR_INT("pixa not defined", __func__, 1);
2804
2805
#ifdef _WIN32
2806
    if ((fp = fopenWriteWinTempfile()) == NULL)
2807
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
2808
#else
2809
0
    if ((fp = tmpfile()) == NULL)
2810
0
        return ERROR_INT("tmpfile stream not opened", __func__, 1);
2811
0
#endif  /* _WIN32 */
2812
2813
0
    n = pixaGetCount(pixa);
2814
0
    for (i = 0; i < n; i++) {
2815
0
        modestr = (i == 0) ? "w" : "a";
2816
0
        pix1 = pixaGetPix(pixa, i, L_CLONE);
2817
0
        if (pixGetDepth(pix1) == 1)
2818
0
            pixWriteStreamTiffWA(fp, pix1, IFF_TIFF_G4, modestr);
2819
0
        else
2820
0
            pixWriteStreamTiffWA(fp, pix1, IFF_TIFF_ZIP, modestr);
2821
0
        pixDestroy(&pix1);
2822
0
    }
2823
2824
0
    rewind(fp);
2825
0
    *pdata = l_binaryReadStream(fp, psize);
2826
0
    fclose(fp);
2827
0
    return 0;
2828
0
}
2829
2830
2831
/*!
2832
 * \brief   pixWriteMemTiff()
2833
 *
2834
 * \param[out]   pdata     data of tiff compressed image
2835
 * \param[out]   psize     size of returned data
2836
 * \param[in]    pix
2837
 * \param[in]    comptype  IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS,
2838
 *                         IFF_TIFF_G3, IFF_TIFF_G4,
2839
 *                         IFF_TIFF_LZW, IFF_TIFF_ZIP, IFF_TIFF_JPEG
2840
 * \return  0 if OK, 1 on error
2841
 *
2842
 *  Usage:
2843
 *      1) See pixWriteTiff(.  This version writes to
2844
 *          memory instead of to a file.
2845
 */
2846
l_ok
2847
pixWriteMemTiff(l_uint8  **pdata,
2848
                size_t    *psize,
2849
                PIX       *pix,
2850
                l_int32    comptype)
2851
0
{
2852
0
    return pixWriteMemTiffCustom(pdata, psize, pix, comptype,
2853
0
                                 NULL, NULL, NULL, NULL);
2854
0
}
2855
2856
2857
/*!
2858
 * \brief   pixWriteMemTiffCustom()
2859
 *
2860
 * \param[out]   pdata     data of tiff compressed image
2861
 * \param[out]   psize     size of returned data
2862
 * \param[in]    pix
2863
 * \param[in]    comptype  IFF_TIFF, IFF_TIFF_RLE, IFF_TIFF_PACKBITS,
2864
 *                         IFF_TIFF_G3, IFF_TIFF_G4,
2865
 *                         IFF_TIFF_LZW, IFF_TIFF_ZIP, IFF_TIFF_JPEG
2866
 * \param[in]    natags    [optional] NUMA of custom tiff tags
2867
 * \param[in]    savals    [optional] SARRAY of values
2868
 * \param[in]    satypes   [optional] SARRAY of types
2869
 * \param[in]    nasizes   [optional] NUMA of sizes
2870
 * \return  0 if OK, 1 on error
2871
 *
2872
 *  Usage:
2873
 *      1) See pixWriteTiffCustom(.  This version writes to
2874
 *          memory instead of to a file.
2875
 *      2) Use TIFFClose(); TIFFCleanup( doesn't free internal memstream.
2876
 */
2877
l_ok
2878
pixWriteMemTiffCustom(l_uint8  **pdata,
2879
                      size_t    *psize,
2880
                      PIX       *pix,
2881
                      l_int32    comptype,
2882
                      NUMA      *natags,
2883
                      SARRAY    *savals,
2884
                      SARRAY    *satypes,
2885
                      NUMA      *nasizes)
2886
0
{
2887
0
l_int32  ret;
2888
0
TIFF    *tif;
2889
2890
0
    if (!pdata)
2891
0
        return ERROR_INT("&data not defined", __func__, 1);
2892
0
    if (!psize)
2893
0
        return ERROR_INT("&size not defined", __func__, 1);
2894
0
    if (!pix)
2895
0
        return ERROR_INT("&pix not defined", __func__, 1);
2896
0
    if (pixGetDepth(pix) != 1 && comptype != IFF_TIFF &&
2897
0
        comptype != IFF_TIFF_LZW && comptype != IFF_TIFF_ZIP &&
2898
0
        comptype != IFF_TIFF_JPEG) {
2899
0
        L_WARNING("invalid compression type for bpp > 1\n", __func__);
2900
0
        comptype = IFF_TIFF_ZIP;
2901
0
    }
2902
2903
0
    if ((tif = fopenTiffMemstream("tifferror", "w", pdata, psize)) == NULL)
2904
0
        return ERROR_INT("tiff stream not opened", __func__, 1);
2905
0
    ret = pixWriteToTiffStream(tif, pix, comptype, natags, savals,
2906
0
                               satypes, nasizes);
2907
2908
0
    TIFFClose(tif);
2909
0
    return ret;
2910
0
}
2911
2912
/* ---------------------------------------*/
2913
#endif  /* HAVE_LIBTIFF && HAVE_LIBJPEG   */
2914
/* ---------------------------------------*/