flate.c
Go to the documentation of this file.
00001 /* Copyright (C) 2001-2007 Peter Selinger.
00002    This file is part of Potrace. It is free software and it is covered
00003    by the GNU General Public License. See the file COPYING for details. */
00004 
00005 /* $Id: flate.c 147 2007-04-09 00:44:09Z selinger $ */
00006 
00007 /* the PostScript compression module of Potrace. The basic interface
00008    is through the *_xship function, which processes a byte array and
00009    outputs it in compressed or verbatim form, depending on whether
00010    filter is 1 or 0. To flush the output, simply call with the empty
00011    string and filter=0. filter=2 is used to output encoded text but
00012    without the PostScript header to turn on the encoding. Each
00013    function has variants for shipping a single character, a
00014    null-terminated string, or a byte array. */
00015 
00016 /* different compression algorithms are available. There is
00017    dummy_xship, which is just the identity, and flate_xship, which
00018    uses zlib compression. Also, lzw_xship provides LZW compression
00019    from the file lzw.c/h. a85_xship provides a85-encoding without
00020    compression. Each function returns the actual number of characters
00021    written. */
00022 
00023 /* note: the functions provided here have global state and are not
00024    reentrant */
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include "config.h"
00028 #endif
00029 
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <stdlib.h>
00033 #include <errno.h>
00034 
00035 #ifdef HAVE_ZLIB
00036 #include <zlib.h>
00037 #endif
00038 
00039 #include "flate.h"
00040 #include "lzw.h"
00041 
00042 #define OUTSIZE 1000
00043 
00044 static int a85init(FILE *f);
00045 static int a85finish(FILE *f);
00046 static int a85write(FILE *f, char *buf, int n);
00047 static int a85out(FILE *f, int n);
00048 static int a85spool(FILE *f, char c);
00049 
00050 /* ---------------------------------------------------------------------- */
00051 /* dummy interface: no encoding */
00052 
00053 int dummy_xship(FILE *f, int filter, char *s, int len) {
00054   fwrite(s, 1, len, f);
00055   return len;
00056 }
00057 
00058 /* ---------------------------------------------------------------------- */
00059 /* flate interface: zlib (=postscript level 3) compression and a85 */
00060 
00061 #ifdef HAVE_ZLIB
00062 
00063 int pdf_xship(FILE *f, int filter, char *s, int len) {
00064         static int fstate = 0;
00065         static z_stream c_stream;
00066         char outbuf[OUTSIZE];
00067         int err;
00068         int n=0;
00069 
00070   if (filter && !fstate) {
00071     /* switch on filtering */
00072     c_stream.zalloc = Z_NULL;
00073     c_stream.zfree = Z_NULL;
00074     c_stream.opaque = Z_NULL;
00075     err = deflateInit(&c_stream, 9);
00076     if (err != Z_OK) {
00077       fprintf(stderr, "deflateInit: %s (%d)\n", c_stream.msg, err);
00078       exit(1);
00079     }
00080     c_stream.avail_in = 0;
00081     fstate = 1;
00082   } else if (!filter && fstate) {
00083     /* switch off filtering */
00084     /* flush stream */
00085     do {
00086       c_stream.next_out = (Bytef*)outbuf;
00087       c_stream.avail_out = OUTSIZE;
00088 
00089       err = deflate(&c_stream, Z_FINISH);
00090       if (err != Z_OK && err != Z_STREAM_END) {
00091         fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
00092         exit(1);
00093       }
00094       n += fwrite(outbuf, 1, OUTSIZE-c_stream.avail_out, f);
00095     } while (err != Z_STREAM_END);
00096 
00097     fstate = 0;
00098   }
00099   if (!fstate) {
00100     fwrite(s, 1, len, f);
00101     return n+len;
00102   }
00103   
00104   /* do the actual compression */
00105   c_stream.next_in = (Bytef*) s;
00106   c_stream.avail_in = len;
00107 
00108   do {
00109     c_stream.next_out = (Bytef*) outbuf;
00110     c_stream.avail_out = OUTSIZE;
00111 
00112     err = deflate(&c_stream, Z_NO_FLUSH);
00113     if (err != Z_OK) {
00114       fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
00115       exit(1);
00116     }
00117     n += fwrite(outbuf, 1, OUTSIZE-c_stream.avail_out, f);
00118   } while (!c_stream.avail_out);
00119   
00120   return n;
00121 }
00122 
00123 /* ship len bytes from s using zlib compression. */
00124 int flate_xship(FILE *f, int filter, char *s, int len) {
00125   static int fstate = 0;
00126   static z_stream c_stream;
00127   char outbuf[OUTSIZE];
00128   int err;
00129   int n=0;
00130 
00131   if (filter && !fstate) {
00132     /* switch on filtering */
00133     if (filter == 1) {
00134       n += fprintf(f, "currentfile /ASCII85Decode filter /FlateDecode filter cvx exec\n");
00135     }
00136     c_stream.zalloc = Z_NULL;
00137     c_stream.zfree = Z_NULL;
00138     c_stream.opaque = Z_NULL;
00139     err = deflateInit(&c_stream, 9);
00140     if (err != Z_OK) {
00141       fprintf(stderr, "deflateInit: %s (%d)\n", c_stream.msg, err);
00142       exit(1);
00143     }
00144     c_stream.avail_in = 0;
00145     n += a85init(f);
00146     fstate = 1;
00147   } else if (!filter && fstate) {
00148     /* switch off filtering */
00149     /* flush stream */
00150     do {
00151       c_stream.next_out = (Bytef*)outbuf;
00152       c_stream.avail_out = OUTSIZE;
00153 
00154       err = deflate(&c_stream, Z_FINISH);
00155       if (err != Z_OK && err != Z_STREAM_END) {
00156         fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
00157         exit(1);
00158       }
00159       n += a85write(f, outbuf, OUTSIZE-c_stream.avail_out);
00160     } while (err != Z_STREAM_END);
00161 
00162     n += a85finish(f);
00163 
00164     fstate = 0;
00165   }
00166   if (!fstate) {
00167     fwrite(s, 1, len, f);
00168     return n+len;
00169   }
00170   
00171   /* do the actual compression */
00172   c_stream.next_in = (Bytef*) s;
00173   c_stream.avail_in = len;
00174 
00175   do {
00176     c_stream.next_out = (Bytef*) outbuf;
00177     c_stream.avail_out = OUTSIZE;
00178 
00179     err = deflate(&c_stream, Z_NO_FLUSH);
00180     if (err != Z_OK) {
00181       fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
00182       exit(1);
00183     }
00184     n += a85write(f, outbuf, OUTSIZE-c_stream.avail_out);
00185   } while (!c_stream.avail_out);
00186   
00187   return n;
00188 }
00189 
00190 #else  /* HAVE_ZLIB */
00191 
00192 int pdf_xship(FILE *f, int filter, char *s, int len) {
00193   return dummy_xship(f, filter, s, len);
00194 }
00195 
00196 int flate_xship(FILE *f, int filter, char *s, int len) {
00197   return dummy_xship(f, filter, s, len);
00198 }
00199 
00200 #endif /* HAVE_ZLIB */
00201 
00202 /* ---------------------------------------------------------------------- */
00203 /* lzw interface: LZW (=postscript level 2) compression with a85.
00204    This relies on lzw.c/h to do the actual compression. */
00205 
00206 /* use Postscript level 2 compression. Ship len bytes from str. */
00207 int lzw_xship(FILE *f, int filter, char *str, int len) {
00208   static int fstate = 0;
00209   static lzw_stream_t *s = NULL;
00210   char outbuf[OUTSIZE];
00211   int err;
00212   int n=0;
00213 
00214   if (filter && !fstate) {
00215     /* switch on filtering */
00216     if (filter == 1) {
00217       n += fprintf(f, "currentfile /ASCII85Decode filter /LZWDecode filter cvx exec\n");
00218     }
00219     s = lzw_init();
00220     if (s == NULL) {
00221       fprintf(stderr, "lzw_init: %s\n", strerror(errno));
00222       exit(1);
00223     }
00224     n += a85init(f);
00225     fstate = 1;
00226   } else if (!filter && fstate) {
00227     /* switch off filtering */
00228     /* flush stream */
00229     s->next_in = 0;
00230     s->avail_in = 0;
00231     do {
00232       s->next_out = outbuf;
00233       s->avail_out = OUTSIZE;
00234 
00235       err = lzw_compress(s, LZW_EOD);
00236       if (err) {
00237         fprintf(stderr, "lzw_compress: %s\n", strerror(errno));
00238         exit(1);
00239       }
00240       n += a85write(f, outbuf, OUTSIZE - s->avail_out);
00241     } while (s->avail_out == 0);
00242 
00243     n += a85finish(f);
00244 
00245     lzw_free(s);
00246     s = NULL;
00247 
00248     fstate = 0;
00249   }
00250   if (!fstate) {
00251     fwrite(str, 1, len, f);
00252     return n+len;
00253   }
00254   
00255   /* do the actual compression */
00256   s->next_in = str;
00257   s->avail_in = len;
00258 
00259   do {
00260     s->next_out = outbuf;
00261     s->avail_out = OUTSIZE;
00262 
00263     err = lzw_compress(s, LZW_NORMAL);
00264     if (err) {
00265       fprintf(stderr, "lzw_compress: %s\n", strerror(errno));
00266       exit(1);
00267     }
00268     n += a85write(f, outbuf, OUTSIZE - s->avail_out);
00269   } while (s->avail_out == 0);
00270   
00271   return n;
00272 }
00273 
00274 /* ---------------------------------------------------------------------- */
00275 /* a85 interface: a85 encoding without compression */
00276 
00277 /* ship len bytes from s using a85 encoding only. */
00278 int a85_xship(FILE *f, int filter, char *s, int len) {
00279   static int fstate = 0;
00280   int n=0;
00281 
00282   if (filter && !fstate) {
00283     /* switch on filtering */
00284     if (filter == 1) {
00285       n += fprintf(f, "currentfile /ASCII85Decode filter cvx exec\n");
00286     }
00287     n += a85init(f);
00288     fstate = 1;
00289   } else if (!filter && fstate) {
00290     /* switch off filtering */
00291     /* flush stream */
00292     n += a85finish(f);
00293     fstate = 0;
00294   }
00295   if (!fstate) {
00296     fwrite(s, 1, len, f);
00297     return n+len;
00298   }
00299   
00300   n += a85write(f, s, len);
00301   
00302   return n;
00303 }
00304 
00305 /* ---------------------------------------------------------------------- */
00306 /* low-level a85 backend */
00307 
00308 static unsigned long a85buf[4];
00309 static int a85n;
00310 static int a85col;
00311 
00312 static int a85init(FILE *f) {
00313   a85n = 0;
00314   a85col = 0;
00315   return 0;
00316 }
00317 
00318 static int a85finish(FILE *f) {
00319   int r=0;
00320 
00321   if (a85n) {
00322     r+=a85out(f, a85n);
00323   }
00324   fputs("~>\n", f);
00325   return r+2;
00326 }
00327 
00328 static int a85write(FILE *f, char *buf, int n) {
00329   int i;
00330   int r=0;
00331 
00332   for (i=0; i<n; i++) {
00333     a85buf[a85n] = (unsigned char)buf[i];
00334     a85n++;
00335     
00336     if (a85n == 4) {
00337       r+=a85out(f, 4);
00338       a85n = 0;
00339     }
00340   }
00341   return r;
00342 }
00343 
00344 static int a85out(FILE *f, int n) {
00345   char out[5];
00346   unsigned long s;
00347   int r=0;
00348   int i;
00349 
00350   for (i=n; i<4; i++) {
00351     a85buf[i] = 0;
00352   }
00353 
00354   s = (a85buf[0]<<24) + (a85buf[1]<<16) + (a85buf[2]<<8) + (a85buf[3]<<0);
00355 
00356   if (!s) {
00357     r+=a85spool(f, 'z');
00358   } else {
00359     for (i=4; i>=0; i--) {
00360       out[i] = s % 85;
00361       s /= 85;
00362     }
00363     for (i=0; i<n+1; i++) {
00364       r+=a85spool(f, out[i]+33);
00365     }
00366   } 
00367   return r;
00368 }
00369 
00370 static int a85spool(FILE *f, char c) {
00371   fputc(c, f);
00372 
00373   a85col++;
00374   if (a85col>70) {
00375     fputc('\n', f);
00376     a85col=0;
00377     return 2;
00378   }
00379   
00380   return 1;
00381 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


portrait_painter
Author(s): Niklas Meinzer, Ina Baumgarten
autogenerated on Wed Dec 26 2012 16:00:43