Coverage Report

Created: 2026-09-13 07:02

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/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
*/
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 *) AcquireCriticalMemory(
269
0
      sizeof(*image->ascii85));
270
0
  (void) memset(image->ascii85,0,sizeof(*image->ascii85));
271
0
  image->ascii85->line_break=(ssize_t) (MaxLineExtent << 1);
272
0
  image->ascii85->offset=0;
273
0
}
274
275
MagickExport void Ascii85Flush(Image *image)
276
0
{
277
0
  assert(image != (Image *) NULL);
278
0
  assert(image->signature == MagickCoreSignature);
279
0
  assert(image->ascii85 != (Ascii85Info *) NULL);
280
0
  if (IsEventLogging() != MagickFalse)
281
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
282
0
  if (image->ascii85->offset > 0)
283
0
    {
284
0
      image->ascii85->buffer[image->ascii85->offset]='\0';
285
0
      image->ascii85->buffer[image->ascii85->offset+1]='\0';
286
0
      image->ascii85->buffer[image->ascii85->offset+2]='\0';
287
0
      Ascii85Tuple(image->ascii85,image->ascii85->buffer);
288
0
      (void) WriteBlob(image,(size_t) image->ascii85->offset+1,
289
0
        (const unsigned char *) (*image->ascii85->tuple == 'z' ? "!!!!" :
290
0
        image->ascii85->tuple));
291
0
    }
292
0
  (void) WriteBlobByte(image,'~');
293
0
  (void) WriteBlobByte(image,'>');
294
0
  (void) WriteBlobByte(image,'\n');
295
0
}
296
297
MagickExport void Ascii85Encode(Image *image,const unsigned char code)
298
0
{
299
0
  char
300
0
    *q;
301
302
0
  unsigned char
303
0
    *p;
304
305
0
  ssize_t
306
0
    n;
307
308
0
  assert(image != (Image *) NULL);
309
0
  assert(image->signature == MagickCoreSignature);
310
0
  assert(image->ascii85 != (Ascii85Info *) NULL);
311
0
  image->ascii85->buffer[image->ascii85->offset]=code;
312
0
  image->ascii85->offset++;
313
0
  if (image->ascii85->offset < 4)
314
0
    return;
315
0
  p=image->ascii85->buffer;
316
0
  for (n=image->ascii85->offset; n >= 4; n-=4)
317
0
  {
318
0
    Ascii85Tuple(image->ascii85,p);
319
0
    for (q=image->ascii85->tuple; *q != '\0'; q++)
320
0
    {
321
0
      image->ascii85->line_break--;
322
0
      if ((image->ascii85->line_break < 0) && (*q != '%'))
323
0
        {
324
0
          (void) WriteBlobByte(image,'\n');
325
0
          image->ascii85->line_break=2*MaxLineExtent;
326
0
        }
327
0
      (void) WriteBlobByte(image,(unsigned char) *q);
328
0
    }
329
0
    p+=(ptrdiff_t) 8;
330
0
  }
331
0
  image->ascii85->offset=n;
332
0
  p-=(ptrdiff_t)4;
333
0
  for (n=0; n < 4; n++)
334
0
    image->ascii85->buffer[n]=(*p++);
335
0
}
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
*/
362
MagickExport MagickBooleanType HuffmanDecodeImage(Image *image,
363
  ExceptionInfo *exception)
