MagickCore  6.7.5
compress.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %           CCCC   OOO   M   M  PPPP   RRRR   EEEEE   SSSSS  SSSSS            %
00007 %          C      O   O  MM MM  P   P  R   R  E       SS     SS               %
00008 %          C      O   O  M M M  PPPP   RRRR   EEE      SSS    SSS             %
00009 %          C      O   O  M   M  P      R R    E          SS     SS            %
00010 %           CCCC   OOO   M   M  P      R  R   EEEEE   SSSSS  SSSSS            %
00011 %                                                                             %
00012 %                                                                             %
00013 %             MagickCore Image Compression/Decompression Methods              %
00014 %                                                                             %
00015 %                           Software Design                                   %
00016 %                             John Cristy                                     %
00017 %                              May  1993                                      %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "MagickCore/studio.h"
00044 #include "MagickCore/blob.h"
00045 #include "MagickCore/blob-private.h"
00046 #include "MagickCore/color-private.h"
00047 #include "MagickCore/cache.h"
00048 #include "MagickCore/compress.h"
00049 #include "MagickCore/constitute.h"
00050 #include "MagickCore/exception.h"
00051 #include "MagickCore/exception-private.h"
00052 #include "MagickCore/image-private.h"
00053 #include "MagickCore/list.h"
00054 #include "MagickCore/memory_.h"
00055 #include "MagickCore/monitor.h"
00056 #include "MagickCore/monitor-private.h"
00057 #include "MagickCore/option.h"
00058 #include "MagickCore/pixel-accessor.h"
00059 #include "MagickCore/resource_.h"
00060 #include "MagickCore/string_.h"
00061 #if defined(MAGICKCORE_TIFF_DELEGATE)
00062 #if defined(MAGICKCORE_HAVE_TIFFCONF_H)
00063 #include "tiffconf.h"
00064 #endif
00065 #include "tiffio.h"
00066 #define CCITTParam  "-1"
00067 #else
00068 #define CCITTParam  "0"
00069 #endif
00070 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00071 #include "zlib.h"
00072 #endif
00073 
00074 /*
00075   Typedef declarations.
00076 */
00077 struct _Ascii85Info
00078 {
00079   ssize_t
00080     offset,
00081     line_break;
00082 
00083   unsigned char
00084     buffer[10];
00085 };
00086 
00087 typedef struct HuffmanTable
00088 {
00089   size_t
00090     id,
00091     code,
00092     length,
00093     count;
00094 } HuffmanTable;
00095 
00096 /*
00097   Huffman coding declarations.
00098 */
00099 #define TWId  23
00100 #define MWId  24
00101 #define TBId  25
00102 #define MBId  26
00103 #define EXId  27
00104 
00105 static const HuffmanTable
00106   MBTable[]=
00107   {
00108     { MBId, 0x0f, 10, 64 }, { MBId, 0xc8, 12, 128 },
00109     { MBId, 0xc9, 12, 192 }, { MBId, 0x5b, 12, 256 },
00110     { MBId, 0x33, 12, 320 }, { MBId, 0x34, 12, 384 },
00111     { MBId, 0x35, 12, 448 }, { MBId, 0x6c, 13, 512 },
00112     { MBId, 0x6d, 13, 576 }, { MBId, 0x4a, 13, 640 },
00113     { MBId, 0x4b, 13, 704 }, { MBId, 0x4c, 13, 768 },
00114     { MBId, 0x4d, 13, 832 }, { MBId, 0x72, 13, 896 },
00115     { MBId, 0x73, 13, 960 }, { MBId, 0x74, 13, 1024 },
00116     { MBId, 0x75, 13, 1088 }, { MBId, 0x76, 13, 1152 },
00117     { MBId, 0x77, 13, 1216 }, { MBId, 0x52, 13, 1280 },
00118     { MBId, 0x53, 13, 1344 }, { MBId, 0x54, 13, 1408 },
00119     { MBId, 0x55, 13, 1472 }, { MBId, 0x5a, 13, 1536 },
00120     { MBId, 0x5b, 13, 1600 }, { MBId, 0x64, 13, 1664 },
00121     { MBId, 0x65, 13, 1728 }, { MBId, 0x00, 0, 0 }
00122   };
00123 
00124 static const HuffmanTable
00125   EXTable[]=
00126   {
00127     { EXId, 0x08, 11, 1792 }, { EXId, 0x0c, 11, 1856 },
00128     { EXId, 0x0d, 11, 1920 }, { EXId, 0x12, 12, 1984 },
00129     { EXId, 0x13, 12, 2048 }, { EXId, 0x14, 12, 2112 },
00130     { EXId, 0x15, 12, 2176 }, { EXId, 0x16, 12, 2240 },
00131     { EXId, 0x17, 12, 2304 }, { EXId, 0x1c, 12, 2368 },
00132     { EXId, 0x1d, 12, 2432 }, { EXId, 0x1e, 12, 2496 },
00133     { EXId, 0x1f, 12, 2560 }, { EXId, 0x00, 0, 0 }
00134   };
00135 
00136 static const HuffmanTable
00137   MWTable[]=
00138   {
00139     { MWId, 0x1b, 5, 64 }, { MWId, 0x12, 5, 128 },
00140     { MWId, 0x17, 6, 192 }, { MWId, 0x37, 7, 256 },
00141     { MWId, 0x36, 8, 320 }, { MWId, 0x37, 8, 384 },
00142     { MWId, 0x64, 8, 448 }, { MWId, 0x65, 8, 512 },
00143     { MWId, 0x68, 8, 576 }, { MWId, 0x67, 8, 640 },
00144     { MWId, 0xcc, 9, 704 }, { MWId, 0xcd, 9, 768 },
00145     { MWId, 0xd2, 9, 832 }, { MWId, 0xd3, 9, 896 },
00146     { MWId, 0xd4, 9, 960 }, { MWId, 0xd5, 9, 1024 },
00147     { MWId, 0xd6, 9, 1088 }, { MWId, 0xd7, 9, 1152 },
00148     { MWId, 0xd8, 9, 1216 }, { MWId, 0xd9, 9, 1280 },
00149     { MWId, 0xda, 9, 1344 }, { MWId, 0xdb, 9, 1408 },
00150     { MWId, 0x98, 9, 1472 }, { MWId, 0x99, 9, 1536 },
00151     { MWId, 0x9a, 9, 1600 }, { MWId, 0x18, 6, 1664 },
00152     { MWId, 0x9b, 9, 1728 }, { MWId, 0x00, 0, 0 }
00153   };
00154 
00155 static const HuffmanTable
00156   TBTable[]=
00157   {
00158     { TBId, 0x37, 10, 0 }, { TBId, 0x02, 3, 1 }, { TBId, 0x03, 2, 2 },
00159     { TBId, 0x02, 2, 3 }, { TBId, 0x03, 3, 4 }, { TBId, 0x03, 4, 5 },
00160     { TBId, 0x02, 4, 6 }, { TBId, 0x03, 5, 7 }, { TBId, 0x05, 6, 8 },
00161     { TBId, 0x04, 6, 9 }, { TBId, 0x04, 7, 10 }, { TBId, 0x05, 7, 11 },
00162     { TBId, 0x07, 7, 12 }, { TBId, 0x04, 8, 13 }, { TBId, 0x07, 8, 14 },
00163     { TBId, 0x18, 9, 15 }, { TBId, 0x17, 10, 16 }, { TBId, 0x18, 10, 17 },
00164     { TBId, 0x08, 10, 18 }, { TBId, 0x67, 11, 19 }, { TBId, 0x68, 11, 20 },
00165     { TBId, 0x6c, 11, 21 }, { TBId, 0x37, 11, 22 }, { TBId, 0x28, 11, 23 },
00166     { TBId, 0x17, 11, 24 }, { TBId, 0x18, 11, 25 }, { TBId, 0xca, 12, 26 },
00167     { TBId, 0xcb, 12, 27 }, { TBId, 0xcc, 12, 28 }, { TBId, 0xcd, 12, 29 },
00168     { TBId, 0x68, 12, 30 }, { TBId, 0x69, 12, 31 }, { TBId, 0x6a, 12, 32 },
00169     { TBId, 0x6b, 12, 33 }, { TBId, 0xd2, 12, 34 }, { TBId, 0xd3, 12, 35 },
00170     { TBId, 0xd4, 12, 36 }, { TBId, 0xd5, 12, 37 }, { TBId, 0xd6, 12, 38 },
00171     { TBId, 0xd7, 12, 39 }, { TBId, 0x6c, 12, 40 }, { TBId, 0x6d, 12, 41 },
00172     { TBId, 0xda, 12, 42 }, { TBId, 0xdb, 12, 43 }, { TBId, 0x54, 12, 44 },
00173     { TBId, 0x55, 12, 45 }, { TBId, 0x56, 12, 46 }, { TBId, 0x57, 12, 47 },
00174     { TBId, 0x64, 12, 48 }, { TBId, 0x65, 12, 49 }, { TBId, 0x52, 12, 50 },
00175     { TBId, 0x53, 12, 51 }, { TBId, 0x24, 12, 52 }, { TBId, 0x37, 12, 53 },
00176     { TBId, 0x38, 12, 54 }, { TBId, 0x27, 12, 55 }, { TBId, 0x28, 12, 56 },
00177     { TBId, 0x58, 12, 57 }, { TBId, 0x59, 12, 58 }, { TBId, 0x2b, 12, 59 },
00178     { TBId, 0x2c, 12, 60 }, { TBId, 0x5a, 12, 61 }, { TBId, 0x66, 12, 62 },
00179     { TBId, 0x67, 12, 63 }, { TBId, 0x00, 0, 0 }
00180   };
00181 
00182 static const HuffmanTable
00183   TWTable[]=
00184   {
00185     { TWId, 0x35, 8, 0 }, { TWId, 0x07, 6, 1 }, { TWId, 0x07, 4, 2 },
00186     { TWId, 0x08, 4, 3 }, { TWId, 0x0b, 4, 4 }, { TWId, 0x0c, 4, 5 },
00187     { TWId, 0x0e, 4, 6 }, { TWId, 0x0f, 4, 7 }, { TWId, 0x13, 5, 8 },
00188     { TWId, 0x14, 5, 9 }, { TWId, 0x07, 5, 10 }, { TWId, 0x08, 5, 11 },
00189     { TWId, 0x08, 6, 12 }, { TWId, 0x03, 6, 13 }, { TWId, 0x34, 6, 14 },
00190     { TWId, 0x35, 6, 15 }, { TWId, 0x2a, 6, 16 }, { TWId, 0x2b, 6, 17 },
00191     { TWId, 0x27, 7, 18 }, { TWId, 0x0c, 7, 19 }, { TWId, 0x08, 7, 20 },
00192     { TWId, 0x17, 7, 21 }, { TWId, 0x03, 7, 22 }, { TWId, 0x04, 7, 23 },
00193     { TWId, 0x28, 7, 24 }, { TWId, 0x2b, 7, 25 }, { TWId, 0x13, 7, 26 },
00194     { TWId, 0x24, 7, 27 }, { TWId, 0x18, 7, 28 }, { TWId, 0x02, 8, 29 },
00195     { TWId, 0x03, 8, 30 }, { TWId, 0x1a, 8, 31 }, { TWId, 0x1b, 8, 32 },
00196     { TWId, 0x12, 8, 33 }, { TWId, 0x13, 8, 34 }, { TWId, 0x14, 8, 35 },
00197     { TWId, 0x15, 8, 36 }, { TWId, 0x16, 8, 37 }, { TWId, 0x17, 8, 38 },
00198     { TWId, 0x28, 8, 39 }, { TWId, 0x29, 8, 40 }, { TWId, 0x2a, 8, 41 },
00199     { TWId, 0x2b, 8, 42 }, { TWId, 0x2c, 8, 43 }, { TWId, 0x2d, 8, 44 },
00200     { TWId, 0x04, 8, 45 }, { TWId, 0x05, 8, 46 }, { TWId, 0x0a, 8, 47 },
00201     { TWId, 0x0b, 8, 48 }, { TWId, 0x52, 8, 49 }, { TWId, 0x53, 8, 50 },
00202     { TWId, 0x54, 8, 51 }, { TWId, 0x55, 8, 52 }, { TWId, 0x24, 8, 53 },
00203     { TWId, 0x25, 8, 54 }, { TWId, 0x58, 8, 55 }, { TWId, 0x59, 8, 56 },
00204     { TWId, 0x5a, 8, 57 }, { TWId, 0x5b, 8, 58 }, { TWId, 0x4a, 8, 59 },
00205     { TWId, 0x4b, 8, 60 }, { TWId, 0x32, 8, 61 }, { TWId, 0x33, 8, 62 },
00206     { TWId, 0x34, 8, 63 }, { TWId, 0x00, 0, 0 }
00207   };
00208 
00209 /*
00210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00211 %                                                                             %
00212 %                                                                             %
00213 %                                                                             %
00214 %   A S C I I 8 5 E n c o d e                                                 %
00215 %                                                                             %
00216 %                                                                             %
00217 %                                                                             %
00218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00219 %
00220 %  ASCII85Encode() encodes data in ASCII base-85 format.  ASCII base-85
00221 %  encoding produces five ASCII printing characters from every four bytes of
00222 %  binary data.
00223 %
00224 %  The format of the ASCII85Encode method is:
00225 %
00226 %      void Ascii85Encode(Image *image,const size_t code)
00227 %
00228 %  A description of each parameter follows:
00229 %
00230 %    o code: a binary unsigned char to encode to ASCII 85.
00231 %
00232 %    o file: write the encoded ASCII character to this file.
00233 %
00234 %
00235 */
00236 #define MaxLineExtent  36
00237 
00238 static char *Ascii85Tuple(unsigned char *data)
00239 {
00240   static char
00241     tuple[6];
00242 
00243   register ssize_t
00244     i,
00245     x;
00246 
00247   size_t
00248     code,
00249     quantum;
00250 
00251   code=((((size_t) data[0] << 8) | (size_t) data[1]) << 16) |
00252     ((size_t) data[2] << 8) | (size_t) data[3];
00253   if (code == 0L)
00254     {
00255       tuple[0]='z';
00256       tuple[1]='\0';
00257       return(tuple);
00258     }
00259   quantum=85UL*85UL*85UL*85UL;
00260   for (i=0; i < 4; i++)
00261   {
00262     x=(ssize_t) (code/quantum);
00263     code-=quantum*x;
00264     tuple[i]=(char) (x+(int) '!');
00265     quantum/=85L;
00266   }
00267   tuple[4]=(char) ((code % 85L)+(int) '!');
00268   tuple[5]='\0';
00269   return(tuple);
00270 }
00271 
00272 MagickExport void Ascii85Initialize(Image *image)
00273 {
00274   /*
00275     Allocate image structure.
00276   */
00277   if (image->ascii85 == (Ascii85Info *) NULL)
00278     image->ascii85=(Ascii85Info *) AcquireMagickMemory(sizeof(*image->ascii85));
00279   if (image->ascii85 == (Ascii85Info *) NULL)
00280     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00281   (void) ResetMagickMemory(image->ascii85,0,sizeof(*image->ascii85));
00282   image->ascii85->line_break=MaxLineExtent << 1;
00283   image->ascii85->offset=0;
00284 }
00285 
00286 MagickExport void Ascii85Flush(Image *image)
00287 {
00288   register char
00289     *tuple;
00290 
00291   assert(image != (Image *) NULL);
00292   assert(image->signature == MagickSignature);
00293   if (image->debug != MagickFalse)
00294     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00295   assert(image->ascii85 != (Ascii85Info *) NULL);
00296   if (image->ascii85->offset > 0)
00297     {
00298       image->ascii85->buffer[image->ascii85->offset]='\0';
00299       image->ascii85->buffer[image->ascii85->offset+1]='\0';
00300       image->ascii85->buffer[image->ascii85->offset+2]='\0';
00301       tuple=Ascii85Tuple(image->ascii85->buffer);
00302       (void) WriteBlob(image,(size_t) image->ascii85->offset+1,
00303         (const unsigned char *) (*tuple == 'z' ? "!!!!" : tuple));
00304     }
00305   (void) WriteBlobByte(image,'~');
00306   (void) WriteBlobByte(image,'>');
00307   (void) WriteBlobByte(image,'\n');
00308 }
00309 
00310 MagickExport void Ascii85Encode(Image *image,const unsigned char code)
00311 {
00312   register char
00313     *q;
00314 
00315   register unsigned char
00316     *p;
00317 
00318   ssize_t
00319     n;
00320 
00321   assert(image != (Image *) NULL);
00322   assert(image->signature == MagickSignature);
00323   assert(image->ascii85 != (Ascii85Info *) NULL);
00324   image->ascii85->buffer[image->ascii85->offset]=code;
00325   image->ascii85->offset++;
00326   if (image->ascii85->offset < 4)
00327     return;
00328   p=image->ascii85->buffer;
00329   for (n=image->ascii85->offset; n >= 4; n-=4)
00330   {
00331     for (q=Ascii85Tuple(p); *q != '\0'; q++)
00332     {
00333       image->ascii85->line_break--;
00334       if ((image->ascii85->line_break < 0) && (*q != '%'))
00335         {
00336           (void) WriteBlobByte(image,'\n');
00337           image->ascii85->line_break=2*MaxLineExtent;
00338         }
00339       (void) WriteBlobByte(image,(unsigned char) *q);
00340     }
00341     p+=8;
00342   }
00343   image->ascii85->offset=n;
00344   p-=4;
00345   for (n=0; n < 4; n++)
00346     image->ascii85->buffer[n]=(*p++);
00347 }
00348 
00349 /*
00350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00351 %                                                                             %
00352 %                                                                             %
00353 %                                                                             %
00354 %   H u f f m a n D e c o d e I m a g e                                       %
00355 %                                                                             %
00356 %                                                                             %
00357 %                                                                             %
00358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00359 %
00360 %  HuffmanDecodeImage() uncompresses an image via Huffman-coding.
00361 %
00362 %  The format of the HuffmanDecodeImage method is:
00363 %
00364 %      MagickBooleanType HuffmanDecodeImage(Image *image,
00365 %        ExceptionInfo *exception)
00366 %
00367 %  A description of each parameter follows:
00368 %
00369 %    o image: the image.
00370 %
00371 %    o exception: return any errors or warnings in this structure.
00372 %
00373 */
00374 
00375 static inline size_t MagickMax(const size_t x,const size_t y)
00376 {
00377   if (x > y)
00378     return(x);
00379   return(y);
00380 }
00381 
00382 static inline size_t MagickMin(const size_t x,const size_t y)
00383 {
00384   if (x < y)
00385     return(x);
00386   return(y);
00387 }
00388 
00389 MagickExport MagickBooleanType HuffmanDecodeImage(Image *image,
00390   ExceptionInfo *exception)
00391 {
00392 #define HashSize  1021
00393 #define MBHashA  293
00394 #define MBHashB  2695
00395 #define MWHashA  3510
00396 #define MWHashB  1178
00397 
00398 #define InitializeHashTable(hash,table,a,b) \
00399 { \
00400   entry=table; \
00401   while (entry->code != 0) \
00402   {  \
00403     hash[((entry->length+a)*(entry->code+b)) % HashSize]=(HuffmanTable *) entry; \
00404     entry++; \
00405   } \
00406 }
00407 
00408 #define InputBit(bit)  \
00409 {  \
00410   if ((mask & 0xff) == 0)  \
00411     {  \
00412       byte=ReadBlobByte(image);  \
00413       if (byte == EOF)  \
00414         break;  \
00415       mask=0x80;  \
00416     }  \
00417   runlength++;  \
00418   bit=(size_t) ((byte & mask) != 0 ? 0x01 : 0x00); \
00419   mask>>=1;  \
00420   if (bit != 0)  \
00421     runlength=0;  \
00422 }
00423 
00424   CacheView
00425     *image_view;
00426 
00427   const HuffmanTable
00428     *entry;
00429 
00430   HuffmanTable
00431     **mb_hash,
00432     **mw_hash;
00433 
00434   int
00435     byte;
00436 
00437   MagickBooleanType
00438     proceed;
00439 
00440   Quantum
00441     index;
00442 
00443   register ssize_t
00444     i;
00445 
00446   register unsigned char
00447     *p;
00448 
00449   size_t
00450     bit,
00451     code,
00452     mask,
00453     length,
00454     null_lines,
00455     runlength;
00456 
00457   ssize_t
00458     count,
00459     y;
00460 
00461   unsigned char
00462     *scanline;
00463 
00464   unsigned int
00465     bail,
00466     color;
00467 
00468   /*
00469     Allocate buffers.
00470   */
00471   assert(image != (Image *) NULL);
00472   assert(image->signature == MagickSignature);
00473   if (image->debug != MagickFalse)
00474     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00475   mb_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mb_hash));
00476   mw_hash=(HuffmanTable **) AcquireQuantumMemory(HashSize,sizeof(*mw_hash));
00477   scanline=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
00478     sizeof(*scanline));
00479   if ((mb_hash == (HuffmanTable **) NULL) ||
00480       (mw_hash == (HuffmanTable **) NULL) ||
00481       (scanline == (unsigned char *) NULL))
00482     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00483       image->filename);
00484   /*
00485     Initialize Huffman tables.
00486   */
00487   for (i=0; i < HashSize; i++)
00488   {
00489     mb_hash[i]=(HuffmanTable *) NULL;
00490     mw_hash[i]=(HuffmanTable *) NULL;
00491   }
00492   InitializeHashTable(mw_hash,TWTable,MWHashA,MWHashB);
00493   InitializeHashTable(mw_hash,MWTable,MWHashA,MWHashB);
00494   InitializeHashTable(mw_hash,EXTable,MWHashA,MWHashB);
00495   InitializeHashTable(mb_hash,TBTable,MBHashA,MBHashB);
00496   InitializeHashTable(mb_hash,MBTable,MBHashA,MBHashB);
00497   InitializeHashTable(mb_hash,EXTable,MBHashA,MBHashB);
00498   /*
00499     Uncompress 1D Huffman to runlength encoded pixels.
00500   */
00501   byte=0;
00502   mask=0;
00503   null_lines=0;
00504   runlength=0;
00505   while (runlength < 11)
00506    InputBit(bit);
00507   do { InputBit(bit); } while ((int) bit == 0);
00508   image->resolution.x=204.0;
00509   image->resolution.y=196.0;
00510   image->units=PixelsPerInchResolution;
00511   image_view=AcquireCacheView(image);
00512   for (y=0; ((y < (ssize_t) image->rows) && (null_lines < 3)); )
00513   {
00514     register Quantum
00515       *restrict q;
00516 
00517     register ssize_t
00518       x;
00519 
00520     /*
00521       Initialize scanline to white.
00522     */
00523     p=scanline;
00524     for (x=0; x < (ssize_t) image->columns; x++)
00525       *p++=(unsigned char) 0;
00526     /*
00527       Decode Huffman encoded scanline.
00528     */
00529     color=MagickTrue;
00530     code=0;
00531     count=0;
00532     length=0;
00533     runlength=0;
00534     x=0;
00535     for ( ; ; )
00536     {
00537       if (byte == EOF)
00538         break;
00539       if (x >= (ssize_t) image->columns)
00540         {
00541           while (runlength < 11)
00542             InputBit(bit);
00543           do { InputBit(bit); } while ((int) bit == 0);
00544           break;
00545         }
00546       bail=MagickFalse;
00547       do
00548       {
00549         if (runlength < 11)
00550           InputBit(bit)
00551         else
00552           {
00553             InputBit(bit);
00554             if ((int) bit != 0)
00555               {
00556                 null_lines++;
00557                 if (x != 0)
00558                   null_lines=0;
00559                 bail=MagickTrue;
00560                 break;
00561               }
00562           }
00563         code=(code << 1)+(size_t) bit;
00564         length++;
00565       } while (code == 0);
00566       if (bail != MagickFalse)
00567         break;
00568       if (length > 13)
00569         {
00570           while (runlength < 11)
00571            InputBit(bit);
00572           do { InputBit(bit); } while ((int) bit == 0);
00573           break;
00574         }
00575       if (color != MagickFalse)
00576         {
00577           if (length < 4)
00578             continue;
00579           entry=mw_hash[((length+MWHashA)*(code+MWHashB)) % HashSize];
00580         }
00581       else
00582         {
00583           if (length < 2)
00584             continue;
00585           entry=mb_hash[((length+MBHashA)*(code+MBHashB)) % HashSize];
00586         }
00587       if (entry == (const HuffmanTable *) NULL)
00588         continue;
00589       if ((entry->length != length) || (entry->code != code))
00590         continue;
00591       switch (entry->id)
00592       {
00593         case TWId:
00594         case TBId:
00595         {
00596           count+=(ssize_t) entry->count;
00597           if ((x+count) > (ssize_t) image->columns)
00598             count=(ssize_t) image->columns-x;
00599           if (count > 0)
00600             {
00601               if (color != MagickFalse)
00602                 {
00603                   x+=count;
00604                   count=0;
00605                 }
00606               else
00607                 for ( ; count > 0; count--)
00608                   scanline[x++]=(unsigned char) 1;
00609             }
00610           color=(unsigned int)
00611             ((color == MagickFalse) ? MagickTrue : MagickFalse);
00612           break;
00613         }
00614         case MWId:
00615         case MBId:
00616         case EXId:
00617         {
00618           count+=(ssize_t) entry->count;
00619           break;
00620         }
00621         default:
00622           break;
00623       }
00624       code=0;
00625       length=0;
00626     }
00627     /*
00628       Transfer scanline to image pixels.
00629     */
00630     p=scanline;
00631     q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
00632     if (q == (Quantum *) NULL)
00633       break;
00634     for (x=0; x < (ssize_t) image->columns; x++)
00635     {
00636       index=(Quantum) (*p++);
00637       SetPixelIndex(image,index,q);
00638       SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
00639       q+=GetPixelChannels(image);
00640     }
00641     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
00642       break;
00643     proceed=SetImageProgress(image,LoadImageTag,y,image->rows);
00644     if (proceed == MagickFalse)
00645       break;
00646     y++;
00647   }
00648   image_view=DestroyCacheView(image_view);
00649   image->rows=(size_t) MagickMax((size_t) y-3,1);
00650   image->compression=FaxCompression;
00651   /*
00652     Free decoder memory.
00653   */
00654   mw_hash=(HuffmanTable **) RelinquishMagickMemory(mw_hash);
00655   mb_hash=(HuffmanTable **) RelinquishMagickMemory(mb_hash);
00656   scanline=(unsigned char *) RelinquishMagickMemory(scanline);
00657   return(MagickTrue);
00658 }
00659 
00660 /*
00661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00662 %                                                                             %
00663 %                                                                             %
00664 %                                                                             %
00665 %   H u f f m a n E n c o d e I m a g e                                       %
00666 %                                                                             %
00667 %                                                                             %
00668 %                                                                             %
00669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00670 %
00671 %  HuffmanEncodeImage() compresses an image via Huffman-coding.
00672 %
00673 %  The format of the HuffmanEncodeImage method is:
00674 %
00675 %      MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
00676 %        Image *image,Image *inject_image,ExceptionInfo *exception)
00677 %
00678 %  A description of each parameter follows:
00679 %
00680 %    o image_info: the image info..
00681 %
00682 %    o image: the image.
00683 %
00684 %    o inject_image: inject into the image stream.
00685 %
00686 %    o exception: return any errors or warnings in this structure.
00687 %
00688 */
00689 MagickExport MagickBooleanType HuffmanEncodeImage(const ImageInfo *image_info,
00690   Image *image,Image *inject_image,ExceptionInfo *exception)
00691 {
00692 #define HuffmanOutputCode(entry)  \
00693 {  \
00694   mask=one << (entry->length-1);  \
00695   while (mask != 0)  \
00696   {  \
00697     OutputBit(((entry->code & mask) != 0 ? 1 : 0));  \
00698     mask>>=1;  \
00699   }  \
00700 }
00701 
00702 #define OutputBit(count)  \
00703 {  \
00704   if (count > 0)  \
00705     byte=byte | bit;  \
00706   bit>>=1;  \
00707   if ((int) (bit & 0xff) == 0)   \
00708     {  \
00709       if (LocaleCompare(image_info->magick,"FAX") == 0) \
00710         (void) WriteBlobByte(image,(unsigned char) byte);  \
00711       else \
00712         Ascii85Encode(image,byte); \
00713       byte='\0';  \
00714       bit=(unsigned char) 0x80;  \
00715     }  \
00716 }
00717 
00718   const HuffmanTable
00719     *entry;
00720 
00721   int
00722     k,
00723     runlength;
00724 
00725   Image
00726     *huffman_image;
00727 
00728   MagickBooleanType
00729     proceed;
00730 
00731   register ssize_t
00732     i,
00733     x;
00734 
00735   register const Quantum
00736     *p;
00737 
00738   register unsigned char
00739     *q;
00740 
00741   size_t
00742     mask,
00743     one,
00744     width;
00745 
00746   ssize_t
00747     n,
00748     y;
00749 
00750   unsigned char
00751     byte,
00752     bit,
00753     *scanline;
00754 
00755   /*
00756     Allocate scanline buffer.
00757   */
00758   assert(image_info != (ImageInfo *) NULL);
00759   assert(image_info->signature == MagickSignature);
00760   assert(image != (Image *) NULL);
00761   assert(image->signature == MagickSignature);
00762   if (image->debug != MagickFalse)
00763     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00764   assert(inject_image != (Image *) NULL);
00765   assert(inject_image->signature == MagickSignature);
00766   one=1;
00767   width=inject_image->columns;
00768   if (LocaleCompare(image_info->magick,"FAX") == 0)
00769     width=(size_t) MagickMax(inject_image->columns,1728);
00770   scanline=(unsigned char *) AcquireQuantumMemory((size_t) width+1UL,
00771     sizeof(*scanline));
00772   if (scanline == (unsigned char *) NULL)
00773     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
00774       inject_image->filename);
00775   (void) ResetMagickMemory(scanline,0,width*sizeof(*scanline));
00776   huffman_image=CloneImage(inject_image,0,0,MagickTrue,exception);
00777   if (huffman_image == (Image *) NULL)
00778     {
00779       scanline=(unsigned char *) RelinquishMagickMemory(scanline);
00780       return(MagickFalse);
00781     }
00782   (void) SetImageType(huffman_image,BilevelType,exception);
00783   byte='\0';
00784   bit=(unsigned char) 0x80;
00785   if (LocaleCompare(image_info->magick,"FAX") != 0)
00786     Ascii85Initialize(image);
00787   else
00788     {
00789       /*
00790         End of line.
00791       */
00792       for (k=0; k < 11; k++)
00793         OutputBit(0);
00794       OutputBit(1);
00795     }
00796   /*
00797     Compress to 1D Huffman pixels.
00798   */
00799   q=scanline;
00800   for (y=0; y < (ssize_t) huffman_image->rows; y++)
00801   {
00802     p=GetVirtualPixels(huffman_image,0,y,huffman_image->columns,1,exception);
00803     if (p == (const Quantum *) NULL)
00804       break;
00805     for (x=0; x < (ssize_t) huffman_image->columns; x++)
00806     {
00807       *q++=(unsigned char) (GetPixelIntensity(huffman_image,p) >=
00808         ((MagickRealType) QuantumRange/2.0) ? 0 : 1);
00809       p+=GetPixelChannels(huffman_image);
00810     }
00811     /*
00812       Huffman encode scanline.
00813     */
00814     q=scanline;
00815     for (n=(ssize_t) width; n > 0; )
00816     {
00817       /*
00818         Output white run.
00819       */
00820       for (runlength=0; ((n > 0) && (*q == 0)); n--)
00821       {
00822         q++;
00823         runlength++;
00824       }
00825       if (runlength >= 64)
00826         {
00827           if (runlength < 1792)
00828             entry=MWTable+((runlength/64)-1);
00829           else
00830             entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
00831           runlength-=(long) entry->count;
00832           HuffmanOutputCode(entry);
00833         }
00834       entry=TWTable+MagickMin((size_t) runlength,63);
00835       HuffmanOutputCode(entry);
00836       if (n != 0)
00837         {
00838           /*
00839             Output black run.
00840           */
00841           for (runlength=0; ((*q != 0) && (n > 0)); n--)
00842           {
00843             q++;
00844             runlength++;
00845           }
00846           if (runlength >= 64)
00847             {
00848               entry=MBTable+((runlength/64)-1);
00849               if (runlength >= 1792)
00850                 entry=EXTable+(MagickMin((size_t) runlength,2560)-1792)/64;
00851               runlength-=(long) entry->count;
00852               HuffmanOutputCode(entry);
00853             }
00854           entry=TBTable+MagickMin((size_t) runlength,63);
00855           HuffmanOutputCode(entry);
00856         }
00857     }
00858     /*
00859       End of line.
00860     */
00861     for (k=0; k < 11; k++)
00862       OutputBit(0);
00863     OutputBit(1);
00864     q=scanline;
00865     if (GetPreviousImageInList(huffman_image) == (Image *) NULL)
00866       {
00867         proceed=SetImageProgress(huffman_image,LoadImageTag,y,
00868           huffman_image->rows);
00869         if (proceed == MagickFalse)
00870           break;
00871       }
00872   }
00873   /*
00874     End of page.
00875   */
00876   for (i=0; i < 6; i++)
00877   {
00878     for (k=0; k < 11; k++)
00879       OutputBit(0);
00880     OutputBit(1);
00881   }
00882   /*
00883     Flush bits.
00884   */
00885   if (((int) bit != 0x80) != 0)
00886     {
00887       if (LocaleCompare(image_info->magick,"FAX") == 0)
00888         (void) WriteBlobByte(image,byte);
00889       else
00890         Ascii85Encode(image,byte);
00891     }
00892   if (LocaleCompare(image_info->magick,"FAX") != 0)
00893     Ascii85Flush(image);
00894   huffman_image=DestroyImage(huffman_image);
00895   scanline=(unsigned char *) RelinquishMagickMemory(scanline);
00896   return(MagickTrue);
00897 }
00898 
00899 /*
00900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00901 %                                                                             %
00902 %                                                                             %
00903 %                                                                             %
00904 %   L Z W E n c o d e I m a g e                                               %
00905 %                                                                             %
00906 %                                                                             %
00907 %                                                                             %
00908 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00909 %
00910 %  LZWEncodeImage() compresses an image via LZW-coding specific to Postscript
00911 %  Level II or Portable Document Format.
00912 %
00913 %  The format of the LZWEncodeImage method is:
00914 %
00915 %      MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
00916 %        unsigned char *pixels,ExceptionInfo *exception)
00917 %
00918 %  A description of each parameter follows:
00919 %
00920 %    o image: the image.
00921 %
00922 %    o length:  A value that specifies the number of pixels to compress.
00923 %
00924 %    o pixels: the address of an unsigned array of characters containing the
00925 %      pixels to compress.
00926 %
00927 %    o exception: return any errors or warnings in this structure.
00928 %
00929 */
00930 MagickExport MagickBooleanType LZWEncodeImage(Image *image,const size_t length,
00931   unsigned char *pixels,ExceptionInfo *exception)
00932 {
00933 #define LZWClr  256UL  /* Clear Table Marker */
00934 #define LZWEod  257UL  /* End of Data marker */
00935 #define OutputCode(code) \
00936 { \
00937     accumulator+=code << (32-code_width-number_bits); \
00938     number_bits+=code_width; \
00939     while (number_bits >= 8) \
00940     { \
00941         (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24)); \
00942         accumulator=accumulator << 8; \
00943         number_bits-=8; \
00944     } \
00945 }
00946 
00947   typedef struct _TableType
00948   {
00949     ssize_t
00950       prefix,
00951       suffix,
00952       next;
00953   } TableType;
00954 
00955   register ssize_t
00956     i;
00957 
00958   size_t
00959     accumulator,
00960     number_bits,
00961     code_width,
00962     last_code,
00963     next_index;
00964 
00965   ssize_t
00966     index;
00967 
00968   TableType
00969     *table;
00970 
00971   /*
00972     Allocate string table.
00973   */
00974   assert(image != (Image *) NULL);
00975   assert(image->signature == MagickSignature);
00976   if (image->debug != MagickFalse)
00977     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00978   assert(pixels != (unsigned char *) NULL);
00979   table=(TableType *) AcquireQuantumMemory(1UL << 12,sizeof(*table));
00980   if (table == (TableType *) NULL)
00981     return(MagickFalse);
00982   /*
00983     Initialize variables.
00984   */
00985   accumulator=0;
00986   code_width=9;
00987   number_bits=0;
00988   last_code=0;
00989   OutputCode(LZWClr);
00990   for (index=0; index < 256; index++)
00991   {
00992     table[index].prefix=(-1);
00993     table[index].suffix=(short) index;
00994     table[index].next=(-1);
00995   }
00996   next_index=LZWEod+1;
00997   code_width=9;
00998   last_code=(size_t) pixels[0];
00999   for (i=1; i < (ssize_t) length; i++)
01000   {
01001     /*
01002       Find string.
01003     */
01004     index=(ssize_t) last_code;
01005     while (index != -1)
01006       if ((table[index].prefix != (ssize_t) last_code) ||
01007           (table[index].suffix != (ssize_t) pixels[i]))
01008         index=table[index].next;
01009       else
01010         {
01011           last_code=(size_t) index;
01012           break;
01013         }
01014     if (last_code != (size_t) index)
01015       {
01016         /*
01017           Add string.
01018         */
01019         OutputCode(last_code);
01020         table[next_index].prefix=(ssize_t) last_code;
01021         table[next_index].suffix=(short) pixels[i];
01022         table[next_index].next=table[last_code].next;
01023         table[last_code].next=(ssize_t) next_index;
01024         next_index++;
01025         /*
01026           Did we just move up to next bit width?
01027         */
01028         if ((next_index >> code_width) != 0)
01029           {
01030             code_width++;
01031             if (code_width > 12)
01032               {
01033                 /*
01034                   Did we overflow the max bit width?
01035                 */
01036                 code_width--;
01037                 OutputCode(LZWClr);
01038                 for (index=0; index < 256; index++)
01039                 {
01040                   table[index].prefix=(-1);
01041                   table[index].suffix=index;
01042                   table[index].next=(-1);
01043                 }
01044                 next_index=LZWEod+1;
01045                 code_width=9;
01046               }
01047             }
01048           last_code=(size_t) pixels[i];
01049       }
01050   }
01051   /*
01052     Flush tables.
01053   */
01054   OutputCode(last_code);
01055   OutputCode(LZWEod);
01056   if (number_bits != 0)
01057     (void) WriteBlobByte(image,(unsigned char) (accumulator >> 24));
01058   table=(TableType *) RelinquishMagickMemory(table);
01059   return(MagickTrue);
01060 }
01061 
01062 /*
01063 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01064 %                                                                             %
01065 %                                                                             %
01066 %                                                                             %
01067 %   P a c k b i t s E n c o d e I m a g e                                     %
01068 %                                                                             %
01069 %                                                                             %
01070 %                                                                             %
01071 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01072 %
01073 %  PackbitsEncodeImage() compresses an image via Macintosh Packbits encoding
01074 %  specific to Postscript Level II or Portable Document Format.  To ensure
01075 %  portability, the binary Packbits bytes are encoded as ASCII Base-85.
01076 %
01077 %  The format of the PackbitsEncodeImage method is:
01078 %
01079 %      MagickBooleanType PackbitsEncodeImage(Image *image,const size_t length,
01080 %        unsigned char *pixels)
01081 %
01082 %  A description of each parameter follows:
01083 %
01084 %    o image: the image.
01085 %
01086 %    o length:  A value that specifies the number of pixels to compress.
01087 %
01088 %    o pixels: the address of an unsigned array of characters containing the
01089 %      pixels to compress.
01090 %
01091 */
01092 MagickExport MagickBooleanType PackbitsEncodeImage(Image *image,
01093   const size_t length,unsigned char *pixels,ExceptionInfo *exception)
01094 {
01095   int
01096     count;
01097 
01098   register ssize_t
01099     i,
01100     j;
01101 
01102   unsigned char
01103     *packbits;
01104 
01105   /*
01106     Compress pixels with Packbits encoding.
01107   */
01108   assert(image != (Image *) NULL);
01109   assert(image->signature == MagickSignature);
01110   if (image->debug != MagickFalse)
01111     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01112   assert(pixels != (unsigned char *) NULL);
01113   packbits=(unsigned char *) AcquireQuantumMemory(128UL,sizeof(*packbits));
01114   if (packbits == (unsigned char *) NULL)
01115     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
01116       image->filename);
01117   for (i=(ssize_t) length; i != 0; )
01118   {
01119     switch (i)
01120     {
01121       case 1:
01122       {
01123         i--;
01124         (void) WriteBlobByte(image,(unsigned char) 0);
01125         (void) WriteBlobByte(image,*pixels);
01126         break;
01127       }
01128       case 2:
01129       {
01130         i-=2;
01131         (void) WriteBlobByte(image,(unsigned char) 1);
01132         (void) WriteBlobByte(image,*pixels);
01133         (void) WriteBlobByte(image,pixels[1]);
01134         break;
01135       }
01136       case 3:
01137       {
01138         i-=3;
01139         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
01140           {
01141             (void) WriteBlobByte(image,(unsigned char) ((256-3)+1));
01142             (void) WriteBlobByte(image,*pixels);
01143             break;
01144           }
01145         (void) WriteBlobByte(image,(unsigned char) 2);
01146         (void) WriteBlobByte(image,*pixels);
01147         (void) WriteBlobByte(image,pixels[1]);
01148         (void) WriteBlobByte(image,pixels[2]);
01149         break;
01150       }
01151       default:
01152       {
01153         if ((*pixels == *(pixels+1)) && (*(pixels+1) == *(pixels+2)))
01154           {
01155             /*
01156               Packed run.
01157             */
01158             count=3;
01159             while (((ssize_t) count < i) && (*pixels == *(pixels+count)))
01160             {
01161               count++;
01162               if (count >= 127)
01163                 break;
01164             }
01165             i-=count;
01166             (void) WriteBlobByte(image,(unsigned char) ((256-count)+1));
01167             (void) WriteBlobByte(image,*pixels);
01168             pixels+=count;
01169             break;
01170           }
01171         /*
01172           Literal run.
01173         */
01174         count=0;
01175         while ((*(pixels+count) != *(pixels+count+1)) ||
01176                (*(pixels+count+1) != *(pixels+count+2)))
01177         {
01178           packbits[count+1]=pixels[count];
01179           count++;
01180           if (((ssize_t) count >= (i-3)) || (count >= 127))
01181             break;
01182         }
01183         i-=count;
01184         *packbits=(unsigned char) (count-1);
01185         for (j=0; j <= (ssize_t) count; j++)
01186           (void) WriteBlobByte(image,packbits[j]);
01187         pixels+=count;
01188         break;
01189       }
01190     }
01191   }
01192   (void) WriteBlobByte(image,(unsigned char) 128);  /* EOD marker */
01193   packbits=(unsigned char *) RelinquishMagickMemory(packbits);
01194   return(MagickTrue);
01195 }
01196 
01197 #if defined(MAGICKCORE_ZLIB_DELEGATE)
01198 /*
01199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01200 %                                                                             %
01201 %                                                                             %
01202 %                                                                             %
01203 %   Z L I B E n c o d e I m a g e                                             %
01204 %                                                                             %
01205 %                                                                             %
01206 %                                                                             %
01207 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01208 %
01209 %  ZLIBEncodeImage compresses an image via ZLIB-coding specific to
01210 %  Postscript Level II or Portable Document Format.
01211 %
01212 %  The format of the ZLIBEncodeImage method is:
01213 %
01214 %      MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
01215 %        unsigned char *pixels,ExceptionInfo *exception)
01216 %
01217 %  A description of each parameter follows:
01218 %
01219 %    o file: the address of a structure of type FILE.  ZLIB encoded pixels
01220 %      are written to this file.
01221 %
01222 %    o length:  A value that specifies the number of pixels to compress.
01223 %
01224 %    o pixels: the address of an unsigned array of characters containing the
01225 %      pixels to compress.
01226 %
01227 %    o exception: return any errors or warnings in this structure.
01228 %
01229 */
01230 
01231 static voidpf AcquireZIPMemory(voidpf context,unsigned int items,
01232   unsigned int size)
01233 {
01234   (void) context;
01235   return((voidpf) AcquireQuantumMemory(items,size));
01236 }
01237 
01238 static void RelinquishZIPMemory(voidpf context,voidpf memory)
01239 {
01240   (void) context;
01241   memory=RelinquishMagickMemory(memory);
01242 }
01243 
01244 MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,const size_t length,
01245   unsigned char *pixels,ExceptionInfo *exception)
01246 {
01247   int
01248     status;
01249 
01250   register ssize_t
01251     i;
01252 
01253   size_t
01254     compress_packets;
01255 
01256   unsigned char
01257     *compress_pixels;
01258 
01259   z_stream
01260     stream;
01261 
01262   assert(image != (Image *) NULL);
01263   assert(image->signature == MagickSignature);
01264   if (image->debug != MagickFalse)
01265     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01266   compress_packets=(size_t) (1.001*length+12);
01267   compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_packets,
01268     sizeof(*compress_pixels));
01269   if (compress_pixels == (unsigned char *) NULL)
01270     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
01271       image->filename);
01272   stream.next_in=pixels;
01273   stream.avail_in=(unsigned int) length;
01274   stream.next_out=compress_pixels;
01275   stream.avail_out=(unsigned int) compress_packets;
01276   stream.zalloc=AcquireZIPMemory;
01277   stream.zfree=RelinquishZIPMemory;
01278   stream.opaque=(voidpf) NULL;
01279   status=deflateInit(&stream,(int) (image->quality ==
01280     UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)));
01281   if (status == Z_OK)
01282     {
01283       status=deflate(&stream,Z_FINISH);
01284       if (status == Z_STREAM_END)
01285         status=deflateEnd(&stream);
01286       else
01287         (void) deflateEnd(&stream);
01288       compress_packets=(size_t) stream.total_out;
01289     }
01290   if (status != Z_OK)
01291     ThrowBinaryException(CoderError,"UnableToZipCompressImage",image->filename)
01292   else
01293     for (i=0; i < (ssize_t) compress_packets; i++)
01294       (void) WriteBlobByte(image,compress_pixels[i]);
01295   compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels);
01296   return(status == Z_OK ? MagickTrue : MagickFalse);
01297 }
01298 #else
01299 MagickExport MagickBooleanType ZLIBEncodeImage(Image *image,
01300   const size_t magick_unused(length),unsigned char *magick_unused(pixels))
01301 {
01302   assert(image != (Image *) NULL);
01303   assert(image->signature == MagickSignature);
01304   if (image->debug != MagickFalse)
01305     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01306   (void) ThrowMagickException(&image->exception,GetMagickModule(),
01307     MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZIP)",
01308     image->filename);
01309   return(MagickFalse);
01310 }
01311 #endif