blob: 1319621befb8223c72c93f588269f411761e6885 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% CCCC OOO M M PPPP RRRR EEEEE SSSSS SSSSS %
7% C O O MM MM P P R R E SS SS %
8% C O O M M M PPPP RRRR EEE SSS SSS %
9% C O O M M P R R E SS SS %
10% CCCC OOO M M P R R EEEEE SSSSS SSSSS %
11% %
12% %
13% MagickCore Image Compression/Decompression Methods %
14% %
15% Software Design %
16% John Cristy %
17% May 1993 %
18% %
19% %
cristy1454be72011-12-19 01:52:48 +000020% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
cristy4c08aed2011-07-01 19:47:50 +000043#include "MagickCore/studio.h"
cristy8941c702012-06-21 01:30:15 +000044#include "MagickCore/attribute.h"
cristy4c08aed2011-07-01 19:47:50 +000045#include "MagickCore/blob.h"
46#include "MagickCore/blob-private.h"
47#include "MagickCore/color-private.h"
48#include "MagickCore/cache.h"
49#include "MagickCore/compress.h"
50#include "MagickCore/constitute.h"
51#include "MagickCore/exception.h"
52#include "MagickCore/exception-private.h"
53#include "MagickCore/image-private.h"
54#include "MagickCore/list.h"
55#include "MagickCore/memory_.h"
56#include "MagickCore/monitor.h"
57#include "MagickCore/monitor-private.h"
58#include "MagickCore/option.h"
59#include "MagickCore/pixel-accessor.h"
60#include "MagickCore/resource_.h"
61#include "MagickCore/string_.h"
cristy3ed852e2009-09-05 21:47:34 +000062#if defined(MAGICKCORE_TIFF_DELEGATE)
63#if defined(MAGICKCORE_HAVE_TIFFCONF_H)
64#include "tiffconf.h"
65#endif
66#include "tiffio.h"
67#define CCITTParam "-1"
68#else
69#define CCITTParam "0"
70#endif
71#if defined(MAGICKCORE_ZLIB_DELEGATE)
72#include "zlib.h"
73#endif
74
75/*
76 Typedef declarations.
77*/
78struct _Ascii85Info
79{
cristybb503372010-05-27 20:51:26 +000080 ssize_t
cristy3ed852e2009-09-05 21:47:34 +000081 offset,
82 line_break;
83
84 unsigned char
85 buffer[10];
86};
87
88typedef struct HuffmanTable
89{
cristybb503372010-05-27 20:51:26 +000090 size_t
cristy3ed852e2009-09-05 21:47:34 +000091 id,
92 code,
93 length,
94 count;
95} HuffmanTable;
96
97/*
98 Huffman coding declarations.
99*/
100#define TWId 23
101#define MWId 24
102#define TBId 25
103#define MBId 26
104#define EXId 27
105
106static const HuffmanTable
107 MBTable[]=
108 {
109 { MBId, 0x0f, 10, 64 }, { MBId, 0xc8, 12, 128 },
110 { MBId, 0xc9, 12, 192 }, { MBId, 0x5b, 12, 256 },
111 { MBId, 0x33, 12, 320 }, { MBId, 0x34, 12, 384 },
112 { MBId, 0x35, 12, 448 }, { MBId, 0x6c, 13, 512 },
113 { MBId, 0x6d, 13, 576 }, { MBId, 0x4a, 13, 640 },
114 { MBId, 0x4b, 13, 704 }, { MBId, 0x4c, 13, 768 },
115 { MBId, 0x4d, 13, 832 }, { MBId, 0x72, 13, 896 },
116 { MBId, 0x73, 13, 960 }, { MBId, 0x74, 13, 1024 },
117 { MBId, 0x75, 13, 1088 }, { MBId, 0x76, 13, 1152 },
118 { MBId, 0x77, 13, 1216 }, { MBId, 0x52, 13, 1280 },
119 { MBId, 0x53, 13, 1344 }, { MBId, 0x54, 13, 1408 },
120 { MBId, 0x55, 13, 1472 }, { MBId, 0x5a, 13, 1536 },
121 { MBId, 0x5b, 13, 1600 }, { MBId, 0x64, 13, 1664 },
122 { MBId, 0x65, 13, 1728 }, { MBId, 0x00, 0, 0 }
123 };
124
125static const HuffmanTable
126 EXTable[]=
127 {
128 { EXId, 0x08, 11, 1792 }, { EXId, 0x0c, 11, 1856 },
129 { EXId, 0x0d, 11, 1920 }, { EXId, 0x12, 12, 1984 },
130 { EXId, 0x13, 12, 2048 }, { EXId, 0x14, 12, 2112 },
131 { EXId, 0x15, 12, 2176 }, { EXId, 0x16, 12, 2240 },
132 { EXId, 0x17, 12, 2304 }, { EXId, 0x1c, 12, 2368 },
133 { EXId, 0x1d, 12, 2432 }, { EXId, 0x1e, 12, 2496 },
134 { EXId, 0x1f, 12, 2560 }, { EXId, 0x00, 0, 0 }
135 };
136
137static const HuffmanTable
138 MWTable[]=
139 {
140 { MWId, 0x1b, 5, 64 }, { MWId, 0x12, 5, 128 },
141 { MWId, 0x17, 6, 192 }, { MWId, 0x37, 7, 256 },
142 { MWId, 0x36, 8, 320 }, { MWId, 0x37, 8, 384 },
143 { MWId, 0x64, 8, 448 }, { MWId, 0x65, 8, 512 },
144 { MWId, 0x68, 8, 576 }, { MWId, 0x67, 8, 640 },
145 { MWId, 0xcc, 9, 704 }, { MWId, 0xcd, 9, 768 },
146 { MWId, 0xd2, 9, 832 }, { MWId, 0xd3, 9, 896 },
147 { MWId, 0xd4, 9, 960 }, { MWId, 0xd5, 9, 1024 },
148 { MWId, 0xd6, 9, 1088 }, { MWId, 0xd7, 9, 1152 },
149 { MWId, 0xd8, 9, 1216 }, { MWId, 0xd9, 9, 1280 },
150 { MWId, 0xda, 9, 1344 }, { MWId, 0xdb, 9, 1408 },
151 { MWId, 0x98, 9, 1472 }, { MWId, 0x99, 9, 1536 },
152 { MWId, 0x9a, 9, 1600 }, { MWId, 0x18, 6, 1664 },
153 { MWId, 0x9b, 9, 1728 }, { MWId, 0x00, 0, 0 }
154 };
155
156static const HuffmanTable
157 TBTable[]=
158 {
159 { TBId, 0x37, 10, 0 }, { TBId, 0x02, 3, 1 }, { TBId, 0x03, 2, 2 },
160 { TBId, 0x02, 2, 3 }, { TBId, 0x03, 3, 4 }, { TBId, 0x03, 4, 5 },
161 { TBId, 0x02, 4, 6 }, { TBId, 0x03, 5, 7 }, { TBId, 0x05, 6, 8 },
162 { TBId, 0x04, 6, 9 }, { TBId, 0x04, 7, 10 }, { TBId, 0x05, 7, 11 },
163 { TBId, 0x07, 7, 12 }, { TBId, 0x04, 8, 13 }, { TBId, 0x07, 8, 14 },
164 { TBId, 0x18, 9, 15 }, { TBId, 0x17, 10, 16 }, { TBId, 0x18, 10, 17 },
165 { TBId, 0x08, 10, 18 }, { TBId, 0x67, 11, 19 }, { TBId, 0x68, 11, 20 },
166 { TBId, 0x6c, 11, 21 }, { TBId, 0x37, 11, 22 }, { TBId, 0x28, 11, 23 },
167 { TBId, 0x17, 11, 24 }, { TBId, 0x18, 11, 25 }, { TBId, 0xca, 12, 26 },
168 { TBId, 0xcb, 12, 27 }, { TBId, 0xcc, 12, 28 }, { TBId, 0xcd, 12, 29 },
169 { TBId, 0x68, 12, 30 }, { TBId, 0x69, 12, 31 }, { TBId, 0x6a, 12, 32 },
170 { TBId, 0x6b, 12, 33 }, { TBId, 0xd2, 12, 34 }, { TBId, 0xd3, 12, 35 },
171 { TBId, 0xd4, 12, 36 }, { TBId, 0xd5, 12, 37 }, { TBId, 0xd6, 12, 38 },
172 { TBId, 0xd7, 12, 39 }, { TBId, 0x6c, 12, 40 }, { TBId, 0x6d, 12, 41 },
173 { TBId, 0xda, 12, 42 }, { TBId, 0xdb, 12, 43 }, { TBId, 0x54, 12, 44 },
174 { TBId, 0x55, 12, 45 }, { TBId, 0x56, 12, 46 }, { TBId, 0x57, 12, 47 },
175 { TBId, 0x64, 12, 48 }, { TBId, 0x65, 12, 49 }, { TBId, 0x52, 12, 50 },
176 { TBId, 0x53, 12, 51 }, { TBId, 0x24, 12, 52 }, { TBId, 0x37, 12, 53 },
177 { TBId, 0x38, 12, 54 }, { TBId, 0x27, 12, 55 }, { TBId, 0x28, 12, 56 },
178 { TBId, 0x58, 12, 57 }, { TBId, 0x59, 12, 58 }, { TBId, 0x2b, 12, 59 },
179 { TBId, 0x2c, 12, 60 }, { TBId, 0x5a, 12, 61 }, { TBId, 0x66, 12, 62 },
180 { TBId, 0x67, 12, 63 }, { TBId, 0x00, 0, 0 }
181 };
182
183static const HuffmanTable
184 TWTable[]=
185 {
186 { TWId, 0x35, 8, 0 }, { TWId, 0x07, 6, 1 }, { TWId, 0x07, 4, 2 },
187 { TWId, 0x08, 4, 3 }, { TWId, 0x0b, 4, 4 }, { TWId, 0x0c, 4, 5 },
188 { TWId, 0x0e, 4, 6 }, { TWId, 0x0f, 4, 7 }, { TWId, 0x13, 5, 8 },
189 { TWId, 0x14, 5, 9 }, { TWId, 0x07, 5, 10 }, { TWId, 0x08, 5, 11 },
190 { TWId, 0x08, 6, 12 }, { TWId, 0x03, 6, 13 }, { TWId, 0x34, 6, 14 },
191 { TWId, 0x35, 6, 15 }, { TWId, 0x2a, 6, 16 }, { TWId, 0x2b, 6, 17 },
192 { TWId, 0x27, 7, 18 }, { TWId, 0x0c, 7, 19 }, { TWId, 0x08, 7, 20 },
193 { TWId, 0x17, 7, 21 }, { TWId, 0x03, 7, 22 }, { TWId, 0x04, 7, 23 },
194 { TWId, 0x28, 7, 24 }, { TWId, 0x2b, 7, 25 }, { TWId, 0x13, 7, 26 },
195 { TWId, 0x24, 7, 27 }, { TWId, 0x18, 7, 28 }, { TWId, 0x02, 8, 29 },
196 { TWId, 0x03, 8, 30 }, { TWId, 0x1a, 8, 31 }, { TWId, 0x1b, 8, 32 },
197 { TWId, 0x12, 8, 33 }, { TWId, 0x13, 8, 34 }, { TWId, 0x14, 8, 35 },
198 { TWId, 0x15, 8, 36 }, { TWId, 0x16, 8, 37 }, { TWId, 0x17, 8, 38 },
199 { TWId, 0x28, 8, 39 }, { TWId, 0x29, 8, 40 }, { TWId, 0x2a, 8, 41 },
200 { TWId, 0x2b, 8, 42 }, { TWId, 0x2c, 8, 43 }, { TWId, 0x2d, 8, 44 },
201 { TWId, 0x04, 8, 45 }, { TWId, 0x05, 8, 46 }, { TWId, 0x0a, 8, 47 },
202 { TWId, 0x0b, 8, 48 }, { TWId, 0x52, 8, 49 }, { TWId, 0x53, 8, 50 },
203 { TWId, 0x54, 8, 51 }, { TWId, 0x55, 8, 52 }, { TWId, 0x24, 8, 53 },
204 { TWId, 0x25, 8, 54 }, { TWId, 0x58, 8, 55 }, { TWId, 0x59, 8, 56 },
205 { TWId, 0x5a, 8, 57 }, { TWId, 0x5b, 8, 58 }, { TWId, 0x4a, 8, 59 },
206 { TWId, 0x4b, 8, 60 }, { TWId, 0x32, 8, 61 }, { TWId, 0x33, 8, 62 },
207 { TWId, 0x34, 8, 63 }, { TWId, 0x00, 0, 0 }
208 };
209
210/*
211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212% %
213% %
214% %
215% A S C I I 8 5 E n c o d e %
216% %
217% %
218% %
219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220%
221% ASCII85Encode() encodes data in ASCII base-85 format. ASCII base-85
222% encoding produces five ASCII printing characters from every four bytes of
223% binary data.
224%
225% The format of the ASCII85Encode method is:
226%
cristybb503372010-05-27 20:51:26 +0000227% void Ascii85Encode(Image *image,const size_t code)
cristy3ed852e2009-09-05 21:47:34 +0000228%
229% A description of each parameter follows:
230%
231% o code: a binary unsigned char to encode to ASCII 85.
232%
233% o file: write the encoded ASCII character to this file.
234%
235%
236*/
237#define MaxLineExtent 36
238
239static char *Ascii85Tuple(unsigned char *data)
240{
241 static char
242 tuple[6];
243
cristybb503372010-05-27 20:51:26 +0000244 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000245 i,
246 x;
247
cristybb503372010-05-27 20:51:26 +0000248 size_t
cristy3ed852e2009-09-05 21:47:34 +0000249 code,
250 quantum;
251
cristybb503372010-05-27 20:51:26 +0000252 code=((((size_t) data[0] << 8) | (size_t) data[1]) << 16) |
253 ((size_t) data[2] << 8) | (size_t) data[3];
cristy3ed852e2009-09-05 21:47:34 +0000254 if (code == 0L)
255 {
256 tuple[0]='z';
257 tuple[1]='\0';
258 return(tuple);
259 }
260 quantum=85UL*85UL*85UL*85UL;
261 for (i=0; i < 4; i++)
262 {
cristybb503372010-05-27 20:51:26 +0000263 x=(ssize_t) (code/quantum);
cristy3ed852e2009-09-05 21:47:34 +0000264 code-=quantum*x;
265 tuple[i]=(char) (x+(int) '!');
266 quantum/=85L;
267 }
268 tuple[4]=(char) ((code % 85L)+(int) '!');
269 tuple[5]='\0';
270 return(tuple);
271}
272
273MagickExport void Ascii85Initialize(Image *image)
274{
275 /*
276 Allocate image structure.
277 */
278 if (image->ascii85 == (Ascii85Info *) NULL)
cristy73bd4a52010-10-05 11:24:23 +0000279 image->ascii85=(Ascii85Info *) AcquireMagickMemory(sizeof(*image->ascii85));
cristy3ed852e2009-09-05 21:47:34 +0000280 if (image->ascii85 == (Ascii85Info *) NULL)
281 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
282 (void) ResetMagickMemory(image->ascii85,0,sizeof(*image->ascii85));
283 image->ascii85->line_break=MaxLineExtent << 1;
284 image->ascii85->offset=0;
285}
286
287MagickExport void Ascii85Flush(Image *image)
288{
289 register char
290 *tuple;
291
292 assert(image != (Image *) NULL);
293 assert(image->signature == MagickSignature);
294 if (image->debug != MagickFalse)
295 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
296 assert(image->ascii85 != (Ascii85Info *) NULL);
297 if (image->ascii85->offset > 0)
298 {
299 image->ascii85->buffer[image->ascii85->offset]='\0';
300 image->ascii85->buffer[image->ascii85->offset+1]='\0';
301 image->ascii85->buffer[image->ascii85->offset+2]='\0';
302 tuple=Ascii85Tuple(image->ascii85->buffer);
303 (void) WriteBlob(image,(size_t) image->ascii85->offset+1,
304 (const unsigned char *) (*tuple == 'z' ? "!!!!" : tuple));
305 }
306 (void) WriteBlobByte(image,'~');
307 (void) WriteBlobByte(image,'>');
308 (void) WriteBlobByte(image,'\n');
309}
310
311MagickExport void Ascii85Encode(Image *image,const unsigned char code)
312{
cristy3ed852e2009-09-05 21:47:34 +0000313 register char
314 *q;
315
316 register unsigned char
317 *p;
318
cristy9d314ff2011-03-09 01:30:28 +0000319 ssize_t
320 n;
321
cristy3ed852e2009-09-05 21:47:34 +0000322 assert(image != (Image *) NULL);
323 assert(image->signature == MagickSignature);
324 assert(image->ascii85 != (Ascii85Info *) NULL);
325 image->ascii85->buffer[image->ascii85->offset]=code;
326 image->ascii85->offset++;
327 if (image->ascii85->offset < 4)
328 return;
329 p=image->ascii85->buffer;
330 for (n=image->ascii85->offset; n >= 4; n-=4)
331 {
332 for (q=Ascii85Tuple(p); *q != '\0'; q++)
333 {
334 image->ascii85->line_break--;
335 if ((image->ascii85->line_break < 0) && (*q != '%'))
336 {
337 (void) WriteBlobByte(image,'\n');
338 image->ascii85->line_break=2*MaxLineExtent;
339 }
340 (void) WriteBlobByte(image,(unsigned char) *q);
341 }
342 p+=8;
343 }
344 image->ascii85->offset=n;
345 p-=4;
346 for (n=0; n < 4; n++)
347 image->ascii85->buffer[n]=(*p++);
348}
349
350/*
351%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
352% %
353% %
354% %
355% H u f f m a n D e c o d e I m a g e %
356% %
357% %
358% %
359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360%
361% HuffmanDecodeImage() uncompresses an image via Huffman-coding.
362%
363% The format of the HuffmanDecodeImage method is:
364%
cristy018f07f2011-09-04 21:15:19 +0000365% MagickBooleanType HuffmanDecodeImage(Image *image,
366% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000367%
368% A description of each parameter follows:
369%
370% o image: the image.
371%
cristy018f07f2011-09-04 21:15:19 +0000372% o exception: return any errors or warnings in this structure.
373%
cristy3ed852e2009-09-05 21:47:34 +0000374*/
375
376static inline size_t MagickMax(const size_t x,const size_t y)
377{
378 if (x > y)
379 return(x);
380 return(y);
381}
382
383static inline size_t MagickMin(const size_t x,const size_t y)
384{
385 if (x < y)
386 return(x);
387 return(y);
388}
389
cristy018f07f2011-09-04 21:15:19 +0000390MagickExport MagickBooleanType HuffmanDecodeImage(Image *image,
391 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000392{
393#define HashSize 1021
394#define MBHashA 293
395#define MBHashB 2695
396#define MWHashA 3510
397#define MWHashB 1178
398
399#define InitializeHashTable(hash,table,a,b) \
400{ \
401 entry=table; \
402 while (entry->code != 0) \
403 { \
404 hash[((entry->length+a)*(entry->code+b)) % HashSize]=(HuffmanTable *) entry; \
405 entry++; \
406 } \
407}
408
409#define InputBit(bit) \
410{ \
411 if ((mask & 0xff) == 0) \
412 { \
413 byte=ReadBlobByte(image); \
414 if (byte == EOF) \
415 break; \
416 mask=0x80; \
417 } \
418 runlength++; \
cristybb503372010-05-27 20:51:26 +0000419 bit=(size_t) ((byte & mask) != 0 ? 0x01 : 0x00); \
cristy3ed852e2009-09-05 21:47:34 +0000420 mask>>=1; \
421 if (bit != 0) \
422 runlength=0; \
423}
424
cristyc5c6f662010-09-22 14:23:02 +0000425 CacheView
426 *image_view;
427
cristy3ed852e2009-09-05 21:47:34 +0000428 const HuffmanTable
429 *entry;
430
cristy3ed852e2009-09-05 21:47:34 +0000431 HuffmanTable
432 **mb_hash,
433 **mw_hash;
434
cristy3ed852e2009-09-05 21:47:34 +0000435 int
436 byte;
437
cristy3ed852e2009-09-05 21:47:34 +0000438 MagickBooleanType
439 proceed;
440
cristy4c08aed2011-07-01 19:47:50 +0000441 Quantum
442 index;
cristy3ed852e2009-09-05 21:47:34 +0000443
cristybb503372010-05-27 20:51:26 +0000444 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000445 i;
446
447 register unsigned char
448 *p;
449
cristy9d314ff2011-03-09 01:30:28 +0000450 size_t
451 bit,
452 code,
453 mask,
454 length,
455 null_lines,
456 runlength;
457
cristy3ed852e2009-09-05 21:47:34 +0000458 ssize_t
cristyc5c6f662010-09-22 14:23:02 +0000459 count,
460 y;
cristy3ed852e2009-09-05 21:47:34 +0000461
462 unsigned char
463 *scanline;
464
465 unsigned int
466 bail,
467 color;
468
cristy3ed852e2009-09-05 21:47:34 +0000469 /*
470 Allocate buffers.
471 */
472 assert(image != (Image *) NULL);
473 assert(image->signature == MagickSignature);
474 if (image->debug != MagickFalse)
475 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
476 mb_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mb_hash));
477 mw_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mw_hash));
478 scanline=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
479 sizeof(*scanline));
480 if ((mb_hash == (HuffmanTable **) NULL) ||
481 (mw_hash == (HuffmanTable **) NULL) ||
482 (scanline == (unsigned char *) NULL))
483 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
484 image->filename);
485 /*
486 Initialize Huffman tables.
487 */
488 for (i=0; i < HashSize; i++)
489 {
490 mb_hash[i]=(HuffmanTable *) NULL;
491 mw_hash[i]=(HuffmanTable *) NULL;
492 }
493 InitializeHashTable(mw_hash,TWTable,MWHashA,MWHashB);
494 InitializeHashTable(mw_hash,MWTable,MWHashA,MWHashB);
495 InitializeHashTable(mw_hash,EXTable,MWHashA,MWHashB);
496 InitializeHashTable(mb_hash,TBTable,MBHashA,MBHashB);
497 InitializeHashTable(mb_hash,MBTable,MBHashA,MBHashB);
498 InitializeHashTable(mb_hash,EXTable,MBHashA,MBHashB);
499 /*
500 Uncompress 1D Huffman to runlength encoded pixels.
501 */
502 byte=0;
503 mask=0;
504 null_lines=0;
505 runlength=0;
506 while (runlength < 11)
507 InputBit(bit);
508 do { InputBit(bit); } while ((int) bit == 0);
cristy2a11bef2011-10-28 18:33:11 +0000509 image->resolution.x=204.0;
510 image->resolution.y=196.0;
cristy3ed852e2009-09-05 21:47:34 +0000511 image->units=PixelsPerInchResolution;
cristydb070952012-04-20 14:33:00 +0000512 image_view=AcquireAuthenticCacheView(image,exception);
cristybb503372010-05-27 20:51:26 +0000513 for (y=0; ((y < (ssize_t) image->rows) && (null_lines < 3)); )
cristy3ed852e2009-09-05 21:47:34 +0000514 {
cristy4c08aed2011-07-01 19:47:50 +0000515 register Quantum
cristyc47d1f82009-11-26 01:44:43 +0000516 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000517
cristyc5c6f662010-09-22 14:23:02 +0000518 register ssize_t
519 x;
520
cristy3ed852e2009-09-05 21:47:34 +0000521 /*
522 Initialize scanline to white.
523 */
524 p=scanline;
cristybb503372010-05-27 20:51:26 +0000525 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000526 *p++=(unsigned char) 0;
527 /*
528 Decode Huffman encoded scanline.
529 */
530 color=MagickTrue;
531 code=0;
532 count=0;
533 length=0;
534 runlength=0;
535 x=0;
536 for ( ; ; )
537 {
538 if (byte == EOF)
539 break;
cristybb503372010-05-27 20:51:26 +0000540 if (x >= (ssize_t) image->columns)
cristy3ed852e2009-09-05 21:47:34 +0000541 {
542 while (runlength < 11)
543 InputBit(bit);
544 do { InputBit(bit); } while ((int) bit == 0);
545 break;
546 }
547 bail=MagickFalse;
548 do
549 {
550 if (runlength < 11)
551 InputBit(bit)
552 else
553 {
554 InputBit(bit);
555 if ((int) bit != 0)
556 {
557 null_lines++;
558 if (x != 0)
559 null_lines=0;
560 bail=MagickTrue;
561 break;
562 }
563 }
cristybb503372010-05-27 20:51:26 +0000564 code=(code << 1)+(size_t) bit;
cristy3ed852e2009-09-05 21:47:34 +0000565 length++;
566 } while (code == 0);
567 if (bail != MagickFalse)
568 break;
569 if (length > 13)
570 {
571 while (runlength < 11)
572 InputBit(bit);
573 do { InputBit(bit); } while ((int) bit == 0);
574 break;
575 }
576 if (color != MagickFalse)
577 {
578 if (length < 4)
579 continue;
580 entry=mw_hash[((length+MWHashA)*(code+MWHashB)) % HashSize];
581 }
582 else
583 {
584 if (length < 2)
585 continue;
586 entry=mb_hash[((length+MBHashA)*(code+MBHashB)) % HashSize];
587 }
588 if (entry == (const HuffmanTable *) NULL)
589 continue;
590 if ((entry->length != length) || (entry->code != code))
591 continue;
592 switch (entry->id)
593 {
594 case TWId:
595 case TBId:
596 {
cristyeaedf062010-05-29 22:36:02 +0000597 count+=(ssize_t) entry->count;
cristybb503372010-05-27 20:51:26 +0000598 if ((x+count) > (ssize_t) image->columns)
cristy3ed852e2009-09-05 21:47:34 +0000599 count=(ssize_t) image->columns-x;
600 if (count > 0)
601 {
602 if (color != MagickFalse)
603 {
604 x+=count;
605 count=0;
606 }
607 else
608 for ( ; count > 0; count--)
609 scanline[x++]=(unsigned char) 1;
610 }
611 color=(unsigned int)
612 ((color == MagickFalse) ? MagickTrue : MagickFalse);
613 break;
614 }
615 case MWId:
616 case MBId:
617 case EXId:
618 {
cristyeaedf062010-05-29 22:36:02 +0000619 count+=(ssize_t) entry->count;
cristy3ed852e2009-09-05 21:47:34 +0000620 break;
621 }
622 default:
623 break;
624 }
625 code=0;
626 length=0;
627 }
628 /*
629 Transfer scanline to image pixels.
630 */
631 p=scanline;
cristyc5c6f662010-09-22 14:23:02 +0000632 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
cristyacd2ed22011-08-30 01:44:23 +0000633 if (q == (Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000634 break;
cristybb503372010-05-27 20:51:26 +0000635 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000636 {
cristy4c08aed2011-07-01 19:47:50 +0000637 index=(Quantum) (*p++);
638 SetPixelIndex(image,index,q);
cristy803640d2011-11-17 02:11:32 +0000639 SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
cristyed231572011-07-14 02:18:59 +0000640 q+=GetPixelChannels(image);
cristy3ed852e2009-09-05 21:47:34 +0000641 }
cristyc5c6f662010-09-22 14:23:02 +0000642 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
cristy3ed852e2009-09-05 21:47:34 +0000643 break;
644 proceed=SetImageProgress(image,LoadImageTag,y,image->rows);
645 if (proceed == MagickFalse)
646 break;
647 y++;
648 }
cristyc5c6f662010-09-22 14:23:02 +0000649 image_view=DestroyCacheView(image_view);
cristybb503372010-05-27 20:51:26 +0000650 image->rows=(size_t) MagickMax((size_t) y-3,1);
cristy3ed852e2009-09-05 21:47:34 +0000651 image->compression=FaxCompression;
652 /*
653 Free decoder memory.
654 */
655 mw_hash=(HuffmanTable **) RelinquishMagickMemory(mw_hash);
656 mb_hash=(HuffmanTable **) RelinquishMagickMemory(mb_hash);
657 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
658 return(MagickTrue);
659}
660
661/*
662%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
663% %
664% %
665% %
666% H u f f m a n E n c o d e I m a g e %
667% %
668% %
669% %
670%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
671%
672% HuffmanEncodeImage() compresses an image via Huffman-coding.
673%
674% The format of the HuffmanEncodeImage method is:
675%
676% MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
cristy018f07f2011-09-04 21:15:19 +0000677% Image *image,Image *inject_image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000678%
679% A description of each parameter follows:
680%
681% o image_info: the image info..
682%
683% o image: the image.
684%
685% o inject_image: inject into the image stream.
686%
cristy018f07f2011-09-04 21:15:19 +0000687% o exception: return any errors or warnings in this structure.
688%
cristy3ed852e2009-09-05 21:47:34 +0000689*/
690MagickExport MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
cristy018f07f2011-09-04 21:15:19 +0000691 Image *image,Image *inject_image,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000692{
693#define HuffmanOutputCode(entry) \
694{ \
cristyeaedf062010-05-29 22:36:02 +0000695 mask=one << (entry->length-1); \
cristy3ed852e2009-09-05 21:47:34 +0000696 while (mask != 0) \
697 { \
698 OutputBit(((entry->code & mask) != 0 ? 1 : 0)); \
699 mask>>=1; \
700 } \
701}
702
703#define OutputBit(count) \
704{ \
705 if (count > 0) \
706 byte=byte | bit; \
707 bit>>=1; \
708 if ((int) (bit & 0xff) == 0) \
709 { \
710 if (LocaleCompare(image_info->magick,"FAX") == 0) \
711 (void) WriteBlobByte(image,(unsigned char) byte); \
712 else \
713 Ascii85Encode(image,byte); \
714 byte='\0'; \
715 bit=(unsigned char) 0x80; \
716 } \
717}
718
719 const HuffmanTable
720 *entry;
721
cristy3ed852e2009-09-05 21:47:34 +0000722 int
723 k,
724 runlength;
725
cristy3ed852e2009-09-05 21:47:34 +0000726 Image
727 *huffman_image;
728
729 MagickBooleanType
730 proceed;
731
cristybb503372010-05-27 20:51:26 +0000732 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000733 i,
734 x;
735
cristy4c08aed2011-07-01 19:47:50 +0000736 register const Quantum
cristy3ed852e2009-09-05 21:47:34 +0000737 *p;
738
739 register unsigned char
740 *q;
741
cristybb503372010-05-27 20:51:26 +0000742 size_t
cristy3ed852e2009-09-05 21:47:34 +0000743 mask,
cristyeaedf062010-05-29 22:36:02 +0000744 one,
cristy3ed852e2009-09-05 21:47:34 +0000745 width;
746
cristy9d314ff2011-03-09 01:30:28 +0000747 ssize_t
748 n,
749 y;
750
751 unsigned char
752 byte,
753 bit,
754 *scanline;
755
cristy3ed852e2009-09-05 21:47:34 +0000756 /*
757 Allocate scanline buffer.
758 */
759 assert(image_info != (ImageInfo *) NULL);
760 assert(image_info->signature == MagickSignature);
761 assert(image != (Image *) NULL);
762 assert(image->signature == MagickSignature);
763 if (image->debug != MagickFalse)
764 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
765 assert(inject_image != (Image *) NULL);
766 assert(inject_image->signature == MagickSignature);
cristyeaedf062010-05-29 22:36:02 +0000767 one=1;
cristy3ed852e2009-09-05 21:47:34 +0000768 width=inject_image->columns;
769 if (LocaleCompare(image_info->magick,"FAX") == 0)
cristybb503372010-05-27 20:51:26 +0000770 width=(size_t) MagickMax(inject_image->columns,1728);
cristy3ed852e2009-09-05 21:47:34 +0000771 scanline=(unsigned char *) AcquireQuantumMemory((size_t) width+1UL,
772 sizeof(*scanline));
773 if (scanline == (unsigned char *) NULL)
774 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
775 inject_image->filename);
776 (void) ResetMagickMemory(scanline,0,width*sizeof(*scanline));
cristyc82a27b2011-10-21 01:07:16 +0000777 huffman_image=CloneImage(inject_image,0,0,MagickTrue,exception);
cristy3ed852e2009-09-05 21:47:34 +0000778 if (huffman_image == (Image *) NULL)
779 {
780 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
781 return(MagickFalse);
782 }
cristy018f07f2011-09-04 21:15:19 +0000783 (void) SetImageType(huffman_image,BilevelType,exception);
cristy3ed852e2009-09-05 21:47:34 +0000784 byte='\0';
785 bit=(unsigned char) 0x80;
786 if (LocaleCompare(image_info->magick,"FAX") != 0)
787 Ascii85Initialize(image);
788 else
789 {
790 /*
791 End of line.
792 */
793 for (k=0; k < 11; k++)
794 OutputBit(0);
795 OutputBit(1);
796 }
797 /*
798 Compress to 1D Huffman pixels.
799 */
cristy3ed852e2009-09-05 21:47:34 +0000800 q=scanline;
cristybb503372010-05-27 20:51:26 +0000801 for (y=0; y < (ssize_t) huffman_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000802 {
803 p=GetVirtualPixels(huffman_image,0,y,huffman_image->columns,1,exception);
cristy4c08aed2011-07-01 19:47:50 +0000804 if (p == (const Quantum *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000805 break;
cristybb503372010-05-27 20:51:26 +0000806 for (x=0; x < (ssize_t) huffman_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000807 {
cristy4c08aed2011-07-01 19:47:50 +0000808 *q++=(unsigned char) (GetPixelIntensity(huffman_image,p) >=
809 ((MagickRealType) QuantumRange/2.0) ? 0 : 1);
cristyed231572011-07-14 02:18:59 +0000810 p+=GetPixelChannels(huffman_image);
cristy3ed852e2009-09-05 21:47:34 +0000811 }
812 /*
813 Huffman encode scanline.
814 */
815 q=scanline;
cristybb503372010-05-27 20:51:26 +0000816 for (n=(ssize_t) width; n > 0; )
cristy3ed852e2009-09-05 21:47:34 +0000817 {
818 /*
819 Output white run.
820 */
821 for (runlength=0; ((n > 0) && (*q == 0)); n--)
822 {
823 q++;
824 runlength++;
825 }
826 if (runlength >= 64)
827 {
828 if (runlength < 1792)
829 entry=MWTable+((runlength/64)-1);
830 else
831 entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
cristy8891f9c2010-06-04 23:32:17 +0000832 runlength-=(long) entry->count;
cristy3ed852e2009-09-05 21:47:34 +0000833 HuffmanOutputCode(entry);
834 }
835 entry=TWTable+MagickMin((size_t) runlength,63);
836 HuffmanOutputCode(entry);
837 if (n != 0)
838 {
839 /*
840 Output black run.
841 */
842 for (runlength=0; ((*q != 0) && (n > 0)); n--)
843 {
844 q++;
845 runlength++;
846 }
847 if (runlength >= 64)
848 {
849 entry=MBTable+((runlength/64)-1);
850 if (runlength >= 1792)
851 entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
cristy8891f9c2010-06-04 23:32:17 +0000852 runlength-=(long) entry->count;
cristy3ed852e2009-09-05 21:47:34 +0000853 HuffmanOutputCode(entry);
854 }
855 entry=TBTable+MagickMin((size_t) runlength,63);
856 HuffmanOutputCode(entry);
857 }
858 }
859 /*
860 End of line.
861 */
862 for (k=0; k < 11; k++)
863 OutputBit(0);
864 OutputBit(1);
865 q=scanline;
866 if (GetPreviousImageInList(huffman_image) == (Image *) NULL)
867 {
868 proceed=SetImageProgress(huffman_image,LoadImageTag,y,
869 huffman_image->rows);
870 if (proceed == MagickFalse)
871 break;
872 }
873 }
874 /*
875 End of page.
876 */
877 for (i=0; i < 6; i++)
878 {
879 for (k=0; k < 11; k++)
880 OutputBit(0);
881 OutputBit(1);
882 }
883 /*
884 Flush bits.
885 */
886 if (((int) bit != 0x80) != 0)
887 {
888 if (LocaleCompare(image_info->magick,"FAX") == 0)
889 (void) WriteBlobByte(image,byte);
890 else
891 Ascii85Encode(image,byte);
892 }
893 if (LocaleCompare(image_info->magick,"FAX") != 0)
894 Ascii85Flush(image);
895 huffman_image=DestroyImage(huffman_image);
896 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
897 return(MagickTrue);
898}
899
cristy3ed852e2009-09-05 21:47:34 +0000900/*
901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902% %
903% %
904% %
905% L Z W E n c o d e I m a g e %
906% %
907% %
908% %
909%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910%
911% LZWEncodeImage() compresses an image via LZW-coding specific to Postscript
912% Level II or Portable Document Format.
913%
914% The format of the LZWEncodeImage method is:
915%
916% MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
cristy018f07f2011-09-04 21:15:19 +0000917% unsigned char *pixels,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000918%
919% A description of each parameter follows:
920%
921% o image: the image.
922%
923% o length: A value that specifies the number of pixels to compress.
924%
925% o pixels: the address of an unsigned array of characters containing the
926% pixels to compress.
927%
cristy018f07f2011-09-04 21:15:19 +0000928% o exception: return any errors or warnings in this structure.
929%
cristy3ed852e2009-09-05 21:47:34 +0000930*/
931MagickExport MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
cristy018f07f2011-09-04 21:15:19 +0000932 unsigned char *pixels,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000933{
934#define LZWClr 256UL /* Clear Table Marker */
935#define LZWEod 257UL /* End of Data marker */
936#define OutputCode(code) \
937{ \
938 accumulator+=code << (32-code_width-number_bits); \
939 number_bits+=code_width; \
940 while (number_bits >= 8) \
941 { \
942 (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24)); \
943 accumulator=accumulator << 8; \
944 number_bits-=8; \
945 } \
946}
947
948 typedef struct _TableType
949 {
cristybb503372010-05-27 20:51:26 +0000950 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000951 prefix,
952 suffix,
953 next;
954 } TableType;
955
cristybb503372010-05-27 20:51:26 +0000956 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000957 i;
958
cristybb503372010-05-27 20:51:26 +0000959 size_t
cristy3ed852e2009-09-05 21:47:34 +0000960 accumulator,
961 number_bits,
962 code_width,
963 last_code,
964 next_index;
965
cristy9d314ff2011-03-09 01:30:28 +0000966 ssize_t
967 index;
968
969 TableType
970 *table;
971
cristy3ed852e2009-09-05 21:47:34 +0000972 /*
973 Allocate string table.
974 */
975 assert(image != (Image *) NULL);
976 assert(image->signature == MagickSignature);
977 if (image->debug != MagickFalse)
978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
979 assert(pixels != (unsigned char *) NULL);
980 table=(TableType *) AcquireQuantumMemory(1UL << 12,sizeof(*table));
981 if (table == (TableType *) NULL)
982 return(MagickFalse);
983 /*
984 Initialize variables.
985 */
986 accumulator=0;
987 code_width=9;
988 number_bits=0;
989 last_code=0;
990 OutputCode(LZWClr);
991 for (index=0; index < 256; index++)
992 {
993 table[index].prefix=(-1);
994 table[index].suffix=(short) index;
995 table[index].next=(-1);
996 }
997 next_index=LZWEod+1;
998 code_width=9;
cristybb503372010-05-27 20:51:26 +0000999 last_code=(size_t) pixels[0];
1000 for (i=1; i < (ssize_t) length; i++)
cristy3ed852e2009-09-05 21:47:34 +00001001 {
1002 /*
1003 Find string.
1004 */
cristybb503372010-05-27 20:51:26 +00001005 index=(ssize_t) last_code;
cristy3ed852e2009-09-05 21:47:34 +00001006 while (index != -1)
cristybb503372010-05-27 20:51:26 +00001007 if ((table[index].prefix != (ssize_t) last_code) ||
1008 (table[index].suffix != (ssize_t) pixels[i]))
cristy3ed852e2009-09-05 21:47:34 +00001009 index=table[index].next;
1010 else
1011 {
cristybb503372010-05-27 20:51:26 +00001012 last_code=(size_t) index;
cristy3ed852e2009-09-05 21:47:34 +00001013 break;
1014 }
cristybb503372010-05-27 20:51:26 +00001015 if (last_code != (size_t) index)
cristy3ed852e2009-09-05 21:47:34 +00001016 {
1017 /*
1018 Add string.
1019 */
1020 OutputCode(last_code);
cristybb503372010-05-27 20:51:26 +00001021 table[next_index].prefix=(ssize_t) last_code;
cristy3ed852e2009-09-05 21:47:34 +00001022 table[next_index].suffix=(short) pixels[i];
1023 table[next_index].next=table[last_code].next;
cristybb503372010-05-27 20:51:26 +00001024 table[last_code].next=(ssize_t) next_index;
cristy3ed852e2009-09-05 21:47:34 +00001025 next_index++;
1026 /*
1027 Did we just move up to next bit width?
1028 */
1029 if ((next_index >> code_width) != 0)
1030 {
1031 code_width++;
1032 if (code_width > 12)
1033 {
1034 /*
1035 Did we overflow the max bit width?
1036 */
1037 code_width--;
1038 OutputCode(LZWClr);
1039 for (index=0; index < 256; index++)
1040 {
1041 table[index].prefix=(-1);
1042 table[index].suffix=index;
1043 table[index].next=(-1);
1044 }
1045 next_index=LZWEod+1;
1046 code_width=9;
1047 }
1048 }
cristybb503372010-05-27 20:51:26 +00001049 last_code=(size_t) pixels[i];
cristy3ed852e2009-09-05 21:47:34 +00001050 }
1051 }
1052 /*
1053 Flush tables.
1054 */
1055 OutputCode(last_code);
1056 OutputCode(LZWEod);
1057 if (number_bits != 0)
1058 (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24));
1059 table=(TableType *) RelinquishMagickMemory(table);
1060 return(MagickTrue);
1061}
1062
1063/*
1064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065% %
1066% %
1067% %
1068% P a c k b i t s E n c o d e I m a g e %
1069% %
1070% %
1071% %
1072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073%
1074% PackbitsEncodeImage() compresses an image via Macintosh Packbits encoding
1075% specific to Postscript Level II or Portable Document Format. To ensure
1076% portability, the binary Packbits bytes are encoded as ASCII Base-85.
1077%
1078% The format of the PackbitsEncodeImage method is:
1079%
1080% MagickBooleanType PackbitsEncodeImage(Image *image,const size_t length,
1081% unsigned char *pixels)
1082%
1083% A description of each parameter follows:
1084%
1085% o image: the image.
1086%
1087% o length: A value that specifies the number of pixels to compress.
1088%
1089% o pixels: the address of an unsigned array of characters containing the
1090% pixels to compress.
1091%
1092*/
1093MagickExport MagickBooleanType PackbitsEncodeImage(Image *image,
cristy018f07f2011-09-04 21:15:19 +00001094 const size_t length,unsigned char *pixels,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001095{
1096 int
1097 count;
1098
cristybb503372010-05-27 20:51:26 +00001099 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001100 i,
1101 j;
1102
1103 unsigned char
1104 *packbits;
1105
1106 /*
1107 Compress pixels with Packbits encoding.
1108 */
1109 assert(image != (Image *) NULL);
1110 assert(image->signature == MagickSignature);
1111 if (image->debug != MagickFalse)
1112 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1113 assert(pixels != (unsigned char *) NULL);
1114 packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
1115 if (packbits == (unsigned char *) NULL)
1116 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1117 image->filename);
cristybb503372010-05-27 20:51:26 +00001118 for (i=(ssize_t) length; i != 0; )
cristy3ed852e2009-09-05 21:47:34 +00001119 {
1120 switch (i)
1121 {
1122 case 1:
1123 {
1124 i--;
1125 (void) WriteBlobByte(image,(unsigned char) 0);
1126 (void) WriteBlobByte(image,*pixels);
1127 break;
1128 }
1129 case 2:
1130 {
1131 i-=2;
1132 (void) WriteBlobByte(image,(unsigned char) 1);
1133 (void) WriteBlobByte(image,*pixels);
1134 (void) WriteBlobByte(image,pixels[1]);
1135 break;
1136 }
1137 case 3:
1138 {
1139 i-=3;
1140 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1141 {
1142 (void) WriteBlobByte(image,(unsigned char) ((256-3)+1));
1143 (void) WriteBlobByte(image,*pixels);
1144 break;
1145 }
1146 (void) WriteBlobByte(image,(unsigned char) 2);
1147 (void) WriteBlobByte(image,*pixels);
1148 (void) WriteBlobByte(image,pixels[1]);
1149 (void) WriteBlobByte(image,pixels[2]);
1150 break;
1151 }
1152 default:
1153 {
1154 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1155 {
1156 /*
1157 Packed run.
1158 */
1159 count=3;
cristybb503372010-05-27 20:51:26 +00001160 while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
cristy3ed852e2009-09-05 21:47:34 +00001161 {
1162 count++;
1163 if (count >= 127)
1164 break;
1165 }
1166 i-=count;
1167 (void) WriteBlobByte(image,(unsigned char) ((256-count)+1));
1168 (void) WriteBlobByte(image,*pixels);
1169 pixels+=count;
1170 break;
1171 }
1172 /*
1173 Literal run.
1174 */
1175 count=0;
1176 while ((*(pixels+count) != *(pixels+count+1)) ||
1177 (*(pixels+count+1) != *(pixels+count+2)))
1178 {
1179 packbits[count+1]=pixels[count];
1180 count++;
cristybb503372010-05-27 20:51:26 +00001181 if (((ssize_t) count >= (i-3)) || (count >= 127))
cristy3ed852e2009-09-05 21:47:34 +00001182 break;
1183 }
1184 i-=count;
1185 *packbits=(unsigned char) (count-1);
cristybb503372010-05-27 20:51:26 +00001186 for (j=0; j <= (ssize_t) count; j++)
cristy3ed852e2009-09-05 21:47:34 +00001187 (void) WriteBlobByte(image,packbits[j]);
1188 pixels+=count;
1189 break;
1190 }
1191 }
1192 }
1193 (void) WriteBlobByte(image,(unsigned char) 128); /* EOD marker */
1194 packbits=(unsigned char *) RelinquishMagickMemory(packbits);
1195 return(MagickTrue);
1196}
1197
1198#if defined(MAGICKCORE_ZLIB_DELEGATE)
1199/*
1200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201% %
1202% %
1203% %
1204% Z L I B E n c o d e I m a g e %
1205% %
1206% %
1207% %
1208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209%
1210% ZLIBEncodeImage compresses an image via ZLIB-coding specific to
1211% Postscript Level II or Portable Document Format.
1212%
1213% The format of the ZLIBEncodeImage method is:
1214%
1215% MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
cristy018f07f2011-09-04 21:15:19 +00001216% unsigned char *pixels,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001217%
1218% A description of each parameter follows:
1219%
1220% o file: the address of a structure of type FILE. ZLIB encoded pixels
1221% are written to this file.
1222%
1223% o length: A value that specifies the number of pixels to compress.
1224%
1225% o pixels: the address of an unsigned array of characters containing the
1226% pixels to compress.
1227%
cristy018f07f2011-09-04 21:15:19 +00001228% o exception: return any errors or warnings in this structure.
1229%
cristy3ed852e2009-09-05 21:47:34 +00001230*/
1231
1232static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
1233 unsigned int size)
1234{
1235 (void) context;
1236 return((voidpf) AcquireQuantumMemory(items,size));
1237}
1238
1239static void RelinquishZIPMemory(voidpf context,voidpf memory)
1240{
1241 (void) context;
1242 memory=RelinquishMagickMemory(memory);
1243}
1244
1245MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
cristy018f07f2011-09-04 21:15:19 +00001246 unsigned char *pixels,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001247{
1248 int
1249 status;
1250
cristybb503372010-05-27 20:51:26 +00001251 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001252 i;
1253
1254 size_t
1255 compress_packets;
1256
1257 unsigned char
1258 *compress_pixels;
1259
1260 z_stream
1261 stream;
1262
1263 assert(image != (Image *) NULL);
1264 assert(image->signature == MagickSignature);
1265 if (image->debug != MagickFalse)
1266 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1267 compress_packets=(size_t) (1.001*length+12);
1268 compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_packets,
1269 sizeof(*compress_pixels));
1270 if (compress_pixels == (unsigned char *) NULL)
1271 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1272 image->filename);
1273 stream.next_in=pixels;
1274 stream.avail_in=(unsigned int) length;
1275 stream.next_out=compress_pixels;
1276 stream.avail_out=(unsigned int) compress_packets;
1277 stream.zalloc=AcquireZIPMemory;
1278 stream.zfree=RelinquishZIPMemory;
1279 stream.opaque=(voidpf) NULL;
1280 status=deflateInit(&stream,(int) (image->quality ==
1281 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
1282 if (status == Z_OK)
1283 {
1284 status=deflate(&stream,Z_FINISH);
1285 if (status == Z_STREAM_END)
1286 status=deflateEnd(&stream);
1287 else
1288 (void) deflateEnd(&stream);
1289 compress_packets=(size_t) stream.total_out;
1290 }
1291 if (status != Z_OK)
1292 ThrowBinaryException(CoderError,"UnableToZipCompressImage",image->filename)
1293 else
cristybb503372010-05-27 20:51:26 +00001294 for (i=0; i < (ssize_t) compress_packets; i++)
cristy3ed852e2009-09-05 21:47:34 +00001295 (void) WriteBlobByte(image,compress_pixels[i]);
1296 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1297 return(status == Z_OK ? MagickTrue : MagickFalse);
1298}
1299#else
1300MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,
cristy54519322012-02-21 13:32:22 +00001301 const size_t magick_unused(length),unsigned char *magick_unused(pixels),
1302 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001303{
1304 assert(image != (Image *) NULL);
1305 assert(image->signature == MagickSignature);
1306 if (image->debug != MagickFalse)
1307 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristy54519322012-02-21 13:32:22 +00001308 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
anthonye5b39652012-04-21 05:37:29 +00001309 "DelegateLibrarySupportNotBuiltIn","'%s' (ZIP)",image->filename);
cristy3ed852e2009-09-05 21:47:34 +00001310 return(MagickFalse);
1311}
1312#endif