364
25
{
365
50
#define HashSize  1021L
366
25
#define MBHashA  293L
367
25
#define MBHashB  2695L
368
25
#define MWHashA  3510L
369
25
#define MWHashB  1178L
370
371
25
#define InitializeHashTable(hash,table,a,b) \
372
0
{ \
373
0
  entry=table; \
374
0
  while (entry->code != 0) \
375
0
  {  \
376
0
    hash[((entry->length+a)*(entry->code+b)) % HashSize]=(HuffmanTable *) entry; \
377
0
    entry++; \
378
0
  } \
379
0
}
380
381
25
#define InputBit(bit)  \
382
0
{  \
383
0
  if ((mask & 0xff) == 0)  \
384
0
    {  \
385
0
      byte=ReadBlobByte(image);  \
386
0
      if (byte == EOF)  \
387
0
        break;  \
388
0
      mask=0x80;  \
389
0
    }  \
390
0
  runlength++;  \
391
0
  bit=(size_t) ((byte & mask) != 0 ? 0x01 : 0x00); \
392
0
  mask>>=1;  \
393
0
  if (bit != 0)  \
394
0
    runlength=0;  \
395
0
}
396
397
25
  CacheView
398
25
    *image_view;
399
400
25
  const HuffmanTable
401
25
    *entry;
402
403
25
  HuffmanTable
404
25
    **mb_hash,
405
25
    **mw_hash;
406
407
25
  int
408
25
    byte,
409
25
    mask;
410
411
25
  MagickBooleanType
412
25
    proceed;
413
414
25
  Quantum
415
25
    index;
416
417
25
  size_t
418
25
    bit,
419
25
    code,
420
25
    length,
421
25
    null_lines,
422
25
    runlength;
423
424
25
  ssize_t
425
25
    count,
426
25
    i,
427
25
    y;
428
429
25
  unsigned char
430
25
    *p,
431
25
    *scanline;
432
433
25
  unsigned int
434
25
    bail,
435
25
    color;
436
437
  /*
438
    Allocate buffers.
439
  */
440
25
  assert(image != (Image *) NULL);
441
25
  assert(image->signature == MagickCoreSignature);
442
25
  if (IsEventLogging() != MagickFalse)
443
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
444
25
  if (image->blob == (BlobInfo *) NULL)
445
25
    ThrowBinaryException(BlobError,"UnableToOpenBlob",image->filename);
446
25
  mb_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mb_hash));
447
25
  mw_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mw_hash));
448
25
  scanline=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
449
25
    sizeof(*scanline));
450
25
  if ((mb_hash == (HuffmanTable **) NULL) ||
451
25
      (mw_hash == (HuffmanTable **) NULL) ||
452
25
      (scanline == (unsigned char *) NULL))
453
25
    {
454
25
      if (mb_hash != (HuffmanTable **) NULL)
455
25
        mb_hash=(HuffmanTable **) RelinquishMagickMemory(mb_hash);
456
25
      if (mw_hash != (HuffmanTable **) NULL)
457
25
        mw_hash=(HuffmanTable **) RelinquishMagickMemory(mw_hash);
458
25
      if (scanline != (unsigned char *) NULL)
459
0
        scanline=(unsigned char *) RelinquishMagickMemory(scanline);
460
25
      ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
461
25
        image->filename);
462
0
    }
463
  /*
464
    Initialize Huffman tables.
465
  */
466
0
  for (i=0; i < HashSize; i++)
467
0
  {
468
0
    mb_hash[i]=(HuffmanTable *) NULL;
469
0
    mw_hash[i]=(HuffmanTable *) NULL;
470
0
  }
471
0
  InitializeHashTable(mw_hash,TWTable,MWHashA,MWHashB);
472
0
  InitializeHashTable(mw_hash,MWTable,MWHashA,MWHashB);
473
0
  InitializeHashTable(mw_hash,EXTable,MWHashA,MWHashB);
474
0
  InitializeHashTable(mb_hash,TBTable,MBHashA,MBHashB);
475
0
  InitializeHashTable(mb_hash,MBTable,MBHashA,MBHashB);
476
0
  InitializeHashTable(mb_hash,EXTable,MBHashA,MBHashB);
477
  /*
478
    Uncompress 1D Huffman to runlength encoded pixels.
479
  */
480
0
  byte=0;
481
0
  mask=0;
482
0
  null_lines=0;
483
0
  runlength=0;
484
0
  while (runlength < 11)
485
0
   InputBit(bit);
486
0
  do { InputBit(bit); } while ((int) bit == 0);
487
0
  image->resolution.x=204.0;
488
0
  image->resolution.y=196.0;
