MagickCore 7.1.2-31
Convert, Edit, Or Compose Bitmap Images
Loading...
Searching...
No Matches
compress.c
1/*
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% Cristy %
17% May 1993 %
18% %
19% %
20% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21% 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% https://imagemagick.org/license/ %
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*/
43#include "MagickCore/studio.h"
44#include "MagickCore/attribute.h"
45#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"
62#if defined(MAGICKCORE_ZLIB_DELEGATE)
63#include "zlib.h"
64#endif
65
66/*
67 Typedef declarations.
68*/
70{
71 ssize_t
72 offset,
73 line_break;
74
75 char
76 tuple[6];
77
78 unsigned char
79 buffer[10];
80};
81
82typedef struct HuffmanTable
83{
84 size_t
85 id,
86 code,
87 length,
88 count;
90
91/*
92 Huffman coding declarations.
93*/
94#define TWId 23L
95#define MWId 24L
96#define TBId 25L
97#define MBId 26L
98#define EXId 27L
99
100static const HuffmanTable
101 MBTable[]=
102 {
103 { MBId, 0x0f, 10, 64 }, { MBId, 0xc8, 12, 128 },
104 { MBId, 0xc9, 12, 192 }, { MBId, 0x5b, 12, 256 },
105 { MBId, 0x33, 12, 320 }, { MBId, 0x34, 12, 384 },
106 { MBId, 0x35, 12, 448 }, { MBId, 0x6c, 13, 512 },
107 { MBId, 0x6d, 13, 576 }, { MBId, 0x4a, 13, 640 },
108 { MBId, 0x4b, 13, 704 }, { MBId, 0x4c, 13, 768 },
109 { MBId, 0x4d, 13, 832 }, { MBId, 0x72, 13, 896 },
110 { MBId, 0x73, 13, 960 }, { MBId, 0x74, 13, 1024 },
111 { MBId, 0x75, 13, 1088 }, { MBId, 0x76, 13, 1152 },
112 { MBId, 0x77, 13, 1216 }, { MBId, 0x52, 13, 1280 },
113 { MBId, 0x53, 13, 1344 }, { MBId, 0x54, 13, 1408 },
114 { MBId, 0x55, 13, 1472 }, { MBId, 0x5a, 13, 1536 },
115 { MBId, 0x5b, 13, 1600 }, { MBId, 0x64, 13, 1664 },
116 { MBId, 0x65, 13, 1728 }, { MBId, 0x00, 0, 0 }
117 };
118
119static const HuffmanTable
120 EXTable[]=
121 {
122 { EXId, 0x08, 11, 1792 }, { EXId, 0x0c, 11, 1856 },
123 { EXId, 0x0d, 11, 1920 }, { EXId, 0x12, 12, 1984 },
124 { EXId, 0x13, 12, 2048 }, { EXId, 0x14, 12, 2112 },
125 { EXId, 0x15, 12, 2176 }, { EXId, 0x16, 12, 2240 },
126 { EXId, 0x17, 12, 2304 }, { EXId, 0x1c, 12, 2368 },
127 { EXId, 0x1d, 12, 2432 }, { EXId, 0x1e, 12, 2496 },
128 { EXId, 0x1f, 12, 2560 }, { EXId, 0x00, 0, 0 }
129 };
130
131static const HuffmanTable
132 MWTable[]=
133 {
134 { MWId, 0x1b, 5, 64 }, { MWId, 0x12, 5, 128 },
135 { MWId, 0x17, 6, 192 }, { MWId, 0x37, 7, 256 },
136 { MWId, 0x36, 8, 320 }, { MWId, 0x37, 8, 384 },
137 { MWId, 0x64, 8, 448 }, { MWId, 0x65, 8, 512 },
138 { MWId, 0x68, 8, 576 }, { MWId, 0x67, 8, 640 },
139 { MWId, 0xcc, 9, 704 }, { MWId, 0xcd, 9, 768 },
140 { MWId, 0xd2, 9, 832 }, { MWId, 0xd3, 9, 896 },
141 { MWId, 0xd4, 9, 960 }, { MWId, 0xd5, 9, 1024 },
142 { MWId, 0xd6, 9, 1088 }, { MWId, 0xd7, 9, 1152 },
143 { MWId, 0xd8, 9, 1216 }, { MWId, 0xd9, 9, 1280 },
144 { MWId, 0xda, 9, 1344 }, { MWId, 0xdb, 9, 1408 },
145 { MWId, 0x98, 9, 1472 }, { MWId, 0x99, 9, 1536 },
146 { MWId, 0x9a, 9, 1600 }, { MWId, 0x18, 6, 1664 },
147 { MWId, 0x9b, 9, 1728 }, { MWId, 0x00, 0, 0 }
148 };
149
150static const HuffmanTable
151 TBTable[]=
152 {
153 { TBId, 0x37, 10, 0 }, { TBId, 0x02, 3, 1 }, { TBId, 0x03, 2, 2 },
154 { TBId, 0x02, 2, 3 }, { TBId, 0x03, 3, 4 }, { TBId, 0x03, 4, 5 },
155 { TBId, 0x02, 4, 6 }, { TBId, 0x03, 5, 7 }, { TBId, 0x05, 6, 8 },
156 { TBId, 0x04, 6, 9 }, { TBId, 0x04, 7, 10 }, { TBId, 0x05, 7, 11 },
157 { TBId, 0x07, 7, 12 }, { TBId, 0x04, 8, 13 }, { TBId, 0x07, 8, 14 },
158 { TBId, 0x18, 9, 15 }, { TBId, 0x17, 10, 16 }, { TBId, 0x18, 10, 17 },
159 { TBId, 0x08, 10, 18 }, { TBId, 0x67, 11, 19 }, { TBId, 0x68, 11, 20 },
160 { TBId, 0x6c, 11, 21 }, { TBId, 0x37, 11, 22 }, { TBId, 0x28, 11, 23 },
161 { TBId, 0x17, 11, 24 }, { TBId, 0x18, 11, 25 }, { TBId, 0xca, 12, 26 },
162 { TBId, 0xcb, 12, 27 }, { TBId, 0xcc, 12, 28 }, { TBId, 0xcd, 12, 29 },
163 { TBId, 0x68, 12, 30 }, { TBId, 0x69, 12, 31 }, { TBId, 0x6a, 12, 32 },
164 { TBId, 0x6b, 12, 33 }, { TBId, 0xd2, 12, 34 }, { TBId, 0xd3, 12, 35 },
165 { TBId, 0xd4, 12, 36 }, { TBId, 0xd5, 12, 37 }, { TBId, 0xd6, 12, 38 },
166 { TBId, 0xd7, 12, 39 }, { TBId, 0x6c, 12, 40 }, { TBId, 0x6d, 12, 41 },
167 { TBId, 0xda, 12, 42 }, { TBId, 0xdb, 12, 43 }, { TBId, 0x54, 12, 44 },
168 { TBId, 0x55, 12, 45 }, { TBId, 0x56, 12, 46 }, { TBId, 0x57, 12, 47 },
169 { TBId, 0x64, 12, 48 }, { TBId, 0x65, 12, 49 }, { TBId, 0x52, 12, 50 },
170 { TBId, 0x53, 12, 51 }, { TBId, 0x24, 12, 52 }, { TBId, 0x37, 12, 53 },
171 { TBId, 0x38, 12, 54 }, { TBId, 0x27, 12, 55 }, { TBId, 0x28, 12, 56 },
172 { TBId, 0x58, 12, 57 }, { TBId, 0x59, 12, 58 }, { TBId, 0x2b, 12, 59 },
173 { TBId, 0x2c, 12, 60 }, { TBId, 0x5a, 12, 61 }, { TBId, 0x66, 12, 62 },
174 { TBId, 0x67, 12, 63 }, { TBId, 0x00, 0, 0 }
175 };
176
177static const HuffmanTable
178 TWTable[]=
179 {
180 { TWId, 0x35, 8, 0 }, { TWId, 0x07, 6, 1 }, { TWId, 0x07, 4, 2 },
181 { TWId, 0x08, 4, 3 }, { TWId, 0x0b, 4, 4 }, { TWId, 0x0c, 4, 5 },
182 { TWId, 0x0e, 4, 6 }, { TWId, 0x0f, 4, 7 }, { TWId, 0x13, 5, 8 },
183 { TWId, 0x14, 5, 9 }, { TWId, 0x07, 5, 10 }, { TWId, 0x08, 5, 11 },
184 { TWId, 0x08, 6, 12 }, { TWId, 0x03, 6, 13 }, { TWId, 0x34, 6, 14 },
185 { TWId, 0x35, 6, 15 }, { TWId, 0x2a, 6, 16 }, { TWId, 0x2b, 6, 17 },
186 { TWId, 0x27, 7, 18 }, { TWId, 0x0c, 7, 19 }, { TWId, 0x08, 7, 20 },
187 { TWId, 0x17, 7, 21 }, { TWId, 0x03, 7, 22 }, { TWId, 0x04, 7, 23 },
188 { TWId, 0x28, 7, 24 }, { TWId, 0x2b, 7, 25 }, { TWId, 0x13, 7, 26 },
189 { TWId, 0x24, 7, 27 }, { TWId, 0x18, 7, 28 }, { TWId, 0x02, 8, 29 },
190 { TWId, 0x03, 8, 30 }, { TWId, 0x1a, 8, 31 }, { TWId, 0x1b, 8, 32 },
191 { TWId, 0x12, 8, 33 }, { TWId, 0x13, 8, 34 }, { TWId, 0x14, 8, 35 },
192 { TWId, 0x15, 8, 36 }, { TWId, 0x16, 8, 37 }, { TWId, 0x17, 8, 38 },
193 { TWId, 0x28, 8, 39 }, { TWId, 0x29, 8, 40 }, { TWId, 0x2a, 8, 41 },
194 { TWId, 0x2b, 8, 42 }, { TWId, 0x2c, 8, 43 }, { TWId, 0x2d, 8, 44 },
195 { TWId, 0x04, 8, 45 }, { TWId, 0x05, 8, 46 }, { TWId, 0x0a, 8, 47 },
196 { TWId, 0x0b, 8, 48 }, { TWId, 0x52, 8, 49 }, { TWId, 0x53, 8, 50 },
197 { TWId, 0x54, 8, 51 }, { TWId, 0x55, 8, 52 }, { TWId, 0x24, 8, 53 },
198 { TWId, 0x25, 8, 54 }, { TWId, 0x58, 8, 55 }, { TWId, 0x59, 8, 56 },
199 { TWId, 0x5a, 8, 57 }, { TWId, 0x5b, 8, 58 }, { TWId, 0x4a, 8, 59 },
200 { TWId, 0x4b, 8, 60 }, { TWId, 0x32, 8, 61 }, { TWId, 0x33, 8, 62 },
201 { TWId, 0x34, 8, 63 }, { TWId, 0x00, 0, 0 }
202 };
203
204/*
205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206% %
207% %
208% %
209% A S C I I 8 5 E n c o d e %
210% %
211% %
212% %
213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214%
215% ASCII85Encode() encodes data in ASCII base-85 format. ASCII base-85
216% encoding produces five ASCII printing characters from every four bytes of
217% binary data.
218%
219% The format of the ASCII85Encode method is:
220%
221% void Ascii85Encode(Image *image,const size_t code)
222%
223% A description of each parameter follows:
224%
225% o code: a binary unsigned char to encode to ASCII 85.
226%
227% o file: write the encoded ASCII character to this file.
228%
229%
230*/
231static inline void Ascii85Tuple(Ascii85Info *ascii85_info,
232 const unsigned char *magick_restrict data)
233{
234#define MaxLineExtent 36L
235
236 size_t
237 code,
238 i,
239 quantum,
240 x;
241
242 code=((((size_t) data[0] << 8) | (size_t) data[1]) << 16) |
243 ((size_t) data[2] << 8) | (size_t) data[3];
244 if (code == 0L)
245 {
246 ascii85_info->tuple[0]='z';
247 ascii85_info->tuple[1]='\0';
248 return;
249 }
250 quantum=85UL*85UL*85UL*85UL;
251 for (i=0; i < 4; i++)
252 {
253 x=(code/quantum);
254 code-=quantum*x;
255 ascii85_info->tuple[i]=(char) (x+(int) '!');
256 quantum/=85L;
257 }
258 ascii85_info->tuple[4]=(char) ((code % 85L)+(int) '!');
259 ascii85_info->tuple[5]='\0';
260}
261
262MagickExport void Ascii85Initialize(Image *image)
263{
264 /*
265 Allocate image structure.
266 */
267 if (image->ascii85 == (Ascii85Info *) NULL)
268 image->ascii85=(Ascii85Info *) AcquireCriticalMemory(
269 sizeof(*image->ascii85));
270 (void) memset(image->ascii85,0,sizeof(*image->ascii85));
271 image->ascii85->line_break=(ssize_t) (MaxLineExtent << 1);
272 image->ascii85->offset=0;
273}
274
275MagickExport void Ascii85Flush(Image *image)
276{
277 assert(image != (Image *) NULL);
278 assert(image->signature == MagickCoreSignature);
279 assert(image->ascii85 != (Ascii85Info *) NULL);
280 if (IsEventLogging() != MagickFalse)
281 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
282 if (image->ascii85->offset > 0)
283 {
284 image->ascii85->buffer[image->ascii85->offset]='\0';
285 image->ascii85->buffer[image->ascii85->offset+1]='\0';
286 image->ascii85->buffer[image->ascii85->offset+2]='\0';
287 Ascii85Tuple(image->ascii85,image->ascii85->buffer);
288 (void) WriteBlob(image,(size_t) image->ascii85->offset+1,
289 (const unsigned char *) (*image->ascii85->tuple == 'z' ? "!!!!" :
290 image->ascii85->tuple));
291 }
292 (void) WriteBlobByte(image,'~');
293 (void) WriteBlobByte(image,'>');
294 (void) WriteBlobByte(image,'\n');
295}
296
297MagickExport void Ascii85Encode(Image *image,const unsigned char code)
298{
299 char
300 *q;
301
302 unsigned char
303 *p;
304
305 ssize_t
306 n;
307
308 assert(image != (Image *) NULL);
309 assert(image->signature == MagickCoreSignature);
310 assert(image->ascii85 != (Ascii85Info *) NULL);
311 image->ascii85->buffer[image->ascii85->offset]=code;
312 image->ascii85->offset++;
313 if (image->ascii85->offset < 4)
314 return;
315 p=image->ascii85->buffer;
316 for (n=image->ascii85->offset; n >= 4; n-=4)
317 {
318 Ascii85Tuple(image->ascii85,p);
319 for (q=image->ascii85->tuple; *q != '\0'; q++)
320 {
321 image->ascii85->line_break--;
322 if ((image->ascii85->line_break < 0) && (*q != '%'))
323 {
324 (void) WriteBlobByte(image,'\n');
325 image->ascii85->line_break=2*MaxLineExtent;
326 }
327 (void) WriteBlobByte(image,(unsigned char) *q);
328 }
329 p+=(ptrdiff_t) 8;
330 }
331 image->ascii85->offset=n;
332 p-=(ptrdiff_t)4;
333 for (n=0; n < 4; n++)
334 image->ascii85->buffer[n]=(*p++);
335}
336
337/*
338%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339% %
340% %
341% %
342% H u f f m a n D e c o d e I m a g e %
343% %
344% %
345% %
346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
347%
348% HuffmanDecodeImage() uncompresses an image via Huffman-coding.
349%
350% The format of the HuffmanDecodeImage method is:
351%
352% MagickBooleanType HuffmanDecodeImage(Image *image,
353% ExceptionInfo *exception)
354%
355% A description of each parameter follows:
356%
357% o image: the image.
358%
359% o exception: return any errors or warnings in this structure.
360%
361*/
362MagickExport MagickBooleanType HuffmanDecodeImage(Image *image,
363 ExceptionInfo *exception)
364{
365#define HashSize 1021L
366#define MBHashA 293L
367#define MBHashB 2695L
368#define MWHashA 3510L
369#define MWHashB 1178L
370
371#define InitializeHashTable(hash,table,a,b) \
372{ \
373 entry=table; \
374 while (entry->code != 0) \
375 { \
376 hash[((entry->length+a)*(entry->code+b)) % HashSize]=(HuffmanTable *) entry; \
377 entry++; \
378 } \
379}
380
381#define InputBit(bit) \
382{ \
383 if ((mask & 0xff) == 0) \
384 { \
385 byte=ReadBlobByte(image); \
386 if (byte == EOF) \
387 break; \
388 mask=0x80; \
389 } \
390 runlength++; \
391 bit=(size_t) ((byte & mask) != 0 ? 0x01 : 0x00); \
392 mask>>=1; \
393 if (bit != 0) \
394 runlength=0; \
395}
396
397 CacheView
398 *image_view;
399
400 const HuffmanTable
401 *entry;
402
404 **mb_hash,
405 **mw_hash;
406
407 int
408 byte,
409 mask;
410
411 MagickBooleanType
412 proceed;
413
414 Quantum
415 index;
416
417 size_t
418 bit,
419 code,
420 length,
421 null_lines,
422 runlength;
423
424 ssize_t
425 count,
426 i,
427 y;
428
429 unsigned char
430 *p,
431 *scanline;
432
433 unsigned int
434 bail,
435 color;
436
437 /*
438 Allocate buffers.
439 */
440 assert(image != (Image *) NULL);
441 assert(image->signature == MagickCoreSignature);
442 if (IsEventLogging() != MagickFalse)
443 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
444 if (image->blob == (BlobInfo *) NULL)
445 ThrowBinaryException(BlobError,"UnableToOpenBlob",image->filename);
446 mb_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mb_hash));
447 mw_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mw_hash));
448 scanline=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
449 sizeof(*scanline));
450 if ((mb_hash == (HuffmanTable **) NULL) ||
451 (mw_hash == (HuffmanTable **) NULL) ||
452 (scanline == (unsigned char *) NULL))
453 {
454 if (mb_hash != (HuffmanTable **) NULL)
455 mb_hash=(HuffmanTable **) RelinquishMagickMemory(mb_hash);
456 if (mw_hash != (HuffmanTable **) NULL)
457 mw_hash=(HuffmanTable **) RelinquishMagickMemory(mw_hash);
458 if (scanline != (unsigned char *) NULL)
459 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
460 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
461 image->filename);
462 }
463 /*
464 Initialize Huffman tables.
465 */
466 for (i=0; i < HashSize; i++)
467 {
468 mb_hash[i]=(HuffmanTable *) NULL;
469 mw_hash[i]=(HuffmanTable *) NULL;
470 }
471 InitializeHashTable(mw_hash,TWTable,MWHashA,MWHashB);
472 InitializeHashTable(mw_hash,MWTable,MWHashA,MWHashB);
473 InitializeHashTable(mw_hash,EXTable,MWHashA,MWHashB);
474 InitializeHashTable(mb_hash,TBTable,MBHashA,MBHashB);
475 InitializeHashTable(mb_hash,MBTable,MBHashA,MBHashB);
476 InitializeHashTable(mb_hash,EXTable,MBHashA,MBHashB);
477 /*
478 Uncompress 1D Huffman to runlength encoded pixels.
479 */
480 byte=0;
481 mask=0;
482 null_lines=0;
483 runlength=0;
484 while (runlength < 11)
485 InputBit(bit);
486 do { InputBit(bit); } while ((int) bit == 0);
487 image->resolution.x=204.0;
488 image->resolution.y=196.0;
489 image->units=PixelsPerInchResolution;
490 image_view=AcquireAuthenticCacheView(image,exception);
491 for (y=0; ((y < (ssize_t) image->rows) && (null_lines < 3)); )
492 {
493 Quantum
494 *magick_restrict q;
495
496 ssize_t
497 x;
498
499 /*
500 Initialize scanline to white.
501 */
502 memset(scanline,0,sizeof(*scanline)*image->columns);
503 /*
504 Decode Huffman encoded scanline.
505 */
506 color=MagickTrue;
507 code=0;
508 count=0;
509 length=0;
510 runlength=0;
511 x=0;
512 for ( ; ; )
513 {
514 if (byte == EOF)
515 break;
516 if (x >= (ssize_t) image->columns)
517 {
518 while (runlength < 11)
519 InputBit(bit);
520 do { InputBit(bit); } while ((int) bit == 0);
521 break;
522 }
523 bail=MagickFalse;
524 do
525 {
526 if (runlength < 11)
527 InputBit(bit)
528 else
529 {
530 InputBit(bit);
531 if ((int) bit != 0)
532 {
533 null_lines++;
534 if (x != 0)
535 null_lines=0;
536 bail=MagickTrue;
537 break;
538 }
539 }
540 code=(code << 1)+(size_t) bit;
541 length++;
542 } while (code == 0);
543 if (bail != MagickFalse)
544 break;
545 if (length > 13)
546 {
547 while (runlength < 11)
548 InputBit(bit);
549 do { InputBit(bit); } while ((int) bit == 0);
550 break;
551 }
552 if (color != MagickFalse)
553 {
554 if (length < 4)
555 continue;
556 entry=mw_hash[((length+MWHashA)*(code+MWHashB)) % HashSize];
557 }
558 else
559 {
560 if (length < 2)
561 continue;
562 entry=mb_hash[((length+MBHashA)*(code+MBHashB)) % HashSize];
563 }
564 if (entry == (const HuffmanTable *) NULL)
565 continue;
566 if ((entry->length != length) || (entry->code != code))
567 continue;
568 switch (entry->id)
569 {
570 case TWId:
571 case TBId:
572 {
573 count+=(ssize_t) entry->count;
574 if ((x+count) > (ssize_t) image->columns)
575 count=(ssize_t) image->columns-x;
576 if (count > 0)
577 {
578 if (color != MagickFalse)
579 {
580 x+=count;
581 count=0;
582 }
583 else
584 for ( ; count > 0; count--)
585 if ((x >= 0) && (x < (ssize_t) image->columns))
586 scanline[x++]=(unsigned char) 1;
587 }
588 color=(unsigned int)
589 ((color == MagickFalse) ? MagickTrue : MagickFalse);
590 break;
591 }
592 case MWId:
593 case MBId:
594 case EXId:
595 {
596 count+=(ssize_t) entry->count;
597 break;
598 }
599 default:
600 break;
601 }
602 code=0;
603 length=0;
604 }
605 /*
606 Transfer scanline to image pixels.
607 */
608 p=scanline;
609 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
610 if (q == (Quantum *) NULL)
611 break;
612 for (x=0; x < (ssize_t) image->columns; x++)
613 {
614 index=(Quantum) (*p++);
615 SetPixelIndex(image,index,q);
616 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
617 q+=(ptrdiff_t) GetPixelChannels(image);
618 }
619 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
620 break;
621 proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
622 image->rows);
623 if (proceed == MagickFalse)
624 break;
625 y++;
626 }
627 image_view=DestroyCacheView(image_view);
628 image->rows=(size_t) MagickMax((size_t) y-3,1);
629 image->compression=FaxCompression;
630 /*
631 Free decoder memory.
632 */
633 mw_hash=(HuffmanTable **) RelinquishMagickMemory(mw_hash);
634 mb_hash=(HuffmanTable **) RelinquishMagickMemory(mb_hash);
635 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
636 return(MagickTrue);
637}
638
639/*
640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641% %
642% %
643% %
644% H u f f m a n E n c o d e I m a g e %
645% %
646% %
647% %
648%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649%
650% HuffmanEncodeImage() compresses an image via Huffman-coding.
651%
652% The format of the HuffmanEncodeImage method is:
653%
654% MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
655% Image *image,Image *inject_image,ExceptionInfo *exception)
656%
657% A description of each parameter follows:
658%
659% o image_info: the image info..
660%
661% o image: the image.
662%
663% o inject_image: inject into the image stream.
664%
665% o exception: return any errors or warnings in this structure.
666%
667*/
668MagickExport MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
669 Image *image,Image *inject_image,ExceptionInfo *exception)
670{
671#define HuffmanOutputCode(entry) \
672{ \
673 mask=one << (entry->length-1); \
674 while (mask != 0) \
675 { \
676 OutputBit(((entry->code & mask) != 0 ? 1 : 0)); \
677 mask>>=1; \
678 } \
679}
680
681#define OutputBit(count) \
682{ \
683DisableMSCWarning(4127) \
684 if (count > 0) \
685 byte=byte | bit; \
686RestoreMSCWarning \
687 bit>>=1; \
688 if ((int) (bit & 0xff) == 0) \
689 { \
690 if (LocaleCompare(image_info->magick,"FAX") == 0) \
691 (void) WriteBlobByte(image,(unsigned char) byte); \
692 else \
693 Ascii85Encode(image,byte); \
694 byte='\0'; \
695 bit=(unsigned char) 0x80; \
696 } \
697}
698
699 const HuffmanTable
700 *entry;
701
702 int
703 k,
704 runlength;
705
706 Image
707 *huffman_image;
708
709 MagickBooleanType
710 proceed;
711
712 ssize_t
713 i,
714 x;
715
716 const Quantum
717 *p;
718
719 unsigned char
720 *q;
721
722 size_t
723 mask,
724 one,
725 width;
726
727 ssize_t
728 n,
729 y;
730
731 unsigned char
732 byte,
733 bit,
734 *scanline;
735
736 /*
737 Allocate scanline buffer.
738 */
739 assert(image_info != (ImageInfo *) NULL);
740 assert(image_info->signature == MagickCoreSignature);
741 assert(image != (Image *) NULL);
742 assert(image->signature == MagickCoreSignature);
743 if (IsEventLogging() != MagickFalse)
744 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
745 assert(inject_image != (Image *) NULL);
746 assert(inject_image->signature == MagickCoreSignature);
747 one=1;
748 width=inject_image->columns;
749 if (LocaleCompare(image_info->magick,"FAX") == 0)
750 width=(size_t) MagickMax(inject_image->columns,1728);
751 scanline=(unsigned char *) AcquireQuantumMemory((size_t) width+1UL,
752 sizeof(*scanline));
753 if (scanline == (unsigned char *) NULL)
754 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
755 inject_image->filename);
756 (void) memset(scanline,0,width*sizeof(*scanline));
757 huffman_image=CloneImage(inject_image,0,0,MagickTrue,exception);
758 if (huffman_image == (Image *) NULL)
759 {
760 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
761 return(MagickFalse);
762 }
763 (void) SetImageType(huffman_image,BilevelType,exception);
764 byte='\0';
765 bit=(unsigned char) 0x80;
766 if (LocaleCompare(image_info->magick,"FAX") != 0)
767 Ascii85Initialize(image);
768 else
769 {
770 /*
771 End of line.
772 */
773 for (k=0; k < 11; k++)
774 OutputBit(0);
775 OutputBit(1);
776 }
777 /*
778 Compress to 1D Huffman pixels.
779 */
780 q=scanline;
781 for (y=0; y < (ssize_t) huffman_image->rows; y++)
782 {
783 p=GetVirtualPixels(huffman_image,0,y,huffman_image->columns,1,exception);
784 if (p == (const Quantum *) NULL)
785 break;
786 for (x=0; x < (ssize_t) huffman_image->columns; x++)
787 {
788 *q++=(unsigned char) (GetPixelIntensity(huffman_image,p) >=
789 ((double) QuantumRange/2.0) ? 0 : 1);
790 p+=(ptrdiff_t) GetPixelChannels(huffman_image);
791 }
792 /*
793 Huffman encode scanline.
794 */
795 q=scanline;
796 for (n=(ssize_t) width; n > 0; )
797 {
798 /*
799 Output white run.
800 */
801 for (runlength=0; ((n > 0) && (*q == 0)); n--)
802 {
803 q++;
804 runlength++;
805 }
806 if (runlength >= 64)
807 {
808 if (runlength < 1792)
809 entry=MWTable+((runlength/64)-1);
810 else
811 entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
812 runlength-=(long) entry->count;
813 HuffmanOutputCode(entry);
814 }
815 entry=TWTable+MagickMin((size_t) runlength,63);
816 HuffmanOutputCode(entry);
817 if (n != 0)
818 {
819 /*
820 Output black run.
821 */
822 for (runlength=0; ((*q != 0) && (n > 0)); n--)
823 {
824 q++;
825 runlength++;
826 }
827 if (runlength >= 64)
828 {
829 entry=MBTable+((runlength/64)-1);
830 if (runlength >= 1792)
831 entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
832 runlength-=(long) entry->count;
833 HuffmanOutputCode(entry);
834 }
835 entry=TBTable+MagickMin((size_t) runlength,63);
836 HuffmanOutputCode(entry);
837 }
838 }
839 /*
840 End of line.
841 */
842 for (k=0; k < 11; k++)
843 OutputBit(0);
844 OutputBit(1);
845 q=scanline;
846 if (GetPreviousImageInList(huffman_image) == (Image *) NULL)
847 {
848 proceed=SetImageProgress(huffman_image,LoadImageTag,
849 (MagickOffsetType) y,huffman_image->rows);
850 if (proceed == MagickFalse)
851 break;
852 }
853 }
854 /*
855 End of page.
856 */
857 for (i=0; i < 6; i++)
858 {
859 for (k=0; k < 11; k++)
860 OutputBit(0);
861 OutputBit(1);
862 }
863 /*
864 Flush bits.
865 */
866 if (((int) bit != 0x80) != 0)
867 {
868 if (LocaleCompare(image_info->magick,"FAX") == 0)
869 (void) WriteBlobByte(image,byte);
870 else
871 Ascii85Encode(image,byte);
872 }
873 if (LocaleCompare(image_info->magick,"FAX") != 0)
874 Ascii85Flush(image);
875 huffman_image=DestroyImage(huffman_image);
876 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
877 return(MagickTrue);
878}
879
880/*
881%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
882% %
883% %
884% %
885% L Z W E n c o d e I m a g e %
886% %
887% %
888% %
889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890%
891% LZWEncodeImage() compresses an image via LZW-coding specific to Postscript
892% Level II or Portable Document Format.
893%
894% The format of the LZWEncodeImage method is:
895%
896% MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
897% unsigned char *magick_restrict pixels,ExceptionInfo *exception)
898%
899% A description of each parameter follows:
900%
901% o image: the image.
902%
903% o length: A value that specifies the number of pixels to compress.
904%
905% o pixels: the address of an unsigned array of characters containing the
906% pixels to compress.
907%
908% o exception: return any errors or warnings in this structure.
909%
910*/
911MagickExport MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
912 unsigned char *magick_restrict pixels,ExceptionInfo *exception)
913{
914#define LZWClr 256UL /* Clear Table Marker */
915#define LZWEod 257UL /* End of Data marker */
916#define OutputCode(code) \
917{ \
918 accumulator+=code << (32-code_width-number_bits); \
919 number_bits+=code_width; \
920 while (number_bits >= 8) \
921 { \
922 (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24)); \
923 accumulator=accumulator << 8; \
924 number_bits-=8; \
925 } \
926}
927
928 typedef struct _TableType
929 {
930 ssize_t
931 prefix,
932 suffix,
933 next;
934 } TableType;
935
936 ssize_t
937 i;
938
939 size_t
940 accumulator,
941 number_bits,
942 code_width,
943 last_code,
944 next_index;
945
946 ssize_t
947 index;
948
949 TableType
950 *table;
951
952 /*
953 Allocate string table.
954 */
955 assert(image != (Image *) NULL);
956 assert(image->signature == MagickCoreSignature);
957 assert(pixels != (unsigned char *) NULL);
958 assert(exception != (ExceptionInfo *) NULL);
959 assert(exception->signature == MagickCoreSignature);
960 if (IsEventLogging() != MagickFalse)
961 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
962 table=(TableType *) AcquireQuantumMemory(1UL << 12,sizeof(*table));
963 if (table == (TableType *) NULL)
964 ThrowBinaryException(ResourceLimitWarning,"MemoryAllocationFailed",
965 image->filename);
966 /*
967 Initialize variables.
968 */
969 accumulator=0;
970 code_width=9;
971 number_bits=0;
972 last_code=0;
973 OutputCode(LZWClr);
974 for (index=0; index < 256; index++)
975 {
976 table[index].prefix=(-1);
977 table[index].suffix=(ssize_t) index;
978 table[index].next=(-1);
979 }
980 next_index=LZWEod+1;
981 code_width=9;
982 last_code=(size_t) pixels[0];
983 for (i=1; i < (ssize_t) length; i++)
984 {
985 /*
986 Find string.
987 */
988 index=(ssize_t) last_code;
989 while (index != -1)
990 if ((table[index].prefix != (ssize_t) last_code) ||
991 (table[index].suffix != (ssize_t) pixels[i]))
992 index=table[index].next;
993 else
994 {
995 last_code=(size_t) index;
996 break;
997 }
998 if (last_code != (size_t) index)
999 {
1000 /*
1001 Add string.
1002 */
1003 OutputCode(last_code);
1004 table[next_index].prefix=(ssize_t) last_code;
1005 table[next_index].suffix=(ssize_t) pixels[i];
1006 table[next_index].next=table[last_code].next;
1007 table[last_code].next=(ssize_t) next_index;
1008 next_index++;
1009 /*
1010 Did we just move up to next bit width?
1011 */
1012 if ((next_index >> code_width) != 0)
1013 {
1014 code_width++;
1015 if (code_width > 12)
1016 {
1017 /*
1018 Did we overflow the max bit width?
1019 */
1020 code_width--;
1021 OutputCode(LZWClr);
1022 for (index=0; index < 256; index++)
1023 {
1024 table[index].prefix=(-1);
1025 table[index].suffix=index;
1026 table[index].next=(-1);
1027 }
1028 next_index=LZWEod+1;
1029 code_width=9;
1030 }
1031 }
1032 last_code=(size_t) pixels[i];
1033 }
1034 }
1035 /*
1036 Flush tables.
1037 */
1038 OutputCode(last_code);
1039 OutputCode(LZWEod);
1040 if (number_bits != 0)
1041 (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24));
1042 table=(TableType *) RelinquishMagickMemory(table);
1043 return(MagickTrue);
1044}
1045
1046/*
1047%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1048% %
1049% %
1050% %
1051% P a c k b i t s E n c o d e I m a g e %
1052% %
1053% %
1054% %
1055%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1056%
1057% PackbitsEncodeImage() compresses an image via Macintosh Packbits encoding
1058% specific to Postscript Level II or Portable Document Format. To ensure
1059% portability, the binary Packbits bytes are encoded as ASCII Base-85.
1060%
1061% The format of the PackbitsEncodeImage method is:
1062%
1063% MagickBooleanType PackbitsEncodeImage(Image *image,const size_t length,
1064% unsigned char *magick_restrict pixels)
1065%
1066% A description of each parameter follows:
1067%
1068% o image: the image.
1069%
1070% o length: A value that specifies the number of pixels to compress.
1071%
1072% o pixels: the address of an unsigned array of characters containing the
1073% pixels to compress.
1074%
1075*/
1076MagickExport MagickBooleanType PackbitsEncodeImage(Image *image,
1077 const size_t length,unsigned char *magick_restrict pixels,
1078 ExceptionInfo *exception)
1079{
1080 int
1081 count;
1082
1083 ssize_t
1084 i,
1085 j;
1086
1087 unsigned char
1088 *packbits;
1089
1090 /*
1091 Compress pixels with Packbits encoding.
1092 */
1093 assert(image != (Image *) NULL);
1094 assert(image->signature == MagickCoreSignature);
1095 assert(pixels != (unsigned char *) NULL);
1096 if (IsEventLogging() != MagickFalse)
1097 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1098 packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
1099 if (packbits == (unsigned char *) NULL)
1100 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1101 image->filename);
1102 for (i=(ssize_t) length; i != 0; )
1103 {
1104 switch (i)
1105 {
1106 case 1:
1107 {
1108 i--;
1109 (void) WriteBlobByte(image,(unsigned char) 0);
1110 (void) WriteBlobByte(image,*pixels);
1111 break;
1112 }
1113 case 2:
1114 {
1115 i-=2;
1116 (void) WriteBlobByte(image,(unsigned char) 1);
1117 (void) WriteBlobByte(image,*pixels);
1118 (void) WriteBlobByte(image,pixels[1]);
1119 break;
1120 }
1121 case 3:
1122 {
1123 i-=3;
1124 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1125 {
1126 (void) WriteBlobByte(image,(unsigned char) ((256-3)+1));
1127 (void) WriteBlobByte(image,*pixels);
1128 break;
1129 }
1130 (void) WriteBlobByte(image,(unsigned char) 2);
1131 (void) WriteBlobByte(image,*pixels);
1132 (void) WriteBlobByte(image,pixels[1]);
1133 (void) WriteBlobByte(image,pixels[2]);
1134 break;
1135 }
1136 default:
1137 {
1138 if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1139 {
1140 /*
1141 Packed run.
1142 */
1143 count=3;
1144 while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
1145 {
1146 count++;
1147 if (count >= 127)
1148 break;
1149 }
1150 i-=count;
1151 (void) WriteBlobByte(image,(unsigned char) ((256-count)+1));
1152 (void) WriteBlobByte(image,*pixels);
1153 pixels+=count;
1154 break;
1155 }
1156 /*
1157 Literal run.
1158 */
1159 count=0;
1160 while ((*(pixels+count) != *(pixels+count+1)) ||
1161 (*(pixels+count+1) != *(pixels+count+2)))
1162 {
1163 packbits[count+1]=pixels[count];
1164 count++;
1165 if (((ssize_t) count >= (i-3)) || (count >= 127))
1166 break;
1167 }
1168 i-=count;
1169 *packbits=(unsigned char) (count-1);
1170 for (j=0; j <= (ssize_t) count; j++)
1171 (void) WriteBlobByte(image,packbits[j]);
1172 pixels+=count;
1173 break;
1174 }
1175 }
1176 }
1177 (void) WriteBlobByte(image,(unsigned char) 128); /* EOD marker */
1178 packbits=(unsigned char *) RelinquishMagickMemory(packbits);
1179 return(MagickTrue);
1180}
1181
1182#if defined(MAGICKCORE_ZLIB_DELEGATE)
1183/*
1184%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185% %
1186% %
1187% %
1188% Z L I B E n c o d e I m a g e %
1189% %
1190% %
1191% %
1192%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193%
1194% ZLIBEncodeImage compresses an image via ZLIB-coding specific to
1195% Postscript Level II or Portable Document Format.
1196%
1197% The format of the ZLIBEncodeImage method is:
1198%
1199% MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
1200% unsigned char *magick_restrict pixels,ExceptionInfo *exception)
1201%
1202% A description of each parameter follows:
1203%
1204% o file: the address of a structure of type FILE. ZLIB encoded pixels
1205% are written to this file.
1206%
1207% o length: A value that specifies the number of pixels to compress.
1208%
1209% o pixels: the address of an unsigned array of characters containing the
1210% pixels to compress.
1211%
1212% o exception: return any errors or warnings in this structure.
1213%
1214*/
1215
1216static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
1217 unsigned int size)
1218{
1219 (void) context;
1220 return((voidpf) AcquireQuantumMemory(items,size));
1221}
1222
1223static void RelinquishZIPMemory(voidpf context,voidpf memory)
1224{
1225 (void) context;
1226 memory=RelinquishMagickMemory(memory);
1227}
1228
1229MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
1230 unsigned char *magick_restrict pixels,ExceptionInfo *exception)
1231{
1232 int
1233 status;
1234
1235 ssize_t
1236 i;
1237
1238 size_t
1239 compress_packets;
1240
1241 unsigned char
1242 *compress_pixels;
1243
1244 z_stream
1245 stream;
1246
1247 assert(image != (Image *) NULL);
1248 assert(image->signature == MagickCoreSignature);
1249 if (IsEventLogging() != MagickFalse)
1250 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1251 compress_packets=(size_t) (1.001*length+12);
1252 compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_packets,
1253 sizeof(*compress_pixels));
1254 if (compress_pixels == (unsigned char *) NULL)
1255 ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1256 image->filename);
1257 (void) memset(&stream,0,sizeof(stream));
1258 stream.next_in=pixels;
1259 stream.avail_in=(unsigned int) length;
1260 stream.next_out=compress_pixels;
1261 stream.avail_out=(unsigned int) compress_packets;
1262 stream.zalloc=AcquireZIPMemory;
1263 stream.zfree=RelinquishZIPMemory;
1264 stream.opaque=(voidpf) NULL;
1265 status=deflateInit(&stream,(int) (image->quality ==
1266 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
1267 if (status == Z_OK)
1268 {
1269 status=deflate(&stream,Z_FINISH);
1270 if (status == Z_STREAM_END)
1271 status=deflateEnd(&stream);
1272 else
1273 (void) deflateEnd(&stream);
1274 compress_packets=(size_t) stream.total_out;
1275 }
1276 if (status != Z_OK)
1277 ThrowBinaryException(CoderError,"UnableToZipCompressImage",image->filename)
1278 for (i=0; i < (ssize_t) compress_packets; i++)
1279 (void) WriteBlobByte(image,compress_pixels[i]);
1280 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1281 return(MagickTrue);
1282}
1283#else
1284MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,
1285 const size_t magick_unused(length),unsigned char *magick_unused(pixels),
1286 ExceptionInfo *exception)
1287{
1288 magick_unreferenced(length);
1289 magick_unreferenced(pixels);
1290 assert(image != (Image *) NULL);
1291 assert(image->signature == MagickCoreSignature);
1292 if (IsEventLogging() != MagickFalse)
1293 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1294 (void) ThrowMagickException(exception,GetMagickModule(),MissingDelegateError,
1295 "DelegateLibrarySupportNotBuiltIn","'%s' (ZIP)",image->filename);
1296 return(MagickFalse);
1297}
1298#endif