# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: address@hidden # mxam0fl6yecepj50 # target_branch: bzr://bzr.sv.gnu.org/pdf/libgnupdf/trunk/ # testament_sha1: d930da392f37564acf022818d69798cad02a2e19 # timestamp: 2011-08-01 12:14:04 +0200 # base_revision_id: address@hidden # # Begin patch === modified file 'AUTHORS' --- AUTHORS 2011-05-21 10:25:50 +0000 +++ AUTHORS 2011-07-30 21:08:22 +0000 @@ -33,6 +33,8 @@ Franck Lesage: changed pdf-hash-helper.c pdf-hash-helper.h gnupdf.texi +Georg Gottleuber: changed pdf-filter.c pdf-stm-f-pred.c pdf-stm-f-pred.h + Gerardo E. Gidoni: changed gnupdf.texi pdf-stm-read.c gnupdf-tsd.texi pdf-stm-write.c configure.ac pdf-filter.c pdf-stm-f-flate.h pdf-stm-f-rl.c check-api-doc-consistency.pl === modified file 'ChangeLog' --- ChangeLog 2011-07-07 16:01:46 +0000 +++ ChangeLog 2011-07-30 21:08:22 +0000 @@ -1,3 +1,15 @@ +2011-07-30 Georg Gottleuber + + base,stm: adapted predictor filter to new stm api + * src/base/pdf-stm-f-pred.h: adapted to new stm api + * src/base/pdf-stm-f-pred.h: adapted to new stm api + * utils/pdf-filter.c: added support for predictor filter + +2011-07-30 Georg Gottleuber + + utils: fix arg evaluation of pdf-filter + * utils/pdf-filter.c + 2011-07-07 Aleksander Morgado base,hash: cast to long all 32bit integers before packing them in a ptr. === modified file 'src/Makefile.am' --- src/Makefile.am 2011-07-07 14:44:28 +0000 +++ src/Makefile.am 2011-07-30 21:08:22 +0000 @@ -58,7 +58,8 @@ 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-lzw.h base/pdf-stm-f-lzw.c \ - base/pdf-stm-f-a85.h base/pdf-stm-f-a85.c + base/pdf-stm-f-a85.h base/pdf-stm-f-a85.c \ + base/pdf-stm-f-pred.h base/pdf-stm-f-pred.c if ZLIB STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h === modified file 'src/base/pdf-stm-f-pred.c' --- src/base/pdf-stm-f-pred.c 2011-02-23 21:18:20 +0000 +++ src/base/pdf-stm-f-pred.c 2011-07-30 21:08:22 +0000 @@ -7,7 +7,7 @@ * */ -/* Copyright (C) 2007, 2008 Free Software Foundation, Inc. */ +/* Copyright (C) 2007-2011 Free Software Foundation, Inc. */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,94 @@ #include #include +#include + +/* Define predictor encoder */ +PDF_STM_FILTER_DEFINE (pdf_stm_f_predenc_get, + stm_f_pred_init, + stm_f_predenc_apply, + stm_f_pred_deinit); + +/* Define predictor decoder */ +PDF_STM_FILTER_DEFINE (pdf_stm_f_preddec_get, + stm_f_pred_init, + stm_f_preddec_apply, + stm_f_pred_deinit); + +#define PRED_PARAM_PREDICTOR "Predictor" +#define PRED_PARAM_COLORS "Colors" +#define PRED_PARAM_BPC "BitsPerComponent" +#define PRED_PARAM_COLUMNS "Columns" + +/* prediction modes */ +typedef enum +{ + PDF_STM_F_PREDENC_NO_PREDICTION = 1, + PDF_STM_F_PREDENC_TIFF_PREDICTOR_2 = 2, + PDF_STM_F_PREDENC_PNG_NONE_ALL_ROWS = 10, + PDF_STM_F_PREDENC_PNG_SUB_ALL_ROWS = 11, + PDF_STM_F_PREDENC_PNG_UP_ALL_ROWS = 12, + PDF_STM_F_PREDENC_PNG_AVERAGE_ALL_ROWS = 13, + PDF_STM_F_PREDENC_PNG_PAETH_ALL_ROWS = 14, + PDF_STM_F_PREDENC_PNG_OPTIMUM = 15 +} pdf_stm_f_predenc_method_t; + +typedef enum +{ + PDF_STM_F_PREDDEC_NO_PREDICTION = 1, + PDF_STM_F_PREDDEC_TIFF_PREDICTOR_2 = 2, + PDF_STM_F_PREDDEC_PNG = 3 +} pdf_stm_f_preddec_type_t; + +typedef enum +{ + PDF_STM_F_PREDDEC_PNG_NONE = 10, + PDF_STM_F_PREDDEC_PNG_SUB = 11, + PDF_STM_F_PREDDEC_PNG_UP = 12, + PDF_STM_F_PREDDEC_PNG_AVERAGE = 13, + PDF_STM_F_PREDDEC_PNG_PAETH = 14 +} pdf_stm_f_predec_png_type_t; + + +/* END PUBLIC */ + +/* Configuration structure */ + +/* Private state */ + +typedef struct pdf_stm_f_pred_s +{ + int predictor; /* A code that selects the predictor algorithm. If + the value of this entry is 1, the filter assumes + that the normal algorithm was used to encode the + data, without prediction. If the value is greater + than 1, the filter assumes that the data was + differenced before being encoded, and `predictor' + selects the predictor algorithm */ + + /* The following parameters are only useful when `predictor' > 1 */ + pdf_size_t colors; /* Number of interleaved color components + per sample. Valid values are 1 or + greater. Default value: 1 */ + pdf_size_t bits_per_component; /* The number of bits used to represent + each color component in a sample. Valid + values are 1, 2, 4, 8 and 16. Default + value: 1 */ + pdf_size_t columns; /* The number of samples in each + row. Default value: 1 */ + + pdf_size_t scanline_len; /* will be calculated from params */ + + /* previous and current buffers for scanlines (rows) + encoder uses prev_row_buf for last input row to the filter + decoder uses prev_row_buf for last filtered output row */ + pdf_buffer_t *prev_row_buf; + pdf_buffer_t *curr_row_buf; + + /* buffer for output scanline (already filtered) */ + pdf_buffer_t *out_row_buf; +} pdf_stm_f_pred_t; + #define PNG_ENC_PREDICTOR_P(pred) \ ((pred) == PDF_STM_F_PREDENC_PNG_NONE_ALL_ROWS || \ @@ -40,6 +128,14 @@ (pred) == PDF_STM_F_PREDENC_PNG_PAETH_ALL_ROWS || \ (pred) == PDF_STM_F_PREDENC_PNG_OPTIMUM) +#define PNG_DEC_PREDICTOR_P(pred) \ + ((pred) == PDF_STM_F_PREDDEC_PNG || \ + (pred) == PDF_STM_F_PREDDEC_PNG_NONE || \ + (pred) == PDF_STM_F_PREDDEC_PNG_SUB || \ + (pred) == PDF_STM_F_PREDDEC_PNG_UP || \ + (pred) == PDF_STM_F_PREDDEC_PNG_AVERAGE || \ + (pred) == PDF_STM_F_PREDDEC_PNG_PAETH) + /* * This is a bit level pointer object optimized for the needs in the * predictor class optimized for its usage within the needs of the predictor @@ -70,10 +166,10 @@ bp->mask = ~bp->mask; } -#define PRED_BIT_PTR_ADV(bp) \ - if ((bp).offset > 0) \ +#define PRED_BIT_PTR_ADV(bp) \ + if ((bp).offset > 0) \ { \ - (bp).offset -= (bp).block_size; \ + (bp).offset -= (bp).block_size; \ } \ else \ { \ @@ -81,63 +177,178 @@ (bp).offset = 8 - (bp).block_size; \ } -#define PRED_BIT_PTR_GET(bp) \ +#define PRED_BIT_PTR_GET(bp) \ ((*(bp).ptr >> (bp).offset) & (bp).mask) -#define PRED_BIT_PTR_SET(bp, e) \ - (*(bp).ptr = (*(bp).ptr & ~((bp).mask << (bp).offset)) | (((e) & (bp).mask) << (bp).offset)) +#define PRED_BIT_PTR_SET(bp, e) \ + (*(bp).ptr = (*(bp).ptr & ~((bp).mask << (bp).offset)) \ + | (((e) & (bp).mask) << (bp).offset)) -int -pdf_stm_f_pred_init (void **filter_data, - void *conf_data) +static pdf_bool_t +stm_f_pred_init (const pdf_hash_t *params, + void **state, + pdf_error_t **error) { - int actual_len; - - pdf_stm_f_pred_data_t *data; - pdf_stm_f_pred_conf_t conf; - - data = (pdf_stm_f_pred_data_t *) filter_data; - conf = (pdf_stm_f_pred_conf_t) conf_data; - - /* Create the private data storage */ - *data = - (pdf_stm_f_pred_data_t) pdf_alloc (sizeof(struct pdf_stm_f_pred_data_s)); - - (*data)->mode = conf->mode; - (*data)->predictor = conf->predictor; - (*data)->colors = conf->colors; - (*data)->bits_per_component = conf->bits_per_component; - (*data)->columns = conf->columns; - + pdf_size_t actual_len; + pdf_stm_f_pred_t* filter_state; + + /* Predictor decides if we need more paramters; so check it first */ + if (!params || !pdf_hash_key_p (params, PRED_PARAM_PREDICTOR)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "cannot initialize predictor encoder/decoder: " + "parameter '"PRED_PARAM_PREDICTOR"' missing"); + return PDF_FALSE; + } + + /* We demand all parameters if predictor > 1 */ + if (pdf_hash_get_size (params, PRED_PARAM_PREDICTOR) > 1) + { + if (!pdf_hash_key_p (params, PRED_PARAM_COLORS) || + !pdf_hash_key_p (params, PRED_PARAM_BPC) || + !pdf_hash_key_p (params, PRED_PARAM_COLUMNS)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "cannot initialize predictor encoder/decoder: " + "parameters missing ('"PRED_PARAM_COLORS"': %s, " + "'"PRED_PARAM_BPC"': %s, '"PRED_PARAM_COLUMNS"': %s)", + ((params && pdf_hash_key_p (params, PRED_PARAM_COLORS)) ? + "available" : "missing"), + ((params && pdf_hash_key_p (params, PRED_PARAM_BPC)) ? + "available" : "missing"), + ((params && pdf_hash_key_p (params, PRED_PARAM_COLUMNS)) ? + "available" : "missing")); + return PDF_FALSE; + } + } + + /* Create the private filter_state storage */ + filter_state = pdf_alloc (sizeof (struct pdf_stm_f_pred_s)); + if (!filter_state) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_ENOMEM, + "cannot create predictor encoder/decoder internal state: " + "couldn't allocate %lu bytes", + (unsigned long) sizeof (pdf_stm_f_pred_t)); + return PDF_FALSE; + } + + filter_state->predictor = pdf_hash_get_size (params, PRED_PARAM_PREDICTOR); + filter_state->colors = pdf_hash_get_size (params, PRED_PARAM_COLORS); + filter_state->bits_per_component = pdf_hash_get_size (params, PRED_PARAM_BPC); + filter_state->columns = pdf_hash_get_size (params, PRED_PARAM_COLUMNS); + + /* as no parameters for predictor 1 (NO_PREDICTION) is needed */ + if (filter_state->predictor == PDF_STM_F_PREDENC_NO_PREDICTION) + { + /* set default values */ + filter_state->colors = 1; + filter_state->bits_per_component = 1; + filter_state->columns = 1; + } + /* else wise check for bad parameter values */ + else + { + if (filter_state->colors < 1 + || filter_state->columns < 1 + || filter_state->bits_per_component < 1) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "cannot initialize predictor encoder/decoder: " + "bad parameter values ('"PRED_PARAM_COLORS"': %s, " + "'"PRED_PARAM_BPC"': %s, '"PRED_PARAM_COLUMNS"': %s)", + ((filter_state->colors < 1) ? + "bad" : "ok"), + ((filter_state->bits_per_component < 1) ? + "bad" : "ok"), + ((filter_state->columns < 1) ? + "bad" : "ok")); + return PDF_FALSE; + } + } + /* We need the number of full bytes that each row has. As defined in the * PNG standard we can assume that if greater than 8 the bits per component * is multiplier of eight. */ - actual_len = conf->columns * conf->colors * conf->bits_per_component; - (*data)->scanline_len = (actual_len >> 3) + (actual_len & 7); - - return PDF_OK; + actual_len = filter_state->columns * filter_state->colors * + filter_state->bits_per_component; + filter_state->scanline_len = (actual_len >> 3) + (actual_len & 7); + + /* one extra byte for PNG predictor */ + filter_state->prev_row_buf = pdf_buffer_new (filter_state->scanline_len + 1, + error); + if (!(filter_state->prev_row_buf)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_ENOMEM, + "cannot create predictor encoder/decoder internal buffer: " + "couldn't allocate %lu bytes", + (unsigned long) filter_state->scanline_len); + return PDF_FALSE; + } + + /* hint for further optimizing (if necessary): if scanlines are smaller than + in and out buffers, curr_row_buf and out_row_buf are not needed and two + memcpys per scanline can be omitted */ + filter_state->curr_row_buf = pdf_buffer_new (filter_state->scanline_len + 1, + error); + if (!(filter_state->curr_row_buf)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_ENOMEM, + "cannot create predictor encoder/decoder internal buffer: " + "couldn't allocate %lu bytes", + (unsigned long) filter_state->scanline_len); + return PDF_FALSE; + } + filter_state->out_row_buf = pdf_buffer_new (filter_state->scanline_len + 1, + error); + if (!(filter_state->out_row_buf)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_ENOMEM, + "cannot create predictor encoder/decoder internal buffer: " + "couldn't allocate %lu bytes", + (unsigned long) filter_state->scanline_len + 1); + return PDF_FALSE; + } + + *state = filter_state; + return PDF_TRUE; } + static void encode_row_none(pdf_char_t* cur, pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - memcpy(out, cur, data->scanline_len); + memcpy(out, cur, state->scanline_len); } static void encode_row_sub(pdf_char_t* cur, pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; + pdf_size_t i; *out++ = *cur++; - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { - *out = *cur - *(cur-1); + *out++ = *cur - *(cur-1); cur++; } } @@ -146,34 +357,34 @@ encode_row_up(pdf_char_t* cur, pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; + pdf_size_t i; if (prev != NULL) { - for (i = 0; i < data->scanline_len; i++) + for (i = 0; i < state->scanline_len; i++) { *out++ = *cur++ - *prev++; } - } + } else { - memcpy(out, cur, data->scanline_len); + memcpy(out, cur, state->scanline_len); } } static void -encode_row_average(pdf_char_t* cur, - pdf_char_t* prev, +encode_row_average(pdf_char_t* cur, + pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - if (prev != NULL) + pdf_size_t i; + if (prev != NULL) { *out++ = *cur++ - (*prev++ >> 1); - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { *out++ = *cur - (pdf_char_t)(((int)*(cur-1) + (int)*prev) >> 1); cur++; @@ -184,7 +395,7 @@ { *out++ = *cur++; - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { *out++ = *cur - (*(cur-1) >> 1); cur++; @@ -196,9 +407,9 @@ encode_row_paeth (pdf_char_t* cur, pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; + pdf_size_t i; int p; int pa; int pb; @@ -208,7 +419,7 @@ { *out++ = *cur++ - *prev++; - for (i = 0; i < data->scanline_len; i++) + for (i = 0; i < state->scanline_len; i++) { p = *(cur-1) + *(prev) - *(prev-1); pa = abs(p - *(cur-1)); @@ -239,9 +450,9 @@ { *out++ = *cur++; - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { - *out = *cur - *(cur-1); + *out++ = *cur - *(cur-1); cur++; } } @@ -251,10 +462,10 @@ encode_row_sub_color16 (pdf_char_t* cur, pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - int j; + pdf_size_t i; + pdf_size_t j; unsigned short *this; unsigned short *next; @@ -264,14 +475,14 @@ next = (unsigned short*) cur; sout = (unsigned short*) out; - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *sout++ = *next++; } - for (i = 1; i < data->columns; i++) + for (i = 1; i < state->columns; i++) { - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *sout++ = *next++ - *this++; } @@ -282,10 +493,10 @@ encode_row_sub_color8 (pdf_char_t* cur, pdf_char_t* prev, pdf_char_t* out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - int j; + pdf_size_t i; + pdf_size_t j; pdf_char_t *this; pdf_char_t *next; pdf_char_t *sout; @@ -294,13 +505,13 @@ next = cur; sout = out; - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *sout++ = *next++; } - for (i = 1; i < data->columns; i++) + for (i = 1; i < state->columns; i++) { - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *sout++ = *next++ - *this++; } @@ -311,29 +522,30 @@ encode_row_sub_colorl8 (pdf_char_t *cur, pdf_char_t *prev, pdf_char_t *out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - int j; + pdf_size_t i; + pdf_size_t j; pred_bit_ptr_t this; pred_bit_ptr_t next; pred_bit_ptr_t sout; - pred_bit_ptr_init (&this, cur, data->bits_per_component); - pred_bit_ptr_init (&next, cur, data->bits_per_component); - pred_bit_ptr_init (&sout, out, data->bits_per_component); + pred_bit_ptr_init (&this, cur, state->bits_per_component); + pred_bit_ptr_init (&next, cur, state->bits_per_component); + pred_bit_ptr_init (&sout, out, state->bits_per_component); - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { PRED_BIT_PTR_SET(sout, PRED_BIT_PTR_GET(next)); PRED_BIT_PTR_ADV(sout); PRED_BIT_PTR_ADV(next); } - for (i = 1; i < data->columns; i++) + for (i = 1; i < state->columns; i++) { - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { - PRED_BIT_PTR_SET(sout, PRED_BIT_PTR_GET(next) - PRED_BIT_PTR_GET(this)); + PRED_BIT_PTR_SET(sout, + PRED_BIT_PTR_GET(next) - PRED_BIT_PTR_GET(this)); PRED_BIT_PTR_ADV(sout); PRED_BIT_PTR_ADV(next); PRED_BIT_PTR_ADV(this); @@ -342,42 +554,48 @@ } static int -encode_row (pdf_char_t *cur, - pdf_char_t *prev, +encode_row (pdf_char_t *cur, + pdf_char_t *prev, pdf_char_t *out, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state, + pdf_error_t **error) { - switch (data->predictor) + switch (state->predictor) { case PDF_STM_F_PREDENC_NO_PREDICTION: case PDF_STM_F_PREDENC_PNG_NONE_ALL_ROWS: { - encode_row_none(cur, prev, out, data); + encode_row_none(cur, prev, out, state); break; } case PDF_STM_F_PREDENC_TIFF_PREDICTOR_2: { - switch (data->bits_per_component) + switch (state->bits_per_component) { case 16: { - encode_row_sub_color16(cur, prev, out, data); + encode_row_sub_color16(cur, prev, out, state); break; } case 8: { - encode_row_sub_color8(cur, prev, out, data); + encode_row_sub_color8(cur, prev, out, state); break; } case 4: case 2: case 1: { - encode_row_sub_colorl8(cur, prev, out, data); + encode_row_sub_colorl8(cur, prev, out, state); break; } default: { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "bad bits_per_component value: " + "expected 1, 2, 4, 8, 16, got %d", + (state->bits_per_component)); return PDF_ERROR; - /* Make stupid compilers happy */ break; } } @@ -386,28 +604,33 @@ } case PDF_STM_F_PREDENC_PNG_SUB_ALL_ROWS: { - encode_row_sub (cur, prev, out, data); + encode_row_sub (cur, prev, out, state); break; } case PDF_STM_F_PREDENC_PNG_UP_ALL_ROWS: { - encode_row_up(cur, prev, out, data); + encode_row_up(cur, prev, out, state); break; } case PDF_STM_F_PREDENC_PNG_AVERAGE_ALL_ROWS: { - encode_row_average(cur, prev, out, data); + encode_row_average(cur, prev, out, state); break; } case PDF_STM_F_PREDENC_PNG_PAETH_ALL_ROWS: { - encode_row_paeth(cur, prev, out, data); + encode_row_paeth(cur, prev, out, state); break; } default: { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "bad predictor value in input data: " + "expected 1, 2, 10, 11, 12, 13, 14 got %d", + (state->predictor)); return PDF_ERROR; - /* Make stupid compilers happy */ break; } } @@ -415,85 +638,26 @@ return PDF_OK; } - -static int -pdf_stm_f_pred_encode (pdf_stm_f_pred_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 *curr; - pdf_char_t *prev; - pdf_char_t *buf; - - int is_png_predictor = PNG_ENC_PREDICTOR_P(data->predictor); - int i; - - curr = in; - prev = NULL; - buf = NULL; - - if (in_size % data->scanline_len != 0) - { - /* Not all rows al full. */ - return PDF_ERROR; - } - - *out_size = is_png_predictor ? in_size + in_size/data->scanline_len : in_size; - - *out = (pdf_char_t *) pdf_alloc (*out_size); - if (*out == NULL) - { - *out_size = 0; - return PDF_ERROR; - } - - buf = *out; - - for (i = 0; i < in_size; i += data->scanline_len) - { - if (is_png_predictor) - { - *buf++ = data->predictor; - } - - if (encode_row(curr, prev, buf, data) == PDF_ERROR) - { - pdf_dealloc (*out); - *out = NULL; - *out_size = 0; - return PDF_ERROR; - } - - prev = curr; - curr += data->scanline_len; - buf += data->scanline_len; - } - - return PDF_OK; -} - static void decode_row_none (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - memcpy (cur, in, data->scanline_len); + memcpy (cur, in, state->scanline_len); } static void decode_row_sub (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; + pdf_size_t i; *cur++ = *in++; - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { *cur = *in++ + *(cur-1); cur++; @@ -504,13 +668,13 @@ decode_row_up (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; + pdf_size_t i; if (prev != NULL) { - for (i = 0; i < data->scanline_len; i++) + for (i = 0; i < state->scanline_len; i++) { *cur++ = *in++ + *prev++; } @@ -518,7 +682,7 @@ } else { - memcpy (cur, in, data->scanline_len); + memcpy (cur, in, state->scanline_len); } } @@ -526,15 +690,15 @@ decode_row_average (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; + pdf_size_t i; if (prev != NULL) { *cur++ = *in++ + (*prev++ >> 1); - - for (i = 1; i < data->scanline_len; i++) + + for (i = 1; i < state->scanline_len; i++) { *cur = *in++ + (pdf_char_t)(((int)*(cur-1) + (int)*prev) >> 1); cur++; @@ -545,7 +709,7 @@ { *cur++ = *in++; - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { *cur = *in++ + (*(cur-1) >> 1); cur++; @@ -557,19 +721,19 @@ decode_row_paeth (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { int p; int pa; int pb; int pc; - int i; + pdf_size_t i; if (prev != NULL) { *cur++ = *in++ + *prev++; - for (i = 0; i < data->scanline_len; i++) + for (i = 0; i < state->scanline_len; i++) { p = *(cur-1) + *(prev) - *(prev-1); pa = abs(p - *(cur-1)); @@ -601,7 +765,7 @@ { *cur++ = *in++; - for (i = 1; i < data->scanline_len; i++) + for (i = 1; i < state->scanline_len; i++) { *cur = *in++ + *(cur-1); cur++; @@ -611,10 +775,10 @@ static void decode_row_sub_color16 (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - int j; + pdf_size_t i; + pdf_size_t j; unsigned short* this; unsigned short* next; unsigned short* sin; @@ -623,13 +787,13 @@ next = (unsigned short*) cur; sin = (unsigned short*) in; - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *next++ = *sin++; } - for (i = 1; i < data->columns; i++) + for (i = 1; i < state->columns; i++) { - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *next++ = *sin++ + *this++; } @@ -640,10 +804,10 @@ decode_row_sub_color8 (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - int j; + pdf_size_t i; + pdf_size_t j; pdf_char_t *this; pdf_char_t *next; pdf_char_t *sin; @@ -652,14 +816,14 @@ next = cur; sin = in; - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *next++ = *sin++; } - for (i = 1; i < data->columns; i++) + for (i = 1; i < state->columns; i++) { - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { *next++ = *sin++ + *this++; } @@ -671,29 +835,30 @@ decode_row_sub_colorl8 (pdf_char_t* in, pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data) + pdf_stm_f_pred_t* state) { - int i; - int j; + pdf_size_t i; + pdf_size_t j; pred_bit_ptr_t this; pred_bit_ptr_t next; pred_bit_ptr_t sin; - pred_bit_ptr_init (&this, cur, data->bits_per_component); - pred_bit_ptr_init (&next, cur, data->bits_per_component); - pred_bit_ptr_init (&sin, in, data->bits_per_component); + pred_bit_ptr_init (&this, cur, state->bits_per_component); + pred_bit_ptr_init (&next, cur, state->bits_per_component); + pred_bit_ptr_init (&sin, in, state->bits_per_component); - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { PRED_BIT_PTR_SET(next, PRED_BIT_PTR_GET(sin)); PRED_BIT_PTR_ADV(next); PRED_BIT_PTR_ADV(sin); } - for (i = 1; i < data->columns; i++) + for (i = 1; i < state->columns; i++) { - for (j = 0; j < data->colors; j++) + for (j = 0; j < state->colors; j++) { - PRED_BIT_PTR_SET(next, PRED_BIT_PTR_GET(sin) + PRED_BIT_PTR_GET(this)); + PRED_BIT_PTR_SET(next, + PRED_BIT_PTR_GET(sin) + PRED_BIT_PTR_GET(this)); PRED_BIT_PTR_ADV(sin); PRED_BIT_PTR_ADV(next); PRED_BIT_PTR_ADV(this); @@ -702,37 +867,44 @@ } static int -decode_row (pdf_char_t* in, - pdf_char_t* cur, +decode_row (pdf_char_t* in, + pdf_char_t* cur, pdf_char_t* prev, - pdf_stm_f_pred_data_t data, - pdf_char_t predictor) + pdf_stm_f_pred_t* state, + pdf_error_t **error) { - switch (predictor) + switch (state->predictor) { case PDF_STM_F_PREDDEC_TIFF_PREDICTOR_2: { - switch(data->bits_per_component) + switch(state->bits_per_component) { case 16: { - decode_row_sub_color16(in, cur, prev, data); + decode_row_sub_color16(in, cur, prev, state); break; } case 8: { - decode_row_sub_color8(in, cur, prev, data); + decode_row_sub_color8(in, cur, prev, state); break; } case 4: case 2: case 1: { - decode_row_sub_colorl8(in, cur, prev, data); + decode_row_sub_colorl8(in, cur, prev, state); break; } - default: + default: { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "bad bits_per_component value: " + "expected 16, 8, 4, 2, 1, got %d", + (state->bits_per_component)); + return PDF_ERROR; break; } } @@ -741,129 +913,317 @@ case PDF_STM_F_PREDDEC_NO_PREDICTION: case PDF_STM_F_PREDDEC_PNG_NONE: { - decode_row_none (in, cur, prev, data); + decode_row_none (in, cur, prev, state); break; } case PDF_STM_F_PREDDEC_PNG_SUB: { - decode_row_sub (in, cur, prev, data); + decode_row_sub (in, cur, prev, state); break; } case PDF_STM_F_PREDDEC_PNG_UP: { - decode_row_up (in, cur, prev, data); + decode_row_up (in, cur, prev, state); break; } case PDF_STM_F_PREDDEC_PNG_AVERAGE: { - decode_row_average (in, cur, prev, data); + decode_row_average (in, cur, prev, state); break; } case PDF_STM_F_PREDDEC_PNG_PAETH: { - decode_row_paeth (in, cur, prev, data); - break; - } - default: - { - return PDF_ERROR; - /* Make stupid compilers happy */ - break; - } - } - - return PDF_OK; -} - -static int -pdf_stm_f_pred_decode (pdf_stm_f_pred_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 *curr = NULL; - pdf_char_t *prev = NULL; - int is_png_predictor; - int i; - pdf_char_t predictor; - - curr = NULL; - prev = NULL; - is_png_predictor = data->predictor == PDF_STM_F_PREDDEC_PNG; - predictor = data->predictor; - - if (is_png_predictor ? - in_size * data->scanline_len % (data->scanline_len + 1) != 0 : - in_size % data->scanline_len != 0 ) - { - /* Not all rows al full. */ - return PDF_ERROR; - } - - *out_size = is_png_predictor ? in_size * data->scanline_len / (data->scanline_len + 1) : in_size; - - if ((*out = (pdf_char_t *) pdf_alloc (*out_size)) == NULL) - { - *out_size = 0; - return PDF_ERROR; - } - - curr = *out; - for (i = 0; i < in_size; i += data->scanline_len + is_png_predictor) - { - if (is_png_predictor) - { - predictor = *in++; - } - - if (decode_row(in, curr, prev, data, predictor) == PDF_ERROR) - { - pdf_dealloc (*out); - *out = NULL; - *out_size = 0; - return PDF_ERROR; - } - - prev = curr; - curr += data->scanline_len; - in += data->scanline_len; - } - - return PDF_OK; -} - -int -pdf_stm_f_pred_apply (void *filter_data, - pdf_char_t *in, pdf_stm_pos_t in_size, - pdf_char_t **out, pdf_stm_pos_t *out_size) -{ - switch (((pdf_stm_f_pred_data_t)filter_data)->mode) - { - case PDF_STM_F_PRED_MODE_ENCODE: - { - return pdf_stm_f_pred_encode (filter_data, in, in_size, out, out_size); - } - case PDF_STM_F_PRED_MODE_DECODE: - { - return pdf_stm_f_pred_decode (filter_data, in, in_size, out, out_size); - } - default: - { - return PDF_ERROR; - } - } -} - -int -pdf_stm_f_pred_dealloc (void **filter_data) -{ - pdf_stm_f_pred_data_t *data; - - data = (pdf_stm_f_pred_data_t *) filter_data; - pdf_dealloc (*data); - - return PDF_OK; + decode_row_paeth (in, cur, prev, state); + break; + } + default: + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "bad predictor value for decode: " + "expected 1, 2, 10, 11, 12, 13, 14 got %d", + (state->predictor)); + return PDF_ERROR; + break; + } + } + + return PDF_OK; +} + +static enum pdf_stm_filter_apply_status_e +stm_f_predenc_apply (void *state, + pdf_buffer_t *in, + pdf_buffer_t *out, + pdf_bool_t finish, + pdf_error_t **error) +{ + pdf_stm_f_pred_t *fs = state; /* filter state */ + + pdf_bool_t is_png_predictor; + is_png_predictor = PNG_ENC_PREDICTOR_P(fs->predictor); + + pdf_char_t *curr_row; + pdf_char_t *prev_row = NULL; + pdf_char_t *out_buf; + + pdf_size_t in_size; + PDF_ASSERT (in->wp >= in->rp); + + size_t tocpy; + + /* copy all at once instead of copying each scanline for predictor 1; + this is needed because we may not know real scanline_len and therefor use + scanline_len = 1 which would be very slow */ + if (fs->predictor == PDF_STM_F_PREDENC_NO_PREDICTION) + { + tocpy = PDF_MIN (out->size - out->wp, in->wp - in->rp); + memcpy(out->data + out->wp, in->data + in->rp, tocpy); + out->wp += tocpy; + in->rp += tocpy; + } + + /* copy in->data to buffer and filter it */ + do + { + in_size = in->wp - in->rp; + tocpy = PDF_MIN (fs->curr_row_buf->size - fs->curr_row_buf->wp - 1, + in_size); + + memcpy (fs->curr_row_buf->data + fs->curr_row_buf->wp, in->data + in->rp, + tocpy); + + fs->curr_row_buf->wp += tocpy; + in->rp += tocpy; + + /* one scanline is in curr_row_buf ready for filtering */ + if (fs->curr_row_buf->wp - fs->curr_row_buf->rp == fs->scanline_len) + { + /* check if out buffer has enough space left */ + pdf_size_t left; + left = fs->out_row_buf->size - fs->out_row_buf->wp; + /* PNG predictor needs extra byte per row */ + if (left >= fs->scanline_len + (is_png_predictor? 1 : 0)) + { + /* write/read PNG predictor at first byte of a row */ + if (is_png_predictor) + fs->out_row_buf->data[fs->out_row_buf->wp++] = fs->predictor; + + curr_row = (pdf_char_t*) fs->curr_row_buf->data; + out_buf = (pdf_char_t*) fs->out_row_buf->data + + fs->out_row_buf->wp; + + /* at first row encode_row expects prev_row to be NULL */ + if (fs->prev_row_buf->wp == 0) + prev_row = NULL; + else + prev_row = (pdf_char_t*) fs->prev_row_buf->data; + + if (encode_row (curr_row, prev_row, out_buf, fs, error) + == PDF_ERROR) + return PDF_STM_FILTER_APPLY_STATUS_ERROR; + + fs->out_row_buf->wp += fs->scanline_len; + + /* instead of copying curr to prev, swap addresses */ + pdf_buffer_t *swap_tmp_buf = fs->prev_row_buf; + fs->prev_row_buf = fs->curr_row_buf; + fs->curr_row_buf = swap_tmp_buf; + + pdf_buffer_rewind (fs->curr_row_buf); + } + } + + /* out_row_buf has data that can be written to out buffer */ + if (out->size - out->wp > 0 && !pdf_buffer_eob_p (fs->out_row_buf)) + { + tocpy = PDF_MIN (fs->out_row_buf->wp - fs->out_row_buf->rp, + out->size - out->wp); + + memcpy (out->data + out->wp, + fs->out_row_buf->data + fs->out_row_buf->rp, + tocpy); + + out->wp += tocpy; + fs->out_row_buf->rp += tocpy; + } + if (pdf_buffer_eob_p (fs->out_row_buf)) + { + pdf_buffer_rewind (fs->out_row_buf); + } + + } + while (!pdf_buffer_eob_p (in) && !pdf_buffer_full_p (out)); + + /* if we do PNG prediction (is_png_predictor) and in->size == out->size + * it happens that out->data is full and we have not read all of in->data */ + if (pdf_buffer_full_p (out) && !pdf_buffer_eob_p (in)) + return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT; + + /* final call of this filter; empty out_row_buf */ + if (finish && in->wp - in->rp < 1) + { + /* out_row_buf has data because out is full */ + if (!pdf_buffer_eob_p (fs->out_row_buf)) + return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT; + /* input % scanline_len != 0 */ + if (!pdf_buffer_eob_p (fs->curr_row_buf)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "filtering with predictor encoder is incomplete: " + "out of data in the middle of a scanline " + "or wrong columns parameter detected"); + return PDF_STM_FILTER_APPLY_STATUS_ERROR; + } + return PDF_STM_FILTER_APPLY_STATUS_EOF; + } + + return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT; +} + +static enum pdf_stm_filter_apply_status_e +stm_f_preddec_apply (void *state, + pdf_buffer_t *in, + pdf_buffer_t *out, + pdf_bool_t finish, + pdf_error_t **error) +{ + pdf_stm_f_pred_t *fs = state; /* filter state */ + + pdf_bool_t is_png_predictor; + is_png_predictor = PNG_DEC_PREDICTOR_P(fs->predictor); + + pdf_char_t *curr_row; + pdf_char_t *prev_row = NULL; + pdf_char_t *out_buf; + + pdf_size_t in_size; + PDF_ASSERT (in->wp >= in->rp); + + size_t tocpy; + + /* copy all at once instead of copying each scanline for predictor 1; + this is needed because we may not know real scanline_len and therefor use + scanline_len = 1 which would be very slow */ + if (fs->predictor == PDF_STM_F_PREDDEC_NO_PREDICTION) + { + tocpy = PDF_MIN (out->size - out->wp, in->wp - in->rp); + memcpy(out->data + out->wp, in->data + in->rp, tocpy); + out->wp += tocpy; + in->rp += tocpy; + } + + /* copy in->data to buffer and filter it */ + do + { + in_size = in->wp - in->rp; + tocpy = fs->curr_row_buf->size - fs->curr_row_buf->wp; + /* PNG predictor needs 1 byte more in a scanline */ + tocpy -= (is_png_predictor? 0 : 1); + tocpy = PDF_MIN (in_size, tocpy); + + memcpy (fs->curr_row_buf->data + fs->curr_row_buf->wp, in->data + in->rp, + tocpy); + + fs->curr_row_buf->wp += tocpy; + in->rp += tocpy; + + /* curr_row_buf has a scanline (+PNG predictor) and is ready to filter */ + if (fs->scanline_len == fs->curr_row_buf->wp - fs->curr_row_buf->rp + - (is_png_predictor ? 1 : 0)) + { + /* check if out buffer has enough space left */ + pdf_size_t left; + left = fs->out_row_buf->size - fs->out_row_buf->wp; + /* PNG predictor needs extra byte per row */ + if (left >= fs->scanline_len + (is_png_predictor? 1 : 0)) + { + /* write/read PNG predictor at first byte of a row */ + if (is_png_predictor) + fs->predictor = fs->curr_row_buf->data[fs->curr_row_buf->rp++]; + + curr_row = (pdf_char_t*) fs->curr_row_buf->data + + fs->curr_row_buf->rp; + out_buf = (pdf_char_t*) fs->out_row_buf->data + + fs->out_row_buf->wp; + + /* at first row decode_row expects prev_row to be NULL */ + if (fs->prev_row_buf->wp == 0) + prev_row = NULL; + else + prev_row = (pdf_char_t*) fs->prev_row_buf->data; + + if (decode_row (curr_row, out_buf, prev_row, fs, error) + == PDF_ERROR) + return PDF_STM_FILTER_APPLY_STATUS_ERROR; + + fs->out_row_buf->wp += fs->scanline_len; + + /* copying out_row to prev_row */ + memcpy (fs->prev_row_buf->data, fs->out_row_buf->data, + fs->out_row_buf->size); + fs->prev_row_buf->rp = fs->out_row_buf->rp; + fs->prev_row_buf->wp = fs->out_row_buf->wp; + + pdf_buffer_rewind (fs->curr_row_buf); + } + } + + /* out_row_buf has data that can be written to out buffer */ + if (out->size - out->wp > 0 && !pdf_buffer_eob_p (fs->out_row_buf)) + { + tocpy = PDF_MIN (fs->out_row_buf->wp - fs->out_row_buf->rp, + out->size - out->wp); + + memcpy (out->data + out->wp, + fs->out_row_buf->data + fs->out_row_buf->rp, tocpy); + + out->wp += tocpy; + fs->out_row_buf->rp += tocpy; + } + if (pdf_buffer_eob_p (fs->out_row_buf)) + { + pdf_buffer_rewind (fs->out_row_buf); + } + } + while (!pdf_buffer_eob_p (in)); + + /* final call of this filter; empty out_row_buf */ + if (finish && in->wp - in->rp < 1) + { + /* out_row_buf has data because out is full */ + if (!pdf_buffer_eob_p (fs->out_row_buf)) + return PDF_STM_FILTER_APPLY_STATUS_NO_OUTPUT; + /* input % scanline_len != 0 */ + if (!pdf_buffer_eob_p (fs->curr_row_buf)) + { + pdf_set_error (error, + PDF_EDOMAIN_BASE_STM, + PDF_EBADDATA, + "filtering with predictor decoder is incomplete: " + "out of data in the middle of a scanline " + "or wrong columns parameter detected"); + return PDF_STM_FILTER_APPLY_STATUS_ERROR; + } + + return PDF_STM_FILTER_APPLY_STATUS_EOF; + } + + return PDF_STM_FILTER_APPLY_STATUS_NO_INPUT; +} + +static void +stm_f_pred_deinit (void *state) +{ + pdf_stm_f_pred_t *filter_state = state; + + pdf_buffer_destroy (filter_state->prev_row_buf); + pdf_buffer_destroy (filter_state->curr_row_buf); + pdf_buffer_destroy (filter_state->out_row_buf); + pdf_dealloc (state); } /* End of pdf_stm_f_pred.c */ === modified file 'src/base/pdf-stm-f-pred.h' --- src/base/pdf-stm-f-pred.h 2010-02-20 16:02:07 +0000 +++ src/base/pdf-stm-f-pred.h 2011-07-30 21:08:22 +0000 @@ -7,7 +7,7 @@ * */ -/* Copyright (C) 2007, 2008 Free Software Foundation, Inc. */ +/* Copyright (C) 2007-2011 Free Software Foundation, Inc. */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,92 +26,14 @@ #ifndef PDF_STM_F_PRED_H #define PDF_STM_F_PRED_H -/* BEGIN PUBLIC */ - -typedef enum -{ - PDF_STM_F_PREDENC_NO_PREDICTION = 1, - PDF_STM_F_PREDENC_TIFF_PREDICTOR_2 = 2, - PDF_STM_F_PREDENC_PNG_NONE_ALL_ROWS = 10, - PDF_STM_F_PREDENC_PNG_SUB_ALL_ROWS = 11, - PDF_STM_F_PREDENC_PNG_UP_ALL_ROWS = 12, - PDF_STM_F_PREDENC_PNG_AVERAGE_ALL_ROWS = 13, - PDF_STM_F_PREDENC_PNG_PAETH_ALL_ROWS = 14, - PDF_STM_F_PREDENC_PNG_OPTIMUM = 15 -} pdf_stm_f_predenc_method_t; - -typedef enum -{ - PDF_STM_F_PREDDEC_NO_PREDICTION = 1, - PDF_STM_F_PREDDEC_TIFF_PREDICTOR_2 = 2, - PDF_STM_F_PREDDEC_PNG = 3 -} pdf_stm_f_preddec_type_t; - -typedef enum -{ - PDF_STM_F_PREDDEC_PNG_NONE = 10, - PDF_STM_F_PREDDEC_PNG_SUB = 11, - PDF_STM_F_PREDDEC_PNG_UP = 12, - PDF_STM_F_PREDDEC_PNG_AVERAGE = 13, - PDF_STM_F_PREDDEC_PNG_PAETH = 14 -} pdf_stm_f_predec_png_type_t; - -typedef enum { - PDF_STM_F_PRED_MODE_ENCODE, - PDF_STM_F_PRED_MODE_DECODE -} pdf_stm_f_pred_mode_t; - -/* END PUBLIC */ - -/* Configuration structure */ - -struct pdf_stm_f_pred_conf_s -{ - int mode; /* It might be encode or decode. */ - int predictor; /* A code that selects the predictor algorithm. If - the value of this entry is 1, the filter assumes - that the normal algorithm was used to encode the - data, without prediction. If the value is greater - than 1, the filter assumes that the data was - differenced before being encoded, and `predictor' - selects the predictor algorithm */ - - - /* The following parameters are only useful when `predictor' > 1 */ - int colors; /* Number of interleaved color components - per sample. Valid values are 1 or - greater. Default value: 1 */ - int bits_per_component; /* The number of bits used to represent - each color component in a sample. Valid - values are 1, 2, 4, 8 and 16. Default - value: 1 */ - int columns; /* The number of samples in each - row. Default value: 1 */ -}; - -typedef struct pdf_stm_f_pred_conf_s *pdf_stm_f_pred_conf_t; - -/* Private data */ - -struct pdf_stm_f_pred_data_s -{ - int mode; - int predictor; - int colors; - int bits_per_component; - int columns; - int scanline_len; -}; - -typedef struct pdf_stm_f_pred_data_s *pdf_stm_f_pred_data_t; - -/* Filter API implementation */ - -int pdf_stm_f_pred_init (void **filter_data, void *conf_data); -int pdf_stm_f_pred_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_pred_dealloc (void **filter_data); + +#include +#include + +const pdf_stm_filter_impl_t *pdf_stm_f_preddec_get (void); + +const pdf_stm_filter_impl_t *pdf_stm_f_predenc_get (void); + #endif /* pdf_stm_f_pred.h */ === modified file 'src/base/pdf-stm-filter.c' --- src/base/pdf-stm-filter.c 2011-05-18 18:30:48 +0000 +++ src/base/pdf-stm-filter.c 2011-07-30 21:08:22 +0000 @@ -34,6 +34,7 @@ #include #include #include +#include /* Build-dependent filters */ @@ -92,8 +93,8 @@ { "JPX encoder", NULL }, { "JPX decoder", NULL }, /* Predictors */ - { "Predictor encoder", NULL }, - { "Predictor decoder", NULL }, + { "Predictor encoder", pdf_stm_f_predenc_get }, + { "Predictor decoder", pdf_stm_f_preddec_get }, /* Crypt filters */ { "AESv2 encoder", pdf_stm_f_aesv2enc_get }, { "AESv2 decoder", pdf_stm_f_aesv2dec_get }, === modified file 'utils/pdf-filter.c' --- utils/pdf-filter.c 2011-07-07 15:29:22 +0000 +++ utils/pdf-filter.c 2011-07-30 21:08:22 +0000 @@ -60,6 +60,7 @@ enum { + FILTER_INSTALL_NONE, HELP_ARG, VERSION_ARG, READ_ARG, @@ -74,9 +75,15 @@ #if 0 CCITTFAXDEC_FILTER_ARG, JXPDEC_FILTER_ARG, +#endif /* 0 */ + PRED_COLORS_ARG, + PRED_BITSPERCOMPONENT_ARG, + PRED_COLUMNS_ARG, + PRED_PREDICTOR_ARG, PREDENC_FILTER_ARG, PREDDEC_FILTER_ARG, -#endif /* 0 */ + PREDENC_FILTER_INSTALL, + PREDDEC_FILTER_INSTALL, #ifdef HAVE_LIBJPEG DCTDEC_FILTER_ARG, #endif /* HAVE_LIBJPEG */ @@ -90,18 +97,37 @@ JBIG2DEC_FILTER_ARG, JBIG2DEC_GLOBAL_SEGMENTS_ARG, JBIG2DEC_PAGE_SIZE, + JBIG2DEC_FILTER_INSTALL, #endif /* HAVE_LIBJBIG2DEC */ LZWENC_FILTER_ARG, LZWDEC_FILTER_ARG, LZW_EARLYCHANGE_ARG, + LZWENC_FILTER_INSTALL, + LZWDEC_FILTER_INSTALL, MD5ENC_FILTER_ARG, KEY_ARG, AESENC_FILTER_ARG, AESDEC_FILTER_ARG, + AESENC_FILTER_INSTALL, + AESDEC_FILTER_INSTALL, V2ENC_FILTER_ARG, - V2DEC_FILTER_ARG + V2DEC_FILTER_ARG, + V2ENC_FILTER_INSTALL, + V2DEC_FILTER_INSTALL }; +/* name filter args here */ +#define IS_FILTER_ARG(arg) \ + ((arg) == PRED_COLORS_ARG || \ + (arg) == PRED_BITSPERCOMPONENT_ARG || \ + (arg) == PRED_COLUMNS_ARG || \ + (arg) == PRED_PREDICTOR_ARG || \ + (arg) == JBIG2DEC_GLOBAL_SEGMENTS_ARG || \ + (arg) == JBIG2DEC_PAGE_SIZE || \ + (arg) == LZW_EARLYCHANGE_ARG || \ + (arg) == KEY_ARG) + + static const struct option GNU_longOptions[] = { {"help", no_argument, NULL, HELP_ARG}, @@ -118,11 +144,15 @@ {"lzw-earlychange", no_argument, NULL, LZW_EARLYCHANGE_ARG}, {"a85dec", no_argument, NULL, ASCII85DEC_FILTER_ARG}, {"a85enc", no_argument, NULL, ASCII85ENC_FILTER_ARG}, + {"predenc", no_argument, NULL, PREDENC_FILTER_ARG}, + {"preddec", no_argument, NULL, PREDDEC_FILTER_ARG}, + {"pred-type", required_argument, NULL, PRED_PREDICTOR_ARG}, + {"pred-colors", required_argument, NULL, PRED_COLORS_ARG}, + {"pred-bpc", required_argument, NULL, PRED_BITSPERCOMPONENT_ARG}, + {"pred-columns", required_argument, NULL, PRED_COLUMNS_ARG}, #if 0 {"cfaxdec", no_argument, NULL, CCITTFAXDEC_FILTER_ARG}, {"jxpdec", no_argument, NULL, JXPDEC_FILTER_ARG}, - {"predenc", no_argument, NULL, PREDENC_FILTER_ARG}, - {"preddec", no_argument, NULL, PREDDEC_FILTER_ARG}, #endif /* 0 */ #ifdef PDF_HAVE_LIBJPEG {"dctdec", no_argument, NULL, DCTDEC_FILTER_ARG}, @@ -168,12 +198,12 @@ --lzwenc use the LZW encoder filter\n\ --lzwdec use the LZW decoder filter\n\ --a85dec use the ASCII 85 decoder filter\n\ - --a85enc use the ASCII 85 encoder filter\n" -#if 0 -"\ - --jxpdec use the JXP decoder filter\n\ + --a85enc use the ASCII 85 encoder filter\n\ --predenc use the predictor encoder filter\n\ --preddec use the predictor decoder filter\n" +#if 0 + --jxpdec use the JXP decoder filter\n\ + #endif /* 0 */ #ifdef PDF_HAVE_LIBJPEG "\ @@ -197,16 +227,11 @@ --help print a help message and exit\n\ --version print a version message and exit\n\ \n\ -Filter properties\n" -#if 0 -"\ - --preddec-type=NUM code for next preddec filters type\n\ - --predenc-type=NUM code for next predenc filters type\n\ +Filter properties\n\ + --pred-type=NUM code for next pred 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 */ -"\ + --pred-columns=NUM next predictors number of samples per row\n\ --lzw-earlychange toggles earlychange for next lzw filters\n\ --jbig2dec-globals=FILE file containing global segments\n\ \n" @@ -324,7 +349,7 @@ else { /* Write stdin into the write stream, - which will be transparently writting the output to stdout. */ + which will be transparently writting the output to stdout. */ do { if (read_pdf_fsys) @@ -392,11 +417,11 @@ *read_mode = PDF_FALSE; while (!finish && - (ci = getopt_long (argc, - argv, - "i:o:", - GNU_longOptions, - NULL)) != -1) + (ci = getopt_long (argc, + argv, + "i:o:", + GNU_longOptions, + NULL)) != -1) { c = ci; switch (c) @@ -562,14 +587,25 @@ pdf_stm_t *stm, int ci) { - char c; - pdf_status_t ret; pdf_hash_t *filter_params = NULL; FILE *file; char *key = NULL; - pdf_status_t status; + pdf_char_t *endptr = NULL; /* Used in strtol */ pdf_bool_t lzw_earlychange = PDF_FALSE; + /* parameters for predictior filter */ + int pred_predictor; + int pred_colors; + int pred_bpc; + int pred_columns; + pdf_bool_t pred_predictor_is_set = PDF_FALSE; + pdf_bool_t pred_colors_is_set = PDF_FALSE; + pdf_bool_t pred_bpc_is_set = PDF_FALSE; + pdf_bool_t pred_columns_set = PDF_FALSE; + pdf_error_t *error = NULL; + char filter_to_install = FILTER_INSTALL_NONE; + char *old_optarg = optarg; + char next_ci = getopt_long (argc, argv, "", GNU_longOptions, NULL); /* Initialize the crypt module */ if (pdf_crypt_init () != PDF_OK) @@ -581,8 +617,7 @@ /* Install filters */ do { - c = ci; - switch (c) + switch (ci) { /* FILTER INSTALLERS */ case NULL_FILTER_ARG: @@ -699,37 +734,186 @@ { break; } - case PREDENC_FILTER_ARG: - { - /* pdf_stm_install_predenc_filter (input, - PDF_STM_FILTER_READ, - args.pred_enc_type, - args.pred_colors, - args.pred_bpc, - args.pred_columns); */ +#endif /* 0 */ + case PRED_COLORS_ARG: + { + pred_colors = strtol (old_optarg, (char **) &endptr, 10); + if ((*endptr != '\0')) + { + /* Error parsing the number */ + fprintf (stdout, "%s\n", pdf_filter_help_msg); + exit (EXIT_FAILURE); + } + pred_colors_is_set = PDF_TRUE; + break; + } + case PRED_BITSPERCOMPONENT_ARG: + { + pred_bpc = strtol (old_optarg, (char **) &endptr, 10); + if ((*endptr != '\0')) + { + /* Error parsing the number */ + fprintf (stdout, "%s\n", pdf_filter_help_msg); + exit (EXIT_FAILURE); + } + pred_bpc_is_set = PDF_TRUE; + break; + } + case PRED_COLUMNS_ARG: + { + pred_columns = strtol (old_optarg, (char **) &endptr, 10); + if ((*endptr != '\0')) + { + /* Error parsing the number */ + fprintf (stdout, "%s\n", pdf_filter_help_msg); + exit (EXIT_FAILURE); + } + pred_columns_set = PDF_TRUE; + break; + } + case PRED_PREDICTOR_ARG: + { + pred_predictor = strtol (old_optarg, (char **) &endptr, 10); + if ((*endptr != '\0')) + { + /* Error parsing the number */ + fprintf (stdout, "%s\n", pdf_filter_help_msg); + exit (EXIT_FAILURE); + } + pred_predictor_is_set = PDF_TRUE; + break; + } + case PREDENC_FILTER_ARG: /* Note that both ENC and DEC go here */ + { + filter_to_install = PREDENC_FILTER_INSTALL; + + /* set parameters as not set */ + pred_predictor_is_set = PDF_FALSE; + pred_colors_is_set = PDF_FALSE; + pred_bpc_is_set = PDF_FALSE; + pred_columns_set = PDF_FALSE; break; } case PREDDEC_FILTER_ARG: { - /* pdf_stm_install_preddec_filter (input, - PDF_STM_FILTER_READ, - args.pred_dec_type, - args.pred_colors, - args.pred_bpc, - args.pred_columns); */ - break; - } -#endif /* 0 */ - + filter_to_install = PREDDEC_FILTER_INSTALL; + + /* set parameters as not set */ + pred_predictor_is_set = PDF_FALSE; + pred_colors_is_set = PDF_FALSE; + pred_bpc_is_set = PDF_FALSE; + pred_columns_set = PDF_FALSE; + break; + } + case PREDENC_FILTER_INSTALL: + case PREDDEC_FILTER_INSTALL: + { + filter_params = pdf_hash_new (&error); + if (!filter_params) + { + pdf_error (pdf_error_get_status (error), + stderr, + "couldn't create hash table: '%s'", + pdf_error_get_message (error)); + exit (EXIT_FAILURE); + } + + if (pred_colors_is_set) + { + if (!pdf_hash_add_size (filter_params, + "Colors", + pred_colors, + &error)) + { + pdf_error (pdf_error_get_status (error), + stderr, + "while creating the predictor filter: '%s'", + pdf_error_get_message (error)); + exit (EXIT_FAILURE); + } + } + if (pred_bpc_is_set) + { + if (!pdf_hash_add_size (filter_params, + "BitsPerComponent", + pred_bpc, + &error)) + { + pdf_error (pdf_error_get_status (error), + stderr, + "while creating the predictor filter: '%s'", + pdf_error_get_message (error)); + exit (EXIT_FAILURE); + } + } + if (pred_columns_set) + { + if (!pdf_hash_add_size (filter_params, + "Columns", + pred_columns, + &error)) + { + pdf_error (pdf_error_get_status (error), + stderr, + "while creating the predictor filter: '%s'", + pdf_error_get_message (error)); + exit (EXIT_FAILURE); + } + } + if (pred_predictor_is_set) + { + if (!pdf_hash_add_size (filter_params, + "Predictor", + pred_predictor, + &error)) + { + pdf_error (pdf_error_get_status (error), + stderr, + "while creating the predictor filter: '%s'", + pdf_error_get_message (error)); + exit (EXIT_FAILURE); + } + } + if (!pdf_stm_install_filter (stm, + (ci == PREDENC_FILTER_INSTALL ? + PDF_STM_FILTER_PRED_ENC : + PDF_STM_FILTER_PRED_DEC), + filter_params, + &error)) + { + pdf_error (pdf_error_get_status (error), + stderr, + "while installing the predictor encoder or decoder filter: '%s'", + pdf_error_get_message (error)); + exit (EXIT_FAILURE); + } + pdf_hash_destroy (filter_params); + break; + } case LZW_EARLYCHANGE_ARG: { lzw_earlychange = PDF_TRUE; break; } + case LZWENC_FILTER_ARG: + { + filter_to_install = LZWENC_FILTER_INSTALL; - case LZWENC_FILTER_ARG: /* Note that both ENC and DEC go here */ + /* set default value */ + lzw_earlychange = PDF_FALSE; + break; + } case LZWDEC_FILTER_ARG: { + filter_to_install = LZWDEC_FILTER_INSTALL; + + /* set default value */ + lzw_earlychange = PDF_FALSE; + break; + } + case LZWENC_FILTER_INSTALL: /* Note that both ENC and DEC go here */ + case LZWDEC_FILTER_INSTALL: + { filter_params = pdf_hash_new (&error); if (!filter_params) { @@ -753,7 +937,7 @@ } if (!pdf_stm_install_filter (stm, - (c == LZWENC_FILTER_ARG ? + (ci == LZWENC_FILTER_INSTALL ? PDF_STM_FILTER_LZW_ENC : PDF_STM_FILTER_LZW_DEC), filter_params, @@ -846,10 +1030,10 @@ { struct stat fstats; - stat (optarg, &fstats); + stat (old_optarg, &fstats); /* Load the contents of a jbig2 global segments file */ - file = fopen (optarg, "r"); + file = fopen (old_optarg, "r"); if (file == NULL) { fprintf (stderr, "error: invalid jbig2 global segments file\n"); @@ -873,6 +1057,11 @@ case JBIG2DEC_FILTER_ARG: { + filter_to_install = JBIG2DEC_FILTER_INSTALL; + break; + } + case JBIG2DEC_FILTER_INSTALL: + { if (jbig2dec_global_segments != NULL) { filter_params = pdf_hash_new (&error); @@ -959,13 +1148,23 @@ key = NULL; } - key = strdup (optarg); + key = strdup (old_optarg); break; } - case AESENC_FILTER_ARG: /* Note that both ENC and DEC go here */ + case AESENC_FILTER_ARG: + { + filter_to_install = AESENC_FILTER_INSTALL; + break; + } case AESDEC_FILTER_ARG: { + filter_to_install = AESDEC_FILTER_INSTALL; + break; + } + case AESENC_FILTER_INSTALL: /* Note that both ENC and DEC go here */ + case AESDEC_FILTER_INSTALL: + { if (key == NULL) { fprintf (stderr, "You should specify a key for the AESv2 filter.\n"); @@ -1007,7 +1206,7 @@ } if (!pdf_stm_install_filter (stm, - (c == AESENC_FILTER_ARG ? + (ci == AESENC_FILTER_INSTALL ? PDF_STM_FILTER_AESV2_ENC : PDF_STM_FILTER_AESV2_DEC), filter_params, @@ -1025,9 +1224,19 @@ break; } - case V2ENC_FILTER_ARG: /* Note that both ENC and DEC go here */ + case V2ENC_FILTER_ARG: + { + filter_to_install = V2ENC_FILTER_INSTALL; + break; + } case V2DEC_FILTER_ARG: { + filter_to_install = V2DEC_FILTER_INSTALL; + break; + } + case V2ENC_FILTER_INSTALL: /* Note that both ENC and DEC go here */ + case V2DEC_FILTER_INSTALL: + { if (key == NULL) { fprintf (stderr, "You should specify a key for the V2 filter.\n"); @@ -1069,7 +1278,7 @@ } if (!pdf_stm_install_filter (stm, - (c == V2ENC_FILTER_ARG ? + (ci == V2ENC_FILTER_INSTALL ? PDF_STM_FILTER_V2_ENC : PDF_STM_FILTER_V2_DEC), filter_params, @@ -1097,13 +1306,34 @@ break; } } + + /* have we installed a delayed filter in this loop? */ + if (filter_to_install == ci) + { + /* no filter delayed anymore */ + filter_to_install = FILTER_INSTALL_NONE; + } + + /* next arg is a new filter and current filter is with args */ + if (!IS_FILTER_ARG(next_ci) && filter_to_install != FILTER_INSTALL_NONE) + { + /* do extra loop installing current filter */ + ci = filter_to_install; + } + else + { + ci = next_ci; + old_optarg = optarg; + next_ci = getopt_long (argc, argv, "", GNU_longOptions, NULL); + } + + if (ci == -1 && filter_to_install != FILTER_INSTALL_NONE) + { + /* end of args and one filter still to install */ + ci = filter_to_install; + } } - while ((ci = getopt_long (argc, - argv, - "", - GNU_longOptions, - NULL)) != -1); - + while (ci != -1); } static pdf_fsys_file_t * # Begin bundle IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWSkUOZkAIYx/gH////h///// ///f/v////9gL27GzB93cUZ9091SO77vgBFeLUa+Sim4fe3Hsu973eg5dihc65sK0AAAAaAdru26 PEZ6dAna2PO7qrUqO7UazY5TYu3vTe9umXp7t3ZZ7ee9NzNCgHWqTnc3WuXYuzXbqbzdHe28673Y DEL3CRIRMQBGIynoT0mmmU9Miemkep6oxPU0AaDQaaaNNNGIyMIaAlNCaCCCEyEaR6pmpoepoPU9 TTR6gBoAAGgAGgAA0FU/U0p4powBMhgRpkYAQ9T0ABBgBMBMAJkDTAAk1EQgggKfojJpqemp5JkZ Maj1GQ0AaB6jRoDQaDIAAAiSgElP0p7TRU/xJgJT8kT8qe0UNqeUfqg0Gmh6Q9QyG0aIAAPUBoFS RCMgCAmTImnpMgmKnsJR7Kn5FMh6npkntKPZU9CAA0A9Q9RpruaQkIYMGNv4vnfmmdz8Xb8H/Y6/ 31ypVdXPtiGeeikUBQiPiqgRFzdpcGpU+ZdbuN+hz618+frxPbtrY2Prflfrdf/Yftg8nfwfxy8K EqeYJKqFaZE8pAkC2FG1ORJerKftWqBpTWmISl3SUOoIge8Wj1RbDg6BEsohnI0+/5b7y7cKMF8i SrsKKVc6pfPjzP2fuH/CWgcnn0+jf38SwGmMoZ/jyElOrDbTZYKcidi/L3yZM5ETriOl8XMmUBLh mmoZMhZnI2FwYYxjODI9hNDp0Zqx+z2TQhS9xi+2OJEx0QEA0fbE5THmaHl5EI4EIkaCAvBuzSmK LMNQJm5FFbLju/mpVdECyjGx3COS+5DuO7ju49cmTIUOzks4mWIHZGWIggjXlVq1kYjQJiT3CGtR sFhtBggaTuQF4T3HgeAuEygt/xJqMfz9eP9e3MUKhOXhYeMrOkqMVpRUEkzCmH0sF9d13fl81aqQ rRt6rZkr4LKzUzevcLdkOhhh16ehVdc69igoFvQncTzNLcAx1l4yMyB9kNzAPs5Yos0M6sOTDHwS 0M27NYsMrs7GiGdFjQt743ecejYt0mIt74cTcpBLuU8gYpzrj4Y93xd7Vu/xLRjochwMBZMzDSkU 4oBysUkBQJkZJrUEZpuNBWiWa1rjvvZ9mszYp+MphIqZRwomHctF1BTXnKSgus5JvYUlorLQEIaU 2M0YJLlsbGLQgpzUM15tpQVhU7lyKlJS+LWlxJ6jMzridwrq7LCaReukVvTTOMkYXAj6VryKRnTQ PHblmhIQHJQqEDZ9XHgJiMBp/DXCPnTJ0VqFOWIgKlaBT80ELSLIgpZEANIwPiMJDLJH3KIAYznh peSYYBLQhSKEto+CKVEAKilQQJEOoqkUzIsRjIiwIjmJEqiLjFe8euU8BBIcKEKqTLUyNfV1P4P/ mp/OcbHwNtCq7VIF7vxHMfFQVK0ljGhg7wTFiw48pJbfGbVYTC6as0/A7JG1Sfx3p/DZ04m1Va61 6ib/vxwxkzl+v95iCq3Jd2H1YyhULGLKhVSCcDdFC7DaTP6TmKa67CpqQ45TXpa23/iz6f6dHd09 bcTBsx5+ku4sWxdvpVKVV5zbE0S72O2LR1et0S5lW1vmSvIVBMkdNMBm78e+s0UOEkdu/fVSo6Sj cMBC7iSsoFdRKrXScZSs6KbZY1emWWE9JCMzTKMhNid0WahO4FviVRWRNlwxjExTCxXtGE5qcYNQ gIyeMhjxmx6R24HWBYMkBQARiqkihIEiISCQi7LS7M7tgB1gh0iAR4R4QvDyPnGjNEQcBxZxAEgY IpaWBBBggLKDiKGWBJgDHZTXvYzI3MtMq4NWYzKtrns5YoM4it+OzTp3cOLNp3ZBYHAh49E/mmZJ lEWLEWEm87WLF7elswUUVDYUyJyE7vS0ulJ8I2y90PD4TZb0EM3IDWtxh91h7O2Vg3Y+iQX3cFlO JBs7hpEJDTyVTkWfZ436Rv55xsZoyiwmIQaWbOckJ4UWdiUCnaMKbPerRdXWLOSh2tObGMvNr2w+ VeqKe878tcxtjU6d3xWnNFtk+2nilSLrV2a0UqQ6ysqZcHw+VeXik+U1JrZxM6TW1q2LYYvGJtl7 LKdGVCysIpWWkWlyM4iEUiE60TbWLffS7aTGkxZDC2HFaSFOQmtbK6jdo3ELO+J1s8O/9dPad8TZ Ld97PqTGJq8XtfcuXmbzK4oOHXSaL3NwisU85xmyB/WCtEGf/WrjN8hPXykxmwvBYCodR1dn83/Z yfxvuymW4S3j7XlSxhlzFYLqEwkUDJSwc6unTeH9Uq1WPrIkqsJY5ss6oJrGhe0EpQyHcFxxbSNv zcYgkr5mkZW+X4c/VTiIcg6Q7FB6gNFCplRxnSTM4p3iZOVQNxVLVUI2Aw1hgo5ICEEJVKqqqojJ VB7PHiaTGzttdt1d0VVp6nnVnNZu7tYsWLLu7/dqWIYKytVXEx7HZZOpx5ns9ktIi7R2I05t96y0 qDydAbt+tYSMGFllz9YKFGfYX+9O3Y8bkA5oej2kbrcc+cdvXs5uzXNOYZF/c459gWUHMzmhSvFm r5cWCzhHkLwY05ItCDMJVOMt6V4GBF8ZPpo+REMvGznYffjjgtP5B33tn6yGK5bo30DcuYOKNOMZ T9ItLT2sjYmma4jmPoPZeUOx8CRM/jF3NfQjaiWPWbX0Mz/Ks14Ea5HJeqNu5ynDvnfqmiqsxeFx EaHAk2nCp3Q+UbGePLC5ydvEKf1gwXGbuM3ct4U/eswKPabVng4QeJ0OanSU06mTFvb1TY77dHH1 1jThHDice7Nz1MXbucr6NSzq29YmAwZrNRpngzUt7/K+Wn0o6zfSNm27hiDwe3iY8BECGSDe6bR7 45EWgUmaUaK+ktzkvRwwZx6B6wRJ59THALfS6kFbGW7h72fQjQ46K9LlXXC0qRxLHfK34SJSg+xZ CW5Judh6GQH1ez8wm4uQL6aSAnoOEs4qL7gHc2HERfFat9wYwG4dwbB7DIO6yO0KOTb7R5FWu7cs aPi9DPu2KMkuAcgCFij7UKKJt7Jy18zPCPHjXXphsbukjTM6XVak3jzo3I9rFCYrnkTV0NE+PZzg oVRs+4diBDG1uLiNOeBccocHSqD28evpazP09x5Nt5Vz4HbBkyc/MbToPWPF4e1yJoeZ78qQVFBE VQ8i4hhRoB26eXpfc43X3PKt5TDxp+eve9UfBvvYz0XnWm4jAtTbQ7j18EYLMOPi3Re1738dwOs8 udM3oxB17YNYR6Yu9Ir6DMekEiJm5ziDe34N35IIhuL6UlKSX8FnM/un8lRTFOCA+GChIiYwXwOw UgmSEe2NtP7QxsfMAQFzjB3w6woiwQ8m4HXZE7GXWlLsIdJdLHbFSD+ysec5y8uVA6XDBtH0c0Sf uxB5icI955AYbObykvZn6dhNWtKRU+ClFkJ4hITduKJJxOaoHeERDaIBwYBtdSGivB6QndEmCwqG 77W4+i+0lRY+WeKpafYaixwfF9CnQ+3QZortvsG6poyGwe98nvPmHgPTeBcAYQGc2+D8Hb8DM7Pr pz7gv9ebfMea+ioTDLcsaeImrhbkdluUv4LvYDMytog6Avo00LbLHa6oiOciBSkECpnQbczWiRBb mKyZaeO6Se2ASBScTEs3HD9+NHBtW2VGI7bpyjbjsYtWXclN5YscejnnMNc5n7fH8BF1Ja1oqNRS oPxFCEKegtOALhoeqF8QEuCZgyY+fRJdFAdwf3oIgUSTY8321FVRtobbQ2+8UEraiDf/F+40bnho qClwai5e2cB+oyY+n+9fdlh+fW1lPDGqS5qFHU0bXyPL1sTSaaWW0xBA4ODhuELdSC+xbXc/OPk+ pJB9iZkt2Sq7OyclYuludbE99dRu5lNrWs3Pj4YFsF3z9Dc2NqcosSvi6mIwYlcqfp+Dw2cObUm5 0jTNdMQzvcwGIrFNi+t4ZzZZ/X6STF/R21V7LPQu2OfgxOhLvS2SyYfEpupMEHmPwMXaywkp+kNz USNlUVRHbOqijriipMGAFkIqoIMQKsEREERiCUXBEiITFgkxUKBhRGUUJalKKH3aHGRcqitu5fjr a3oz7zihkwmVoJ7OBIhZyAmhcBiPEJBXoMGDg3s2TcMmPRJbdTlxVKiIGxIHZJAvCTC3kntwE9GQ geVPpRZ7wUFel6Rdp6bKGxCsXahSJY3dQbfeLT2cGCHa6nQVXNJ1r6sqqkx3SiXYUad0s8Eao4Gh qjrZUgW2dKttCbJjE64rdGkjCGg02zy26qGWGc6WQyyHcSR0xchW+iUkpDchskNybkhbDCE0SOal swzZIa5ED3QslgXvupLN6Sa5klMJ3xOKcMVwZJCqBoiWAVRe1VggayGNs6AzKUKmTSJ4DYbRkrcT qC9fKNK5IYRN+CkETD89kJTjHxnMdelj4zWGYhhtxnAWBDATN+YmWGd2YOC14OwtbmWYpmTSx3AM jhY5uLU2sbs7rsKwe6h6mYab+N6l5I0qSIcJiyGykJQOMzUi1OzdOyc4vl8ycX1Re93paOmmt40x naWIbbwwy5GIYViMiMmE3Nt7eeWB5GaaSFHkeQzWclREZFIA6IVtV+07drFb4GzI147NGBSryLVS 1CF6hdkcqyNG5k7NfXPOAhkWEEGn387cZDf1c73gRbx0HPUfv5j5gtBBDDnoLFuakORmV+wP3OwS EfIeJtids51LOm9Rfrv8RZuLhNpbvs8LXRPTIQsKtvsxvJMPQ+870S1gBUHDswcjP8s3uvN2NGbY 7ezdm0+Luza1Zz8wcM8N90SqaV4pvJMLCIe/Xu83Ww+tZMZp5y96fEOQRGMaj/w3cMZEETkkMSBc w08cnaITiUVPOGQhWzWZMwXpY9J9fuPgANY6VmcjB6FOzFu7+Fcv4R2GDbN0lt1HDcWluUHuM34V FZwmhYojIsVq2+qLHZ9U5sS/Ab2tzbsesfpvapS9h7eGZv0j5khJkx4kHh0Njj4dHJQ5Y62jfpyN ZAkN4IEhC8p7ahVwbSvIUKL9KsRG+nCWYkIY8SJ2ylqnGAWvKeDiz8RjHVtHOB8uGKjMyJvo8Xik OLQAhnu91iB9KyYgPvw5JJMCV8AEEweEHBtvF73UBCZvespIk9BzViQ8FujFFLujYhzuiDk3OxzT rscybnU9Rc9jZ2NjB5/wh9v06dQG8EeSOs9+Np4H8pyFni5OZrF1bvN8yqnNr1nNyi+zEbNcfa0k DMmVXgkWDYH6rZ3nyzjbaApY14mZzBixwYzOpJwvL6VYNnzFwrwwewUhe8Bk9Bzvbg7yITcEma4g LBxw/eQuDg1rY8Dz4O5jInsehxgz59Q8ZOjN4S+4pTPC3Utb1aLDxD2h33m6h7Qz0sW721owTYAx R+OO8ZkBJmoy3kzdicXxV4y8Dz5WOTub2yqGYrDwPYRbh26ACY7kb71u6oPAN3s9X1fhEcYycY2k ygwiwixwORbG8tSahe1x0Zc3FYXYbc0ce86j9+pyQLbBYR2IOvTt7di4fcm9879WMwnZ+3V97onE PPe02irYTQp6jutWtjOLlVbMO9ZCQRrUrL1YLJCUu+Lj102Ium0tKk0rCavT0vLG21Tjcam0a9Z7 eIvzcSgx6Mx1nl2TtwjuPrT9KzdqH36WVjSax8OD0N2G0Y5NzyO/Y9LkMxkYOL9H3SZNbo7za110 3nBa83qo7c1d1d84xExBp2Ie5DMO7swO+YIJZ/CHYXoPON94XvLHaDDfH3JOLdCi4wCDIq8Dk6Tx zsRQpJHLdBOws7WPK3oj2GXXTeEs9M+Gz2Xd+h4jjF1MEmGxsUu6ZTfOXAs5tzY2RO0Or0cORUud 3jIOMuloPCb1YeK57WzHgVlWvirmYrEZVzWnm3xdErUbYMzfaN7+dmYdhEX4ni18z4lzUZtcYILR d38SS+dZlnq9PvRe/iLPfaMCwKk2MPInIKp5bxTo4u7ENtfibLYRua6nJ+Hwc6OTrwcjknQ8A65P IArU9eEzK5OofpI8j8Xd6q9RsglnW8Wbtxr0kh/A8CTO2eZMry6k8qe86jolNupQ+4BwQZOpzzra IzAXKLF5fmDjh1waKfiSTxKARbRBuWCTJc5+IARudzH1PkPmPOLkSzWatCaaZIXoFEkVKqimnYcZ frOk8/jx7m6qHNQ8e5S0u71xbF4FieWS6Smp32yBWJKywZQq0X31EAZw9I3z383oNZTh1WRafgkT ZgYfOeuqvfjCUKNRhvYHMZNwn8zpVx4kFguwSl8g+UXT/HBD0TQ5o+94uGWG8dQ7O4ShQYiVhkhC MhVZJWsLdmbgZEy6+dZKsWiA49X+rty5esMhprwOXk5MlGpO2MUF11FGCxVyVE/peuEfQiilT+cp 8Ch99yliEWhlAq1UKEIMBkVBVZFk/SV9QuWMLSBYTmOU5EWCCT44UyM5ZTIlwQNCHwDIHLieh4j2 gpgjknIw5oAN5BUShOTeqG3iUilmxD6CHbYB5noZ3hPbRwBC9LETAvVPw2qYKkRePK9Gw+NDJTSW PpN04hkkCISEmSHpLkfSLCaJHGpx/Z9+GAs+6JT/r8G4IdQNghpsCqCDBggqiRiRREUUVR3E651A vpwPbgaSBgN3jy8Kr/Kt3bVhQoTBVMg3wiVA10hNcfx0n51Tgiue2LUWlrS1Q0R1bURlJEvEpIlm DvMNC/TpRDxEO8KIhQ8OwWVnCjQOfqN1BwLnrEk5DheqqqWnWj5c8HQVlE2nmaSSdioiXimTgSS0 J4LRI78TpjYika0obZiktlGR+rAuUIfeMihxHQfnjteHOCWHKN3AknBGHYl3FIYRME2fJrP4oqHT hI6a3BMNfgoooUlIVFI62SLRHEklkUjl5pGcM0ZPBnN7tKkaQbHFMUXNutDIRUem6YJrSFlibUY1 IYGtDvydKUQowTfO6onyt8yiXjiyZ9hHbE7yxqS0m4rpMuaypSZ+SoXhzMW5L1PG7+yXCusdw855 w+FooCmBYonIfGUK8YbqmVi+xQUxHuBxKWBYrBgrCfqGfiECx7ggiCILJ1rgV151jqeoY1FaonhN kkUZI3wiZmCSaHaKjIagiZhQ1IUigqhUEIFRKmOHhhRRGEkwueBExKTdKbUZiFGAIWKATVgq1UrY nnVG5dtNBhGcNJJGwkmDBWxu8EyiJSTGcDGMYbTc0kUWkN0zY1ujGQ6NyM5SOEjVGjhNU08ahhKf AMUOMgjothpGJoPXPPU19Pzf7mBxerr9/ipP5fluq9wOIOw6valyHCs/NsjomkcMo2gz1HE3ARBA xwzrOpccJ3oTvhEEjCzJ5+hIYxQbCIibEKRMFLD5i0RVijilHSUCFw4HdSYJlGF8plLTDOSKQxhM U1xZgYTJnDcaLY1nUiOACZnApKfIH2vaDWfjPsBsYNyKH2Lz7aBZREtVlGCEsfuTENRC2nKx4TAp TBG9U/KinlhQQtPUGDiqTCQoyPQqU9SktLjZN4Z7WDRa1qaWt8m0A4MBVkFhN09WJNeYNNZynGBw kaP1SYMRtiTPjEj6mdFKio2pkZbN4e5gSUJlLC5ZY3GiqBaqojBKaURlSilKoqDGDBKjQxRKKsky ZEa4mCLlRzT9dkYRJrkhZNy4hyAcszJxZN0ZYw4BChAQZdiiQKS1lcVw38Nb4W1DGWtLWFo11P1/ pn3N50suCT9tIyWfe1bn3tT7P0a/yu6dT9U0YP1ZuacX7nF/Z4GxzZ0/DzzT/I3Mm/wYMy36++qv OKpUnG5yfeCCgZTTqy3FhlLTvi2AxpLJpV9JdPgWlEh+8HJxrpfMc4cKtjcSgyhqzWhsziHvvnEN tTkTNzLSJ5N0s0TdUTGTFGKRMcPXKMN474UvLFDYqGYvMCNijtFO4JSEack+6zmyN+vSTGW3weiR hEbWL1N18EwSizhINRinTtirWqSSTXZkuWO1z1sIeIzP3PZG1n0T1G1ufXu3uw9rf/QqdPqWpT2K s9eRVxmOw5DQXZCZyJ1Gi8eEgxi8aRMwGla2j2OWFL9lV4OOzp6tjisx5M4WUnB3lKKEZY9ji844 e8EIpLw9a1CwOkGvmxd4/76D4l+7CEuBBxEirDpCCZnr4+IxUPcgIJ139hCDDkrvU9Ns5agJkHAb xe5dBO3Yb5yHIVHf754SRaXYMV3uuPPdyqqpSrRVmLsT45JHsk8IO4yMuLb0uPJ7rLF0N7I5reXQ 6Mt0htdTs08Cp3y2x3L/O7Xsdr1l57khRb+ZV1rJe7g21M3dtPf1rIiKiqKqoiosEVQGUak8EHwJ dhKgwaLoqyXcPAaFBlJH8nHvlxwjsD4JN4oqIrCHe3pxSQo5F/G940XiQSRHiUWdMxGBKanu74dI OBSFQ4DVVRvGWNiiCMGoyqEEaEHNyXLM+MGBQdBpB4DaYdnKWeEqN06jlkc68PiLbWNjv8eTY2vm MnOJdo0cklmmmb2a2b29eDckdQjshSOZQno7FnJ0MWZ3h3lUpVPotaODexU7HS5MD4W6S3JXpOU+ FB1WgGkjj6MorHkNuqOgIThcwP6HCrCu2Amufq+RBnbW5b1TRHWvgGt7AMDQKd01nGWIqm0pFJIa LE8LcXpjM3RhDDVNrd8vCe0+n6uZBo2DgcXyjUEO7EmVLse4s9hhHIQVexQ7Tfqbrtnml0DEQeYZ nGL2DT6/jzghj00jZ1zzJF9rPj6ZFOSYLu9/kcaTBjiuCnoc0Jw6M7ETI25Q96EalnNN089djIwe r38wwCqK0jcgvBGkkulnk9rsfG37/o62z5HHSsul129HDLEyVxb0GDBj3hmWFBmG2MRqEYqgr3Gw LyNbpdkJSuoEMFTJVuNZzGz0Q4XO66Iz9CxN3mzYvdqTYdqHC+hUJvNqmi10DvSPP3RxU+zQeNvE ozTiRIEJhmYuICjYWk6lJIXlPM55d3q3Dz+DZxs+xvP0UpU39jCXhg4OzrHTuXymEmzZsejzWbuf yrmba7TuTh/Z3yr/YOcGw0OqA4w4yKmzFdWHRtV2VGMpOyIdZ4k+ALDb08QbTFdA0URToG+ywWl7 0j2v5E7Uh3oZR1nuKntVYrrWWupLypVEZYdi754M7CWIjJLaA4Uay5UNSlpLJD/GuZIYhZKlCipI UKDjM4spfnce/mnGQ6pzpXVHcSv2YVeJjALyLWm8CwGj0tLxPCyUbhMpeDxLPIDREFYaQwVYRGIG JYWg9RLW8UuBSCpvEg2Qo/3p+M/KYsZG9IsfiGj9/JySR87DUKsuJKBGTwSpKLiNUVeblmAIH2zK gaBoXkMwyDl7ekocRQ9YZ4NhZ2WXjy+Q4CnAaSInqiRSEfjbG3qFNa2tx5Ni+P0vP9ehNFEja2Os nCEVS5z7Dwfm+1GufMRwiNbNDQECwBwEKSCYF71eZHr06HNz88ftci6lVRQoqixk1Pm1Ul1DoGc0 hZ8kuTtEDn6lm8GRixVVVVkmsZ2Tph54dsJ7CPLgHQg+2nWhDoEAj7Nnx3HZpksXlFUgicQQQQm1 hDr1ixAah0W8ZCPGkZhMCLGC3kChIE8IQd4LQpVOW4OSwpWPeAogQisH2TuBHaWFARa5gzqt09TY 94+xY/lhifNKP5EhXr4wyqf4T25fD2H1GMLKoTxGKmMVZY0dGhglmCAsCZLP1KTbSJQy5yGKLqk+ 6pKVI2dWoyNXdlrilpFrRPnUn5Dg/LM/IRGpDyQuWhDjFDFyU5jkuW+LsvdUDtayO6KhdsQ2ZTMJ G0ukZLlfXN0wQHKDkiUbg4bGyCGc5ASJg8J7GeQpIXNmOAI8XhGtCkwYhtSPt8XKS4frpES0djbP x1Jv20t8q9riocypCz8a7+N8GjoLNx7sk8YxhRSkhr2tG/13Q55leGm6BeWBkGlcWHqLCRWDvwjI 4fG95wbJNiqSUfb3G6NGyVJUqKKaFKm2ScPI1h7sWT2opqKPyJlHJUqVeX/mUhqxUqbXCSOmVBKw zJuJRPJD2SOwPfDBPZ2OS2z2xrlvqC75Peklulae3tXrCK/SyNs/d1b/Ovy9AazdSK7cSJAjOW8G wLu5C7oeiR510xmspnO9SapxbNTVZjCoxkODwmteJakaa2mj4nis2ydQjHQ9RIwmlPNJIxWTeqJV MFFe6tLqRxsIxThvNk2lSmUQ6GWMa9EtGYtIkmD6jpyecoM0T08nHlY6Xg3TyxNd188KVEtuSF0P PgRPp+XTo6J8y8dTaMCaSL/FPN3r3nyah3J7zvZkvZxTaZzhK6fUy0upEw9lNGbYTUuahOL67om4 ryeSHvL5TVUmu9E5yQbiXKmIrLPfDzoVYJGGBIQYpYLIwil07jVLK4SMn51JkrNkWiMGkai8RYrp LFtNMQtC+KQiQgQ17ihcS7iXk+v2PqX7721NSpSlSRQ74R7oOcTbFDfL1CixVLouB9dhnJ0MpOLt ZnnF6mdUpJoaXmImIqqikFQqSqDnCo1yXT62Xv97lXieVWrhsLSVEj3OSiwAzqdK0i8PrijpxvNA J0h7x7pmDq74h3nOmtDl8fMuvQL2kRYQA0blKWDQtYCkbrT7DaJFKsivDSrvKi8iCZQ2gGIvyWNb UFqsAuOAOOdaFeEkxXhKGDuIhzSTkSWDEyCBR1RC1VEEYIhKVBWRQsSoqKDvxp3p3wpIeM1OrKLJ qo8CpDqXTIyidH4HWW/QmKQxMxuo7jNuJbhi3zUG3aEiKkEAxnk+GDynEUEYXlGJHyxICFU9XGhw ER0kQVqJwagCOJI5xoNBIGDGhNNNhzUpqSJlAbdSqWslp7juC5dSmWDQ1utv2O2yK65a/ssytEwU +cYiuBKAxIO2OxlpEd0KJOIZKmzyDA4zeJFqdg8oyFy81Dxo0fnSX9A9oPNP5Bkn+95uNg4hVTLa qqfcOJ3uVBmCEYxVP8dMXb9n33hy15aqKeItNV+FEQjHnM4223sBfU+swOAYFc3Tk5Tn5hC55w+e IbQGI3A0KUeHMngOG/nk5p6yh6oxGYJ1f6VQujd0LbdlS+QlYxQuMEJqyKTACeiLKpCT/xZcugpZ SA8+lfCSB0BRQaCJCq4gnhN4XQE9D4A8ZEzjqfC+OQ+criEQYM+V+L26+gxj9nI7+w+c8bGVNsVa CV0FC1S3ivLMFQlEZBjJFBMVShElUSqYFEUnrUUIjO00IENBFkMEdAshMANhDlhRdSNJCMREgMG4 aSlbBgMkCogmspixEggGAbRklyQPMTri1TJzqVTJhAxvkNW1liSZuo7u0gMNskQfIEUR/JCRkUIR R+mWuhzqOZMfH5vp+mPpZWe1dd+Fsb65JHsa1yes9yRtdqUEiqRA9W3sKcg7S9jWmwtwKHlDhFLU 8PczcNuydcEWOBVUKVFUfLS1RIn4sz8RJt2putCLSH9RSJOCUKqiqQpoxhrRFJq8iTRuKCJFUgcS u51KsTxc85cLWze1JJCr1ERO2c5KSJGtkRDILPaEmHTWZ7k+m45UvBanttVqBOl+qNPo5RzixSC7 vQssTJhvUeSwRRbFVJUStTUacGMWiGKkvaUkZOkDUHrLVKal8pKIhISmjabHKDOyXvIz/qwn9vXr 8duLBy6Aq0WLKidBubaURrnmoqoxRyPP+nb1FGYdGqFIpVVUiN01bHa64d1RWJjss27z4pGYRgRc YkytQNCJnmqXXiUJJxABfahSCwslEQjBIgUCBQIwiqd4OtY/M/MZGWkqLcIn8Gf2qpmiWtaLWtDR NWlJPCDFY6AaSKPC+jmgeAw8NiRcd48AaBdY2Y9FYo7EHWSRgVtM4BQ7uT/SHzvQbBdYIJK2C2Wu X1gI9kZGaEYasEAQITl2wZ+QJw22VV1q9ryJnbAl2cpqMZuBxtZV2WhDOwzQEkj2QWGccZgcVFBw SYM5JqM4mKPxSyaJikjFF4pFJqkHPaqYKQEQ6QxSlLlOeRIO0EEVtHYYbjSWd3nDO8KLOeYzUBEg lVJLGERvjCS3ltN5F2JjuN0tj66hVCV0Wj2K87yapq6S3BpaWM5zxTwOjnkdCoq8q5I46iQ7HBCg 875FHpYfZUG+OU2QhmFaJwm6DzGvLGicVmo5cqI2YJLJzJGMbUjId7Ta8VuhyPMbYd62rrLOQ2kj 2cpgR9Ekg5Op8hy6MJLSc0h0Dij+/T5E4Py7kTN+5IcHoOznWtwkk06ZIsiONjmhrNw+QhSai5JE gQUGwO+Wnw8Vz5zuOdiBvQR0uZoyE8UCch3AudgxuL0D31K1ntR31PVvhGCkhAiHuwQH3CC7HWZD 4e7hf/9UeaKbDO2cUe6adhd+SRFSZdT7zy95DsOW5F3ntIjewehoVHgoY09TxWVo5LMMmsyMKku/ lXYKVgk1yYl48EM1niyP3hb7tsMJ8LtR28YNOskKre3vjHsi9niFsQ7TwCeEIvGYD/wCoJEPkmFX XdEyLD/wykhE5RCkrpjaLiaCaC4KggPcuYJ/8XckU4UJApFDmZA=