489
0
  image->units=PixelsPerInchResolution;
490
0
  image_view=AcquireAuthenticCacheView(image,exception);
491
0
  for (y=0; ((y < (ssize_t) image->rows) && (null_lines < 3)); )
492
0
  {
493
0
    Quantum
494
0
      *magick_restrict q;
495
496
0
    ssize_t
497
0
      x;
498
499
    /*
500
      Initialize scanline to white.
501
    */
502
0
    memset(scanline,0,sizeof(*scanline)*image->columns);
503
    /*
504
      Decode Huffman encoded scanline.
505
    */
506
0
    color=MagickTrue;
507
0
    code=0;
508
0
    count=0;
509
0
    length=0;
510
0
    runlength=0;
511
0
    x=0;
512
0
    for ( ; ; )
513
0
    {
514
0
      if (byte == EOF)
515
0
        break;
516
0
      if (x >= (ssize_t) image->columns)
517
0
        {
518
0
          while (runlength < 11)
519
0
            InputBit(bit);
520
0
          do { InputBit(bit); } while ((int) bit == 0);
521
0
          break;
522
0
        }
523
0
      bail=MagickFalse;
524
0
      do
525
0
      {
526
0
        if (runlength < 11)
527
0
          InputBit(bit)
528
0
        else
529
0
          {
530
0
            InputBit(bit);
531
0
            if ((int) bit != 0)
532
0
              {
533
0
                null_lines++;
534
0
                if (x != 0)
535
0
                  null_lines=0;
536
0
                bail=MagickTrue;
537
0
                break;
538
0
              }
539
0
          }
540
0
        code=(code << 1)+(size_t) bit;
541
0
        length++;
542
0
      } while (code == 0);
543
0
      if (bail != MagickFalse)
544
0
        break;
545
0
      if (length > 13)
546
0
        {
547
0
          while (runlength < 11)
548
0
            InputBit(bit);
549
0
          do { InputBit(bit); } while ((int) bit == 0);
550
0
          break;
551
0
        }
552
0
      if (color != MagickFalse)
553
0
        {
554
0
          if (length < 4)
555
0
            continue;
556
0
          entry=mw_hash[((length+MWHashA)*(code+MWHashB)) % HashSize];
557
0
        }
558
0
      else
559
0
        {
560
0
          if (length < 2)
561
0
            continue;
562
0
          entry=mb_hash[((length+MBHashA)*(code+MBHashB)) % HashSize];
563
0
        }
564
0
      if (entry == (const HuffmanTable *) NULL)
565
0
        continue;
566
0
      if ((entry->length != length) || (entry->code != code))
567
0
        continue;
568
0
      switch (entry->id)
569
0
      {
570
0
        case TWId:
571
0
        case TBId:
572
0
        {
573
0
          count+=(ssize_t) entry->count;
574
0
          if ((x+count) > (ssize_t) image->columns)
575
0
            count=(ssize_t) image->columns-x;
576
0
          if (count > 0)
577
0
            {
578
0
              if (color != MagickFalse)
579
0
                {
580
0
                  x+=count;
581
0
                  count=0;
582
0
                }
583
0
              else
584
0
                for ( ; count > 0; count--)
585
0
                  if ((x >= 0) && (x < (ssize_t) image->columns))
586
0
                    scanline[x++]=(unsigned char) 1;
587
0
            }
588
0
          color=(unsigned int)
589
0
            ((color == MagickFalse) ? MagickTrue : MagickFalse);
590
0
          break;
591
0
        }
592
0
        case MWId:
593
0
        case MBId:
594
0
        case EXId:
595
0
        {
596
0
          count+=(ssize_t) entry->count;
597
0
          break;
598
0
        }
599
0
        default:
600
0
          break;
601
0
      }
602
0
      code=0;
603
0
      length=0;
604
0
    }
605
    /*
606
      Transfer scanline to image pixels.
607
    */
608
0
    p=scanline;
609
0
    q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
610
0
    if (q == (Quantum *) NULL)
611
0
      break;
612
0
    for (x=0; x < (ssize_t) image->columns; x++)
613
0
    {
614
0
      index=(Quantum) (*p++);
615
0
      SetPixelIndex(image,index,q);
616
0
      SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
617
0
      q+=(ptrdiff_t) GetPixelChannels(image);
618
0
    }
619
0
    if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
620
0
      break;
621
0
    proceed=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
622
0
      image->rows);
