1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright (c) 1988-1997 Sam Leffler
3c2c66affSColin Finck * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4c2c66affSColin Finck *
5c2c66affSColin Finck * Permission to use, copy, modify, distribute, and sell this software and
6c2c66affSColin Finck * its documentation for any purpose is hereby granted without fee, provided
7c2c66affSColin Finck * that (i) the above copyright notices and this permission notice appear in
8c2c66affSColin Finck * all copies of the software and related documentation, and (ii) the names of
9c2c66affSColin Finck * Sam Leffler and Silicon Graphics may not be used in any advertising or
10c2c66affSColin Finck * publicity relating to the software without the specific, prior written
11c2c66affSColin Finck * permission of Sam Leffler and Silicon Graphics.
12c2c66affSColin Finck *
13c2c66affSColin Finck * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14c2c66affSColin Finck * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15c2c66affSColin Finck * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16c2c66affSColin Finck *
17c2c66affSColin Finck * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18c2c66affSColin Finck * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19c2c66affSColin Finck * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20c2c66affSColin Finck * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21c2c66affSColin Finck * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22c2c66affSColin Finck * OF THIS SOFTWARE.
23c2c66affSColin Finck */
24c2c66affSColin Finck
25c2c66affSColin Finck /*
26c2c66affSColin Finck * TIFF Library.
27c2c66affSColin Finck */
28c2c66affSColin Finck #include <precomp.h>
29c2c66affSColin Finck
30c2c66affSColin Finck /*
31c2c66affSColin Finck * Dummy functions to fill the omitted client procedures.
32c2c66affSColin Finck */
33c2c66affSColin Finck static int
_tiffDummyMapProc(thandle_t fd,void ** pbase,toff_t * psize)34c2c66affSColin Finck _tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize)
35c2c66affSColin Finck {
36c2c66affSColin Finck (void) fd; (void) pbase; (void) psize;
37c2c66affSColin Finck return (0);
38c2c66affSColin Finck }
39c2c66affSColin Finck
40c2c66affSColin Finck static void
_tiffDummyUnmapProc(thandle_t fd,void * base,toff_t size)41c2c66affSColin Finck _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size)
42c2c66affSColin Finck {
43c2c66affSColin Finck (void) fd; (void) base; (void) size;
44c2c66affSColin Finck }
45c2c66affSColin Finck
46c2c66affSColin Finck int
_TIFFgetMode(const char * mode,const char * module)47c2c66affSColin Finck _TIFFgetMode(const char* mode, const char* module)
48c2c66affSColin Finck {
49c2c66affSColin Finck int m = -1;
50c2c66affSColin Finck
51c2c66affSColin Finck switch (mode[0]) {
52c2c66affSColin Finck case 'r':
53c2c66affSColin Finck m = O_RDONLY;
54c2c66affSColin Finck if (mode[1] == '+')
55c2c66affSColin Finck m = O_RDWR;
56c2c66affSColin Finck break;
57c2c66affSColin Finck case 'w':
58c2c66affSColin Finck case 'a':
59c2c66affSColin Finck m = O_RDWR|O_CREAT;
60c2c66affSColin Finck if (mode[0] == 'w')
61c2c66affSColin Finck m |= O_TRUNC;
62c2c66affSColin Finck break;
63c2c66affSColin Finck default:
64c2c66affSColin Finck TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
65c2c66affSColin Finck break;
66c2c66affSColin Finck }
67c2c66affSColin Finck return (m);
68c2c66affSColin Finck }
69c2c66affSColin Finck
70c2c66affSColin Finck TIFF*
TIFFClientOpen(const char * name,const char * mode,thandle_t clientdata,TIFFReadWriteProc readproc,TIFFReadWriteProc writeproc,TIFFSeekProc seekproc,TIFFCloseProc closeproc,TIFFSizeProc sizeproc,TIFFMapFileProc mapproc,TIFFUnmapFileProc unmapproc)71c2c66affSColin Finck TIFFClientOpen(
72c2c66affSColin Finck const char* name, const char* mode,
73c2c66affSColin Finck thandle_t clientdata,
74c2c66affSColin Finck TIFFReadWriteProc readproc,
75c2c66affSColin Finck TIFFReadWriteProc writeproc,
76c2c66affSColin Finck TIFFSeekProc seekproc,
77c2c66affSColin Finck TIFFCloseProc closeproc,
78c2c66affSColin Finck TIFFSizeProc sizeproc,
79c2c66affSColin Finck TIFFMapFileProc mapproc,
80c2c66affSColin Finck TIFFUnmapFileProc unmapproc
81c2c66affSColin Finck )
82c2c66affSColin Finck {
83c2c66affSColin Finck static const char module[] = "TIFFClientOpen";
84c2c66affSColin Finck TIFF *tif;
85c2c66affSColin Finck int m;
86c2c66affSColin Finck const char* cp;
87c2c66affSColin Finck
88c2c66affSColin Finck /* The following are configuration checks. They should be redundant, but should not
89c2c66affSColin Finck * compile to any actual code in an optimised release build anyway. If any of them
90c2c66affSColin Finck * fail, (makefile-based or other) configuration is not correct */
91c2c66affSColin Finck assert(sizeof(uint8)==1);
92c2c66affSColin Finck assert(sizeof(int8)==1);
93c2c66affSColin Finck assert(sizeof(uint16)==2);
94c2c66affSColin Finck assert(sizeof(int16)==2);
95c2c66affSColin Finck assert(sizeof(uint32)==4);
96c2c66affSColin Finck assert(sizeof(int32)==4);
97c2c66affSColin Finck assert(sizeof(uint64)==8);
98c2c66affSColin Finck assert(sizeof(int64)==8);
99c2c66affSColin Finck assert(sizeof(tmsize_t)==sizeof(void*));
100c2c66affSColin Finck {
101c2c66affSColin Finck union{
102c2c66affSColin Finck uint8 a8[2];
103c2c66affSColin Finck uint16 a16;
104c2c66affSColin Finck } n;
105c2c66affSColin Finck n.a8[0]=1;
106c2c66affSColin Finck n.a8[1]=0;
107c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
108c2c66affSColin Finck assert(n.a16==256);
109c2c66affSColin Finck #else
110c2c66affSColin Finck assert(n.a16==1);
111c2c66affSColin Finck #endif
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck m = _TIFFgetMode(mode, module);
115c2c66affSColin Finck if (m == -1)
116c2c66affSColin Finck goto bad2;
117c2c66affSColin Finck tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1));
118c2c66affSColin Finck if (tif == NULL) {
119c2c66affSColin Finck TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
120c2c66affSColin Finck goto bad2;
121c2c66affSColin Finck }
122c2c66affSColin Finck _TIFFmemset(tif, 0, sizeof (*tif));
123c2c66affSColin Finck tif->tif_name = (char *)tif + sizeof (TIFF);
124c2c66affSColin Finck strcpy(tif->tif_name, name);
125c2c66affSColin Finck tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
126c2c66affSColin Finck tif->tif_curdir = (uint16) -1; /* non-existent directory */
127c2c66affSColin Finck tif->tif_curoff = 0;
128c2c66affSColin Finck tif->tif_curstrip = (uint32) -1; /* invalid strip */
129c2c66affSColin Finck tif->tif_row = (uint32) -1; /* read/write pre-increment */
130c2c66affSColin Finck tif->tif_clientdata = clientdata;
131c2c66affSColin Finck if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
132c2c66affSColin Finck TIFFErrorExt(clientdata, module,
133c2c66affSColin Finck "One of the client procedures is NULL pointer.");
134*f87faf67SThomas Faber _TIFFfree(tif);
135c2c66affSColin Finck goto bad2;
136c2c66affSColin Finck }
137c2c66affSColin Finck tif->tif_readproc = readproc;
138c2c66affSColin Finck tif->tif_writeproc = writeproc;
139c2c66affSColin Finck tif->tif_seekproc = seekproc;
140c2c66affSColin Finck tif->tif_closeproc = closeproc;
141c2c66affSColin Finck tif->tif_sizeproc = sizeproc;
142c2c66affSColin Finck if (mapproc)
143c2c66affSColin Finck tif->tif_mapproc = mapproc;
144c2c66affSColin Finck else
145c2c66affSColin Finck tif->tif_mapproc = _tiffDummyMapProc;
146c2c66affSColin Finck if (unmapproc)
147c2c66affSColin Finck tif->tif_unmapproc = unmapproc;
148c2c66affSColin Finck else
149c2c66affSColin Finck tif->tif_unmapproc = _tiffDummyUnmapProc;
150c2c66affSColin Finck _TIFFSetDefaultCompressionState(tif); /* setup default state */
151c2c66affSColin Finck /*
152c2c66affSColin Finck * Default is to return data MSB2LSB and enable the
153c2c66affSColin Finck * use of memory-mapped files and strip chopping when
154c2c66affSColin Finck * a file is opened read-only.
155c2c66affSColin Finck */
156c2c66affSColin Finck tif->tif_flags = FILLORDER_MSB2LSB;
157c2c66affSColin Finck if (m == O_RDONLY )
158c2c66affSColin Finck tif->tif_flags |= TIFF_MAPPED;
159c2c66affSColin Finck
160c2c66affSColin Finck #ifdef STRIPCHOP_DEFAULT
161c2c66affSColin Finck if (m == O_RDONLY || m == O_RDWR)
162c2c66affSColin Finck tif->tif_flags |= STRIPCHOP_DEFAULT;
163c2c66affSColin Finck #endif
164c2c66affSColin Finck
165c2c66affSColin Finck /*
166c2c66affSColin Finck * Process library-specific flags in the open mode string.
167c2c66affSColin Finck * The following flags may be used to control intrinsic library
168c2c66affSColin Finck * behaviour that may or may not be desirable (usually for
169c2c66affSColin Finck * compatibility with some application that claims to support
170c2c66affSColin Finck * TIFF but only supports some brain dead idea of what the
171c2c66affSColin Finck * vendor thinks TIFF is):
172c2c66affSColin Finck *
173c2c66affSColin Finck * 'l' use little-endian byte order for creating a file
174c2c66affSColin Finck * 'b' use big-endian byte order for creating a file
175c2c66affSColin Finck * 'L' read/write information using LSB2MSB bit order
176c2c66affSColin Finck * 'B' read/write information using MSB2LSB bit order
177c2c66affSColin Finck * 'H' read/write information using host bit order
178c2c66affSColin Finck * 'M' enable use of memory-mapped files when supported
179c2c66affSColin Finck * 'm' disable use of memory-mapped files
180c2c66affSColin Finck * 'C' enable strip chopping support when reading
181c2c66affSColin Finck * 'c' disable strip chopping support
182c2c66affSColin Finck * 'h' read TIFF header only, do not load the first IFD
183c2c66affSColin Finck * '4' ClassicTIFF for creating a file (default)
184c2c66affSColin Finck * '8' BigTIFF for creating a file
185*f87faf67SThomas Faber * 'D' enable use of deferred strip/tile offset/bytecount array loading.
186*f87faf67SThomas Faber * 'O' on-demand loading of values instead of whole array loading (implies D)
187c2c66affSColin Finck *
188c2c66affSColin Finck * The use of the 'l' and 'b' flags is strongly discouraged.
189c2c66affSColin Finck * These flags are provided solely because numerous vendors,
190c2c66affSColin Finck * typically on the PC, do not correctly support TIFF; they
191c2c66affSColin Finck * only support the Intel little-endian byte order. This
192c2c66affSColin Finck * support is not configured by default because it supports
193c2c66affSColin Finck * the violation of the TIFF spec that says that readers *MUST*
194c2c66affSColin Finck * support both byte orders. It is strongly recommended that
195c2c66affSColin Finck * you not use this feature except to deal with busted apps
196c2c66affSColin Finck * that write invalid TIFF. And even in those cases you should
197c2c66affSColin Finck * bang on the vendors to fix their software.
198c2c66affSColin Finck *
199c2c66affSColin Finck * The 'L', 'B', and 'H' flags are intended for applications
200c2c66affSColin Finck * that can optimize operations on data by using a particular
201c2c66affSColin Finck * bit order. By default the library returns data in MSB2LSB
202c2c66affSColin Finck * bit order for compatibility with older versions of this
203c2c66affSColin Finck * library. Returning data in the bit order of the native CPU
204c2c66affSColin Finck * makes the most sense but also requires applications to check
205c2c66affSColin Finck * the value of the FillOrder tag; something they probably do
206c2c66affSColin Finck * not do right now.
207c2c66affSColin Finck *
208c2c66affSColin Finck * The 'M' and 'm' flags are provided because some virtual memory
209c2c66affSColin Finck * systems exhibit poor behaviour when large images are mapped.
210c2c66affSColin Finck * These options permit clients to control the use of memory-mapped
211c2c66affSColin Finck * files on a per-file basis.
212c2c66affSColin Finck *
213c2c66affSColin Finck * The 'C' and 'c' flags are provided because the library support
214c2c66affSColin Finck * for chopping up large strips into multiple smaller strips is not
215c2c66affSColin Finck * application-transparent and as such can cause problems. The 'c'
216c2c66affSColin Finck * option permits applications that only want to look at the tags,
217c2c66affSColin Finck * for example, to get the unadulterated TIFF tag information.
218c2c66affSColin Finck */
219c2c66affSColin Finck for (cp = mode; *cp; cp++)
220c2c66affSColin Finck switch (*cp) {
221c2c66affSColin Finck case 'b':
222c2c66affSColin Finck #ifndef WORDS_BIGENDIAN
223c2c66affSColin Finck if (m&O_CREAT)
224c2c66affSColin Finck tif->tif_flags |= TIFF_SWAB;
225c2c66affSColin Finck #endif
226c2c66affSColin Finck break;
227c2c66affSColin Finck case 'l':
228c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
229c2c66affSColin Finck if ((m&O_CREAT))
230c2c66affSColin Finck tif->tif_flags |= TIFF_SWAB;
231c2c66affSColin Finck #endif
232c2c66affSColin Finck break;
233c2c66affSColin Finck case 'B':
234c2c66affSColin Finck tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
235c2c66affSColin Finck FILLORDER_MSB2LSB;
236c2c66affSColin Finck break;
237c2c66affSColin Finck case 'L':
238c2c66affSColin Finck tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
239c2c66affSColin Finck FILLORDER_LSB2MSB;
240c2c66affSColin Finck break;
241c2c66affSColin Finck case 'H':
242c2c66affSColin Finck tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
243c2c66affSColin Finck HOST_FILLORDER;
244c2c66affSColin Finck break;
245c2c66affSColin Finck case 'M':
246c2c66affSColin Finck if (m == O_RDONLY)
247c2c66affSColin Finck tif->tif_flags |= TIFF_MAPPED;
248c2c66affSColin Finck break;
249c2c66affSColin Finck case 'm':
250c2c66affSColin Finck if (m == O_RDONLY)
251c2c66affSColin Finck tif->tif_flags &= ~TIFF_MAPPED;
252c2c66affSColin Finck break;
253c2c66affSColin Finck case 'C':
254c2c66affSColin Finck if (m == O_RDONLY)
255c2c66affSColin Finck tif->tif_flags |= TIFF_STRIPCHOP;
256c2c66affSColin Finck break;
257c2c66affSColin Finck case 'c':
258c2c66affSColin Finck if (m == O_RDONLY)
259c2c66affSColin Finck tif->tif_flags &= ~TIFF_STRIPCHOP;
260c2c66affSColin Finck break;
261c2c66affSColin Finck case 'h':
262c2c66affSColin Finck tif->tif_flags |= TIFF_HEADERONLY;
263c2c66affSColin Finck break;
264c2c66affSColin Finck case '8':
265c2c66affSColin Finck if (m&O_CREAT)
266c2c66affSColin Finck tif->tif_flags |= TIFF_BIGTIFF;
267c2c66affSColin Finck break;
268*f87faf67SThomas Faber case 'D':
269*f87faf67SThomas Faber tif->tif_flags |= TIFF_DEFERSTRILELOAD;
270*f87faf67SThomas Faber break;
271*f87faf67SThomas Faber case 'O':
272*f87faf67SThomas Faber if( m == O_RDONLY )
273*f87faf67SThomas Faber tif->tif_flags |= (TIFF_LAZYSTRILELOAD | TIFF_DEFERSTRILELOAD);
274*f87faf67SThomas Faber break;
275c2c66affSColin Finck }
276*f87faf67SThomas Faber
277*f87faf67SThomas Faber #ifdef DEFER_STRILE_LOAD
278*f87faf67SThomas Faber /* Compatibility with old DEFER_STRILE_LOAD compilation flag */
279*f87faf67SThomas Faber /* Probably unneeded, since to the best of my knowledge (E. Rouault) */
280*f87faf67SThomas Faber /* GDAL was the only user of this, and will now use the new 'D' flag */
281*f87faf67SThomas Faber tif->tif_flags |= TIFF_DEFERSTRILELOAD;
282*f87faf67SThomas Faber #endif
283*f87faf67SThomas Faber
284c2c66affSColin Finck /*
285c2c66affSColin Finck * Read in TIFF header.
286c2c66affSColin Finck */
287c2c66affSColin Finck if ((m & O_TRUNC) ||
288c2c66affSColin Finck !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) {
289c2c66affSColin Finck if (tif->tif_mode == O_RDONLY) {
290c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
291c2c66affSColin Finck "Cannot read TIFF header");
292c2c66affSColin Finck goto bad;
293c2c66affSColin Finck }
294c2c66affSColin Finck /*
295c2c66affSColin Finck * Setup header and write.
296c2c66affSColin Finck */
297c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
298c2c66affSColin Finck tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
299c2c66affSColin Finck ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
300c2c66affSColin Finck #else
301c2c66affSColin Finck tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
302c2c66affSColin Finck ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
303c2c66affSColin Finck #endif
304c2c66affSColin Finck if (!(tif->tif_flags&TIFF_BIGTIFF))
305c2c66affSColin Finck {
306c2c66affSColin Finck tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
307c2c66affSColin Finck tif->tif_header.classic.tiff_diroff = 0;
308c2c66affSColin Finck if (tif->tif_flags & TIFF_SWAB)
309c2c66affSColin Finck TIFFSwabShort(&tif->tif_header.common.tiff_version);
310c2c66affSColin Finck tif->tif_header_size = sizeof(TIFFHeaderClassic);
311c2c66affSColin Finck }
312c2c66affSColin Finck else
313c2c66affSColin Finck {
314c2c66affSColin Finck tif->tif_header.common.tiff_version = TIFF_VERSION_BIG;
315c2c66affSColin Finck tif->tif_header.big.tiff_offsetsize = 8;
316c2c66affSColin Finck tif->tif_header.big.tiff_unused = 0;
317c2c66affSColin Finck tif->tif_header.big.tiff_diroff = 0;
318c2c66affSColin Finck if (tif->tif_flags & TIFF_SWAB)
319c2c66affSColin Finck {
320c2c66affSColin Finck TIFFSwabShort(&tif->tif_header.common.tiff_version);
321c2c66affSColin Finck TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
322c2c66affSColin Finck }
323c2c66affSColin Finck tif->tif_header_size = sizeof (TIFFHeaderBig);
324c2c66affSColin Finck }
325c2c66affSColin Finck /*
326c2c66affSColin Finck * The doc for "fopen" for some STD_C_LIBs says that if you
327c2c66affSColin Finck * open a file for modify ("+"), then you must fseek (or
328c2c66affSColin Finck * fflush?) between any freads and fwrites. This is not
329c2c66affSColin Finck * necessary on most systems, but has been shown to be needed
330c2c66affSColin Finck * on Solaris.
331c2c66affSColin Finck */
332c2c66affSColin Finck TIFFSeekFile( tif, 0, SEEK_SET );
333c2c66affSColin Finck if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) {
334c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
335c2c66affSColin Finck "Error writing TIFF header");
336c2c66affSColin Finck goto bad;
337c2c66affSColin Finck }
338c2c66affSColin Finck /*
339c2c66affSColin Finck * Setup the byte order handling.
340c2c66affSColin Finck */
341c2c66affSColin Finck if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
342c2c66affSColin Finck #ifndef WORDS_BIGENDIAN
343c2c66affSColin Finck tif->tif_flags |= TIFF_SWAB;
344c2c66affSColin Finck #endif
345c2c66affSColin Finck } else {
346c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
347c2c66affSColin Finck tif->tif_flags |= TIFF_SWAB;
348c2c66affSColin Finck #endif
349c2c66affSColin Finck }
350c2c66affSColin Finck /*
351c2c66affSColin Finck * Setup default directory.
352c2c66affSColin Finck */
353c2c66affSColin Finck if (!TIFFDefaultDirectory(tif))
354c2c66affSColin Finck goto bad;
355c2c66affSColin Finck tif->tif_diroff = 0;
356c2c66affSColin Finck tif->tif_dirlist = NULL;
357c2c66affSColin Finck tif->tif_dirlistsize = 0;
358c2c66affSColin Finck tif->tif_dirnumber = 0;
359c2c66affSColin Finck return (tif);
360c2c66affSColin Finck }
361c2c66affSColin Finck /*
362c2c66affSColin Finck * Setup the byte order handling.
363c2c66affSColin Finck */
364c2c66affSColin Finck if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
365c2c66affSColin Finck tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
366c2c66affSColin Finck #if MDI_SUPPORT
367c2c66affSColin Finck &&
368c2c66affSColin Finck #if HOST_BIGENDIAN
369c2c66affSColin Finck tif->tif_header.common.tiff_magic != MDI_BIGENDIAN
370c2c66affSColin Finck #else
371c2c66affSColin Finck tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN
372c2c66affSColin Finck #endif
373c2c66affSColin Finck ) {
374c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
375c2c66affSColin Finck "Not a TIFF or MDI file, bad magic number %d (0x%x)",
376c2c66affSColin Finck #else
377c2c66affSColin Finck ) {
378c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
379c2c66affSColin Finck "Not a TIFF file, bad magic number %d (0x%x)",
380c2c66affSColin Finck #endif
381c2c66affSColin Finck tif->tif_header.common.tiff_magic,
382c2c66affSColin Finck tif->tif_header.common.tiff_magic);
383c2c66affSColin Finck goto bad;
384c2c66affSColin Finck }
385c2c66affSColin Finck if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
386c2c66affSColin Finck #ifndef WORDS_BIGENDIAN
387c2c66affSColin Finck tif->tif_flags |= TIFF_SWAB;
388c2c66affSColin Finck #endif
389c2c66affSColin Finck } else {
390c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
391c2c66affSColin Finck tif->tif_flags |= TIFF_SWAB;
392c2c66affSColin Finck #endif
393c2c66affSColin Finck }
394c2c66affSColin Finck if (tif->tif_flags & TIFF_SWAB)
395c2c66affSColin Finck TIFFSwabShort(&tif->tif_header.common.tiff_version);
396c2c66affSColin Finck if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&&
397c2c66affSColin Finck (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) {
398c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
399c2c66affSColin Finck "Not a TIFF file, bad version number %d (0x%x)",
400c2c66affSColin Finck tif->tif_header.common.tiff_version,
401c2c66affSColin Finck tif->tif_header.common.tiff_version);
402c2c66affSColin Finck goto bad;
403c2c66affSColin Finck }
404c2c66affSColin Finck if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC)
405c2c66affSColin Finck {
406c2c66affSColin Finck if (tif->tif_flags & TIFF_SWAB)
407c2c66affSColin Finck TIFFSwabLong(&tif->tif_header.classic.tiff_diroff);
408c2c66affSColin Finck tif->tif_header_size = sizeof(TIFFHeaderClassic);
409c2c66affSColin Finck }
410c2c66affSColin Finck else
411c2c66affSColin Finck {
412c2c66affSColin Finck if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic))))
413c2c66affSColin Finck {
414c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
415c2c66affSColin Finck "Cannot read TIFF header");
416c2c66affSColin Finck goto bad;
417c2c66affSColin Finck }
418c2c66affSColin Finck if (tif->tif_flags & TIFF_SWAB)
419c2c66affSColin Finck {
420c2c66affSColin Finck TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
421c2c66affSColin Finck TIFFSwabLong8(&tif->tif_header.big.tiff_diroff);
422c2c66affSColin Finck }
423c2c66affSColin Finck if (tif->tif_header.big.tiff_offsetsize != 8)
424c2c66affSColin Finck {
425c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
426c2c66affSColin Finck "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)",
427c2c66affSColin Finck tif->tif_header.big.tiff_offsetsize,
428c2c66affSColin Finck tif->tif_header.big.tiff_offsetsize);
429c2c66affSColin Finck goto bad;
430c2c66affSColin Finck }
431c2c66affSColin Finck if (tif->tif_header.big.tiff_unused != 0)
432c2c66affSColin Finck {
433c2c66affSColin Finck TIFFErrorExt(tif->tif_clientdata, name,
434c2c66affSColin Finck "Not a TIFF file, bad BigTIFF unused %d (0x%x)",
435c2c66affSColin Finck tif->tif_header.big.tiff_unused,
436c2c66affSColin Finck tif->tif_header.big.tiff_unused);
437c2c66affSColin Finck goto bad;
438c2c66affSColin Finck }
439c2c66affSColin Finck tif->tif_header_size = sizeof(TIFFHeaderBig);
440c2c66affSColin Finck tif->tif_flags |= TIFF_BIGTIFF;
441c2c66affSColin Finck }
442c2c66affSColin Finck tif->tif_flags |= TIFF_MYBUFFER;
443c2c66affSColin Finck tif->tif_rawcp = tif->tif_rawdata = 0;
444c2c66affSColin Finck tif->tif_rawdatasize = 0;
445c2c66affSColin Finck tif->tif_rawdataoff = 0;
446c2c66affSColin Finck tif->tif_rawdataloaded = 0;
447c2c66affSColin Finck
448c2c66affSColin Finck switch (mode[0]) {
449c2c66affSColin Finck case 'r':
450c2c66affSColin Finck if (!(tif->tif_flags&TIFF_BIGTIFF))
451c2c66affSColin Finck tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff;
452c2c66affSColin Finck else
453c2c66affSColin Finck tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff;
454c2c66affSColin Finck /*
455c2c66affSColin Finck * Try to use a memory-mapped file if the client
456c2c66affSColin Finck * has not explicitly suppressed usage with the
457c2c66affSColin Finck * 'm' flag in the open mode (see above).
458c2c66affSColin Finck */
459c2c66affSColin Finck if (tif->tif_flags & TIFF_MAPPED)
460c2c66affSColin Finck {
461c2c66affSColin Finck toff_t n;
462c2c66affSColin Finck if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n))
463c2c66affSColin Finck {
464c2c66affSColin Finck tif->tif_size=(tmsize_t)n;
465c2c66affSColin Finck assert((toff_t)tif->tif_size==n);
466c2c66affSColin Finck }
467c2c66affSColin Finck else
468c2c66affSColin Finck tif->tif_flags &= ~TIFF_MAPPED;
469c2c66affSColin Finck }
470c2c66affSColin Finck /*
471c2c66affSColin Finck * Sometimes we do not want to read the first directory (for example,
472c2c66affSColin Finck * it may be broken) and want to proceed to other directories. I this
473c2c66affSColin Finck * case we use the TIFF_HEADERONLY flag to open file and return
474c2c66affSColin Finck * immediately after reading TIFF header.
475c2c66affSColin Finck */
476c2c66affSColin Finck if (tif->tif_flags & TIFF_HEADERONLY)
477c2c66affSColin Finck return (tif);
478c2c66affSColin Finck
479c2c66affSColin Finck /*
480c2c66affSColin Finck * Setup initial directory.
481c2c66affSColin Finck */
482c2c66affSColin Finck if (TIFFReadDirectory(tif)) {
483c2c66affSColin Finck tif->tif_rawcc = (tmsize_t)-1;
484c2c66affSColin Finck tif->tif_flags |= TIFF_BUFFERSETUP;
485c2c66affSColin Finck return (tif);
486c2c66affSColin Finck }
487c2c66affSColin Finck break;
488c2c66affSColin Finck case 'a':
489c2c66affSColin Finck /*
490c2c66affSColin Finck * New directories are automatically append
491c2c66affSColin Finck * to the end of the directory chain when they
492c2c66affSColin Finck * are written out (see TIFFWriteDirectory).
493c2c66affSColin Finck */
494c2c66affSColin Finck if (!TIFFDefaultDirectory(tif))
495c2c66affSColin Finck goto bad;
496c2c66affSColin Finck return (tif);
497c2c66affSColin Finck }
498c2c66affSColin Finck bad:
499c2c66affSColin Finck tif->tif_mode = O_RDONLY; /* XXX avoid flush */
500c2c66affSColin Finck TIFFCleanup(tif);
501c2c66affSColin Finck bad2:
502c2c66affSColin Finck return ((TIFF*)0);
503c2c66affSColin Finck }
504c2c66affSColin Finck
505c2c66affSColin Finck /*
506c2c66affSColin Finck * Query functions to access private data.
507c2c66affSColin Finck */
508c2c66affSColin Finck
509c2c66affSColin Finck /*
510c2c66affSColin Finck * Return open file's name.
511c2c66affSColin Finck */
512c2c66affSColin Finck const char *
513c2c66affSColin Finck TIFFFileName(TIFF* tif)
514c2c66affSColin Finck {
515c2c66affSColin Finck return (tif->tif_name);
516c2c66affSColin Finck }
517c2c66affSColin Finck
518c2c66affSColin Finck /*
519c2c66affSColin Finck * Set the file name.
520c2c66affSColin Finck */
521c2c66affSColin Finck const char *
522c2c66affSColin Finck TIFFSetFileName(TIFF* tif, const char *name)
523c2c66affSColin Finck {
524c2c66affSColin Finck const char* old_name = tif->tif_name;
525c2c66affSColin Finck tif->tif_name = (char *)name;
526c2c66affSColin Finck return (old_name);
527c2c66affSColin Finck }
528c2c66affSColin Finck
529c2c66affSColin Finck /*
530c2c66affSColin Finck * Return open file's I/O descriptor.
531c2c66affSColin Finck */
532c2c66affSColin Finck int
533c2c66affSColin Finck TIFFFileno(TIFF* tif)
534c2c66affSColin Finck {
535c2c66affSColin Finck return (tif->tif_fd);
536c2c66affSColin Finck }
537c2c66affSColin Finck
538c2c66affSColin Finck /*
539c2c66affSColin Finck * Set open file's I/O descriptor, and return previous value.
540c2c66affSColin Finck */
541c2c66affSColin Finck int
542c2c66affSColin Finck TIFFSetFileno(TIFF* tif, int fd)
543c2c66affSColin Finck {
544c2c66affSColin Finck int old_fd = tif->tif_fd;
545c2c66affSColin Finck tif->tif_fd = fd;
546c2c66affSColin Finck return old_fd;
547c2c66affSColin Finck }
548c2c66affSColin Finck
549c2c66affSColin Finck /*
550c2c66affSColin Finck * Return open file's clientdata.
551c2c66affSColin Finck */
552c2c66affSColin Finck thandle_t
553c2c66affSColin Finck TIFFClientdata(TIFF* tif)
554c2c66affSColin Finck {
555c2c66affSColin Finck return (tif->tif_clientdata);
556c2c66affSColin Finck }
557c2c66affSColin Finck
558c2c66affSColin Finck /*
559c2c66affSColin Finck * Set open file's clientdata, and return previous value.
560c2c66affSColin Finck */
561c2c66affSColin Finck thandle_t
562c2c66affSColin Finck TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
563c2c66affSColin Finck {
564c2c66affSColin Finck thandle_t m = tif->tif_clientdata;
565c2c66affSColin Finck tif->tif_clientdata = newvalue;
566c2c66affSColin Finck return m;
567c2c66affSColin Finck }
568c2c66affSColin Finck
569c2c66affSColin Finck /*
570c2c66affSColin Finck * Return read/write mode.
571c2c66affSColin Finck */
572c2c66affSColin Finck int
573c2c66affSColin Finck TIFFGetMode(TIFF* tif)
574c2c66affSColin Finck {
575c2c66affSColin Finck return (tif->tif_mode);
576c2c66affSColin Finck }
577c2c66affSColin Finck
578c2c66affSColin Finck /*
579c2c66affSColin Finck * Return read/write mode.
580c2c66affSColin Finck */
581c2c66affSColin Finck int
582c2c66affSColin Finck TIFFSetMode(TIFF* tif, int mode)
583c2c66affSColin Finck {
584c2c66affSColin Finck int old_mode = tif->tif_mode;
585c2c66affSColin Finck tif->tif_mode = mode;
586c2c66affSColin Finck return (old_mode);
587c2c66affSColin Finck }
588c2c66affSColin Finck
589c2c66affSColin Finck /*
590c2c66affSColin Finck * Return nonzero if file is organized in
591c2c66affSColin Finck * tiles; zero if organized as strips.
592c2c66affSColin Finck */
593c2c66affSColin Finck int
594c2c66affSColin Finck TIFFIsTiled(TIFF* tif)
595c2c66affSColin Finck {
596c2c66affSColin Finck return (isTiled(tif));
597c2c66affSColin Finck }
598c2c66affSColin Finck
599c2c66affSColin Finck /*
600c2c66affSColin Finck * Return current row being read/written.
601c2c66affSColin Finck */
602c2c66affSColin Finck uint32
603c2c66affSColin Finck TIFFCurrentRow(TIFF* tif)
604c2c66affSColin Finck {
605c2c66affSColin Finck return (tif->tif_row);
606c2c66affSColin Finck }
607c2c66affSColin Finck
608c2c66affSColin Finck /*
609c2c66affSColin Finck * Return index of the current directory.
610c2c66affSColin Finck */
611c2c66affSColin Finck uint16
612c2c66affSColin Finck TIFFCurrentDirectory(TIFF* tif)
613c2c66affSColin Finck {
614c2c66affSColin Finck return (tif->tif_curdir);
615c2c66affSColin Finck }
616c2c66affSColin Finck
617c2c66affSColin Finck /*
618c2c66affSColin Finck * Return current strip.
619c2c66affSColin Finck */
620c2c66affSColin Finck uint32
621c2c66affSColin Finck TIFFCurrentStrip(TIFF* tif)
622c2c66affSColin Finck {
623c2c66affSColin Finck return (tif->tif_curstrip);
624c2c66affSColin Finck }
625c2c66affSColin Finck
626c2c66affSColin Finck /*
627c2c66affSColin Finck * Return current tile.
628c2c66affSColin Finck */
629c2c66affSColin Finck uint32
630c2c66affSColin Finck TIFFCurrentTile(TIFF* tif)
631c2c66affSColin Finck {
632c2c66affSColin Finck return (tif->tif_curtile);
633c2c66affSColin Finck }
634c2c66affSColin Finck
635c2c66affSColin Finck /*
636c2c66affSColin Finck * Return nonzero if the file has byte-swapped data.
637c2c66affSColin Finck */
638c2c66affSColin Finck int
639c2c66affSColin Finck TIFFIsByteSwapped(TIFF* tif)
640c2c66affSColin Finck {
641c2c66affSColin Finck return ((tif->tif_flags & TIFF_SWAB) != 0);
642c2c66affSColin Finck }
643c2c66affSColin Finck
644c2c66affSColin Finck /*
645c2c66affSColin Finck * Return nonzero if the data is returned up-sampled.
646c2c66affSColin Finck */
647c2c66affSColin Finck int
648c2c66affSColin Finck TIFFIsUpSampled(TIFF* tif)
649c2c66affSColin Finck {
650c2c66affSColin Finck return (isUpSampled(tif));
651c2c66affSColin Finck }
652c2c66affSColin Finck
653c2c66affSColin Finck /*
654c2c66affSColin Finck * Return nonzero if the data is returned in MSB-to-LSB bit order.
655c2c66affSColin Finck */
656c2c66affSColin Finck int
657c2c66affSColin Finck TIFFIsMSB2LSB(TIFF* tif)
658c2c66affSColin Finck {
659c2c66affSColin Finck return (isFillOrder(tif, FILLORDER_MSB2LSB));
660c2c66affSColin Finck }
661c2c66affSColin Finck
662c2c66affSColin Finck /*
663c2c66affSColin Finck * Return nonzero if given file was written in big-endian order.
664c2c66affSColin Finck */
665c2c66affSColin Finck int
666c2c66affSColin Finck TIFFIsBigEndian(TIFF* tif)
667c2c66affSColin Finck {
668c2c66affSColin Finck return (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN);
669c2c66affSColin Finck }
670c2c66affSColin Finck
671c2c66affSColin Finck /*
672c2c66affSColin Finck * Return pointer to file read method.
673c2c66affSColin Finck */
674c2c66affSColin Finck TIFFReadWriteProc
675c2c66affSColin Finck TIFFGetReadProc(TIFF* tif)
676c2c66affSColin Finck {
677c2c66affSColin Finck return (tif->tif_readproc);
678c2c66affSColin Finck }
679c2c66affSColin Finck
680c2c66affSColin Finck /*
681c2c66affSColin Finck * Return pointer to file write method.
682c2c66affSColin Finck */
683c2c66affSColin Finck TIFFReadWriteProc
684c2c66affSColin Finck TIFFGetWriteProc(TIFF* tif)
685c2c66affSColin Finck {
686c2c66affSColin Finck return (tif->tif_writeproc);
687c2c66affSColin Finck }
688c2c66affSColin Finck
689c2c66affSColin Finck /*
690c2c66affSColin Finck * Return pointer to file seek method.
691c2c66affSColin Finck */
692c2c66affSColin Finck TIFFSeekProc
693c2c66affSColin Finck TIFFGetSeekProc(TIFF* tif)
694c2c66affSColin Finck {
695c2c66affSColin Finck return (tif->tif_seekproc);
696c2c66affSColin Finck }
697c2c66affSColin Finck
698c2c66affSColin Finck /*
699c2c66affSColin Finck * Return pointer to file close method.
700c2c66affSColin Finck */
701c2c66affSColin Finck TIFFCloseProc
702c2c66affSColin Finck TIFFGetCloseProc(TIFF* tif)
703c2c66affSColin Finck {
704c2c66affSColin Finck return (tif->tif_closeproc);
705c2c66affSColin Finck }
706c2c66affSColin Finck
707c2c66affSColin Finck /*
708c2c66affSColin Finck * Return pointer to file size requesting method.
709c2c66affSColin Finck */
710c2c66affSColin Finck TIFFSizeProc
711c2c66affSColin Finck TIFFGetSizeProc(TIFF* tif)
712c2c66affSColin Finck {
713c2c66affSColin Finck return (tif->tif_sizeproc);
714c2c66affSColin Finck }
715c2c66affSColin Finck
716c2c66affSColin Finck /*
717c2c66affSColin Finck * Return pointer to memory mapping method.
718c2c66affSColin Finck */
719c2c66affSColin Finck TIFFMapFileProc
720c2c66affSColin Finck TIFFGetMapFileProc(TIFF* tif)
721c2c66affSColin Finck {
722c2c66affSColin Finck return (tif->tif_mapproc);
723c2c66affSColin Finck }
724c2c66affSColin Finck
725c2c66affSColin Finck /*
726c2c66affSColin Finck * Return pointer to memory unmapping method.
727c2c66affSColin Finck */
728c2c66affSColin Finck TIFFUnmapFileProc
729c2c66affSColin Finck TIFFGetUnmapFileProc(TIFF* tif)
730c2c66affSColin Finck {
731c2c66affSColin Finck return (tif->tif_unmapproc);
732c2c66affSColin Finck }
733c2c66affSColin Finck
734c2c66affSColin Finck /* vim: set ts=8 sts=8 sw=8 noet: */
735c2c66affSColin Finck /*
736c2c66affSColin Finck * Local Variables:
737c2c66affSColin Finck * mode: c
738c2c66affSColin Finck * c-basic-offset: 8
739c2c66affSColin Finck * fill-column: 78
740c2c66affSColin Finck * End:
741c2c66affSColin Finck */
742