PageRenderTime 30ms CodeModel.GetById 6ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/LibTIFF/tif_zip.c

https://bitbucket.org/cabalistic/ogredeps/
C | 419 lines | 277 code | 49 blank | 93 comment | 59 complexity | a3cf712089ffdaf629f1f1ed4c1f8494 MD5 | raw file
  1/* $Id: tif_zip.c,v 1.37 2011/04/10 17:14:09 drolon Exp $ */
  2
  3/*
  4 * Copyright (c) 1995-1997 Sam Leffler
  5 * Copyright (c) 1995-1997 Silicon Graphics, Inc.
  6 *
  7 * Permission to use, copy, modify, distribute, and sell this software and 
  8 * its documentation for any purpose is hereby granted without fee, provided
  9 * that (i) the above copyright notices and this permission notice appear in
 10 * all copies of the software and related documentation, and (ii) the names of
 11 * Sam Leffler and Silicon Graphics may not be used in any advertising or
 12 * publicity relating to the software without the specific, prior written
 13 * permission of Sam Leffler and Silicon Graphics.
 14 * 
 15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 18 * 
 19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
 20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 24 * OF THIS SOFTWARE.
 25 */
 26
 27#include "tiffiop.h"
 28#ifdef ZIP_SUPPORT
 29/*
 30 * TIFF Library.
 31 *
 32 * ZIP (aka Deflate) Compression Support
 33 *
 34 * This file is simply an interface to the zlib library written by
 35 * Jean-loup Gailly and Mark Adler.  You must use version 1.0 or later
 36 * of the library: this code assumes the 1.0 API and also depends on
 37 * the ability to write the zlib header multiple times (one per strip)
 38 * which was not possible with versions prior to 0.95.  Note also that
 39 * older versions of this codec avoided this bug by supressing the header
 40 * entirely.  This means that files written with the old library cannot
 41 * be read; they should be converted to a different compression scheme
 42 * and then reconverted.
 43 *
 44 * The data format used by the zlib library is described in the files
 45 * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the
 46 * directory ftp://ftp.uu.net/pub/archiving/zip/doc.  The library was
 47 * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz.
 48 */
 49#include "tif_predict.h"
 50#include "../ZLib/zlib.h"
 51
 52#include <stdio.h>
 53
 54/*
 55 * Sigh, ZLIB_VERSION is defined as a string so there's no
 56 * way to do a proper check here.  Instead we guess based
 57 * on the presence of #defines that were added between the
 58 * 0.95 and 1.0 distributions.
 59 */
 60#if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED)
 61#error "Antiquated ZLIB software; you must use version 1.0 or later"
 62#endif
 63
 64/*
 65 * State block for each open TIFF
 66 * file using ZIP compression/decompression.
 67 */
 68typedef	struct {
 69	TIFFPredictorState predict;
 70	z_stream	stream;
 71	int		zipquality;		/* compression level */
 72	int		state;			/* state flags */
 73#define ZSTATE_INIT_DECODE 0x01
 74#define ZSTATE_INIT_ENCODE 0x02
 75
 76	TIFFVGetMethod	vgetparent;		/* super-class method */
 77	TIFFVSetMethod	vsetparent;		/* super-class method */
 78} ZIPState;
 79
 80#define	ZState(tif)		((ZIPState*) (tif)->tif_data)
 81#define	DecoderState(tif)	ZState(tif)
 82#define	EncoderState(tif)	ZState(tif)
 83
 84static	int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t);
 85static	int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t);
 86
 87static int
 88ZIPSetupDecode(TIFF* tif)
 89{
 90	ZIPState* sp = DecoderState(tif);
 91	static const char module[] = "ZIPSetupDecode";
 92
 93	assert(sp != NULL);
 94        
 95        /* if we were last encoding, terminate this mode */
 96	if (sp->state & ZSTATE_INIT_ENCODE) {
 97            deflateEnd(&sp->stream);
 98            sp->state = 0;
 99        }
100
101	if (inflateInit(&sp->stream) != Z_OK) {
102		TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
103		return (0);
104	} else {
105		sp->state |= ZSTATE_INIT_DECODE;
106		return (1);
107	}
108}
109
110/*
111 * Setup state for decoding a strip.
112 */
113static int
114ZIPPreDecode(TIFF* tif, tsample_t s)
115{
116	ZIPState* sp = DecoderState(tif);
117
118	(void) s;
119	assert(sp != NULL);
120
121        if( (sp->state & ZSTATE_INIT_DECODE) == 0 )
122            tif->tif_setupdecode( tif );
123
124	sp->stream.next_in = tif->tif_rawdata;
125	sp->stream.avail_in = tif->tif_rawcc;
126	return (inflateReset(&sp->stream) == Z_OK);
127}
128
129static int
130ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
131{
132	ZIPState* sp = DecoderState(tif);
133	static const char module[] = "ZIPDecode";
134
135	(void) s;
136	assert(sp != NULL);
137        assert(sp->state == ZSTATE_INIT_DECODE);
138
139	sp->stream.next_out = op;
140	sp->stream.avail_out = occ;
141	do {
142		int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
143		if (state == Z_STREAM_END)
144			break;
145		if (state == Z_DATA_ERROR) {
146			TIFFErrorExt(tif->tif_clientdata, module,
147			    "%s: Decoding error at scanline %d, %s",
148			    tif->tif_name, tif->tif_row, sp->stream.msg);
149			if (inflateSync(&sp->stream) != Z_OK)
150				return (0);
151			continue;
152		}
153		if (state != Z_OK) {
154			TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
155			    tif->tif_name, sp->stream.msg);
156			return (0);
157		}
158	} while (sp->stream.avail_out > 0);
159	if (sp->stream.avail_out != 0) {
160		TIFFErrorExt(tif->tif_clientdata, module,
161		    "%s: Not enough data at scanline %d (short %d bytes)",
162		    tif->tif_name, tif->tif_row, sp->stream.avail_out);
163		return (0);
164	}
165	return (1);
166}
167
168static int
169ZIPSetupEncode(TIFF* tif)
170{
171	ZIPState* sp = EncoderState(tif);
172	static const char module[] = "ZIPSetupEncode";
173
174	assert(sp != NULL);
175	if (sp->state & ZSTATE_INIT_DECODE) {
176            inflateEnd(&sp->stream);
177            sp->state = 0;
178        }
179
180	if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) {
181		TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
182		return (0);
183	} else {
184		sp->state |= ZSTATE_INIT_ENCODE;
185		return (1);
186	}
187}
188
189/*
190 * Reset encoding state at the start of a strip.
191 */
192static int
193ZIPPreEncode(TIFF* tif, tsample_t s)
194{
195	ZIPState *sp = EncoderState(tif);
196
197	(void) s;
198	assert(sp != NULL);
199        if( sp->state != ZSTATE_INIT_ENCODE )
200            tif->tif_setupencode( tif );
201
202	sp->stream.next_out = tif->tif_rawdata;
203	sp->stream.avail_out = tif->tif_rawdatasize;
204	return (deflateReset(&sp->stream) == Z_OK);
205}
206
207/*
208 * Encode a chunk of pixels.
209 */
210static int
211ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
212{
213	ZIPState *sp = EncoderState(tif);
214	static const char module[] = "ZIPEncode";
215
216        assert(sp != NULL);
217        assert(sp->state == ZSTATE_INIT_ENCODE);
218
219	(void) s;
220	sp->stream.next_in = bp;
221	sp->stream.avail_in = cc;
222	do {
223		if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
224			TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s",
225			    tif->tif_name, sp->stream.msg);
226			return (0);
227		}
228		if (sp->stream.avail_out == 0) {
229			tif->tif_rawcc = tif->tif_rawdatasize;
230			TIFFFlushData1(tif);
231			sp->stream.next_out = tif->tif_rawdata;
232			sp->stream.avail_out = tif->tif_rawdatasize;
233		}
234	} while (sp->stream.avail_in > 0);
235	return (1);
236}
237
238/*
239 * Finish off an encoded strip by flushing the last
240 * string and tacking on an End Of Information code.
241 */
242static int
243ZIPPostEncode(TIFF* tif)
244{
245	ZIPState *sp = EncoderState(tif);
246	static const char module[] = "ZIPPostEncode";
247	int state;
248
249	sp->stream.avail_in = 0;
250	do {
251		state = deflate(&sp->stream, Z_FINISH);
252		switch (state) {
253		case Z_STREAM_END:
254		case Z_OK:
255		    if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize)
256                    {
257			    tif->tif_rawcc =
258				tif->tif_rawdatasize - sp->stream.avail_out;
259			    TIFFFlushData1(tif);
260			    sp->stream.next_out = tif->tif_rawdata;
261			    sp->stream.avail_out = tif->tif_rawdatasize;
262		    }
263		    break;
264		default:
265			TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
266			tif->tif_name, sp->stream.msg);
267		    return (0);
268		}
269	} while (state != Z_STREAM_END);
270	return (1);
271}
272
273static void
274ZIPCleanup(TIFF* tif)
275{
276	ZIPState* sp = ZState(tif);
277
278	assert(sp != 0);
279
280	(void)TIFFPredictorCleanup(tif);
281
282	tif->tif_tagmethods.vgetfield = sp->vgetparent;
283	tif->tif_tagmethods.vsetfield = sp->vsetparent;
284
285	if (sp->state & ZSTATE_INIT_ENCODE) {
286            deflateEnd(&sp->stream);
287            sp->state = 0;
288        } else if( sp->state & ZSTATE_INIT_DECODE) {
289            inflateEnd(&sp->stream);
290            sp->state = 0;
291	}
292	_TIFFfree(sp);
293	tif->tif_data = NULL;
294
295	_TIFFSetDefaultCompressionState(tif);
296}
297
298static int
299ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap)
300{
301	ZIPState* sp = ZState(tif);
302	static const char module[] = "ZIPVSetField";
303
304	switch (tag) {
305	case TIFFTAG_ZIPQUALITY:
306		sp->zipquality = va_arg(ap, int);
307		if ( sp->state&ZSTATE_INIT_ENCODE ) {
308			if (deflateParams(&sp->stream,
309			    sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) {
310				TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
311				    tif->tif_name, sp->stream.msg);
312				return (0);
313			}
314		}
315		return (1);
316	default:
317		return (*sp->vsetparent)(tif, tag, ap);
318	}
319	/*NOTREACHED*/
320}
321
322static int
323ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap)
324{
325	ZIPState* sp = ZState(tif);
326
327	switch (tag) {
328	case TIFFTAG_ZIPQUALITY:
329		*va_arg(ap, int*) = sp->zipquality;
330		break;
331	default:
332		return (*sp->vgetparent)(tif, tag, ap);
333	}
334	return (1);
335}
336
337static const TIFFFieldInfo zipFieldInfo[] = {
338    { TIFFTAG_ZIPQUALITY,	 0, 0,	TIFF_ANY,	FIELD_PSEUDO,
339      TRUE,	FALSE,	"" },
340};
341
342int
343TIFFInitZIP(TIFF* tif, int scheme)
344{
345	static const char module[] = "TIFFInitZIP";
346	ZIPState* sp;
347
348	assert( (scheme == COMPRESSION_DEFLATE)
349		|| (scheme == COMPRESSION_ADOBE_DEFLATE));
350
351	/*
352	 * Merge codec-specific tag information.
353	 */
354	if (!_TIFFMergeFieldInfo(tif, zipFieldInfo,
355				 TIFFArrayCount(zipFieldInfo))) {
356		TIFFErrorExt(tif->tif_clientdata, module,
357			     "Merging Deflate codec-specific tags failed");
358		return 0;
359	}
360
361	/*
362	 * Allocate state block so tag methods have storage to record values.
363	 */
364	tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState));
365	if (tif->tif_data == NULL)
366		goto bad;
367	sp = ZState(tif);
368	sp->stream.zalloc = NULL;
369	sp->stream.zfree = NULL;
370	sp->stream.opaque = NULL;
371	sp->stream.data_type = Z_BINARY;
372
373	/*
374	 * Override parent get/set field methods.
375	 */
376	sp->vgetparent = tif->tif_tagmethods.vgetfield;
377	tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */
378	sp->vsetparent = tif->tif_tagmethods.vsetfield;
379	tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */
380
381	/* Default values for codec-specific fields */
382	sp->zipquality = Z_DEFAULT_COMPRESSION;	/* default comp. level */
383	sp->state = 0;
384
385	/*
386	 * Install codec methods.
387	 */
388	tif->tif_setupdecode = ZIPSetupDecode;
389	tif->tif_predecode = ZIPPreDecode;
390	tif->tif_decoderow = ZIPDecode;
391	tif->tif_decodestrip = ZIPDecode;
392	tif->tif_decodetile = ZIPDecode;
393	tif->tif_setupencode = ZIPSetupEncode;
394	tif->tif_preencode = ZIPPreEncode;
395	tif->tif_postencode = ZIPPostEncode;
396	tif->tif_encoderow = ZIPEncode;
397	tif->tif_encodestrip = ZIPEncode;
398	tif->tif_encodetile = ZIPEncode;
399	tif->tif_cleanup = ZIPCleanup;
400	/*
401	 * Setup predictor setup.
402	 */
403	(void) TIFFPredictorInit(tif);
404	return (1);
405bad:
406	TIFFErrorExt(tif->tif_clientdata, module,
407		     "No space for ZIP state block");
408	return (0);
409}
410#endif /* ZIP_SUPORT */
411
412/* vim: set ts=8 sts=8 sw=8 noet: */
413/*
414 * Local Variables:
415 * mode: c
416 * c-basic-offset: 8
417 * fill-column: 78
418 * End:
419 */