623
0
    if (proceed == MagickFalse)
624
0
      break;
625
0
    y++;
626
0
  }
627
0
  image_view=DestroyCacheView(image_view);
628
0
  image->rows=(size_t) MagickMax((size_t) y-3,1);
629
0
  image->compression=FaxCompression;
630
  /*
631
    Free decoder memory.
632
  */
633
0
  mw_hash=(HuffmanTable **) RelinquishMagickMemory(mw_hash);
634
0
  mb_hash=(HuffmanTable **) RelinquishMagickMemory(mb_hash);
635
0
  scanline=(unsigned char *) RelinquishMagickMemory(scanline);
636
0
  return(MagickTrue);
637
0
}
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
*/
668
MagickExport MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
669
  Image *image,Image *inject_image,ExceptionInfo *exception)
670
0
{
671
0
#define HuffmanOutputCode(entry)  \
672
0
{  \
673
0
  mask=one << (entry->length-1);  \
674
0
  while (mask != 0)  \
675
0
  {  \
676
0
    OutputBit(((entry->code & mask) != 0 ? 1 : 0));  \
677
0
    mask>>=1;  \
678
0
  }  \
679
0
}
680
681
0
#define OutputBit(count)  \
682
0
{  \
683
0
DisableMSCWarning(4127) \
684
0
  if (count > 0)  \
685
0
    byte=byte | bit;  \
686
0
RestoreMSCWarning \
687
0
  bit>>=1;  \
688
0
  if ((int) (bit & 0xff) == 0)   \
689
0
    {  \
690
0
      if (LocaleCompare(image_info->magick,"FAX") == 0) \
691
0
        (void) WriteBlobByte(image,(unsigned char) byte);  \
692
0
      else \
693
0
        Ascii85Encode(image,byte); \
694
0
      byte='\0';  \
695
0
      bit=(unsigned char) 0x80;  \
696
0
    }  \
697
0
}
698
699
0
  const HuffmanTable
700
0
    *entry;
701
702
0
  int
703
0
    k,
704
0
    runlength;
705
706
0
  Image
707
0
    *huffman_image;
708
709
0
  MagickBooleanType
710
0
    proceed;
711
712
0
  ssize_t
713
0
    i,
714
0
    x;
715
716
0
  const Quantum
717
0
    *p;
718
719
0
  unsigned char
720
0
    *q;
721
722
0
  size_t
723
0
    mask,
724
0
    one,
725
0
    width;
726
727
0
  ssize_t
728
0
    n,
729
0
    y;
730
731
0
  unsigned char
732
0
    byte,
733
0
    bit,
734
0
    *scanline;
735
736
  /*
737
    Allocate scanline buffer.
738
  */
739
0
  assert(image_info != (ImageInfo *) NULL);
740
0
  assert(image_info->signature == MagickCoreSignature);
741
0
  assert(image != (Image *) NULL);
742
0
  assert(image->signature == MagickCoreSignature);
743
0
  if (IsEventLogging() != MagickFalse)
744
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
745
0
  assert(inject_image != (Image *) NULL);
746
0
  assert(inject_image->signature == MagickCoreSignature);
747
0
  one=1;
748
0
  width=inject_image->columns;
749
0
  if (LocaleCompare(image_info->magick,"FAX") == 0)
750
0
    width=(size_t) MagickMax(inject_image->columns,1728);
751
0
  scanline=(unsigned char *) AcquireQuantumMemory((size_t) width+1UL,
752
0
    sizeof(*scanline));
753
0
  if (scanline == (unsigned char *) NULL)
754
0
    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
755
0
      inject_image->filename);
