Coverage Report

Created: 2025-11-14 07:32

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