-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi,
I attach a new patch trying to adapt the LZW filter implementation to the new filter API. Some comments: 1. The filter now works with any cache size. I tested with the submited test cases (from the standard specification) and long playing with pdf-filter :) 2. Because of the cache size stuff, those embarrassing weird goto's are kept. Maybe we can consider allowing the filters specify a "minimum-cache" parameter to avoid non-necessary code bloat and/or efficiency tradeoffs? 3. I added the pdf-filter patch submitted by jemarch the other day. 4. I factored out the test cases sent by Brad Hards using fixtures to allocate/deallocate the stream. This may cause an overhead in the overall runing time as the fixture is setup/teareddown on every test cases. I still think that it would be useful to factor-out other tests to use this fixture and so avoid setup/dealloc boilerplate -I did not do it in case their authors disagree. 5. I disabled the tokenizer utility, it seems that a header file was forgotten in the last commit. 6. Many thanks to Brad Hards for his work in this task. Enjoy :) JP -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkpGq88ACgkQchi8veCammch/ACgnWu88IA2zgJOnG58MdaAcM60 TgEAnAllNQRLslljhfNYfjThT8zTasn2 =REVR -----END PGP SIGNATURE-----
# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: [email protected] # target_branch: http://bzr.savannah.gnu.org/r/pdf/libgnupdf/branches\ # /trunk/ # testament_sha1: 6260da11d5ebb802e1a33b95dd7ec3a00cf74f2d # timestamp: 2009-06-28 01:20:01 +0200 # base_revision_id: [email protected] # # Begin patch === modified file 'AUTHORS' --- AUTHORS 2009-06-24 19:25:52 +0000 +++ AUTHORS 2009-06-27 23:19:51 +0000 @@ -282,6 +282,7 @@ and changed utils/pdf-filter.c utils/pdf-filter.h src/base/pdf-stm.c src/base/pdf-stm.h src/base/pdf-stm-be.c src/base/pdf-stm-be.h + torture/unit/base/stm/pdf-stm-write.c Karl Berry: changed doc/gnupdf.texi doc/gnupdf-utils.texi doc/Makefile.am === modified file 'ChangeLog' --- ChangeLog 2009-06-24 19:25:52 +0000 +++ ChangeLog 2009-06-27 23:19:51 +0000 @@ -1,3 +1,16 @@ +2009-06-28 Juan Pedro BolÃvar Puente <[email protected]> + + * src/base/pdf-stm-f-lzw.c: port of LZW filter to new API + * src/base/pdf-stm-f-lzw.h: likewise + * src/base/pdf-stm-filter.c: likewise + * src/base/pdf-stm-filter.h: likewise + * src/Makefile.am: integrate pdf-stm-f-lzw.[c,h] back into build + system + * torture/unit/base/stm/pdf-stm-write.c: add test case from PDF + specification version 1.7. + * (Brad Hards contributed to this patch) + * util/pdf-filter.c: added LZW filter. (by Jose E. Marchesi) + 2009-06-24 Jose E. Marchesi <[email protected]> * doc/pdf-tokeniser.1: New file, generated from @@ -14,6 +27,19 @@ * utils/pdf-tokeniser.c: Renamed from 'utils/toktest.c'. + +2009-06-24 Jose E. Marchesi <[email protected]> + + * src/base/pdf-hash-helper.h: Added functions 'pdf_hash_add_bool' + and 'pdf_hash_get_bool'. + + * src/base/pdf-hash-helper.c: Likewise. + + * utils/pdf-filter.h: Added support for the LZW filters. + + * utils/pdf-filter.c: Likewise. + + 2009-06-22 Brad Hards <[email protected]> * src/base/pdf-text.c (pdf_text_dup): Protect against NULL arg. === modified file 'src/Makefile.am' --- src/Makefile.am 2009-05-20 15:54:43 +0000 +++ src/Makefile.am 2009-06-27 23:19:51 +0000 @@ -46,7 +46,8 @@ base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c \ base/pdf-stm-f-v2.h base/pdf-stm-f-v2.c \ base/pdf-stm-f-aesv2.h base/pdf-stm-f-aesv2.c \ - base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c + base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c \ + base/pdf-stm-f-lzw.h base/pdf-stm-f-lzw.c if ZLIB STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h === modified file 'src/base/pdf-hash-helper.c' --- src/base/pdf-hash-helper.c 2009-01-27 20:59:40 +0000 +++ src/base/pdf-hash-helper.c 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "09/01/27 21:37:10 jemarch" +/* -*- mode: C -*- Time-stamp: "09/06/24 20:13:29 jemarch" * * File: pdf-hash-helper.c * Date: Thu Jul 24 21:05:05 2008 @@ -97,6 +97,37 @@ } pdf_status_t +pdf_hash_add_bool (pdf_hash_t table, const char *key, const pdf_bool_t elt) +{ + pdf_bool_t *vbool; + + vbool = pdf_alloc (sizeof(pdf_bool_t)); + if (vbool == NULL) + { + return PDF_ERROR; + } + + *vbool = elt; + + return (pdf_hash_add (table, key, vbool, pdf_dealloc)); +} + +pdf_status_t +pdf_hash_get_bool (pdf_hash_t table, const char *key, pdf_bool_t *elt) +{ + pdf_status_t ret; + pdf_bool_t *vbool; + + ret = pdf_hash_get (table, key, (const void **) &vbool); + if (ret == PDF_OK) + { + *elt = *vbool; + } + + return ret; +} + +pdf_status_t pdf_hash_add_size (pdf_hash_t table, const char *key, const pdf_size_t elt) { pdf_size_t *size; === modified file 'src/base/pdf-hash-helper.h' --- src/base/pdf-hash-helper.h 2008-12-28 01:13:47 +0000 +++ src/base/pdf-hash-helper.h 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/12/28 02:10:50 jemarch" +/* -*- mode: C -*- Time-stamp: "09/06/24 20:13:57 jemarch" * * File: pdf-hash-helper.h * Date: Thu Jul 24 21:05:05 2008 @@ -73,6 +73,12 @@ pdf_hash_get_size (pdf_hash_t table, const char *key, pdf_size_t *elt); pdf_status_t +pdf_hash_add_bool (pdf_hash_t table, const char *key, const pdf_bool_t elt); + +pdf_status_t +pdf_hash_get_bool (pdf_hash_t table, const char *key, pdf_bool_t *elt); + +pdf_status_t pdf_hash_add_string (pdf_hash_t table, const char *key, const pdf_char_t *elt); pdf_status_t === modified file 'src/base/pdf-stm-f-lzw.c' --- src/base/pdf-stm-f-lzw.c 2009-01-11 21:37:29 +0000 +++ src/base/pdf-stm-f-lzw.c 2009-06-27 23:19:51 +0000 @@ -1,9 +1,9 @@ -/* -*- mode: C -*- Time-stamp: "09/01/11 22:04:33 jemarch" +/* -*- mode: C -*- Time-stamp: "2009-06-28 00:40:49 raskolnikov" * * File: pdf-stm-f-lzw.c * Date: Wed Aug 15 14:41:18 2007 * - * GNU PDF Library - LWZ encoder/decoder filter + * GNU PDF Library - LZW encoder/decoder filter * */ @@ -25,23 +25,23 @@ #include <string.h> #include <pdf-alloc.h> +#include <pdf-hash-helper.h> #include <pdf-stm-f-lzw.h> -#define MIN_BITSIZE 9 -#define MAX_BITSIZE 12 -#define MAX_DICTSIZE (1 << MAX_BITSIZE) - -#define MAX_COMPRESSION_FACTOR 1.5 - -#define NULL_INDEX ~0U - -enum { - LZW_RESET_CODE = 256, - LZW_EOD_CODE, - LZW_FIRST_CODE -} lzw_special_codes; - - +#define LZW_DEFAULT_EARLY_CHANGE 1 + +#define LZW_CACHE_SIZE 16 +#define LZW_MIN_BITSIZE 9 +#define LZW_MAX_BITSIZE 12 +#define LZW_MAX_DICTSIZE (1 << LZW_MAX_BITSIZE) +#define LZW_NULL_INDEX ~0U + +enum lzw_special_codes_e + { + LZW_RESET_CODE = 256, + LZW_EOD_CODE, + LZW_FIRST_CODE + }; /* -- LZW code output/input -- */ @@ -49,54 +49,79 @@ * Object to read and write codes of variable bitsize in a buffer. * Warning: using both get and put functions may break the buffer. */ -typedef struct lzw_buffer_s +struct lzw_buffer_s { - pdf_char_t* curp; - pdf_char_t* endp; + pdf_buffer_t buf; + pdf_char_t cache [LZW_CACHE_SIZE]; + int cache_rp; + int cache_wp; unsigned long valbuf; - unsigned valbits; - unsigned bitsize; - unsigned maxval; -} lzw_buffer_t; + int valbits; + int bitsize; + int maxval; +}; +typedef struct lzw_buffer_s* lzw_buffer_t; static void -lzw_buffer_init (lzw_buffer_t* b, - pdf_char_t* ptr, - int size, +lzw_buffer_init (lzw_buffer_t b, int bitsize) { - b->curp = ptr; - b->endp = ptr + size; + b->buf = NULL; b->valbuf = 0; b->valbits = 0; b->bitsize = bitsize; b->maxval = (1 << bitsize) - 1; -} - -static unsigned int -lzw_buffer_get_code (lzw_buffer_t* b) + b->cache_wp = 0; + b->cache_rp = 0; +} + +static void +lzw_buffer_set (lzw_buffer_t b, + pdf_buffer_t buf) +{ + b->buf = buf; +} + +static pdf_status_t +lzw_buffer_get_code (lzw_buffer_t b, + unsigned int* code, + pdf_bool_t finish_p) { unsigned long r; - - while (b->valbits <= 24) - { - if (b->curp > b->endp) - return NULL_INDEX; - - b->valbuf |= (unsigned long) *b->curp++ << (24 - b->valbits); - b->valbits += 8; - } + + while (b->valbits <= 24 && !finish_p) + { + if (pdf_buffer_eob_p (b->buf)) + { + return PDF_ENINPUT; + } + else + { + b->valbuf |= + (unsigned int) b->buf->data [b->buf->rp++] << + (24 - b->valbits); + + b->valbits += 8; + } + } + + if (b->valbits < b->bitsize) + { + return PDF_EEOF; + } r = b->valbuf >> (32 - b->bitsize); b->valbuf <<= b->bitsize; b->valbits -= b->bitsize; - - return r; + + *code = r; + + return PDF_OK; } /* Once finished, call with 0 as code value to flush the buffer. */ static void -lzw_buffer_put_code (lzw_buffer_t* b, +lzw_buffer_put_code (lzw_buffer_t b, unsigned int code) { b->valbuf |= (unsigned long) code << (32 - b->bitsize - b->valbits); @@ -104,17 +129,46 @@ while (b->valbits >= 8) { - *b->curp++ = b->valbuf >> 24; + if (pdf_buffer_full_p (b->buf)) + { + b->cache [b->cache_wp++] = (pdf_char_t) (b->valbuf >> 24); + } + else + { + b->buf->data [b->buf->wp++] = (pdf_char_t) (b->valbuf >> 24); + } b->valbuf <<= 8; b->valbits -= 8; } } +static pdf_status_t +lzw_buffer_flush (lzw_buffer_t b) +{ + while (b->cache_rp != b->cache_wp && + !pdf_buffer_full_p (b->buf)) + { + b->buf->data [b->buf->wp++] = b->cache [b->cache_rp++]; + } + + if (pdf_buffer_full_p (b->buf)) + { + return PDF_ENOUTPUT; + } + + b->cache_wp = 0; + b->cache_rp = 0; + + return PDF_OK; +} + static int -lzw_buffer_inc_bitsize (lzw_buffer_t* b) +lzw_buffer_inc_bitsize (lzw_buffer_t b) { - if (b->bitsize == MAX_BITSIZE) - return PDF_ERROR; + if (b->bitsize == LZW_MAX_BITSIZE) + { + return PDF_ERROR; + } ++b->bitsize; b->maxval = (1 << b->bitsize) - 1; @@ -123,20 +177,19 @@ } static void -lzw_buffer_set_bitsize (lzw_buffer_t* b, +lzw_buffer_set_bitsize (lzw_buffer_t b, int newsize) { b->bitsize = newsize; b->maxval = (1 << newsize) - 1; } - /* -- LZW dictionary handler -- */ /* * The strings are stored in a non balanced ordered binary tree. */ -typedef struct lzw_string_s +struct lzw_string_s { unsigned prefix; /* Prefix string code */ pdf_char_t suffix; /* Appended character */ @@ -144,44 +197,48 @@ unsigned first; /* First string with the same prefix. */ unsigned left; /* Next string with smaller suffix and same prefix. */ unsigned right; /* Next string with greater suffix and same prefix. */ -} lzw_string_t; +}; + +typedef struct lzw_string_s* lzw_string_t; static void -lzw_string_init (lzw_string_t* s) +lzw_string_init (lzw_string_t s) { - memset(s, 0xFF, sizeof(lzw_string_t)); + memset (s, 0xFF, sizeof (struct lzw_string_s)); } - -typedef struct lzw_dict_s +struct lzw_dict_s { - lzw_string_t table[MAX_DICTSIZE]; + struct lzw_string_s table [LZW_MAX_DICTSIZE]; unsigned size; -} lzw_dict_t; +}; +typedef struct lzw_dict_s* lzw_dict_t; static void -lzw_dict_init (lzw_dict_t* d) +lzw_dict_init (lzw_dict_t d) { int i; - memset(d->table, 0xFF, sizeof(lzw_string_t) * MAX_DICTSIZE); + memset (d->table, + 0xFF, + sizeof (struct lzw_string_s) * LZW_MAX_DICTSIZE); for (i = 0; i < LZW_FIRST_CODE; i++) { - d->table[i].suffix = i; + d->table[i].suffix = (pdf_char_t) (i & 0xFF); } d->size = LZW_FIRST_CODE; } -static int -lzw_dict_add (lzw_dict_t* d, - lzw_string_t* s) +static pdf_bool_t +lzw_dict_add (lzw_dict_t d, + lzw_string_t s) { unsigned index; int must_add; - if (s->prefix == NULL_INDEX) + if (s->prefix == LZW_NULL_INDEX) { s->prefix = s->suffix; return PDF_FALSE; /* The string is a basic character, found! */ @@ -189,7 +246,7 @@ index = d->table[s->prefix].first; - if (index == NULL_INDEX) + if (index == LZW_NULL_INDEX) { d->table[s->prefix].first = d->size; } @@ -205,7 +262,7 @@ } else if (s->suffix < d->table[index].suffix) { - if (d->table[index].left == NULL_INDEX) + if (d->table[index].left == LZW_NULL_INDEX) { d->table[index].left = d->size; must_add = PDF_TRUE; @@ -217,7 +274,7 @@ } else { - if (d->table[index].right == NULL_INDEX) + if (d->table[index].right == LZW_NULL_INDEX) { d->table[index].right = d->size; must_add = PDF_TRUE; @@ -235,10 +292,14 @@ return PDF_TRUE; } -#define lzw_dict_reset lzw_dict_init +static void +lzw_dict_reset (lzw_dict_t dict) +{ + lzw_dict_init (dict); +} static void -lzw_dict_fast_add (lzw_dict_t* d, +lzw_dict_fast_add (lzw_dict_t d, unsigned prefix, pdf_char_t suffix) { @@ -248,309 +309,392 @@ } static void -lzw_dict_decode (lzw_dict_t* d, +lzw_dict_decode (lzw_dict_t d, unsigned code, pdf_char_t** decode, unsigned* size) { *size = 0; - do { - *(*decode)-- = d->table[code].suffix; - ++(*size); - code = d->table[code].prefix; - } while (code != NULL_INDEX); + do + { + *(*decode)-- = d->table[code].suffix; + ++(*size); + code = d->table[code].prefix; + } + while (code != LZW_NULL_INDEX); + (*decode)++; - } -/* -- The encoder -- */ - -static int -pdf_stm_f_lzw_encode (pdf_stm_f_lzw_data_t data, - pdf_char_t *in, - pdf_stm_pos_t in_size, - pdf_char_t **out, - pdf_stm_pos_t *out_size) -{ - lzw_buffer_t buffer; - lzw_dict_t dict; - lzw_string_t string; - - /* Allocate buffer with enough space. */ - *out_size = in_size * MAX_COMPRESSION_FACTOR; - if ((*out = (pdf_char_t *) pdf_alloc (*out_size)) == NULL) +/* -- THE ENCODER -- */ + +struct lzwenc_state_s +{ + /* cached params */ + pdf_i32_t early_change; + + /* encoding state */ + pdf_bool_t must_reset_p; + struct lzw_buffer_s buffer; + struct lzw_dict_s dict; + struct lzw_string_s string; + + pdf_bool_t really_finish_p; +}; +typedef struct lzwenc_state_s* lzwenc_state_t; + +pdf_status_t +pdf_stm_f_lzwenc_init (pdf_hash_t params, + void **ext_state) +{ + pdf_char_t *early_change_str; + lzwenc_state_t state; + + state = pdf_alloc (sizeof (struct lzwenc_state_s)); + if (!state) { - *out_size = 0; return PDF_ERROR; } - - /* Do the actual encoding. */ - lzw_buffer_init(&buffer, *out, *out_size, MIN_BITSIZE); - lzw_dict_init(&dict); - lzw_string_init(&string); - - lzw_buffer_put_code(&buffer, LZW_RESET_CODE); - - while (--in_size >= 0) - { - string.suffix = *in++; - - if (lzw_dict_add(&dict, &string)) + + state->early_change = 1; /* set default */ + + if (pdf_hash_key_p (params, "EarlyChange") == PDF_TRUE) + { + pdf_hash_get_string (params, "EarlyChange", &early_change_str); + if (early_change_str[0] == '0') + { + state->early_change = 0; + } + } + + lzw_buffer_init (&state->buffer, LZW_MIN_BITSIZE); + lzw_dict_init (&state->dict); + lzw_string_init (&state->string); + state->must_reset_p = PDF_TRUE; + state->really_finish_p = PDF_FALSE; + + *ext_state = state; + return PDF_OK; +} + +pdf_status_t +pdf_stm_f_lzwenc_apply (pdf_hash_t params, + void *ext_state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p) +{ + pdf_status_t ret; + lzwenc_state_t st; + + ret = PDF_OK; + st = ext_state; + lzw_buffer_set (&st->buffer, out); + + ret = lzw_buffer_flush (&st->buffer); + if (ret != PDF_OK) + { + return ret; + } + + if (st->really_finish_p) + { + return PDF_EEOF; + } + + if (st->must_reset_p) + { + lzw_buffer_put_code (&st->buffer, LZW_RESET_CODE); + st->must_reset_p = PDF_FALSE; + } + + while (!pdf_buffer_eob_p (in) && + !pdf_buffer_full_p (out)) + { + st->string.suffix = in->data [in->rp++]; + if (lzw_dict_add (&st->dict, &st->string)) { - lzw_buffer_put_code(&buffer, string.prefix); - string.prefix = string.suffix; + lzw_buffer_put_code (&st->buffer, st->string.prefix); + st->string.prefix = st->string.suffix; - if (buffer.maxval - data->early_change == dict.size) + if (st->buffer.maxval - st->early_change == st->dict.size) { - if (!lzw_buffer_inc_bitsize(&buffer)) + if (!lzw_buffer_inc_bitsize(&st->buffer)) { - lzw_buffer_put_code(&buffer, LZW_RESET_CODE); - lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE); - lzw_dict_reset(&dict); + lzw_buffer_put_code (&st->buffer, LZW_RESET_CODE); + lzw_buffer_set_bitsize (&st->buffer, LZW_MIN_BITSIZE); + lzw_dict_reset (&st->dict); } } } } - - lzw_buffer_put_code(&buffer, string.prefix); - if (buffer.maxval - data->early_change == dict.size) - lzw_buffer_inc_bitsize(&buffer); - lzw_buffer_put_code(&buffer, LZW_EOD_CODE); - lzw_buffer_put_code(&buffer, 0); - - /* Resize buffer to fit the data. */ - *out_size = (buffer.curp - *out); - if ((*out = pdf_realloc(*out, *out_size)) == NULL) - { - *out_size = 0; - return PDF_ERROR; - } - - return PDF_OK; -} - -/* -- The decoder -- */ - -/* Utility to write to the output. */ - -typedef struct lzw_writer_s -{ - pdf_char_t* buf; - pdf_char_t* cur; - int writen; - int allocated; -} lzw_writer_t; - -static int -lzw_writer_init (lzw_writer_t* s, - int size) -{ - if ((s->buf = pdf_alloc(size)) == NULL) - { - return PDF_ERROR; - } - - s->cur = s->buf; - s->writen = 0; - s->allocated = size; - - return PDF_OK; -} - -static int -lzw_writer_fit (lzw_writer_t* s) -{ - if ((s->buf = pdf_realloc(s->buf, s->writen)) == NULL) - { - return PDF_ERROR; - } - - s->cur = s->buf + s->writen; - s->allocated = s->writen; - - return PDF_OK; -} - -static int -lzw_writer_put (lzw_writer_t* s, - pdf_char_t* data, - unsigned size) -{ - if (s->allocated < s->writen + size) - { - s->allocated = s->allocated * 2 + 1; - if ((s->buf = pdf_realloc(s->buf, s->allocated)) == NULL) - { - return PDF_ERROR; - } - s->cur = s->buf + s->writen; - } - - memcpy(s->cur, data, size); - s->cur += size; - s->writen += size; - - return PDF_OK; -} - -static void -lzw_writer_destroy (lzw_writer_t* s) -{ - pdf_dealloc (s->buf); -} - -static int -pdf_stm_f_lzw_decode (pdf_stm_f_lzw_data_t data, - pdf_char_t *in, - pdf_stm_pos_t in_size, - pdf_char_t **out, - pdf_stm_pos_t *out_size) -{ - pdf_char_t dec_buf[MAX_DICTSIZE]; + + if (finish_p) + { + lzw_buffer_put_code (&st->buffer, st->string.prefix); + if ((st->buffer.maxval - st->early_change) == st->dict.size) + { + lzw_buffer_inc_bitsize(&st->buffer); + } + + lzw_buffer_put_code (&st->buffer, LZW_EOD_CODE); + lzw_buffer_put_code (&st->buffer, 0); /* flush */ + + if (pdf_buffer_full_p (out)) + { + ret = PDF_ENOUTPUT; + } + else + { + ret = PDF_EEOF; + } + + st->really_finish_p = PDF_TRUE; + } + else if (pdf_buffer_full_p (out)) + { + ret = PDF_ENOUTPUT; + } + else if (pdf_buffer_eob_p (in)) + { + ret = PDF_ENINPUT; + } + + return ret; +} + +pdf_status_t +pdf_stm_f_lzwenc_dealloc_state (void *state) +{ + pdf_dealloc (state); + return PDF_OK; +} + +/* -- THE DECODER -- */ + +enum lzwdec_state + { + LZWDEC_STATE_START, + LZWDEC_STATE_CLEAN, + LZWDEC_STATE_WRITE, + LZWDEC_STATE_READ, + LZWDEC_STATE_LOOP_WRITE, + LZWDEC_STATE_LOOP_READ + }; + +struct lzwdec_state_s +{ + /* cached params */ + pdf_i32_t early_change; + + /* state */ + pdf_char_t dec_buf [LZW_MAX_DICTSIZE]; pdf_char_t* decoded; - unsigned dec_size; + unsigned dec_size; unsigned new_code; unsigned old_code; - - lzw_buffer_t buffer; - lzw_dict_t dict; - lzw_writer_t writer; - - *out = NULL; - *out_size = 0; - - if (lzw_writer_init(&writer, in_size) == PDF_ERROR) - return PDF_ERROR; - - lzw_buffer_init(&buffer, in, in_size, MIN_BITSIZE); - lzw_dict_init(&dict); - old_code = NULL_INDEX; - - do { - lzw_buffer_set_bitsize(&buffer, MIN_BITSIZE); - lzw_dict_reset(&dict); - - do { - new_code = lzw_buffer_get_code(&buffer); - } while(new_code == LZW_RESET_CODE); - - if (new_code == NULL_INDEX) - { - lzw_writer_destroy(&writer); - return PDF_ERROR; - } - - if (new_code != LZW_EOD_CODE) - { - if (lzw_writer_put(&writer, (pdf_char_t*)&new_code, 1) == PDF_ERROR) - return PDF_ERROR; - - old_code = new_code; - new_code = lzw_buffer_get_code(&buffer); - } - - while (new_code != LZW_EOD_CODE && new_code != LZW_RESET_CODE) - { - decoded = &(dec_buf[MAX_DICTSIZE-2]); - - if (new_code < dict.size) /* Is new code in the dict? */ - { - lzw_dict_decode(&dict, new_code, &decoded, &dec_size); - lzw_dict_fast_add(&dict, old_code, decoded[0]); - } - else - { - lzw_dict_decode(&dict, old_code, &decoded, &dec_size); - lzw_dict_fast_add(&dict, old_code, decoded[0]); - decoded[dec_size++] = decoded[0]; - } - - if (lzw_writer_put(&writer, decoded, dec_size) == PDF_ERROR) - return PDF_ERROR; - - if (dict.size == buffer.maxval - 1 - data->early_change) - if (!lzw_buffer_inc_bitsize(&buffer)); - /* break; We must wait for the reset code, don't reset yet. */ - - old_code = new_code; - new_code = lzw_buffer_get_code(&buffer); - - if (new_code == NULL_INDEX) - { - lzw_writer_destroy(&writer); - return PDF_ERROR; - } - } - } while (new_code != LZW_EOD_CODE); - - if (lzw_writer_fit(&writer) == PDF_ERROR) - return PDF_ERROR; - - *out = writer.buf; - *out_size = writer.writen; - - return PDF_OK; -} - - -/* -- PDF Filter functions --*/ - -int -pdf_stm_f_lzw_init (void **filter_data, - void *conf_data) -{ - pdf_stm_f_lzw_data_t *data; - pdf_stm_f_lzw_conf_t conf; - - data = (pdf_stm_f_lzw_data_t *) filter_data; - conf = (pdf_stm_f_lzw_conf_t) conf_data; - - /* Create the private data storage */ - *data = - (pdf_stm_f_lzw_data_t) pdf_alloc (sizeof(struct pdf_stm_f_lzw_data_s)); - (*data)->mode = conf->mode; - (*data)->early_change = conf->early_change; - - return PDF_OK; -} - -int -pdf_stm_f_lzw_apply (void *filter_data, - pdf_char_t *in, pdf_stm_pos_t in_size, - pdf_char_t **out, pdf_stm_pos_t *out_size) -{ - pdf_stm_f_lzw_data_t data; - - data = (pdf_stm_f_lzw_data_t) filter_data; - switch (data->mode) - { - case PDF_STM_F_LZW_MODE_ENCODE: - { - return pdf_stm_f_lzw_encode (data, in, in_size, out, out_size); - } - case PDF_STM_F_LZW_MODE_DECODE: - { - return pdf_stm_f_lzw_decode (data, in, in_size, out, out_size); - } + + /* flow managment */ + enum lzwdec_state state_pos; + pdf_status_t tmp_ret; + + struct lzw_buffer_s buffer; + struct lzw_dict_s dict; +}; +typedef struct lzwdec_state_s* lzwdec_state_t; + + +pdf_status_t +pdf_stm_f_lzwdec_init (pdf_hash_t params, + void **ext_state) +{ + pdf_char_t *early_change_str; + lzwdec_state_t state; + + state = pdf_alloc (sizeof (struct lzwdec_state_s)); + if (!state) + { + return PDF_ERROR; + } + + state->early_change = 1; /* set default */ + + if (pdf_hash_key_p (params, "EarlyChange") == PDF_TRUE) + { + pdf_hash_get_string (params, "EarlyChange", &early_change_str); + if (early_change_str[0] == '0') + { + state->early_change = 0; + } + } + + lzw_buffer_init (&state->buffer, LZW_MIN_BITSIZE); + lzw_dict_init (&state->dict); + state->old_code = LZW_NULL_INDEX; + state->decoded = state->dec_buf + (LZW_MAX_DICTSIZE-2); + state->dec_size = 0; + state->state_pos = LZWDEC_STATE_START; + state->tmp_ret = 0; + + *ext_state = state; + return PDF_OK; +} + +pdf_status_t +lzwdec_put_decoded (lzwdec_state_t st, pdf_buffer_t out) +{ + pdf_status_t ret; + pdf_size_t to_write; + + ret = PDF_OK; + + if (st->dec_size) + { + /* output the decoded string */ + to_write = st->dec_size; + if (st->dec_size > (out->size - out->wp)) + { + to_write = out->size - out->wp; + ret = PDF_ENOUTPUT; + } + + memcpy (out->data + out->wp, st->decoded, to_write); + out->wp += to_write; + st->decoded += to_write; + st->dec_size -= to_write; + } + + return ret; +} + +pdf_status_t +lzwdec_put_code (lzwdec_state_t st, + pdf_buffer_t out, + unsigned long code) +{ + if (pdf_buffer_full_p (out)) + { + return PDF_ENOUTPUT; + } + + out->data [out->wp++] = (pdf_char_t) (code & 0xFF); + + return PDF_OK; +} + +#define LZWDEC_CHECK(st, pos, what) \ + do { (st)->state_pos = (pos); \ + if (((st)->tmp_ret = (what)) != PDF_OK) \ + { return ((st)->tmp_ret); } \ + } while (0); + +pdf_status_t +pdf_stm_f_lzwdec_apply (pdf_hash_t params, + void *ext_state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p) +{ + lzwdec_state_t st; + + st = ext_state; + lzw_buffer_set (&st->buffer, in); + + switch (st->state_pos) + { + case LZWDEC_STATE_START: + break; + case LZWDEC_STATE_CLEAN: + goto lzwdec_state_clean; + case LZWDEC_STATE_WRITE: + goto lzwdec_state_write; + case LZWDEC_STATE_READ: + goto lzwdec_state_read; + case LZWDEC_STATE_LOOP_WRITE: + goto lzwdec_state_loop_write; + case LZWDEC_STATE_LOOP_READ: + goto lzwdec_state_loop_read; default: - { - return PDF_ERROR; - } - } - - /* Not reached */ + break; + } + + do + { + /* need a reset */ + lzw_buffer_set_bitsize (&st->buffer, LZW_MIN_BITSIZE); + lzw_dict_reset (&st->dict); + + do + { + lzwdec_state_clean: + LZWDEC_CHECK (st, LZWDEC_STATE_CLEAN, + lzw_buffer_get_code (&st->buffer, &st->new_code, finish_p)); + } + while (st->new_code == LZW_RESET_CODE); + + if (st->new_code != LZW_EOD_CODE) + { + lzwdec_state_write: + LZWDEC_CHECK (st, LZWDEC_STATE_WRITE, + lzwdec_put_code (st, out, st->new_code)); + + st->old_code = st->new_code; + lzwdec_state_read: + LZWDEC_CHECK (st, LZWDEC_STATE_READ, + lzw_buffer_get_code (&st->buffer, &st->new_code, finish_p)); + } + + while (st->new_code != LZW_EOD_CODE && + st->new_code != LZW_RESET_CODE) + { + st->decoded = st->dec_buf + (LZW_MAX_DICTSIZE-2); + + /* Is new code in the dict? */ + if (st->new_code < st->dict.size) + { + lzw_dict_decode (&st->dict, st->new_code, + &st->decoded, &st->dec_size); + lzw_dict_fast_add (&st->dict, st->old_code, st->decoded[0]); + } + else + { + lzw_dict_decode (&st->dict, st->old_code, + &st->decoded, &st->dec_size); + lzw_dict_fast_add (&st->dict, st->old_code, st->decoded[0]); + st->decoded [st->dec_size++] = st->decoded [0]; + } + + /* output the decoded string */ + lzwdec_state_loop_write: + LZWDEC_CHECK (st, LZWDEC_STATE_LOOP_WRITE, + lzwdec_put_decoded (st, out)); + + if (st->dict.size == st->buffer.maxval - 1 - st->early_change) + { + if (!lzw_buffer_inc_bitsize (&st->buffer)); + /* break; We must wait for the reset code, don't reset yet. */ + } + + /* get next code */ + st->old_code = st->new_code; + lzwdec_state_loop_read: + LZWDEC_CHECK (st, LZWDEC_STATE_LOOP_READ, + lzw_buffer_get_code (&st->buffer, &st->new_code, finish_p)); + } + } + while (st->new_code != LZW_EOD_CODE); + + st->state_pos = LZWDEC_STATE_START; + + return PDF_EEOF; } -int -pdf_stm_f_lzw_dealloc (void **filter_data) +pdf_status_t +pdf_stm_f_lzwdec_dealloc_state (void *state) { - pdf_stm_f_lzw_data_t *data; - - data = (pdf_stm_f_lzw_data_t *) filter_data; - pdf_dealloc (*data); - + pdf_dealloc (state); return PDF_OK; } === modified file 'src/base/pdf-stm-f-lzw.h' --- src/base/pdf-stm-f-lzw.h 2009-01-11 21:37:29 +0000 +++ src/base/pdf-stm-f-lzw.h 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "09/01/11 22:04:37 jemarch" +/* -*- mode: C -*- Time-stamp: "2009-06-24 20:18:48 raskolnikov" * * File: pdf-stm-f-lzw.h * Date: Wed Aug 15 14:13:20 2007 @@ -27,54 +27,31 @@ #define PDF_STM_F_LZW_H #include <config.h> -#include <pdf-base.h> - -/* Configuration data */ - -/* BEGIN PUBLIC */ - -enum pdf_stm_f_lzw_mode_t -{ - PDF_STM_F_LZW_MODE_ENCODE, - PDF_STM_F_LZW_MODE_DECODE -}; - -/* END PUBLIC */ - -struct pdf_stm_f_lzw_conf_s -{ - int mode; - int early_change; /* An indication of when to increase the code - length. If the value of this entry is 0, code - length increases are postponed as long as - possible. If the value is 1, code length - increases occur one code early. This - parameter is included because LZW sample code - distributed by some vendors increases the - code length one code earlier than necessary. - - Default value: 1 */ -}; - -typedef struct pdf_stm_f_lzw_conf_s *pdf_stm_f_lzw_conf_t; - -/* Private data */ - -struct pdf_stm_f_lzw_data_s -{ - int mode; - int early_change; -}; - -typedef struct pdf_stm_f_lzw_data_s *pdf_stm_f_lzw_data_t; + +#include <pdf-types.h> +#include <pdf-hash.h> /* Filter API implementation */ -int pdf_stm_f_lzw_init (void **filter_data, void *conf_data); -int pdf_stm_f_lzw_apply (void *filter_data, - pdf_char_t *in, pdf_stm_pos_t in_size, - pdf_char_t **out, pdf_stm_pos_t *out_size); -int pdf_stm_f_lzw_dealloc (void **filter_data); +pdf_status_t pdf_stm_f_lzwenc_init (pdf_hash_t params, + void **state); +pdf_status_t pdf_stm_f_lzwenc_apply (pdf_hash_t params, + void *state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_lzwdec_init (pdf_hash_t params, + void **state); +pdf_status_t pdf_stm_f_lzwdec_apply (pdf_hash_t params, + void *state, + pdf_buffer_t in, + pdf_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_lzwdec_dealloc_state (void *state); + +pdf_status_t pdf_stm_f_lzwenc_dealloc_state (void *state); #endif /* pdf_stm_f_lzw.h */ === modified file 'src/base/pdf-stm-filter.c' --- src/base/pdf-stm-filter.c 2009-05-19 13:26:02 +0000 +++ src/base/pdf-stm-filter.c 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "09/05/19 15:13:06 jemarch" +/* -*- mode: C -*- Time-stamp: "2009-06-28 00:33:54 raskolnikov" * * File: pdf-stm-filter.c * Date: Thu Jun 12 22:13:31 2008 @@ -162,6 +162,20 @@ new->impl.dealloc_state_fn = pdf_stm_f_md5enc_dealloc_state; break; } + case PDF_STM_FILTER_LZW_ENC: + { + new->impl.init_fn = pdf_stm_f_lzwenc_init; + new->impl.apply_fn = pdf_stm_f_lzwenc_apply; + new->impl.dealloc_state_fn = pdf_stm_f_lzwenc_dealloc_state; + break; + } + case PDF_STM_FILTER_LZW_DEC: + { + new->impl.init_fn = pdf_stm_f_lzwdec_init; + new->impl.apply_fn = pdf_stm_f_lzwdec_apply; + new->impl.dealloc_state_fn = pdf_stm_f_lzwdec_dealloc_state; + break; + } #if defined(HAVE_LIBJBIG2DEC) case PDF_STM_FILTER_JBIG2_DEC: { === modified file 'src/base/pdf-stm-filter.h' --- src/base/pdf-stm-filter.h 2009-01-12 13:30:36 +0000 +++ src/base/pdf-stm-filter.h 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "09/01/11 22:03:22 jemarch" +/* -*- mode: C -*- Time-stamp: "2009-06-28 00:32:10 raskolnikov" * * File: pdf-stm-filter.h * Date: Thu Jun 12 22:05:06 2008 @@ -37,6 +37,7 @@ #include <pdf-stm-f-v2.h> #include <pdf-stm-f-aesv2.h> #include <pdf-stm-f-md5.h> +#include <pdf-stm-f-lzw.h> #if defined(HAVE_LIBZ) # include <pdf-stm-f-flate.h> @@ -74,7 +75,9 @@ PDF_STM_FILTER_AESV2_DEC, PDF_STM_FILTER_V2_ENC, PDF_STM_FILTER_V2_DEC, - PDF_STM_FILTER_MD5_ENC + PDF_STM_FILTER_MD5_ENC, + PDF_STM_FILTER_LZW_DEC, + PDF_STM_FILTER_LZW_ENC }; /* END PUBLIC */ === modified file 'torture/unit/base/stm/pdf-stm-write.c' --- torture/unit/base/stm/pdf-stm-write.c 2009-05-15 17:55:40 +0000 +++ torture/unit/base/stm/pdf-stm-write.c 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "2009-05-15 13:53:39 gerel" +/* -*- mode: C -*- Time-stamp: "2009-06-28 01:16:15 raskolnikov" * * File: pdf-stm-write.c * Date: Sun Sep 21 16:37:27 2008 @@ -30,6 +30,44 @@ #include <pdf.h> /* + * Fixture: mem_stm_fixture. + * Description: + * Common data for memory stream based tests. + */ +struct +{ + pdf_stm_t stm; + pdf_char_t *buf; +} mem_stm_fixture; + +#define MEM_STM_FIXTURE_BUFFER_SIZE 1024 +#define MEM_STM_FIXTURE_CACHE_SIZE 1 + +static void +mem_stm_fixture_setup () +{ + pdf_status_t ret; + + mem_stm_fixture.buf = pdf_alloc (MEM_STM_FIXTURE_BUFFER_SIZE); + fail_if (mem_stm_fixture.buf == NULL); + + ret = pdf_stm_mem_new (mem_stm_fixture.buf, + MEM_STM_FIXTURE_BUFFER_SIZE, + MEM_STM_FIXTURE_CACHE_SIZE, + PDF_STM_WRITE, + &mem_stm_fixture.stm); + fail_if (ret != PDF_OK); +} + +static void +mem_stm_fixture_teardown () +{ + pdf_stm_destroy (mem_stm_fixture.stm); + pdf_dealloc (mem_stm_fixture.buf); +} + + +/* * Test: pdf_stm_write_001 * Description: * Write some bytes to a write memory stream. @@ -871,6 +909,82 @@ END_TEST + +/* + * Test: pdf_stm_write_015 + * Description: + * Create a memory-based writing stream and attach an LZW filter + * encoder to it. + * Success condition: + * The encoded data should be correct. + */ +START_TEST (pdf_stm_write_015) +{ + pdf_status_t ret; + pdf_hash_t params; + pdf_size_t tmp = 0; + + pdf_char_t *decoded = + "-----A---B"; + pdf_char_t *encoded = + "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01"; + + + /* Create the filter */ + pdf_hash_new (NULL, ¶ms); + fail_if (pdf_stm_install_filter (mem_stm_fixture.stm, + PDF_STM_FILTER_LZW_ENC, + params) + != PDF_OK); + + /* Write and test some stuff */ + ret = pdf_stm_write (mem_stm_fixture.stm, decoded, 10, &tmp); + fail_if (ret == PDF_ERROR); + fail_if (pdf_stm_flush (mem_stm_fixture.stm, PDF_TRUE, &tmp) == PDF_ERROR); + fail_if (memcmp (mem_stm_fixture.buf, encoded, 9) != 0); + + /* Cleanup */ + pdf_hash_destroy (params); +} +END_TEST + +/* + * Test: pdf_stm_write_015 + * Description: + * Create a memory-based writing stream and attach an LZW filter + * encoder to it. + * Success condition: + * The encoded data should be correct. + */ +START_TEST (pdf_stm_write_016) +{ + pdf_status_t ret; + pdf_hash_t params; + pdf_size_t tmp = 0; + + pdf_char_t *encoded = + "\x80\x0B\x60\x50\x22\x0C\x0C\x85\x01"; + pdf_char_t *decoded = + "-----A---B"; + + /* Create the filter */ + pdf_hash_new (NULL, ¶ms); + fail_if (pdf_stm_install_filter (mem_stm_fixture.stm, + PDF_STM_FILTER_LZW_DEC, + params) + != PDF_OK); + + /* Test some data */ + ret = pdf_stm_write (mem_stm_fixture.stm, encoded, 9, &tmp); + fail_if (ret == PDF_ERROR); + fail_if (pdf_stm_flush (mem_stm_fixture.stm, PDF_TRUE, &tmp) == PDF_ERROR); + fail_if (memcmp (mem_stm_fixture.buf, decoded, 10) != 0); + + /* Cleanup */ + pdf_hash_destroy (params); +} +END_TEST + /* * Test case creation function */ @@ -879,6 +993,10 @@ { TCase *tc = tcase_create ("pdf_stm_write"); + tcase_add_checked_fixture(tc, + mem_stm_fixture_setup, + mem_stm_fixture_teardown); + tcase_add_test(tc, pdf_stm_write_001); tcase_add_test(tc, pdf_stm_write_002); tcase_add_test(tc, pdf_stm_write_003); @@ -896,6 +1014,8 @@ tcase_add_test(tc, pdf_stm_write_012); tcase_add_test(tc, pdf_stm_write_013); tcase_add_test(tc, pdf_stm_write_014); + tcase_add_test(tc, pdf_stm_write_015); + tcase_add_test(tc, pdf_stm_write_016); return tc; } === modified file 'utils/Makefile.am' --- utils/Makefile.am 2009-06-24 19:25:52 +0000 +++ utils/Makefile.am 2009-06-27 23:19:51 +0000 @@ -22,7 +22,7 @@ ICONV_LIBS = -liconv endif #ICONV -bin_PROGRAMS = pdf-filter pdf-tokeniser +bin_PROGRAMS = pdf-filter LDADD = $(top_builddir)/src/libgnupdf.la \ $(ICONV_LIBS) @@ -31,6 +31,6 @@ -I$(top_srcdir)/src/base -I $(top_srcdir)/src/object pdf_filter_SOURCES = pdf-filter.h pdf-filter.c -pdf_tokeniser__SOURCES = pdf-tokeniser.c +# pdf_tokeniser__SOURCES = pdf-tokeniser.c # End of Makefile.am === modified file 'utils/pdf-filter.c' --- utils/pdf-filter.c 2009-06-24 19:25:52 +0000 +++ utils/pdf-filter.c 2009-06-27 23:19:51 +0000 @@ -58,11 +58,12 @@ {"null", no_argument, NULL, NULL_FILTER_ARG}, {"ahexdec", no_argument, NULL, ASCIIHEXDEC_FILTER_ARG}, {"ahexenc", no_argument, NULL, ASCIIHEXENC_FILTER_ARG}, + {"lzwenc", no_argument, NULL, LZWENC_FILTER_ARG}, + {"lzwdec", no_argument, NULL, LZWDEC_FILTER_ARG}, + {"lzw-earlychange", no_argument, NULL, LZW_EARLYCHANGE_ARG}, #if 0 {"a85dec", no_argument, NULL, ASCII85DEC_FILTER_ARG}, {"a85enc", no_argument, NULL, ASCII85ENC_FILTER_ARG}, - {"lzwenc", no_argument, NULL, LZWENC_FILTER_ARG}, - {"lzwdec", no_argument, NULL, LZWDEC_FILTER_ARG}, {"cfaxdec", no_argument, NULL, CCITTFAXDEC_FILTER_ARG}, {"jxpdec", no_argument, NULL, JXPDEC_FILTER_ARG}, {"predenc", no_argument, NULL, PREDENC_FILTER_ARG}, @@ -108,12 +109,12 @@ available filters\n\ --null use the NULL filter\n\ --ahexdec use the ASCII Hex decoder filter\n\ - --ahexenc use the ASCII Hex encoder filter\n" + --ahexenc use the ASCII Hex encoder filter\n\ + --lzwenc use the LZW encoder filter\n\ + --lzwdec use the LZW decoder filter\n" #if 0 " --a85dec use the ASCII 85 decoder filter\n\ --a85enc use the ASCII 85 encoder filter\n\ - --lzwenc use the LZW encoder filter\n\ - --lzwdec use the LZW decoder filter\n --jxpdec use the JXP decoder filter\n\ --predenc use the predictor encoder filter\n\ --preddec use the predictor decoder filter\n" @@ -139,14 +140,15 @@ --version show pdf-filter version and exit\n\ \nfilter properties\n" #if 0 -" --lzw-earlychange toggles earlychange for next lzw filters\n\ +" --preddec-type=NUM code for next preddec filters type\n\ --predenc-type=NUM code for next predenc filters type\n\ --pred-colors=NUM next predictors colors per sample\n\ --pred-bpc=NUM next predictors bits per color component\n\ --pred-columns=NUM next predictors number of samples per row\n" #endif /* 0 */ -" --jbig2dec-globals=FILE file containing global segments\n\ +" --lzw-earlychange toggles earlychange for next lzw filters\n\ + --jbig2dec-globals=FILE file containing global segments\n\ "; char *pdf_filter_help_msg = ""; @@ -448,6 +450,7 @@ char *key = NULL; pdf_size_t jbig2dec_global_segments_size = 0; pdf_status_t status; + pdf_bool_t lzw_earlychange = PDF_FALSE; /* Initialize the crypt module */ if (pdf_crypt_init () != PDF_OK) @@ -554,14 +557,6 @@ { break; } - case LZWENC_FILTER_ARG: - { - break; - } - case LZWDEC_FILTER_ARG: - { - break; - } case CCITTFAXDEC_FILTER_ARG: { break; @@ -591,6 +586,57 @@ break; } #endif /* 0 */ + case LZW_EARLYCHANGE_ARG: + { + lzw_earlychange = PDF_TRUE; + break; + } + case LZWENC_FILTER_ARG: + { + ret = pdf_hash_new (NULL, &filter_params); + if (ret != PDF_OK) + { + pdf_error (ret, stderr, "while creating the lzwenc filter parameters hash table"); + exit (1); + } + + pdf_hash_add_bool (filter_params, "EarlyChange", lzw_earlychange); + + status = pdf_stm_install_filter (stm, + PDF_STM_FILTER_LZW_ENC, + filter_params); + + if (status != PDF_OK) + { + pdf_error (status, stderr, "while creating the LZW encoder filter"); + exit (1); + } + + break; + } + case LZWDEC_FILTER_ARG: + { + ret = pdf_hash_new (NULL, &filter_params); + if (ret != PDF_OK) + { + pdf_error (ret, stderr, "while creating the lzwdec filter parameters hash table"); + exit (1); + } + + pdf_hash_add_bool (filter_params, "EarlyChange", lzw_earlychange); + + status = pdf_stm_install_filter (stm, + PDF_STM_FILTER_LZW_DEC, + filter_params); + + if (status != PDF_OK) + { + pdf_error (status, stderr, "while creating the LZW decoder filter"); + exit (1); + } + + break; + } #ifdef HAVE_LIBZ case FLATEDEC_FILTER_ARG: { === modified file 'utils/pdf-filter.h' --- utils/pdf-filter.h 2009-05-06 17:54:48 +0000 +++ utils/pdf-filter.h 2009-06-27 23:19:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "09/05/06 19:46:33 jemarch" +/* -*- mode: C -*- Time-stamp: "09/06/24 19:37:20 jemarch" * * File: pdf-filter.h * Date: Tue Jul 10 18:40:55 2007 @@ -46,8 +46,6 @@ #if 0 ASCII85DEC_FILTER_ARG, ASCII85ENC_FILTER_ARG, - LZWENC_FILTER_ARG, - LZWDEC_FILTER_ARG, CCITTFAXDEC_FILTER_ARG, JXPDEC_FILTER_ARG, PREDENC_FILTER_ARG, @@ -67,6 +65,9 @@ JBIG2DEC_GLOBAL_SEGMENTS_ARG, JBIG2DEC_PAGE_SIZE, #endif /* HAVE_LIBJBIG2DEC */ + LZWENC_FILTER_ARG, + LZWDEC_FILTER_ARG, + LZW_EARLYCHANGE_ARG, MD5ENC_FILTER_ARG, KEY_ARG, AESENC_FILTER_ARG, # Begin bundle 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
lzw-28-06-09.patch.sig
Description: PGP signature