756
0
  (void) memset(scanline,0,width*sizeof(*scanline));
757
0
  huffman_image=CloneImage(inject_image,0,0,MagickTrue,exception);
758
0
  if (huffman_image == (Image *) NULL)
759
0
    {
760
0
      scanline=(unsigned char *) RelinquishMagickMemory(scanline);
761
0
      return(MagickFalse);
762
0
    }
763
0
  (void) SetImageType(huffman_image,BilevelType,exception);
764
0
  byte='\0';
765
0
  bit=(unsigned char) 0x80;
766
0
  if (LocaleCompare(image_info->magick,"FAX") != 0)
767
0
    Ascii85Initialize(image);
768
0
  else
769
0
    {
770
      /*
771
        End of line.
772
      */
773
0
      for (k=0; k < 11; k++)
774
0
        OutputBit(0);
775
0
      OutputBit(1);
776
0
    }
777
  /*
778
    Compress to 1D Huffman pixels.
779
  */
780
0
  q=scanline;
781
0
  for (y=0; y < (ssize_t) huffman_image->rows; y++)
782
0
  {
783
0
    p=GetVirtualPixels(huffman_image,0,y,huffman_image->columns,1,exception);
784
0
    if (p == (const Quantum *) NULL)
785
0
      break;
786
0
    for (x=0; x < (ssize_t) huffman_image->columns; x++)
787
0
    {
788
0
      *q++=(unsigned char) (GetPixelIntensity(huffman_image,p) >=
789
0
        ((double) QuantumRange/2.0) ? 0 : 1);
790
0
      p+=(ptrdiff_t) GetPixelChannels(huffman_image);
791
0
    }
792
    /*
793
      Huffman encode scanline.
794
    */
795
0
    q=scanline;
796
0
    for (n=(ssize_t) width; n > 0; )
797
0
    {
798
      /*
799
        Output white run.
800
      */
801
0
      for (runlength=0; ((n > 0) && (*q == 0)); n--)
802
0
      {
803
0
        q++;
804
0
        runlength++;
805
0
      }
806
0
      if (runlength >= 64)
807
0
        {
808
0
          if (runlength < 1792)
809
0
            entry=MWTable+((runlength/64)-1);
810
0
          else
811
0
            entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
812
0
          runlength-=(long) entry->count;
813
0
          HuffmanOutputCode(entry);
814
0
        }
815
0
      entry=TWTable+MagickMin((size_t) runlength,63);
816
0
      HuffmanOutputCode(entry);
817
0
      if (n != 0)
818
0
        {
819
          /*
820
            Output black run.
821
          */
822
0
          for (runlength=0; ((*q != 0) && (n > 0)); n--)
823
0
          {
824
0
            q++;
825
0
            runlength++;
826
0
          }
827
0
          if (runlength >= 64)
828
0
            {
829
0
              entry=MBTable+((runlength/64)-1);
830
0
              if (runlength >= 1792)
831
0
                entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
832
0
              runlength-=(long) entry->count;
833
0
              HuffmanOutputCode(entry);
834
0
            }
835
0
          entry=TBTable+MagickMin((size_t) runlength,63);
836
0
          HuffmanOutputCode(entry);
837
0
        }
838
0
    }
839
    /*
840
      End of line.
841
    */
842
0
    for (k=0; k < 11; k++)
843
0
      OutputBit(0);
844
0
    OutputBit(1);
845
0
    q=scanline;
846
0
    if (GetPreviousImageInList(huffman_image) == (Image *) NULL)
847
0
      {
848
0
        proceed=SetImageProgress(huffman_image,LoadImageTag,
849
0
          (MagickOffsetType) y,huffman_image->rows);
850
0
        if (proceed == MagickFalse)
851
0
          break;
852
0
      }
853
0
  }
854
  /*
855
    End of page.
856
  */
857
0
  for (i=0; i < 6; i++)
858
0
  {
859
0
    for (k=0; k < 11; k++)
860
0
      OutputBit(0);
861
0
    OutputBit(1);
862
0
  }
