Leptonica 1.83.1
Image processing and image analysis suite
Loading...
Searching...
No Matches
tiffio.c
Go to the documentation of this file.
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
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 /* defined in environ.h */
135/* --------------------------------------------*/
136
137#include "tiff.h"
138#include "tiffio.h"
139
140static const l_int32 DefaultResolution = 300; /* ppi */
141static const l_int32 ManyPagesInTiffFile = 3000; /* warn if big */
142
143 /* Verified that tiflib makes valid g4 files of this size */
144static const l_int32 MaxTiffWidth = 1 << 20; /* 1M pixels */
145static const l_int32 MaxTiffHeight = 1 << 20; /* 1M pixels */
146
147 /* Check g4 data size */
148static const size_t MaxNumTiffBytes = (1 << 28) - 1; /* 256 MB */
149
150 /* All functions with TIFF interfaces are static. */
151static PIX *pixReadFromTiffStream(TIFF *tif);
152static l_int32 getTiffStreamResolution(TIFF *tif, l_int32 *pxres,
153 l_int32 *pyres);
154static 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);
158static l_int32 writeCustomTiffTags(TIFF *tif, NUMA *natags,
159 SARRAY *savals, SARRAY *satypes,
160 NUMA *nasizes);
161static l_int32 pixWriteToTiffStream(TIFF *tif, PIX *pix, l_int32 comptype,
162 NUMA *natags, SARRAY *savals,
163 SARRAY *satypes, NUMA *nasizes);
164static TIFF *fopenTiff(FILE *fp, const char *modestring);
165static TIFF *openTiff(const char *filename, const char *modestring);
166
167 /* Static helper for tiff compression type */
168static l_int32 getTiffCompressedFormat(l_uint16 tiffcomp);
169
170 /* Static function for memory I/O */
171static 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). */
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(). */
190static 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 */
205static 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 *-----------------------------------------------------------------------*/
232static tsize_t
233lept_read_proc(thandle_t cookie,
234 tdata_t buff,
235 tsize_t size)
236{
237 FILE* fp = (FILE *)cookie;
238 tsize_t done;
239 if (!buff || !cookie || !fp)
240 return (tsize_t)-1;
241 done = fread(buff, 1, size, fp);
242 return done;
243}
244
245static tsize_t
246lept_write_proc(thandle_t cookie,
247 tdata_t buff,
248 tsize_t size)
249{
250 FILE* fp = (FILE *)cookie;
251 tsize_t done;
252 if (!buff || !cookie || !fp)
253 return (tsize_t)-1;
254 done = fwrite(buff, 1, size, fp);
255 return done;
256}
257
258static toff_t
259lept_seek_proc(thandle_t cookie,
260 toff_t offs,
261 int whence)
262{
263 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 break;
275 case SEEK_END:
276 _fseeki64(fp, 0, SEEK_END);
277 pos = _ftelli64(fp);
278 break;
279 }
280 pos = (__int64)(pos + offs);
281 _fseeki64(fp, pos, SEEK_SET);
282 if (pos == _ftelli64(fp))
283 return (tsize_t)pos;
284#elif defined(_LARGEFILE64_SOURCE)
285 off64_t pos = 0;
286 if (!cookie || !fp)
287 return (tsize_t)-1;
288 switch (whence) {
289 case SEEK_SET:
290 pos = 0;
291 break;
292 case SEEK_CUR:
293 pos = ftello(fp);
294 break;
295 case SEEK_END:
296 fseeko(fp, 0, SEEK_END);
297 pos = ftello(fp);
298 break;
299 }
300 pos = (off64_t)(pos + offs);
301 fseeko(fp, pos, SEEK_SET);
302 if (pos == ftello(fp))
303 return (tsize_t)pos;
304#else
305 off_t pos = 0;
306 if (!cookie || !fp)
307 return (tsize_t)-1;
308 switch (whence) {
309 case SEEK_SET:
310 pos = 0;
311 break;
312 case SEEK_CUR:
313 pos = ftell(fp);
314 break;
315 case SEEK_END:
316 fseek(fp, 0, SEEK_END);
317 pos = ftell(fp);
318 break;
319 }
320 pos = (off_t)(pos + offs);
321 fseek(fp, pos, SEEK_SET);
322 if (pos == ftell(fp))
323 return (tsize_t)pos;
324#endif
325 return (tsize_t)-1;
326}
327
328static int
329lept_close_proc(thandle_t cookie)
330{
331 FILE* fp = (FILE *)cookie;
332 if (!cookie || !fp)
333 return 0;
334 fseek(fp, 0, SEEK_SET);
335 return 0;
336}
337
338static toff_t
339lept_size_proc(thandle_t cookie)
340{
341 FILE* fp = (FILE *)cookie;
342#if defined(_MSC_VER)
343 __int64 pos;
344 __int64 size;
345 if (!cookie || !fp)
346 return (tsize_t)-1;
347 pos = _ftelli64(fp);
348 _fseeki64(fp, 0, SEEK_END);
349 size = _ftelli64(fp);
350 _fseeki64(fp, pos, SEEK_SET);
351#elif defined(_LARGEFILE64_SOURCE)
352 off64_t pos;
353 off64_t size;
354 if (!fp)
355 return (tsize_t)-1;
356 pos = ftello(fp);
357 fseeko(fp, 0, SEEK_END);
358 size = ftello(fp);
359 fseeko(fp, pos, SEEK_SET);
360#else
361 off_t pos;
362 off_t size;
363 if (!cookie || !fp)
364 return (tsize_t)-1;
365 pos = ftell(fp);
366 fseek(fp, 0, SEEK_END);
367 size = ftell(fp);
368 fseek(fp, pos, SEEK_SET);
369#endif
370 return (toff_t)size;
371}
372
373
374/*--------------------------------------------------------------*
375 * Reading from file *
376 *--------------------------------------------------------------*/
393PIX *
394pixReadTiff(const char *filename,
395 l_int32 n)
396{
397FILE *fp;
398PIX *pix;
399
400 if (!filename)
401 return (PIX *)ERROR_PTR("filename not defined", __func__, NULL);
402
403 if ((fp = fopenReadStream(filename)) == NULL)
404 return (PIX *)ERROR_PTR("image file not found", __func__, NULL);
405 pix = pixReadStreamTiff(fp, n);
406 fclose(fp);
407 return pix;
408}
409
410
411/*--------------------------------------------------------------*
412 * Reading from stream *
413 *--------------------------------------------------------------*/
428PIX *
430 l_int32 n)
431{
432PIX *pix;
433TIFF *tif;
434
435 if (!fp)
436 return (PIX *)ERROR_PTR("stream not defined", __func__, NULL);
437
438 if ((tif = fopenTiff(fp, "r")) == NULL)
439 return (PIX *)ERROR_PTR("tif not opened", __func__, NULL);
440
441 if (TIFFSetDirectory(tif, n) == 0) {
442 TIFFCleanup(tif);
443 return NULL;
444 }
445 if ((pix = pixReadFromTiffStream(tif)) == NULL) {
446 TIFFCleanup(tif);
447 return NULL;
448 }
449 TIFFCleanup(tif);
450 return pix;
451}
452
453
496static PIX *
498{
499char *text;
500l_uint8 *linebuf, *data, *rowptr;
501l_uint16 spp, bps, photometry, tiffcomp, orientation, sample_fmt;
502l_uint16 *redmap, *greenmap, *bluemap;
503l_int32 d, wpl, bpl, comptype, i, j, k, ncolors, rval, gval, bval, aval;
504l_int32 xres, yres, tiffbpl, packedbpl, half_size, twothirds_size;
505l_uint32 w, h, tiffword, read_oriented;
506l_uint32 *line, *ppixel, *tiffdata, *pixdata;
507PIX *pix, *pix1;
508PIXCMAP *cmap;
509
510 if (!tif)
511 return (PIX *)ERROR_PTR("tif not defined", __func__, NULL);
512
513 read_oriented = 0;
514
515 /* Only accept uint image data:
516 * SAMPLEFORMAT_UINT = 1;
517 * SAMPLEFORMAT_INT = 2;
518 * SAMPLEFORMAT_IEEEFP = 3;
519 * SAMPLEFORMAT_VOID = 4; */
520 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLEFORMAT, &sample_fmt);
521 if (sample_fmt != SAMPLEFORMAT_UINT) {
522 L_ERROR("sample format = %d is not uint\n", __func__, sample_fmt);
523 return NULL;
524 }
525
526 /* Can't read tiff in tiled format. For what is involved, see, e.g:
527 * https://www.cs.rochester.edu/~nelson/courses/vision/\
528 * resources/tiff/libtiff.html#Tiles
529 * A tiled tiff can be converted to a normal (strip) tif:
530 * tiffcp -s <input-tiled-tif> <output-strip-tif> */
531 if (TIFFIsTiled(tif)) {
532 L_ERROR("tiled format is not supported\n", __func__);
533 return NULL;
534 }
535
536 /* Old style jpeg is not supported. We tried supporting 8 bpp.
537 * TIFFReadScanline() fails on this format, so we used RGBA
538 * reading, which generates a 4 spp image, and pulled out the
539 * red component. However, there were problems with double-frees
540 * in cleanup. For RGB, tiffbpl is exactly half the size that
541 * you would expect for the raster data in a scanline, which
542 * is 3 * w. */
543 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp);
544 if (tiffcomp == COMPRESSION_OJPEG) {
545 L_ERROR("old style jpeg format is not supported\n", __func__);
546 return NULL;
547 }
548
549 /* webp in tiff is in 4.1.0 and not yet supported in Adobe registry */
550#if defined(COMPRESSION_WEBP)
551 if (tiffcomp == COMPRESSION_WEBP) {
552 L_ERROR("webp in tiff not generally supported yet\n", __func__);
553 return NULL;
554 }
555#endif /* COMPRESSION_WEBP */
556
557 /* Use default fields for bps and spp */
558 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps);
559 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
560 if (bps != 1 && bps != 2 && bps != 4 && bps != 8 && bps != 16) {
561 L_ERROR("invalid bps = %d\n", __func__, bps);
562 return NULL;
563 }
564 if (spp == 2 && bps != 8) {
565 L_ERROR("for 2 spp, only handle 8 bps; this is %d bps\n",
566 __func__, bps);
567 return NULL;
568 }
569 if ((spp == 3 || spp == 4) && bps < 8) {
570 L_ERROR("for 3 and 4 spp, only handle 8 and 16 bps; this is %d bps\n",
571 __func__, bps);
572 return NULL;
573 }
574 if (spp == 1) {
575 d = bps;
576 } else if (spp == 2) { /* gray plus alpha */
577 d = 32; /* will convert to RGBA */
578 } else if (spp == 3 || spp == 4) {
579 d = 32;
580 } else {
581 L_ERROR("spp = %d; not in {1,2,3,4}\n", __func__, spp);
582 return NULL;
583 }
584
585 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
586 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
587 if (w > MaxTiffWidth) {
588 L_ERROR("width = %d pixels; too large\n", __func__, w);
589 return NULL;
590 }
591 if (h > MaxTiffHeight) {
592 L_ERROR("height = %d pixels; too large\n", __func__, h);
593 return NULL;
594 }
595
596 /* The relation between the size of a byte buffer required to hold
597 a raster of image pixels (packedbpl) and the size of the tiff
598 buffer (tiffbuf) is either 1:1 or approximately 1.5:1 or 2:1,
599 depending on how the data is stored and subsampled. For security,
600 we test this relation between tiffbuf and the image parameters
601 w, spp and bps. */
602 tiffbpl = TIFFScanlineSize(tif);
603 packedbpl = (bps * spp * w + 7) / 8;
604 half_size = (L_ABS(2 * tiffbpl - packedbpl) <= 8);
605 twothirds_size = (L_ABS(3 * tiffbpl - 2 * packedbpl) <= 8);
606#if 0
607 if (half_size)
608 L_INFO("half_size: packedbpl = %d is approx. twice tiffbpl = %d\n",
609 __func__, packedbpl, tiffbpl);
610 if (twothirds_size)
611 L_INFO("twothirds_size: packedbpl = %d is approx. 1.5 tiffbpl = %d\n",
612 __func__, packedbpl, tiffbpl);
613 lept_stderr("tiffbpl = %d, packedbpl = %d, bps = %d, spp = %d, w = %d\n",
614 tiffbpl, packedbpl, bps, spp, w);
615#endif
616 if (tiffbpl != packedbpl && !half_size && !twothirds_size) {
617 L_ERROR("invalid tiffbpl: tiffbpl = %d, packedbpl = %d, "
618 "bps = %d, spp = %d, w = %d\n",
619 __func__, tiffbpl, packedbpl, bps, spp, w);
620 return NULL;
621 }
622
623 /* Use a linebuf that will hold all the pixels generated
624 by tiff when reading (decompressing) a scanline. */
625 if ((pix = pixCreate(w, h, d)) == NULL)
626 return (PIX *)ERROR_PTR("pix not made", __func__, NULL);
627 pixSetInputFormat(pix, IFF_TIFF);
628 data = (l_uint8 *)pixGetData(pix);
629 wpl = pixGetWpl(pix);
630 bpl = 4 * wpl;
631 if (spp == 1) {
632 linebuf = (l_uint8 *)LEPT_CALLOC(4 * wpl, sizeof(l_uint8));
633 for (i = 0; i < h; i++) {
634 if (TIFFReadScanline(tif, linebuf, i, 0) < 0) {
635 LEPT_FREE(linebuf);
636 pixDestroy(&pix);
637 L_ERROR("spp = 1, read fail at line %d\n", __func__, i);
638 return NULL;
639 }
640 memcpy(data, linebuf, tiffbpl);
641 data += bpl;
642 }
643 if (bps <= 8)
644 pixEndianByteSwap(pix);
645 else /* bps == 16 */
646 pixEndianTwoByteSwap(pix);
647 LEPT_FREE(linebuf);
648 } else if (spp == 2 && bps == 8) { /* gray plus alpha */
649 L_INFO("gray+alpha is not supported; converting to RGBA\n", __func__);
650 pixSetSpp(pix, 4);
651 linebuf = (l_uint8 *)LEPT_CALLOC(4 * wpl, sizeof(l_uint8));
652 pixdata = pixGetData(pix);
653 for (i = 0; i < h; i++) {
654 if (TIFFReadScanline(tif, linebuf, i, 0) < 0) {
655 LEPT_FREE(linebuf);
656 pixDestroy(&pix);
657 L_ERROR("spp = 2, read fail at line %d\n", __func__, i);
658 return NULL;
659 }
660 rowptr = linebuf;
661 ppixel = pixdata + i * wpl;
662 for (j = k = 0; j < w; j++) {
663 /* Copy gray value into r, g and b */
664 SET_DATA_BYTE(ppixel, COLOR_RED, rowptr[k]);
665 SET_DATA_BYTE(ppixel, COLOR_GREEN, rowptr[k]);
666 SET_DATA_BYTE(ppixel, COLOR_BLUE, rowptr[k++]);
667 SET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL, rowptr[k++]);
668 ppixel++;
669 }
670 }
671 LEPT_FREE(linebuf);
672 } else { /* rgb and rgba */
673 if ((tiffdata = (l_uint32 *)LEPT_CALLOC((size_t)w * h,
674 sizeof(l_uint32))) == NULL) {
675 pixDestroy(&pix);
676 return (PIX *)ERROR_PTR("calloc fail for tiffdata", __func__, NULL);
677 }
678 /* TIFFReadRGBAImageOriented() converts to 8 bps */
679 if (!TIFFReadRGBAImageOriented(tif, w, h, tiffdata,
680 ORIENTATION_TOPLEFT, 0)) {
681 LEPT_FREE(tiffdata);
682 pixDestroy(&pix);
683 return (PIX *)ERROR_PTR("failed to read tiffdata", __func__, NULL);
684 } else {
685 read_oriented = 1;
686 }
687
688 if (spp == 4) pixSetSpp(pix, 4);
689 line = pixGetData(pix);
690 for (i = 0; i < h; i++, line += wpl) {
691 for (j = 0, ppixel = line; j < w; j++) {
692 /* TIFFGet* are macros */
693 tiffword = tiffdata[i * w + j];
694 rval = TIFFGetR(tiffword);
695 gval = TIFFGetG(tiffword);
696 bval = TIFFGetB(tiffword);
697 if (spp == 3) {
698 composeRGBPixel(rval, gval, bval, ppixel);
699 } else { /* spp == 4 */
700 aval = TIFFGetA(tiffword);
701 composeRGBAPixel(rval, gval, bval, aval, ppixel);
702 }
703 ppixel++;
704 }
705 }
706 LEPT_FREE(tiffdata);
707 }
708
709 if (getTiffStreamResolution(tif, &xres, &yres) == 0) {
710 pixSetXRes(pix, xres);
711 pixSetYRes(pix, yres);
712 }
713
714 /* Find and save the compression type */
715 comptype = getTiffCompressedFormat(tiffcomp);
716 pixSetInputFormat(pix, comptype);
717
718 if (TIFFGetField(tif, TIFFTAG_COLORMAP, &redmap, &greenmap, &bluemap)) {
719 /* Save the colormap as a pix cmap. Because the
720 * tiff colormap components are 16 bit unsigned,
721 * and go from black (0) to white (0xffff), the
722 * the pix cmap takes the most significant byte. */
723 if (bps > 8) {
724 pixDestroy(&pix);
725 return (PIX *)ERROR_PTR("colormap size > 256", __func__, NULL);
726 }
727 if ((cmap = pixcmapCreate(bps)) == NULL) {
728 pixDestroy(&pix);
729 return (PIX *)ERROR_PTR("colormap not made", __func__, NULL);
730 }
731 ncolors = 1 << bps;
732 for (i = 0; i < ncolors; i++)
733 pixcmapAddColor(cmap, redmap[i] >> 8, greenmap[i] >> 8,
734 bluemap[i] >> 8);
735 if (pixSetColormap(pix, cmap)) {
736 pixDestroy(&pix);
737 return (PIX *)ERROR_PTR("invalid colormap", __func__, NULL);
738 }
739
740 /* Remove the colormap for 1 bpp. */
741 if (bps == 1) {
742 pix1 = pixRemoveColormap(pix, REMOVE_CMAP_BASED_ON_SRC);
743 pixDestroy(&pix);
744 pix = pix1;
745 }
746 } else { /* No colormap: check photometry and invert if necessary */
747 if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometry)) {
748 /* Guess default photometry setting. Assume min_is_white
749 * if compressed 1 bpp; min_is_black otherwise. */
750 if (tiffcomp == COMPRESSION_CCITTFAX3 ||
751 tiffcomp == COMPRESSION_CCITTFAX4 ||
752 tiffcomp == COMPRESSION_CCITTRLE ||
753 tiffcomp == COMPRESSION_CCITTRLEW) {
754 photometry = PHOTOMETRIC_MINISWHITE;
755 } else {
756 photometry = PHOTOMETRIC_MINISBLACK;
757 }
758 }
759 if ((d == 1 && photometry == PHOTOMETRIC_MINISBLACK) ||
760 (d == 8 && photometry == PHOTOMETRIC_MINISWHITE))
761 pixInvert(pix, pix);
762 }
763
764 if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation)) {
765 if (orientation >= 1 && orientation <= 8) {
766 struct tiff_transform *transform = (read_oriented) ?
767 &tiff_partial_orientation_transforms[orientation - 1] :
768 &tiff_orientation_transforms[orientation - 1];
769 if (transform->vflip) pixFlipTB(pix, pix);
770 if (transform->hflip) pixFlipLR(pix, pix);
771 if (transform->rotate) {
772 PIX *oldpix = pix;
773 pix = pixRotate90(oldpix, transform->rotate);
774 pixDestroy(&oldpix);
775 }
776 }
777 }
778
779 text = NULL;
780 TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &text);
781 if (text) pixSetText(pix, text);
782 return pix;
783}
784
785
786/*--------------------------------------------------------------*
787 * Writing to file *
788 *--------------------------------------------------------------*/
810l_ok
811pixWriteTiff(const char *filename,
812 PIX *pix,
813 l_int32 comptype,
814 const char *modestr)
815{
816 return pixWriteTiffCustom(filename, pix, comptype, modestr,
817 NULL, NULL, NULL, NULL);
818}
819
820
867l_ok
868pixWriteTiffCustom(const char *filename,
869 PIX *pix,
870 l_int32 comptype,
871 const char *modestr,
872 NUMA *natags,
873 SARRAY *savals,
874 SARRAY *satypes,
875 NUMA *nasizes)
876{
877l_int32 ret;
878TIFF *tif;
879
880 if (!filename)
881 return ERROR_INT("filename not defined", __func__, 1);
882 if (!pix)
883 return ERROR_INT("pix not defined", __func__, 1);
884
885 if ((tif = openTiff(filename, modestr)) == NULL)
886 return ERROR_INT("tif not opened", __func__, 1);
887 ret = pixWriteToTiffStream(tif, pix, comptype, natags, savals,
888 satypes, nasizes);
889 TIFFClose(tif);
890 return ret;
891}
892
893
894/*--------------------------------------------------------------*
895 * Writing to stream *
896 *--------------------------------------------------------------*/
924l_ok
926 PIX *pix,
927 l_int32 comptype)
928{
929 return pixWriteStreamTiffWA(fp, pix, comptype, "w");
930}
931
932
949l_ok
951 PIX *pix,
952 l_int32 comptype,
953 const char *modestr)
954{
955TIFF *tif;
956
957 if (!fp)
958 return ERROR_INT("stream not defined", __func__, 1 );
959 if (!pix)
960 return ERROR_INT("pix not defined", __func__, 1 );
961 if (strcmp(modestr, "w") && strcmp(modestr, "a")) {
962 L_ERROR("modestr = %s; not 'w' or 'a'\n", __func__, modestr);
963 return 1;
964 }
965
966 if (pixGetDepth(pix) != 1 && comptype != IFF_TIFF &&
967 comptype != IFF_TIFF_LZW && comptype != IFF_TIFF_ZIP &&
968 comptype != IFF_TIFF_JPEG) {
969 L_WARNING("invalid compression type %d for bpp > 1; using TIFF_ZIP\n",
970 __func__, comptype);
971 comptype = IFF_TIFF_ZIP;
972 }
973
974 if ((tif = fopenTiff(fp, modestr)) == NULL)
975 return ERROR_INT("tif not opened", __func__, 1);
976
977 if (pixWriteToTiffStream(tif, pix, comptype, NULL, NULL, NULL, NULL)) {
978 TIFFCleanup(tif);
979 return ERROR_INT("tif write error", __func__, 1);
980 }
981
982 TIFFCleanup(tif);
983 return 0;
984}
985
986
1022static l_int32
1024 PIX *pix,
1025 l_int32 comptype,
1026 NUMA *natags,
1027 SARRAY *savals,
1028 SARRAY *satypes,
1029 NUMA *nasizes)
1030{
1031l_uint8 *linebuf, *data;
1032l_uint16 redmap[256], greenmap[256], bluemap[256];
1033l_int32 w, h, d, spp, i, j, k, wpl, bpl, tiffbpl, ncolors, cmapsize;
1034l_int32 *rmap, *gmap, *bmap;
1035l_int32 xres, yres;
1036l_uint32 *line, *ppixel;
1037PIX *pixt;
1038PIXCMAP *cmap;
1039char *text;
1040
1041 if (!tif)
1042 return ERROR_INT("tif stream not defined", __func__, 1);
1043 if (!pix)
1044 return ERROR_INT( "pix not defined", __func__, 1 );
1045
1046 pixSetPadBits(pix, 0);
1047 pixGetDimensions(pix, &w, &h, &d);
1048 spp = pixGetSpp(pix);
1049 xres = pixGetXRes(pix);
1050 yres = pixGetYRes(pix);
1051 if (xres == 0) xres = DefaultResolution;
1052 if (yres == 0) yres = DefaultResolution;
1053
1054 /* ------------------ Write out the header ------------- */
1055 TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, (l_uint32)RESUNIT_INCH);
1056 TIFFSetField(tif, TIFFTAG_XRESOLUTION, (l_float64)xres);
1057 TIFFSetField(tif, TIFFTAG_YRESOLUTION, (l_float64)yres);
1058
1059 TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (l_uint32)w);
1060 TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (l_uint32)h);
1061 TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
1062
1063 if ((text = pixGetText(pix)) != NULL)
1064 TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, text);
1065
1066 if (d == 1 && !pixGetColormap(pix)) {
1067 /* If d == 1, preserve the colormap. Note that when
1068 * d == 1 pix with colormaps are read, the colormaps
1069 * are removed. The only pix in leptonica that have
1070 * colormaps are made programmatically. */
1071 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE);
1072 } else if ((d == 32 && spp == 3) || d == 24) {
1073 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1074 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)3);
1075 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,
1076 (l_uint16)8, (l_uint16)8, (l_uint16)8);
1077 } else if (d == 32 && spp == 4) {
1078 l_uint16 val[1];
1079 val[0] = EXTRASAMPLE_ASSOCALPHA;
1080 TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, (l_uint16)1, &val);
1081 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
1082 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)4);
1083 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE,
1084 (l_uint16)8, (l_uint16)8, (l_uint16)8, (l_uint16)8);
1085 } else if (d == 16) { /* we only support spp = 1, bps = 16 */
1086 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1087 } else if ((cmap = pixGetColormap(pix)) == NULL) {
1088 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
1089 } else { /* Save colormap in the tiff; not more than 256 colors */
1090 if (d > 8) {
1091 L_ERROR("d = %d > 8 with colormap!; reducing to 8\n", __func__, d);
1092 d = 8;
1093 }
1094 pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL);
1095 ncolors = pixcmapGetCount(cmap);
1096 ncolors = L_MIN(256, ncolors); /* max 256 */
1097 cmapsize = 1 << d;
1098 cmapsize = L_MIN(256, cmapsize); /* power of 2; max 256 */
1099 if (ncolors > cmapsize) {
1100 L_WARNING("too many colors in cmap for tiff; truncating\n",
1101 __func__);
1102 ncolors = cmapsize;
1103 }
1104 for (i = 0; i < ncolors; i++) {
1105 redmap[i] = (rmap[i] << 8) | rmap[i];
1106 greenmap[i] = (gmap[i] << 8) | gmap[i];
1107 bluemap[i] = (bmap[i] << 8) | bmap[i];
1108 }
1109 for (i = ncolors; i < cmapsize; i++) /* init, even though not used */
1110 redmap[i] = greenmap[i] = bluemap[i] = 0;
1111 LEPT_FREE(rmap);
1112 LEPT_FREE(gmap);
1113 LEPT_FREE(bmap);
1114
1115 TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
1116 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)1);
1117 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (l_uint16)d);
1118 TIFFSetField(tif, TIFFTAG_COLORMAP, redmap, greenmap, bluemap);
1119 }
1120
1121 if (d <= 16) {
1122 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, (l_uint16)d);
1123 TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (l_uint16)1);
1124 }
1125
1126 TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1127 if (comptype == IFF_TIFF) { /* no compression */
1128 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1129 } else if (comptype == IFF_TIFF_G4) {
1130 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
1131 } else if (comptype == IFF_TIFF_G3) {
1132 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX3);
1133 } else if (comptype == IFF_TIFF_RLE) {
1134 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTRLE);
1135 } else if (comptype == IFF_TIFF_PACKBITS) {
1136 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
1137 } else if (comptype == IFF_TIFF_LZW) {
1138 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
1139 } else if (comptype == IFF_TIFF_ZIP) {
1140 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_ADOBE_DEFLATE);
1141 } else if (comptype == IFF_TIFF_JPEG) {
1142 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
1143 } else {
1144 L_WARNING("unknown tiff compression; using none\n", __func__);
1145 TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
1146 }
1147
1148 /* This is a no-op if arrays are NULL */
1149 writeCustomTiffTags(tif, natags, savals, satypes, nasizes);
1150
1151 /* ------------- Write out the image data ------------- */
1152 tiffbpl = TIFFScanlineSize(tif);
1153 wpl = pixGetWpl(pix);
1154 bpl = 4 * wpl;
1155 if (tiffbpl > bpl)
1156 lept_stderr("Big trouble: tiffbpl = %d, bpl = %d\n", tiffbpl, bpl);
1157 if ((linebuf = (l_uint8 *)LEPT_CALLOC(1, bpl)) == NULL)
1158 return ERROR_INT("calloc fail for linebuf", __func__, 1);
1159
1160 /* Use single strip for image */
1161 TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, h);
1162
1163 if (d != 24 && d != 32) {
1164 if (d == 16)
1165 pixt = pixEndianTwoByteSwapNew(pix);
1166 else
1167 pixt = pixEndianByteSwapNew(pix);
1168 data = (l_uint8 *)pixGetData(pixt);
1169 for (i = 0; i < h; i++, data += bpl) {
1170 memcpy(linebuf, data, tiffbpl);
1171 if (TIFFWriteScanline(tif, linebuf, i, 0) < 0)
1172 break;
1173 }
1174 pixDestroy(&pixt);
1175 } else if (d == 24) { /* See note 4 above: special case of 24 bpp rgb */
1176 for (i = 0; i < h; i++) {
1177 line = pixGetData(pix) + i * wpl;
1178 if (TIFFWriteScanline(tif, (l_uint8 *)line, i, 0) < 0)
1179 break;
1180 }
1181 } else { /* 32 bpp rgb or rgba */
1182 for (i = 0; i < h; i++) {
1183 line = pixGetData(pix) + i * wpl;
1184 for (j = 0, k = 0, ppixel = line; j < w; j++) {
1185 linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_RED);
1186 linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_GREEN);
1187 linebuf[k++] = GET_DATA_BYTE(ppixel, COLOR_BLUE);
1188 if (spp == 4)
1189 linebuf[k++] = GET_DATA_BYTE(ppixel, L_ALPHA_CHANNEL);
1190 ppixel++;
1191 }
1192 if (TIFFWriteScanline(tif, linebuf, i, 0) < 0)
1193 break;
1194 }
1195 }
1196
1197/* TIFFWriteDirectory(tif); */
1198 LEPT_FREE(linebuf);
1199
1200 return 0;
1201}
1202
1203
1233static l_int32
1235 NUMA *natags,
1236 SARRAY *savals,
1237 SARRAY *satypes,
1238 NUMA *nasizes)
1239{
1240char *sval, *type;
1241l_int32 i, n, ns, size, tagval, val;
1242l_float64 dval;
1243l_uint32 uval, uval2;
1244
1245 if (!tif)
1246 return ERROR_INT("tif stream not defined", __func__, 1);
1247 if (!natags && !savals && !satypes)
1248 return 0;
1249 if (!natags || !savals || !satypes)
1250 return ERROR_INT("not all arrays defined", __func__, 1);
1251 n = numaGetCount(natags);
1252 if ((sarrayGetCount(savals) != n) || (sarrayGetCount(satypes) != n))
1253 return ERROR_INT("not all sa the same size", __func__, 1);
1254
1255 /* The sized arrays (4 args to TIFFSetField) are written first */
1256 if (nasizes) {
1257 ns = numaGetCount(nasizes);
1258 if (ns > n)
1259 return ERROR_INT("too many 4-arg tag calls", __func__, 1);
1260 for (i = 0; i < ns; i++) {
1261 numaGetIValue(natags, i, &tagval);
1262 sval = sarrayGetString(savals, i, L_NOCOPY);
1263 type = sarrayGetString(satypes, i, L_NOCOPY);
1264 numaGetIValue(nasizes, i, &size);
1265 if (strcmp(type, "char*") && strcmp(type, "l_uint8*"))
1266 L_WARNING("array type not char* or l_uint8*; ignore\n",
1267 __func__);
1268 TIFFSetField(tif, tagval, size, sval);
1269 }
1270 } else {
1271 ns = 0;
1272 }
1273
1274 /* The typical tags (3 args to TIFFSetField) are now written */
1275 for (i = ns; i < n; i++) {
1276 numaGetIValue(natags, i, &tagval);
1277 sval = sarrayGetString(savals, i, L_NOCOPY);
1278 type = sarrayGetString(satypes, i, L_NOCOPY);
1279 if (!strcmp(type, "char*") || !strcmp(type, "const char*")) {
1280 TIFFSetField(tif, tagval, sval);
1281 } else if (!strcmp(type, "l_uint16")) {
1282 if (sscanf(sval, "%u", &uval) == 1) {
1283 TIFFSetField(tif, tagval, (l_uint16)uval);
1284 } else {
1285 lept_stderr("val %s not of type %s\n", sval, type);
1286 return ERROR_INT("custom tag(s) not written", __func__, 1);
1287 }
1288 } else if (!strcmp(type, "l_uint32")) {
1289 if (sscanf(sval, "%u", &uval) == 1) {
1290 TIFFSetField(tif, tagval, uval);
1291 } else {
1292 lept_stderr("val %s not of type %s\n", sval, type);
1293 return ERROR_INT("custom tag(s) not written", __func__, 1);
1294 }
1295 } else if (!strcmp(type, "l_int32")) {
1296 if (sscanf(sval, "%d", &val) == 1) {
1297 TIFFSetField(tif, tagval, val);
1298 } else {
1299 lept_stderr("val %s not of type %s\n", sval, type);
1300 return ERROR_INT("custom tag(s) not written", __func__, 1);
1301 }
1302 } else if (!strcmp(type, "l_float64")) {
1303 if (sscanf(sval, "%lf", &dval) == 1) {
1304 TIFFSetField(tif, tagval, dval);
1305 } else {
1306 lept_stderr("val %s not of type %s\n", sval, type);
1307 return ERROR_INT("custom tag(s) not written", __func__, 1);
1308 }
1309 } else if (!strcmp(type, "l_uint16-l_uint16")) {
1310 if (sscanf(sval, "%u-%u", &uval, &uval2) == 2) {
1311 TIFFSetField(tif, tagval, (l_uint16)uval, (l_uint16)uval2);
1312 } else {
1313 lept_stderr("val %s not of type %s\n", sval, type);
1314 return ERROR_INT("custom tag(s) not written", __func__, 1);
1315 }
1316 } else {
1317 lept_stderr("unknown type %s\n",type);
1318 return ERROR_INT("unknown type; tag(s) not written", __func__, 1);
1319 }
1320 }
1321 return 0;
1322}
1323
1324
1325/*--------------------------------------------------------------*
1326 * Reading and writing multipage tiff *
1327 *--------------------------------------------------------------*/
1359PIX *
1361 size_t *poffset)
1362{
1363l_int32 retval;
1364size_t offset;
1365PIX *pix;
1366TIFF *tif;
1367
1368 if (!fname)
1369 return (PIX *)ERROR_PTR("fname not defined", __func__, NULL);
1370 if (!poffset)
1371 return (PIX *)ERROR_PTR("&offset not defined", __func__, NULL);
1372
1373 if ((tif = openTiff(fname, "r")) == NULL) {
1374 L_ERROR("tif open failed for %s\n", __func__, fname);
1375 return NULL;
1376 }
1377
1378 /* Set ptrs in the TIFF to the beginning of the image */
1379 offset = *poffset;
1380 retval = (offset == 0) ? TIFFSetDirectory(tif, 0)
1381 : TIFFSetSubDirectory(tif, offset);
1382 if (retval == 0) {
1383 TIFFClose(tif);
1384 return NULL;
1385 }
1386
1387 if ((pix = pixReadFromTiffStream(tif)) == NULL) {
1388 TIFFClose(tif);
1389 return NULL;
1390 }
1391
1392 /* Advance to the next image and return the new offset */
1393 TIFFReadDirectory(tif);
1394 *poffset = TIFFCurrentDirOffset(tif);
1395 TIFFClose(tif);
1396 return pix;
1397}
1398
1399
1406PIXA *
1407pixaReadMultipageTiff(const char *filename)
1408{
1409l_int32 i, npages;
1410FILE *fp;
1411PIX *pix;
1412PIXA *pixa;
1413TIFF *tif;
1414
1415 if (!filename)
1416 return (PIXA *)ERROR_PTR("filename not defined", __func__, NULL);
1417
1418 if ((fp = fopenReadStream(filename)) == NULL)
1419 return (PIXA *)ERROR_PTR("stream not opened", __func__, NULL);
1420 if (fileFormatIsTiff(fp)) {
1421 tiffGetCount(fp, &npages);
1422 L_INFO(" Tiff: %d pages\n", __func__, npages);
1423 } else {
1424 return (PIXA *)ERROR_PTR("file not tiff", __func__, NULL);
1425 }
1426
1427 if ((tif = fopenTiff(fp, "r")) == NULL)
1428 return (PIXA *)ERROR_PTR("tif not opened", __func__, NULL);
1429
1430 pixa = pixaCreate(npages);
1431 pix = NULL;
1432 for (i = 0; i < npages; i++) {
1433 if ((pix = pixReadFromTiffStream(tif)) != NULL) {
1434 pixaAddPix(pixa, pix, L_INSERT);
1435 } else {
1436 L_WARNING("pix not read for page %d\n", __func__, i);
1437 }
1438
1439 /* Advance to the next directory (i.e., the next image) */
1440 if (TIFFReadDirectory(tif) == 0)
1441 break;
1442 }
1443
1444 fclose(fp);
1445 TIFFCleanup(tif);
1446 return pixa;
1447}
1448
1449
1464l_ok
1465pixaWriteMultipageTiff(const char *fname,
1466 PIXA *pixa)
1467{
1468const char *modestr;
1469l_int32 i, n;
1470PIX *pix1;
1471
1472 if (!fname)
1473 return ERROR_INT("fname not defined", __func__, 1);
1474 if (!pixa)
1475 return ERROR_INT("pixa not defined", __func__, 1);
1476
1477 n = pixaGetCount(pixa);
1478 for (i = 0; i < n; i++) {
1479 modestr = (i == 0) ? "w" : "a";
1480 pix1 = pixaGetPix(pixa, i, L_CLONE);
1481 if (pixGetDepth(pix1) == 1)
1482 pixWriteTiff(fname, pix1, IFF_TIFF_G4, modestr);
1483 else
1484 pixWriteTiff(fname, pix1, IFF_TIFF_ZIP, modestr);
1485 pixDestroy(&pix1);
1486 }
1487
1488 return 0;
1489}
1490
1491
1516l_ok
1517writeMultipageTiff(const char *dirin,
1518 const char *substr,
1519 const char *fileout)
1520{
1521SARRAY *sa;
1522
1523 if (!dirin)
1524 return ERROR_INT("dirin not defined", __func__, 1);
1525 if (!fileout)
1526 return ERROR_INT("fileout not defined", __func__, 1);
1527
1528 /* Get all filtered and sorted full pathnames. */
1529 sa = getSortedPathnamesInDirectory(dirin, substr, 0, 0);
1530
1531 /* Generate the tiff file */
1532 writeMultipageTiffSA(sa, fileout);
1533 sarrayDestroy(&sa);
1534 return 0;
1535}
1536
1537
1550l_ok
1552 const char *fileout)
1553{
1554char *fname;
1555const char *op;
1556l_int32 i, nfiles, firstfile, format;
1557PIX *pix;
1558
1559 if (!sa)
1560 return ERROR_INT("sa not defined", __func__, 1);
1561 if (!fileout)
1562 return ERROR_INT("fileout not defined", __func__, 1);
1563
1564 nfiles = sarrayGetCount(sa);
1565 firstfile = TRUE;
1566 for (i = 0; i < nfiles; i++) {
1567 op = (firstfile) ? "w" : "a";
1568 fname = sarrayGetString(sa, i, L_NOCOPY);
1569 findFileFormat(fname, &format);
1570 if (format == IFF_UNKNOWN) {
1571 L_INFO("format of %s not known\n", __func__, fname);
1572 continue;
1573 }
1574
1575 if ((pix = pixRead(fname)) == NULL) {
1576 L_WARNING("pix not made for file: %s\n", __func__, fname);
1577 continue;
1578 }
1579 if (pixGetDepth(pix) == 1)
1580 pixWriteTiff(fileout, pix, IFF_TIFF_G4, op);
1581 else
1582 pixWriteTiff(fileout, pix, IFF_TIFF_ZIP, op);
1583 firstfile = FALSE;
1584 pixDestroy(&pix);
1585 }
1586
1587 return 0;
1588}
1589
1590
1591/*--------------------------------------------------------------*
1592 * Print info to stream *
1593 *--------------------------------------------------------------*/
1601l_ok
1602fprintTiffInfo(FILE *fpout,
1603 const char *tiffile)
1604{
1605TIFF *tif;
1606
1607 if (!tiffile)
1608 return ERROR_INT("tiffile not defined", __func__, 1);
1609 if (!fpout)
1610 return ERROR_INT("stream out not defined", __func__, 1);
1611
1612 if ((tif = openTiff(tiffile, "rb")) == NULL)
1613 return ERROR_INT("tif not open for read", __func__, 1);
1614
1615 TIFFPrintDirectory(tif, fpout, 0);
1616 TIFFClose(tif);
1617
1618 return 0;
1619}
1620
1621
1622/*--------------------------------------------------------------*
1623 * Get page count *
1624 *--------------------------------------------------------------*/
1632l_ok
1634 l_int32 *pn)
1635{
1636l_int32 i;
1637TIFF *tif;
1638
1639 if (!fp)
1640 return ERROR_INT("stream not defined", __func__, 1);
1641 if (!pn)
1642 return ERROR_INT("&n not defined", __func__, 1);
1643 *pn = 0;
1644
1645 if ((tif = fopenTiff(fp, "r")) == NULL)
1646 return ERROR_INT("tif not open for read", __func__, 1);
1647
1648 for (i = 1; ; i++) {
1649 if (TIFFReadDirectory(tif) == 0)
1650 break;
1651 if (i == ManyPagesInTiffFile + 1) {
1652 L_WARNING("big file: more than %d pages\n", __func__,
1653 ManyPagesInTiffFile);
1654 }
1655 }
1656 *pn = i;
1657 TIFFCleanup(tif);
1658 return 0;
1659}
1660
1661
1662/*--------------------------------------------------------------*
1663 * Get resolution from tif *
1664 *--------------------------------------------------------------*/
1678l_ok
1680 l_int32 *pxres,
1681 l_int32 *pyres)
1682{
1683TIFF *tif;
1684
1685 if (!pxres || !pyres)
1686 return ERROR_INT("&xres and &yres not both defined", __func__, 1);
1687 *pxres = *pyres = 0;
1688 if (!fp)
1689 return ERROR_INT("stream not opened", __func__, 1);
1690
1691 if ((tif = fopenTiff(fp, "r")) == NULL)
1692 return ERROR_INT("tif not open for read", __func__, 1);
1693 getTiffStreamResolution(tif, pxres, pyres);
1694 TIFFCleanup(tif);
1695 return 0;
1696}
1697
1698
1712static l_int32
1714 l_int32 *pxres,
1715 l_int32 *pyres)
1716{
1717l_uint16 resunit;
1718l_int32 foundxres, foundyres;
1719l_float32 fxres, fyres;
1720
1721 if (!tif)
1722 return ERROR_INT("tif not opened", __func__, 1);
1723 if (!pxres || !pyres)
1724 return ERROR_INT("&xres and &yres not both defined", __func__, 1);
1725 *pxres = *pyres = 0;
1726
1727 TIFFGetFieldDefaulted(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
1728 foundxres = TIFFGetField(tif, TIFFTAG_XRESOLUTION, &fxres);
1729 foundyres = TIFFGetField(tif, TIFFTAG_YRESOLUTION, &fyres);
1730 if (!foundxres && !foundyres) return 1;
1731 if (isnan(fxres) || isnan(fyres)) return 1;
1732 if (!foundxres && foundyres)
1733 fxres = fyres;
1734 else if (foundxres && !foundyres)
1735 fyres = fxres;
1736
1737 /* Avoid overflow into int32; set max fxres and fyres to 5 x 10^8 */
1738 if (fxres < 0 || fxres > (1L << 29) || fyres < 0 || fyres > (1L << 29))
1739 return ERROR_INT("fxres and/or fyres values are invalid", __func__, 1);
1740
1741 if (resunit == RESUNIT_CENTIMETER) { /* convert to ppi */
1742 *pxres = (l_int32)(2.54 * fxres + 0.5);
1743 *pyres = (l_int32)(2.54 * fyres + 0.5);
1744 } else {
1745 *pxres = (l_int32)(fxres + 0.5);
1746 *pyres = (l_int32)(fyres + 0.5);
1747 }
1748
1749 return 0;
1750}
1751
1752
1753/*--------------------------------------------------------------*
1754 * Get some tiff header information *
1755 *--------------------------------------------------------------*/
1776l_ok
1777readHeaderTiff(const char *filename,
1778 l_int32 n,
1779 l_int32 *pw,
1780 l_int32 *ph,
1781 l_int32 *pbps,
1782 l_int32 *pspp,
1783 l_int32 *pres,
1784 l_int32 *pcmap,
1785 l_int32 *pformat)
1786{
1787l_int32 ret;
1788FILE *fp;
1789
1790 if (pw) *pw = 0;
1791 if (ph) *ph = 0;
1792 if (pbps) *pbps = 0;
1793 if (pspp) *pspp = 0;
1794 if (pres) *pres = 0;
1795 if (pcmap) *pcmap = 0;
1796 if (pformat) *pformat = 0;
1797 if (!filename)
1798 return ERROR_INT("filename not defined", __func__, 1);
1799 if (!pw && !ph && !pbps && !pspp && !pres && !pcmap && !pformat)
1800 return ERROR_INT("no results requested", __func__, 1);
1801
1802 if ((fp = fopenReadStream(filename)) == NULL)
1803 return ERROR_INT("image file not found", __func__, 1);
1804 ret = freadHeaderTiff(fp, n, pw, ph, pbps, pspp, pres, pcmap, pformat);
1805 fclose(fp);
1806 return ret;
1807}
1808
1809
1830l_ok
1832 l_int32 n,
1833 l_int32 *pw,
1834 l_int32 *ph,
1835 l_int32 *pbps,
1836 l_int32 *pspp,
1837 l_int32 *pres,
1838 l_int32 *pcmap,
1839 l_int32 *pformat)
1840{
1841l_int32 i, ret, format;
1842TIFF *tif;
1843
1844 if (pw) *pw = 0;
1845 if (ph) *ph = 0;
1846 if (pbps) *pbps = 0;
1847 if (pspp) *pspp = 0;
1848 if (pres) *pres = 0;
1849 if (pcmap) *pcmap = 0;
1850 if (pformat) *pformat = 0;
1851 if (!fp)
1852 return ERROR_INT("stream not defined", __func__, 1);
1853 if (n < 0)
1854 return ERROR_INT("image index must be >= 0", __func__, 1);
1855 if (!pw && !ph && !pbps && !pspp && !pres && !pcmap && !pformat)
1856 return ERROR_INT("no results requested", __func__, 1);
1857
1858 findFileFormatStream(fp, &format);
1859 if (!L_FORMAT_IS_TIFF(format))
1860 return ERROR_INT("file not tiff format", __func__, 1);
1861
1862 if ((tif = fopenTiff(fp, "r")) == NULL)
1863 return ERROR_INT("tif not open for read", __func__, 1);
1864
1865 for (i = 0; i < n; i++) {
1866 if (TIFFReadDirectory(tif) == 0)
1867 return ERROR_INT("image n not found in file", __func__, 1);
1868 }
1869
1870 ret = tiffReadHeaderTiff(tif, pw, ph, pbps, pspp, pres, pcmap, pformat);
1871 TIFFCleanup(tif);
1872 return ret;
1873}
1874
1875
1897l_ok
1898readHeaderMemTiff(const l_uint8 *cdata,
1899 size_t size,
1900 l_int32 n,
1901 l_int32 *pw,
1902 l_int32 *ph,
1903 l_int32 *pbps,
1904 l_int32 *pspp,
1905 l_int32 *pres,
1906 l_int32 *pcmap,
1907 l_int32 *pformat)
1908{
1909l_uint8 *data;
1910l_int32 i, ret;
1911TIFF *tif;
1912
1913 if (pw) *pw = 0;
1914 if (ph) *ph = 0;
1915 if (pbps) *pbps = 0;
1916 if (pspp) *pspp = 0;
1917 if (pres) *pres = 0;
1918 if (pcmap) *pcmap = 0;
1919 if (pformat) *pformat = 0;
1920 if (!pw && !ph && !pbps && !pspp && !pres && !pcmap && !pformat)
1921 return ERROR_INT("no results requested", __func__, 1);
1922 if (!cdata)
1923 return ERROR_INT("cdata not defined", __func__, 1);
1924
1925 /* Open a tiff stream to memory */
1926 data = (l_uint8 *)cdata; /* we're really not going to change this */
1927 if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL)
1928 return ERROR_INT("tiff stream not opened", __func__, 1);
1929
1930 for (i = 0; i < n; i++) {
1931 if (TIFFReadDirectory(tif) == 0) {
1932 TIFFClose(tif);
1933 return ERROR_INT("image n not found in file", __func__, 1);
1934 }
1935 }
1936
1937 ret = tiffReadHeaderTiff(tif, pw, ph, pbps, pspp, pres, pcmap, pformat);
1938 TIFFClose(tif);
1939 return ret;
1940}
1941
1942
1956static l_int32
1958 l_int32 *pw,
1959 l_int32 *ph,
1960 l_int32 *pbps,
1961 l_int32 *pspp,
1962 l_int32 *pres,
1963 l_int32 *pcmap,
1964 l_int32 *pformat)
1965{
1966l_uint16 tiffcomp;
1967l_uint16 bps, spp;
1968l_uint16 *rmap, *gmap, *bmap;
1969l_int32 xres, yres;
1970l_uint32 w, h;
1971
1972 if (!tif)
1973 return ERROR_INT("tif not opened", __func__, 1);
1974
1975 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
1976 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
1977 TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps);
1978 TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
1979 if (w < 1 || h < 1)
1980 return ERROR_INT("tif w and h not both > 0", __func__, 1);
1981 if (bps != 1 && bps != 2 && bps != 4 && bps != 8 && bps != 16)
1982 return ERROR_INT("bps not in set {1,2,4,8,16}", __func__, 1);
1983 if (spp != 1 && spp != 2 && spp != 3 && spp != 4)
1984 return ERROR_INT("spp not in set {1,2,3,4}", __func__, 1);
1985 if (pw) *pw = w;
1986 if (ph) *ph = h;
1987 if (pbps) *pbps = bps;
1988 if (pspp) *pspp = spp;
1989 if (pres) {
1990 if (getTiffStreamResolution(tif, &xres, &yres) == 0)
1991 *pres = (l_int32)xres;
1992 }
1993 if (pcmap) {
1994 if (TIFFGetField(tif, TIFFTAG_COLORMAP, &rmap, &gmap, &bmap))
1995 *pcmap = 1;
1996 }
1997 if (pformat) {
1998 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp);
1999 *pformat = getTiffCompressedFormat(tiffcomp);
2000 }
2001 return 0;
2002}
2003
2004
2024l_ok
2026 l_int32 *pcomptype)
2027{
2028l_uint16 tiffcomp;
2029TIFF *tif;
2030
2031 if (!pcomptype)
2032 return ERROR_INT("&comptype not defined", __func__, 1);
2033 *pcomptype = IFF_UNKNOWN; /* init */
2034 if (!fp)
2035 return ERROR_INT("stream not defined", __func__, 1);
2036
2037 if ((tif = fopenTiff(fp, "r")) == NULL)
2038 return ERROR_INT("tif not opened", __func__, 1);
2039 TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &tiffcomp);
2040 *pcomptype = getTiffCompressedFormat(tiffcomp);
2041 TIFFCleanup(tif);
2042 return 0;
2043}
2044
2045
2060static l_int32
2061getTiffCompressedFormat(l_uint16 tiffcomp)
2062{
2063l_int32 comptype;
2064
2065 switch (tiffcomp)
2066 {
2067 case COMPRESSION_CCITTFAX4:
2068 comptype = IFF_TIFF_G4;
2069 break;
2070 case COMPRESSION_CCITTFAX3:
2071 comptype = IFF_TIFF_G3;
2072 break;
2073 case COMPRESSION_CCITTRLE:
2074 comptype = IFF_TIFF_RLE;
2075 break;
2076 case COMPRESSION_PACKBITS:
2077 comptype = IFF_TIFF_PACKBITS;
2078 break;
2079 case COMPRESSION_LZW:
2080 comptype = IFF_TIFF_LZW;
2081 break;
2082 case COMPRESSION_ADOBE_DEFLATE:
2083 comptype = IFF_TIFF_ZIP;
2084 break;
2085 case COMPRESSION_JPEG:
2086 comptype = IFF_TIFF_JPEG;
2087 break;
2088 default:
2089 comptype = IFF_TIFF;
2090 break;
2091 }
2092 return comptype;
2093}
2094
2095
2096/*--------------------------------------------------------------*
2097 * Extraction of tiff g4 data *
2098 *--------------------------------------------------------------*/
2110l_ok
2111extractG4DataFromFile(const char *filein,
2112 l_uint8 **pdata,
2113 size_t *pnbytes,
2114 l_int32 *pw,
2115 l_int32 *ph,
2116 l_int32 *pminisblack)
2117{
2118l_uint8 *inarray, *data;
2119l_uint16 minisblack, comptype; /* accessors require l_uint16 */
2120l_int32 istiff;
2121l_uint32 w, h, rowsperstrip; /* accessors require l_uint32 */
2122l_uint32 diroff;
2123size_t fbytes, nbytes;
2124FILE *fpin;
2125TIFF *tif;
2126
2127 if (!pdata)
2128 return ERROR_INT("&data not defined", __func__, 1);
2129 if (!pnbytes)
2130 return ERROR_INT("&nbytes not defined", __func__, 1);
2131 if (!pw && !ph && !pminisblack)
2132 return ERROR_INT("no output data requested", __func__, 1);
2133 *pdata = NULL;
2134 *pnbytes = 0;
2135
2136 if ((fpin = fopenReadStream(filein)) == NULL)
2137 return ERROR_INT("stream not opened to file", __func__, 1);
2138 istiff = fileFormatIsTiff(fpin);
2139 fclose(fpin);
2140 if (!istiff)
2141 return ERROR_INT("filein not tiff", __func__, 1);
2142
2143 if ((inarray = l_binaryRead(filein, &fbytes)) == NULL)
2144 return ERROR_INT("inarray not made", __func__, 1);
2145
2146 /* Get metadata about the image */
2147 if ((tif = openTiff(filein, "rb")) == NULL) {
2148 LEPT_FREE(inarray);
2149 return ERROR_INT("tif not open for read", __func__, 1);
2150 }
2151 TIFFGetField(tif, TIFFTAG_COMPRESSION, &comptype);
2152 if (comptype != COMPRESSION_CCITTFAX4) {
2153 LEPT_FREE(inarray);
2154 TIFFClose(tif);
2155 return ERROR_INT("filein is not g4 compressed", __func__, 1);
2156 }
2157
2158 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
2159 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
2160 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
2161 if (h != rowsperstrip)
2162 L_WARNING("more than 1 strip\n", __func__);
2163 /* From the standard:
2164 TIFFTAG_PHOTOMETRIC = 0 (false) --> min value is white.
2165 TIFFTAG_PHOTOMETRIC = 1 (true) --> min value is black.
2166 Most 1 bpp tiffs have the tag value 0 (black is 1),
2167 because there are fewer black pixels than white pixels,
2168 so it makes sense to encode runs of black pixels. */
2169 TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &minisblack);
2170/* TIFFPrintDirectory(tif, stderr, 0); */
2171 TIFFClose(tif);
2172 if (pw) *pw = (l_int32)w;
2173 if (ph) *ph = (l_int32)h;
2174 if (pminisblack) *pminisblack = (l_int32)minisblack;
2175
2176 /* The header has 8 bytes: the first 2 are the magic number,
2177 * the next 2 are the version, and the last 4 are the
2178 * offset to the first directory. That's what we want here.
2179 * We have to test the byte order before decoding 4 bytes! */
2180 if (inarray[0] == 0x4d) { /* big-endian */
2181 diroff = (inarray[4] << 24) | (inarray[5] << 16) |
2182 (inarray[6] << 8) | inarray[7];
2183 } else { /* inarray[0] == 0x49 : little-endian */
2184 diroff = (inarray[7] << 24) | (inarray[6] << 16) |
2185 (inarray[5] << 8) | inarray[4];
2186 }
2187/* lept_stderr(" diroff = %d, %x\n", diroff, diroff); */
2188
2189 /* Extract the ccittg4 encoded data from the tiff file.
2190 * We skip the 8 byte header and take nbytes of data,
2191 * up to the beginning of the directory (at diroff) */
2192 nbytes = diroff - 8;
2193 if (nbytes > MaxNumTiffBytes) {
2194 LEPT_FREE(inarray);
2195 L_ERROR("requesting %zu bytes > %zu\n", __func__,
2196 nbytes, MaxNumTiffBytes);
2197 return 1;
2198 }
2199 *pnbytes = nbytes;
2200 if ((data = (l_uint8 *)LEPT_CALLOC(nbytes, sizeof(l_uint8))) == NULL) {
2201 LEPT_FREE(inarray);
2202 return ERROR_INT("data not allocated", __func__, 1);
2203 }
2204 *pdata = data;
2205 memcpy(data, inarray + 8, nbytes);
2206 LEPT_FREE(inarray);
2207
2208 return 0;
2209}
2210
2211
2212/*--------------------------------------------------------------*
2213 * Open tiff stream from file stream *
2214 *--------------------------------------------------------------*/
2235static TIFF *
2236fopenTiff(FILE *fp,
2237 const char *modestring)
2238{
2239 if (!fp)
2240 return (TIFF *)ERROR_PTR("stream not opened", __func__, NULL);
2241 if (!modestring)
2242 return (TIFF *)ERROR_PTR("modestring not defined", __func__, NULL);
2243
2244 TIFFSetWarningHandler(NULL); /* disable warnings */
2245 TIFFSetErrorHandler(NULL); /* disable error messages */
2246
2247 fseek(fp, 0, SEEK_SET);
2248 return TIFFClientOpen("TIFFstream", modestring, (thandle_t)fp,
2249 lept_read_proc, lept_write_proc, lept_seek_proc,
2250 lept_close_proc, lept_size_proc, NULL, NULL);
2251}
2252
2253
2254/*--------------------------------------------------------------*
2255 * Wrapper for TIFFOpen *
2256 *--------------------------------------------------------------*/
2269static TIFF *
2270openTiff(const char *filename,
2271 const char *modestring)
2272{
2273char *fname;
2274TIFF *tif;
2275
2276 if (!filename)
2277 return (TIFF *)ERROR_PTR("filename not defined", __func__, NULL);
2278 if (!modestring)
2279 return (TIFF *)ERROR_PTR("modestring not defined", __func__, NULL);
2280
2281 TIFFSetWarningHandler(NULL); /* disable warnings */
2282 TIFFSetErrorHandler(NULL); /* disable error messages */
2283
2284 fname = genPathname(filename, NULL);
2285 tif = TIFFOpen(fname, modestring);
2286 LEPT_FREE(fname);
2287 return tif;
2288}
2289
2290
2291/*----------------------------------------------------------------------*
2292 * Memory I/O: reading memory --> pix and writing pix --> memory *
2293 *----------------------------------------------------------------------*/
2294/* It would be nice to use open_memstream() and fmemopen()
2295 * for writing and reading to memory, rsp. These functions manage
2296 * memory for writes and reads that use a file streams interface.
2297 * Unfortunately, the tiff library only has an interface for reading
2298 * and writing to file descriptors, not to file streams. The tiff
2299 * library procedure is to open a "tiff stream" and read/write to it.
2300 * The library provides a client interface for managing the I/O
2301 * from memory, which requires seven callbacks. See the TIFFClientOpen
2302 * man page for callback signatures. Adam Langley provided the code
2303 * to do this. */
2304
2326{
2327 l_uint8 *buffer; /* expands to hold data when written to; */
2328 /* fixed size when read from. */
2329 size_t bufsize; /* current size allocated when written to; */
2330 /* fixed size of input data when read from. */
2331 size_t offset; /* byte offset from beginning of buffer. */
2332 size_t hw; /* high-water mark; max bytes in buffer. */
2333 l_uint8 **poutdata; /* input param for writing; data goes here. */
2334 size_t *poutsize; /* input param for writing; data size goes here. */
2335};
2336typedef struct L_Memstream L_MEMSTREAM;
2337
2338
2339 /* These are static functions for memory I/O */
2340static L_MEMSTREAM *memstreamCreateForRead(l_uint8 *indata, size_t pinsize);
2341static L_MEMSTREAM *memstreamCreateForWrite(l_uint8 **poutdata,
2342 size_t *poutsize);
2343static tsize_t tiffReadCallback(thandle_t handle, tdata_t data, tsize_t length);
2344static tsize_t tiffWriteCallback(thandle_t handle, tdata_t data,
2345 tsize_t length);
2346static toff_t tiffSeekCallback(thandle_t handle, toff_t offset, l_int32 whence);
2347static l_int32 tiffCloseCallback(thandle_t handle);
2348static toff_t tiffSizeCallback(thandle_t handle);
2349static l_int32 tiffMapCallback(thandle_t handle, tdata_t *data, toff_t *length);
2350static void tiffUnmapCallback(thandle_t handle, tdata_t data, toff_t length);
2351
2352
2353static L_MEMSTREAM *
2354memstreamCreateForRead(l_uint8 *indata,
2355 size_t insize)
2356{
2357L_MEMSTREAM *mstream;
2358
2359 mstream = (L_MEMSTREAM *)LEPT_CALLOC(1, sizeof(L_MEMSTREAM));
2360 mstream->buffer = indata; /* handle to input data array */
2361 mstream->bufsize = insize; /* amount of input data */
2362 mstream->hw = insize; /* high-water mark fixed at input data size */
2363 mstream->offset = 0; /* offset always starts at 0 */
2364 return mstream;
2365}
2366
2367
2368static L_MEMSTREAM *
2369memstreamCreateForWrite(l_uint8 **poutdata,
2370 size_t *poutsize)
2371{
2372L_MEMSTREAM *mstream;
2373
2374 mstream = (L_MEMSTREAM *)LEPT_CALLOC(1, sizeof(L_MEMSTREAM));
2375 mstream->buffer = (l_uint8 *)LEPT_CALLOC(8 * 1024, 1);
2376 mstream->bufsize = 8 * 1024;
2377 mstream->poutdata = poutdata; /* used only at end of write */
2378 mstream->poutsize = poutsize; /* ditto */
2379 mstream->hw = mstream->offset = 0;
2380 return mstream;
2381}
2382
2383
2384static tsize_t
2385tiffReadCallback(thandle_t handle,
2386 tdata_t data,
2387 tsize_t length)
2388{
2389L_MEMSTREAM *mstream;
2390size_t amount;
2391
2392 mstream = (L_MEMSTREAM *)handle;
2393 amount = L_MIN((size_t)length, mstream->hw - mstream->offset);
2394
2395 /* Fuzzed files can create this condition! */
2396 if (mstream->offset + amount < amount || /* overflow */
2397 mstream->offset + amount > mstream->hw) {
2398 lept_stderr("Bad file: amount too big: %zu\n", amount);
2399 return 0;
2400 }
2401
2402 memcpy(data, mstream->buffer + mstream->offset, amount);
2403 mstream->offset += amount;
2404 return amount;
2405}
2406
2407
2408static tsize_t
2409tiffWriteCallback(thandle_t handle,
2410 tdata_t data,
2411 tsize_t length)
2412{
2413L_MEMSTREAM *mstream;
2414size_t newsize;
2415
2416 /* reallocNew() uses calloc to initialize the array.
2417 * If malloc is used instead, for some of the encoding methods,
2418 * not all the data in 'bufsize' bytes in the buffer will
2419 * have been initialized by the end of the compression. */
2420 mstream = (L_MEMSTREAM *)handle;
2421 if (mstream->offset + length > mstream->bufsize) {
2422 newsize = 2 * (mstream->offset + length);
2423 mstream->buffer = (l_uint8 *)reallocNew((void **)&mstream->buffer,
2424 mstream->hw, newsize);
2425 mstream->bufsize = newsize;
2426 }
2427
2428 memcpy(mstream->buffer + mstream->offset, data, length);
2429 mstream->offset += length;
2430 mstream->hw = L_MAX(mstream->offset, mstream->hw);
2431 return length;
2432}
2433
2434
2435static toff_t
2436tiffSeekCallback(thandle_t handle,
2437 toff_t offset,
2438 l_int32 whence)
2439{
2440L_MEMSTREAM *mstream;
2441
2442 mstream = (L_MEMSTREAM *)handle;
2443 switch (whence) {
2444 case SEEK_SET:
2445/* lept_stderr("seek_set: offset = %d\n", offset); */
2446 if((size_t)offset != offset) { /* size_t overflow on uint32 */
2447 return (toff_t)ERROR_INT("too large offset value", __func__, 1);
2448 }
2449 mstream->offset = offset;
2450 break;
2451 case SEEK_CUR:
2452/* lept_stderr("seek_cur: offset = %d\n", offset); */
2453 mstream->offset += offset;
2454 break;
2455 case SEEK_END:
2456/* lept_stderr("seek end: hw = %d, offset = %d\n",
2457 mstream->hw, offset); */
2458 mstream->offset = mstream->hw - offset; /* offset >= 0 */
2459 break;
2460 default:
2461 return (toff_t)ERROR_INT("bad whence value", __func__,
2462 mstream->offset);
2463 }
2464
2465 return mstream->offset;
2466}
2467
2468
2469static l_int32
2470tiffCloseCallback(thandle_t handle)
2471{
2472L_MEMSTREAM *mstream;
2473
2474 mstream = (L_MEMSTREAM *)handle;
2475 if (mstream->poutdata) { /* writing: save the output data */
2476 *mstream->poutdata = mstream->buffer;
2477 *mstream->poutsize = mstream->hw;
2478 }
2479 LEPT_FREE(mstream); /* never free the buffer! */
2480 return 0;
2481}
2482
2483
2484static toff_t
2485tiffSizeCallback(thandle_t handle)
2486{
2487L_MEMSTREAM *mstream;
2488
2489 mstream = (L_MEMSTREAM *)handle;
2490 return mstream->hw;
2491}
2492
2493
2494static l_int32
2495tiffMapCallback(thandle_t handle,
2496 tdata_t *data,
2497 toff_t *length)
2498{
2499L_MEMSTREAM *mstream;
2500
2501 mstream = (L_MEMSTREAM *)handle;
2502 *data = mstream->buffer;
2503 *length = mstream->hw;
2504 return 0;
2505}
2506
2507
2508static void
2509tiffUnmapCallback(thandle_t handle,
2510 tdata_t data,
2511 toff_t length)
2512{
2513 return;
2514}
2515
2516
2537static TIFF *
2538fopenTiffMemstream(const char *filename,
2539 const char *operation,
2540 l_uint8 **pdata,
2541 size_t *pdatasize)
2542{
2543L_MEMSTREAM *mstream;
2544TIFF *tif;
2545
2546 if (!filename)
2547 return (TIFF *)ERROR_PTR("filename not defined", __func__, NULL);
2548 if (!operation)
2549 return (TIFF *)ERROR_PTR("operation not defined", __func__, NULL);
2550 if (!pdata)
2551 return (TIFF *)ERROR_PTR("&data not defined", __func__, NULL);
2552 if (!pdatasize)
2553 return (TIFF *)ERROR_PTR("&datasize not defined", __func__, NULL);
2554 if (strcmp(operation, "r") && strcmp(operation, "w"))
2555 return (TIFF *)ERROR_PTR("op not 'r' or 'w'", __func__, NULL);
2556
2557 if (!strcmp(operation, "r"))
2558 mstream = memstreamCreateForRead(*pdata, *pdatasize);
2559 else
2560 mstream = memstreamCreateForWrite(pdata, pdatasize);
2561 if (!mstream)
2562 return (TIFF *)ERROR_PTR("mstream not made", __func__, NULL);
2563
2564 TIFFSetWarningHandler(NULL); /* disable warnings */
2565 TIFFSetErrorHandler(NULL); /* disable error messages */
2566
2567 tif = TIFFClientOpen(filename, operation, (thandle_t)mstream,
2568 tiffReadCallback, tiffWriteCallback,
2569 tiffSeekCallback, tiffCloseCallback,
2570 tiffSizeCallback, tiffMapCallback,
2571 tiffUnmapCallback);
2572 if (!tif)
2573 LEPT_FREE(mstream);
2574 return tif;
2575}
2576
2577
2598PIX *
2599pixReadMemTiff(const l_uint8 *cdata,
2600 size_t size,
2601 l_int32 n)
2602{
2603l_uint8 *data;
2604l_int32 i;
2605PIX *pix;
2606TIFF *tif;
2607
2608 if (!cdata)
2609 return (PIX *)ERROR_PTR("cdata not defined", __func__, NULL);
2610
2611 data = (l_uint8 *)cdata; /* we're really not going to change this */
2612 if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL)
2613 return (PIX *)ERROR_PTR("tiff stream not opened", __func__, NULL);
2614
2615 pix = NULL;
2616 for (i = 0; ; i++) {
2617 if (i == n) {
2618 if ((pix = pixReadFromTiffStream(tif)) == NULL) {
2619 TIFFClose(tif);
2620 return NULL;
2621 }
2622 pixSetInputFormat(pix, IFF_TIFF);
2623 break;
2624 }
2625 if (TIFFReadDirectory(tif) == 0)
2626 break;
2627 if (i == ManyPagesInTiffFile + 1) {
2628 L_WARNING("big file: more than %d pages\n", __func__,
2629 ManyPagesInTiffFile);
2630 }
2631 }
2632
2633 TIFFClose(tif);
2634 return pix;
2635}
2636
2637
2661PIX *
2662pixReadMemFromMultipageTiff(const l_uint8 *cdata,
2663 size_t size,
2664 size_t *poffset)
2665{
2666l_uint8 *data;
2667l_int32 retval;
2668size_t offset;
2669PIX *pix;
2670TIFF *tif;
2671
2672 if (!cdata)
2673 return (PIX *)ERROR_PTR("cdata not defined", __func__, NULL);
2674 if (!poffset)
2675 return (PIX *)ERROR_PTR("&offset not defined", __func__, NULL);
2676
2677 data = (l_uint8 *)cdata; /* we're really not going to change this */
2678 if ((tif = fopenTiffMemstream("tifferror", "r", &data, &size)) == NULL)
2679 return (PIX *)ERROR_PTR("tiff stream not opened", __func__, NULL);
2680
2681 /* Set ptrs in the TIFF to the beginning of the image */
2682 offset = *poffset;
2683 retval = (offset == 0) ? TIFFSetDirectory(tif, 0)
2684 : TIFFSetSubDirectory(tif, offset);
2685 if (retval == 0) {
2686 TIFFClose(tif);
2687 return NULL;
2688 }
2689
2690 if ((pix = pixReadFromTiffStream(tif)) == NULL) {
2691 TIFFClose(tif);
2692 return NULL;
2693 }
2694
2695 /* Advance to the next image and return the new offset */
2696 TIFFReadDirectory(tif);
2697 *poffset = TIFFCurrentDirOffset(tif);
2698 TIFFClose(tif);
2699 return pix;
2700}
2701
2702
2715PIXA *
2716pixaReadMemMultipageTiff(const l_uint8 *data,
2717 size_t size)
2718{
2719size_t offset;
2720PIX *pix;
2721PIXA *pixa;
2722
2723 if (!data)
2724 return (PIXA *)ERROR_PTR("data not defined", __func__, NULL);
2725
2726 offset = 0;
2727 pixa = pixaCreate(0);
2728 do {
2729 pix = pixReadMemFromMultipageTiff(data, size, &offset);
2730 pixaAddPix(pixa, pix, L_INSERT);
2731 } while (offset != 0);
2732 return pixa;
2733}
2734
2735
2753l_ok
2755 size_t *psize,
2756 PIXA *pixa)
2757{
2758const char *modestr;
2759l_int32 i, n;
2760FILE *fp;
2761PIX *pix1;
2762
2763 if (pdata) *pdata = NULL;
2764 if (!pdata)
2765 return ERROR_INT("pdata not defined", __func__, 1);
2766 if (!pixa)
2767 return ERROR_INT("pixa not defined", __func__, 1);
2768
2769#ifdef _WIN32
2770 if ((fp = fopenWriteWinTempfile()) == NULL)
2771 return ERROR_INT("tmpfile stream not opened", __func__, 1);
2772#else
2773 if ((fp = tmpfile()) == NULL)
2774 return ERROR_INT("tmpfile stream not opened", __func__, 1);
2775#endif /* _WIN32 */
2776
2777 n = pixaGetCount(pixa);
2778 for (i = 0; i < n; i++) {
2779 modestr = (i == 0) ? "w" : "a";
2780 pix1 = pixaGetPix(pixa, i, L_CLONE);
2781 if (pixGetDepth(pix1) == 1)
2782 pixWriteStreamTiffWA(fp, pix1, IFF_TIFF_G4, modestr);
2783 else
2784 pixWriteStreamTiffWA(fp, pix1, IFF_TIFF_ZIP, modestr);
2785 pixDestroy(&pix1);
2786 }
2787
2788 rewind(fp);
2789 *pdata = l_binaryReadStream(fp, psize);
2790 fclose(fp);
2791 return 0;
2792}
2793
2794
2810l_ok
2811pixWriteMemTiff(l_uint8 **pdata,
2812 size_t *psize,
2813 PIX *pix,
2814 l_int32 comptype)
2815{
2816 return pixWriteMemTiffCustom(pdata, psize, pix, comptype,
2817 NULL, NULL, NULL, NULL);
2818}
2819
2820
2841l_ok
2843 size_t *psize,
2844 PIX *pix,
2845 l_int32 comptype,
2846 NUMA *natags,
2847 SARRAY *savals,
2848 SARRAY *satypes,
2849 NUMA *nasizes)
2850{
2851l_int32 ret;
2852TIFF *tif;
2853
2854 if (!pdata)
2855 return ERROR_INT("&data not defined", __func__, 1);
2856 if (!psize)
2857 return ERROR_INT("&size not defined", __func__, 1);
2858 if (!pix)
2859 return ERROR_INT("&pix not defined", __func__, 1);
2860 if (pixGetDepth(pix) != 1 && comptype != IFF_TIFF &&
2861 comptype != IFF_TIFF_LZW && comptype != IFF_TIFF_ZIP &&
2862 comptype != IFF_TIFF_JPEG) {
2863 L_WARNING("invalid compression type for bpp > 1\n", __func__);
2864 comptype = IFF_TIFF_ZIP;
2865 }
2866
2867 if ((tif = fopenTiffMemstream("tifferror", "w", pdata, psize)) == NULL)
2868 return ERROR_INT("tiff stream not opened", __func__, 1);
2869 ret = pixWriteToTiffStream(tif, pix, comptype, natags, savals,
2870 satypes, nasizes);
2871
2872 TIFFClose(tif);
2873 return ret;
2874}
2875
2876/* --------------------------------------------*/
2877#endif /* HAVE_LIBTIFF */
2878/* --------------------------------------------*/
struct Numa NUMA
Definition array.h:66
struct Sarray SARRAY
Definition array.h:81
#define GET_DATA_BYTE(pdata, n)
#define SET_DATA_BYTE(pdata, n, val)
@ REMOVE_CMAP_BASED_ON_SRC
Definition pix.h:384
@ L_CLONE
Definition pix.h:506
@ L_NOCOPY
Definition pix.h:503
@ L_INSERT
Definition pix.h:504
struct Pix PIX
Definition pix.h:228
struct PixColormap PIXCMAP
Definition pix.h:231
@ COLOR_BLUE
Definition pix.h:330
@ COLOR_RED
Definition pix.h:328
@ L_ALPHA_CHANNEL
Definition pix.h:331
@ COLOR_GREEN
Definition pix.h:329
struct Pixa PIXA
Definition pix.h:243
Memory stream buffer used with TIFFClientOpen()
Definition tiffio.c:2326
static l_int32 tiffReadHeaderTiff(TIFF *tif, l_int32 *pwidth, l_int32 *pheight, l_int32 *pbps, l_int32 *pspp, l_int32 *pres, l_int32 *pcmap, l_int32 *pformat)
tiffReadHeaderTiff()
Definition tiffio.c:1957
static TIFF * fopenTiffMemstream(const char *filename, const char *operation, l_uint8 **pdata, size_t *pdatasize)
fopenTiffMemstream()
Definition tiffio.c:2538
l_ok pixaWriteMemMultipageTiff(l_uint8 **pdata, size_t *psize, PIXA *pixa)
pixaWriteMemMultipageTiff()
Definition tiffio.c:2754
l_ok fprintTiffInfo(FILE *fpout, const char *tiffile)
fprintTiffInfo()
Definition tiffio.c:1602
PIX * pixReadTiff(const char *filename, l_int32 n)
pixReadTiff()
Definition tiffio.c:394
PIXA * pixaReadMultipageTiff(const char *filename)
pixaReadMultipageTiff()
Definition tiffio.c:1407
l_ok pixWriteStreamTiffWA(FILE *fp, PIX *pix, l_int32 comptype, const char *modestr)
pixWriteStreamTiffWA()
Definition tiffio.c:950
static TIFF * openTiff(const char *filename, const char *modestring)
openTiff()
Definition tiffio.c:2270
l_ok readHeaderTiff(const char *filename, l_int32 n, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *pres, l_int32 *pcmap, l_int32 *pformat)
readHeaderTiff()
Definition tiffio.c:1777
l_ok readHeaderMemTiff(const l_uint8 *cdata, size_t size, l_int32 n, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *pres, l_int32 *pcmap, l_int32 *pformat)
readHeaderMemTiff()
Definition tiffio.c:1898
l_ok pixWriteMemTiffCustom(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 comptype, NUMA *natags, SARRAY *savals, SARRAY *satypes, NUMA *nasizes)
pixWriteMemTiffCustom()
Definition tiffio.c:2842
l_ok findTiffCompression(FILE *fp, l_int32 *pcomptype)
findTiffCompression()
Definition tiffio.c:2025
static l_int32 writeCustomTiffTags(TIFF *tif, NUMA *natags, SARRAY *savals, SARRAY *satypes, NUMA *nasizes)
writeCustomTiffTags()
Definition tiffio.c:1234
PIX * pixReadFromMultipageTiff(const char *fname, size_t *poffset)
pixReadFromMultipageTiff()
Definition tiffio.c:1360
l_ok getTiffResolution(FILE *fp, l_int32 *pxres, l_int32 *pyres)
getTiffResolution()
Definition tiffio.c:1679
PIX * pixReadStreamTiff(FILE *fp, l_int32 n)
pixReadStreamTiff()
Definition tiffio.c:429
static PIX * pixReadFromTiffStream(TIFF *tif)
pixReadFromTiffStream()
Definition tiffio.c:497
PIXA * pixaReadMemMultipageTiff(const l_uint8 *data, size_t size)
pixaReadMemMultipageTiff()
Definition tiffio.c:2716
l_ok pixWriteTiff(const char *filename, PIX *pix, l_int32 comptype, const char *modestr)
pixWriteTiff()
Definition tiffio.c:811
l_ok writeMultipageTiff(const char *dirin, const char *substr, const char *fileout)
writeMultipageTiff()
Definition tiffio.c:1517
l_ok pixWriteTiffCustom(const char *filename, PIX *pix, l_int32 comptype, const char *modestr, NUMA *natags, SARRAY *savals, SARRAY *satypes, NUMA *nasizes)
pixWriteTiffCustom()
Definition tiffio.c:868
PIX * pixReadMemFromMultipageTiff(const l_uint8 *cdata, size_t size, size_t *poffset)
pixReadMemFromMultipageTiff()
Definition tiffio.c:2662
static l_int32 pixWriteToTiffStream(TIFF *tif, PIX *pix, l_int32 comptype, NUMA *natags, SARRAY *savals, SARRAY *satypes, NUMA *nasizes)
pixWriteToTiffStream()
Definition tiffio.c:1023
l_ok pixWriteStreamTiff(FILE *fp, PIX *pix, l_int32 comptype)
pixWriteStreamTiff()
Definition tiffio.c:925
PIX * pixReadMemTiff(const l_uint8 *cdata, size_t size, l_int32 n)
pixReadMemTiff()
Definition tiffio.c:2599
l_ok writeMultipageTiffSA(SARRAY *sa, const char *fileout)
writeMultipageTiffSA()
Definition tiffio.c:1551
l_ok pixWriteMemTiff(l_uint8 **pdata, size_t *psize, PIX *pix, l_int32 comptype)
pixWriteMemTiff()
Definition tiffio.c:2811
static TIFF * fopenTiff(FILE *fp, const char *modestring)
fopenTiff()
Definition tiffio.c:2236
l_ok pixaWriteMultipageTiff(const char *fname, PIXA *pixa)
pixaWriteMultipageTiff()
Definition tiffio.c:1465
static l_int32 getTiffCompressedFormat(l_uint16 tiffcomp)
getTiffCompressedFormat()
Definition tiffio.c:2061
l_ok tiffGetCount(FILE *fp, l_int32 *pn)
tiffGetCount()
Definition tiffio.c:1633
static l_int32 getTiffStreamResolution(TIFF *tif, l_int32 *pxres, l_int32 *pyres)
getTiffStreamResolution()
Definition tiffio.c:1713
l_ok freadHeaderTiff(FILE *fp, l_int32 n, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp, l_int32 *pres, l_int32 *pcmap, l_int32 *pformat)
freadHeaderTiff()
Definition tiffio.c:1831
l_ok extractG4DataFromFile(const char *filein, l_uint8 **pdata, size_t *pnbytes, l_int32 *pw, l_int32 *ph, l_int32 *pminisblack)
extractG4DataFromFile()
Definition tiffio.c:2111