863
  /*
864
    Flush bits.
865
  */
866
0
  if (((int) bit != 0x80) != 0)
867
0
    {
868
0
      if (LocaleCompare(image_info->magick,"FAX") == 0)
869
0
        (void) WriteBlobByte(image,byte);
870
0
      else
871
0
        Ascii85Encode(image,byte);
872
0
    }
873
0
  if (LocaleCompare(image_info->magick,"FAX") != 0)
874
0
    Ascii85Flush(image);
875
0
  huffman_image=DestroyImage(huffman_image);
876
0
  scanline=(unsigned char *) RelinquishMagickMemory(scanline);
877
0
  return(MagickTrue);
878
0
}
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
*/
911
MagickExport MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
912
  unsigned char *magick_restrict pixels,ExceptionInfo *exception)
913
0
{
914
0
#define LZWClr  256UL  /* Clear Table Marker */
915
0
#define LZWEod  257UL  /* End of Data marker */
916
0
#define OutputCode(code) \
917
0
{ \
918
0
    accumulator+=code << (32-code_width-number_bits); \
919
0
    number_bits+=code_width; \
920
0
    while (number_bits >= 8) \
921
0
    { \
922
0
      (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24)); \
923
0
      accumulator=accumulator << 8; \
924
0
      number_bits-=8; \
925
0
    } \
926
0
}
927
928
0
  typedef struct _TableType
929
0
  {
930
0
    ssize_t
931
0
      prefix,
932
0
      suffix,
933
0
      next;
934
0
  } TableType;
935
936
0
  ssize_t
937
0
    i;
938
939
0
  size_t
940
0
    accumulator,
941
0
    number_bits,
942
0
    code_width,
943
0
    last_code,
944
0
    next_index;
945
946
0
  ssize_t
947
0
    index;
948
949
0
  TableType
950
0
    *table;
951
952
  /*
953
    Allocate string table.
954
  */
955
0
  assert(image != (Image *) NULL);
956
0
  assert(image->signature == MagickCoreSignature);
957
0
  assert(pixels != (unsigned char *) NULL);
958
0
  assert(exception != (ExceptionInfo *) NULL);
959
0
  assert(exception->signature == MagickCoreSignature);
960
0
  if (IsEventLogging() != MagickFalse)
961
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
962
0
  table=(TableType *) AcquireQuantumMemory(1UL << 12,sizeof(*table));
963
0
  if (table == (TableType *) NULL)
964
0
    ThrowBinaryException(ResourceLimitWarning,"MemoryAllocationFailed",
965
0
      image->filename);
966
  /*
967
    Initialize variables.
968
  */
969
0
  accumulator=0;
970
0
  code_width=9;
971
0
  number_bits=0;
972
0
  last_code=0;
973
0
  OutputCode(LZWClr);
974
0
  for (index=0; index < 256; index++)
975
0
  {
976
0
    table[index].prefix=(-1);
977
0
    table[index].suffix=(ssize_t) index;
978
0
    table[index].next=(-1);
979
0
  }
980
0
  next_index=LZWEod+1;
981
0
  code_width=9;
982
0
  last_code=(size_t) pixels[0];
983
0
  for (i=1; i < (ssize_t) length; i++)
984
0
  {
985
    /*
986
      Find string.
987
    */
988
0
    index=(ssize_t) last_code;
989
0
    while (index != -1)
990
0
      if ((table[index].prefix != (ssize_t) last_code) ||
991
0
          (table[index].suffix != (ssize_t) pixels[i]))
992
0
        index=table[index].next;
993
0
      else
994
0
        {
995
0
          last_code=(size_t) index;
996
0
          break;
997
0
        }
998
0
    if (last_code != (size_t) index)
999
0
      {
1000
        /*
1001
          Add string.
1002
        */
1003
0
        OutputCode(last_code);
1004
0
        table[next_index].prefix=(ssize_t) last_code;
1005
0
        table[next_index].suffix=(ssize_t) pixels[i];
1006
0
        table[next_index].next=table[last_code].next;
1007
0
        table[last_code].next=(ssize_t) next_index;
1008
0
        next_index++;
1009
        /*
1010
          Did we just move up to next bit width?
1011
        */
1012
0
        if ((next_index >> code_width) != 0)
1013
0
          {
1014
0
            code_width++;
1015
0
            if (code_width > 12)
1016
0
              {
1017
                /*
1018
                  Did we overflow the max bit width?
1019
                */
1020
0
                code_width--;
1021
0
                OutputCode(LZWClr);
1022
0
                for (index=0; index < 256; index++)
1023
0
                {
1024
0
                  table[index].prefix=(-1);
1025
0
                  table[index].suffix=index;
1026
0
                  table[index].next=(-1);
1027
0
                }
1028
0
                next_index=LZWEod+1;
1029
0
                code_width=9;
1030
0
              }
1031
0
            }
1032
0
          last_code=(size_t) pixels[i];
1033
0
      }
1034
0
  }
1035
  /*
1036
    Flush tables.
1037
  */
1038
0
  OutputCode(last_code);
1039
0
  OutputCode(LZWEod);
1040
0
  if (number_bits != 0)
1041
0
    (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24));
1042
0
  table=(TableType *) RelinquishMagickMemory(table);
1043
0
  return(MagickTrue);
1044
0
}
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
*/
1076
MagickExport MagickBooleanType PackbitsEncodeImage(Image *image,
1077
  const size_t length,unsigned char *magick_restrict pixels,
1078
  ExceptionInfo *exception)
1079
0
{
1080
0
  int
1081
0
    count;
1082
1083
0
  ssize_t
1084
0
    i,
1085
0
    j;
1086
1087
0
  unsigned char
1088
0
    *packbits;
1089
1090
  /*
1091
    Compress pixels with Packbits encoding.
1092
  */
1093
0
  assert(image != (Image *) NULL);
1094
0
  assert(image->signature == MagickCoreSignature);
1095
0
  assert(pixels != (unsigned char *) NULL);
1096
0
  if (IsEventLogging() != MagickFalse)
1097
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1098
0
  packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
1099
0
  if (packbits == (unsigned char *) NULL)
1100
0
    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1101
0
      image->filename);
1102
0
  for (i=(ssize_t) length; i != 0; )
1103
0
  {
1104
0
    switch (i)
1105
0
    {
1106
0
      case 1:
1107
0
      {
1108
0
        i--;
1109
0
        (void) WriteBlobByte(image,(unsigned char) 0);
1110
0
        (void) WriteBlobByte(image,*pixels);
1111
0
        break;
1112
0
      }
1113
0
      case 2:
1114
0
      {
1115
0
        i-=2;
1116
0
        (void) WriteBlobByte(image,(unsigned char) 1);
1117
0
        (void) WriteBlobByte(image,*pixels);
1118
0
        (void) WriteBlobByte(image,pixels[1]);
1119
0
        break;
1120
0
      }
1121
0
      case 3:
1122
0
      {
1123
0
        i-=3;
1124
0
        if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1125
0
          {
1126
0
            (void) WriteBlobByte(image,(unsigned char) ((256-3)+1));
1127
0
            (void) WriteBlobByte(image,*pixels);
1128
0
            break;
1129
0
          }
1130
0
        (void) WriteBlobByte(image,(unsigned char) 2);
1131
0
        (void) WriteBlobByte(image,*pixels);
1132
0
        (void) WriteBlobByte(image,pixels[1]);
1133
0
        (void) WriteBlobByte(image,pixels[2]);
1134
0
        break;
1135
0
      }
1136
0
      default:
1137
0
      {
1138
0
        if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
1139
0
          {
1140
            /*
1141
              Packed run.
1142
            */
1143
0
            count=3;
1144
0
            while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
1145
0
            {
1146
0
              count++;
1147
0
              if (count >= 127)
1148
0
                break;
1149
0
            }
1150
0
            i-=count;
1151
0
            (void) WriteBlobByte(image,(unsigned char) ((256-count)+1));
1152
0
            (void) WriteBlobByte(image,*pixels);
1153
0
            pixels+=count;
1154
0
            break;
1155
0
          }
1156
        /*
1157
          Literal run.
1158
        */
1159
0
        count=0;
1160
0
        while ((*(pixels+count) != *(pixels+count+1)) ||
1161
0
               (*(pixels+count+1) != *(pixels+count+2)))
1162
0
        {
1163
0
          packbits[count+1]=pixels[count];
1164
0
          count++;
1165
0
          if (((ssize_t) count >= (i-3)) || (count >= 127))
1166
0
            break;
1167
0
        }
1168
0
        i-=count;
1169
0
        *packbits=(unsigned char) (count-1);
1170
0
        for (j=0; j <= (ssize_t) count; j++)
1171
0
          (void) WriteBlobByte(image,packbits[j]);
1172
0
        pixels+=count;
1173
0
        break;
1174
0
      }
1175
0
    }
1176
0
  }
1177
0
  (void) WriteBlobByte(image,(unsigned char) 128);  /* EOD marker */
1178
0
  packbits=(unsigned char *) RelinquishMagickMemory(packbits);
1179
0
  return(MagickTrue);
1180
0
}
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
1216
static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
1217
  unsigned int size)
1218
0
{
1219
0
  (void) context;
1220
0
  return((voidpf) AcquireQuantumMemory(items,size));
1221
0
}
1222
1223
static void RelinquishZIPMemory(voidpf context,voidpf memory)
1224
0
{
1225
0
  (void) context;
1226
0
  memory=RelinquishMagickMemory(memory);
1227
0
}
1228
1229
MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
1230
  unsigned char *magick_restrict pixels,ExceptionInfo *exception)
1231
0
{
1232
0
  int
1233
0
    status;
1234
1235
0
  ssize_t
1236
0
    i;
1237
1238
0
  size_t
1239
0
    compress_packets;
1240
1241
0
  unsigned char
1242
0
    *compress_pixels;
1243
1244
0
  z_stream
1245
0
    stream;
1246
1247
0
  assert(image != (Image *) NULL);
1248
0
  assert(image->signature == MagickCoreSignature);
1249
0
  if (IsEventLogging() != MagickFalse)
1250
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1251
0
  compress_packets=(size_t) (1.001*length+12);
1252
0
  compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_packets,
1253
0
    sizeof(*compress_pixels));
1254
0
  if (compress_pixels == (unsigned char *) NULL)
1255
0
    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
1256
0
      image->filename);
1257
0
  (void) memset(&stream,0,sizeof(stream));
1258
0
  stream.next_in=pixels;
1259
0
  stream.avail_in=(unsigned int) length;
1260
0
  stream.next_out=compress_pixels;
1261
0
  stream.avail_out=(unsigned int) compress_packets;
1262
0
  stream.zalloc=AcquireZIPMemory;
1263
0
  stream.zfree=RelinquishZIPMemory;
1264
0
  stream.opaque=(voidpf) NULL;
1265
0
  status=deflateInit(&stream,(int) (image->quality ==
1266
0
    UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
1267
0
  if (status == Z_OK)
1268
0
    {
1269
0
      status=deflate(&stream,Z_FINISH);
1270
0
      if (status == Z_STREAM_END)
1271
0
        status=deflateEnd(&stream);
1272
0
      else
1273
0
        (void) deflateEnd(&stream);
1274
0
      compress_packets=(size_t) stream.total_out;
1275
0
    }
1276
0
  if (status != Z_OK)
1277
0
    ThrowBinaryException(CoderError,"UnableToZipCompressImage",image->filename)
1278
0
  for (i=0; i < (ssize_t) compress_packets; i++)
1279
0
    (void) WriteBlobByte(image,compress_pixels[i]);
1280
0
  compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
1281
0
  return(MagickTrue);
1282
0
}
1283
#else
1284
MagickExport 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