summaryrefslogtreecommitdiff
path: root/Build/source/libs/pplib/pplib-src/src/util/utilfpred.c
diff options
context:
space:
mode:
authorDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
committerDenis Bitouzé <dbitouze@wanadoo.fr>2021-02-25 18:23:07 +0000
commitc6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch)
tree1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/libs/pplib/pplib-src/src/util/utilfpred.c
parent07ee7222e389b0777456b427a55c22d0e6ffd267 (diff)
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/pplib/pplib-src/src/util/utilfpred.c')
-rw-r--r--Build/source/libs/pplib/pplib-src/src/util/utilfpred.c778
1 files changed, 0 insertions, 778 deletions
diff --git a/Build/source/libs/pplib/pplib-src/src/util/utilfpred.c b/Build/source/libs/pplib/pplib-src/src/util/utilfpred.c
deleted file mode 100644
index 9203c5e0742..00000000000
--- a/Build/source/libs/pplib/pplib-src/src/util/utilfpred.c
+++ /dev/null
@@ -1,778 +0,0 @@
-/* predictor filters; common for flate and lzw */
-
-#include "utilmem.h"
-#include "utillog.h"
-#include "utilfpred.h"
-
-/*
-Here we implement predictor filters used with flate and lzw compressions in PDF streams. The main idea of data prediction
-is to compute and output the differences between data records instead of those records. Adjacent pixels in images are usually
-similar, so differences between pixel values tends to be zero. And both Flate and LZW performs better when the input
-is rather smooth. Although a preliminary use of predictors is related to bitmap data, The actual need for predictor filter
-came from the fact that xref streams may also be predicted (usually with PNG up-predictor).
-
-PDF specification allows to use several predictor algorithms, specified by /Predictor key in /DecodeParms dictionary:
-
- 1 - no predictor (default)
- 2 - TIFF horizontal predictor
- 10 - PNG none predictor
- 11 - PNG sub predictor
- 12 - PNG up predictor
- 13 - PNG average predictor
- 14 - PNG paeth predictor
-
-All PNG predictors works on bytes, regardless the image color-depth. While encoding, every input data byte is decreased
-by the appropriate byte of the previous pixel. Even if the pixel does not fit a full byte, PNG predictors use an artificial
-pixel size rounded up to a full byte. PNG predictors utilizes previous (left) pixel, pixel above and previous to above
-pixel. In case of PNG, the type of the predictor is written on a dedicated byte at the beginning of every scanline. It
-means all predictor functions must maintain and information about left, above and left-above pixels.
-
-Despite the same differencing idea, TIFF predictors are different. The prediction process bases on pixel components,
-which are not necessarily bytes (component of a pixel is added/substracted from a relevant component of a previous
-pixel). In TIFF predictor 2, only the previous (the left) pixel is taken into account, there is no need to keep
-an information about other surrounding pixels. Also there is no expicit algorithm marker in data; the same prediction
-method is applied to all input rows.
-
-Not surprisingly, predictor encoders and decoders are pretty similar. Encoders take some input value and the previous
-input value (or 0 at the beginning of the scanline) and output a difference between them. Decoders takes an input value,
-previously decoded value (or zero) and outputs their sum. When encoding, the result is cast to the proper unsigned integer,
-when decoding, modulo 256 (or appropriate) is used, which makes encoding and decoding looseless.
-
-Some extra bits trickery is involved in TIFF predictor function, when components don't fit bytes boundary. In that case,
-an input is treated as a bits stream. Every input byte is "buffered" in a larger integer, as its lower bits (from right).
-Every output value is taken from its higher (left) bits. In a special case of bits-per-component equal 1, we buffer all
-pixel bits and use XOR to compute bits difference between pixels. I've excerpted that trick from poppler, but I'm not
-really sure if it works any better, especially when the number of components per pixel is 1. In that case we do a hard
-bit-by-bit work anyway.
-
-In PNG prediction, we record every pixel byte (in decoded form) in state->rowsave. At the end of a scanline
-we copy state->rowsave to state->rowup, so that in the next scanline we can access up-pixel byte.
-Left pixel byte is accessed as state->rowsave (the byte recently stored or virtual left edge byte \0).
-Up-left pixel byte is accessed via state->rowup, but with state->pixelsize offset (same as left byte, possibly \0
-at the left edge of the row). Both state->rowup and state->rowsave has a safe span of pixelsize bytes on the left,
-that are permanently \0.
-*/
-
-#define predictor_component_t uint16_t
-#define predictor_pixel1b_t uint32_t
-
-#define MAX_COMPONENTS 8
-
-struct predictor_state {
- int default_predictor; /* default predictor indicator */
- int current_predictor; /* current predictor, possibly taken from algorithm marker in PNG data */
- int rowsamples; /* number of pixels in a scanline (/DecodeParms << /Columns ... >>) */
- int compbits; /* number of bits per component (/DecodeParms << /BitsPerComponent ... >>) */
- int components; /* number of components (/DecodeParms << /Colors ... >>) */
- uint8_t *buffer; /* temporary private buffer area */
- uint8_t *rowin; /* an input row buffer position */
- int rowsize; /* size of a current scanline in bytes (rounded up) */
- int rowend; /* an input buffer end position */
- int rowindex; /* an output buffer position */
- union {
- struct { /* used by PNG predictor codecs */
- uint8_t *rowup, *rowsave; /* previous scanline buffers */
- int predictorbyte; /* flag indicating that algorithm byte is read/written */
- int pixelsize; /* number of bytes per pixel (rounded up) */
- };
- struct { /* used by TIFF predictor codecs */
- predictor_component_t compbuffer[MAX_COMPONENTS];
- union {
- predictor_component_t *prevcomp; /* an array of left pixel components, typically eq ->compbuffer */
- predictor_pixel1b_t *prevpixel; /* left pixel value stored on a single integer (for 1bit color-depth) */
- };
- int compin, compout; /* bit stream buffers */
- int bitsin, bitsout; /* bit stream counters */
- int sampleindex; /* pixel counter */
- int compindex; /* component counter */
- int pixbufsize; /* size of pixel buffer in bytes */
- };
- };
- int flush;
- int status;
-};
-
-typedef union { predictor_state *predictorstate; void *voidstate; } predictor_state_pointer; // to avoid 'dereferencing type-puned ...' warnings
-
-enum {
- STATUS_LAST = 0,
- STATUS_CONTINUE = 1 // any value different then IOFEOF, IOFERR, ... which are < 0
-};
-
-/*
-Predictor type identifiers (pdf spec 76). lpdf doesn't hire the codec if predictor is 1. Predictor 15 indicates
-that the type of PNG prediction algorithm may change in subsequent lines. We always check algorithm marker anyway.
-*/
-
-enum predictor_code {
- NONE_PREDICTOR = 1,
- TIFF_PREDICTOR = 2,
- PNG_NONE_PREDICTOR = 10,
- PNG_SUB_PREDICTOR = 11,
- PNG_UP_PREDICTOR = 12,
- PNG_AVERAGE_PREDICTOR = 13,
- PNG_PAETH_PREDICTOR = 14,
- PNG_OPTIMUM_PREDICTOR = 15
-};
-
-predictor_state * predictor_decoder_init (predictor_state *state, int predictor, int rowsamples, int components, int compbits)
-{
- int rowsize, pixelsize;
-#define storage_pos(b, p, size) ((b = p), (p += size))
- uint8_t *buffer, *p;
- size_t buffersize;
-
- pixelsize = (components * compbits + 7) >> 3; // to bytes, rounded up
- rowsize = (rowsamples * components * compbits + 7) >> 3;
-
- state->default_predictor = state->current_predictor = predictor;
- state->rowsamples = rowsamples;
- state->components = components;
- state->compbits = compbits;
-
- if (predictor == TIFF_PREDICTOR)
- { /* tiff predictor */
- size_t compbuf, pixbuf;
- compbuf = components * sizeof(predictor_component_t);
- pixbuf = 1 * sizeof(predictor_pixel1b_t);
- state->pixbufsize = (int)(compbuf > pixbuf ? compbuf : pixbuf);
- buffersize = rowsize * sizeof(uint8_t);
- buffer = (uint8_t *)util_calloc(buffersize, 1);
- if ((size_t)state->pixbufsize > sizeof(state->compbuffer)) // components > MAX_COMPONENTS
- state->prevcomp = (predictor_component_t *)util_calloc(state->pixbufsize, 1);
- else
- state->prevcomp = state->compbuffer;
- // &state->prevcomp == &state->prevpixel
- state->sampleindex = state->compindex = 0;
- state->bitsin = state->bitsout = 0;
- state->compin = state->compout = 0;
- }
- else
- { /* png predictors */
- buffersize = (3 * rowsize + 2 * pixelsize + 1) * sizeof(uint8_t);
- p = buffer = (uint8_t *)util_calloc(buffersize, 1);
- storage_pos(state->rowin, p, 1 + rowsize); // one extra byte for prediction algorithm tag
- p += pixelsize; // pixelsize extra bytes for virtual left pixel at the edge, eg. rowup[-1] (permanently \0)
- storage_pos(state->rowup, p, rowsize); // actual row byte
- p += pixelsize; // ditto
- storage_pos(state->rowsave, p, rowsize);
- state->pixelsize = pixelsize;
- state->predictorbyte = 0;
- }
- state->buffer = buffer;
- state->rowsize = rowsize;
- state->rowindex = 0;
- state->rowend = 0;
- state->status = STATUS_CONTINUE;
- return state;
-}
-
-predictor_state * predictor_encoder_init (predictor_state *state, int predictor, int rowsamples, int components, int compbits)
-{
- return predictor_decoder_init(state, predictor, rowsamples, components, compbits);
-}
-
-void predictor_decoder_close (predictor_state *state)
-{
- util_free(state->buffer);
- if (state->default_predictor == TIFF_PREDICTOR && state->prevcomp != NULL && state->prevcomp != state->compbuffer)
- util_free(state->prevcomp);
-}
-
-void predictor_encoder_close (predictor_state *state)
-{
- predictor_decoder_close(state);
-}
-
-/*
-All predoctor codecs first read the entire data row into a buffer. This is not crucial for the process,
-but allows to separate read/write states. In particular, there is one place in which codec functions
-may return on EOD.
-*/
-
-#define start_row(state) (state->rowindex = 0, state->rowin = state->buffer)
-
-static int read_scanline (predictor_state *state, iof *I, int size)
-{
- int rowtail, left;
- while ((rowtail = size - state->rowend) > 0)
- {
- left = (int)iof_left(I);
- if (left >= rowtail)
- {
- memcpy(state->buffer + state->rowend, I->pos, (size_t)rowtail);
- state->rowend += rowtail;
- I->pos += rowtail;
- start_row(state);
- break;
- }
- else
- {
- if ((rowtail = left) > 0)
- {
- memcpy(state->buffer + state->rowend, I->pos, (size_t)rowtail);
- state->rowend += rowtail;
- I->pos += rowtail;
- }
- if (iof_input(I) == 0)
- {
- if (state->rowend == 0) // no scanline to process, no more input
- return state->flush ? IOFEOF : IOFEMPTY;
- /* If we are here, there is an incomplete scanline in buffer:
- - if there is a chance for more (state->flush == 0), than wait for more
- - otherwise encode/decode the last incomplete line?
- pdf spec p. 76 says that "A row occupies a whole number of bytes",
- so this situation should be considered abnormal (not found so far).
- */
- if (!state->flush)
- return IOFEMPTY;
- loggerf("incomplete scanline in predictor filter");
- //return IOFERR;
- state->status = STATUS_LAST;
- state->rowsize -= size - state->rowend;
- start_row(state);
- break;
- }
- }
- }
- return STATUS_CONTINUE;
-}
-
-#define read_row(state, I, size, status) if ((status = read_scanline(state, I, size)) != STATUS_CONTINUE) return status
-
-#define ensure_output_bytes(O, n) if (!iof_ensure(O, n)) return IOFFULL
-
-#define tobyte(c) ((uint8_t)(c))
-#define tocomp(c) ((uint16_t)(c))
-
-#define row_byte(state) (state->rowin[state->rowindex])
-
-/* png predictor macros; on bytes */
-
-#define up_pixel_byte(state) (state->rowup[state->rowindex])
-#define upleft_pixel_byte(state) (state->rowup[state->rowindex - state->pixelsize])
-#define left_pixel_byte(state) (state->rowsave[state->rowindex - state->pixelsize])
-#define save_pixel_byte(state, c) (state->rowsave[state->rowindex] = (uint8_t)(c))
-
-/* tiff predictor macros; on components */
-
-#define left_pixel_component(state) (state->prevcomp[state->compindex]) // tiff predictor with 2, 4, 8, 16 components
-#define left_pixel_value(state) (state->prevpixel[0]) // tiff predictor with 1bit components
-
-/* assignment in conditional
-#define save_pixel_component(state, c) ((void)\
- ((state->prevcomp[state->compindex] = (predictor_component_t)(c)), \
- ++state->compindex, (state->compindex < state->components || (state->compindex = 0))))
-*/
-#define save_pixel_component(state, c) \
- do { state->prevcomp[state->compindex] = (predictor_component_t)(c); if (++state->compindex >= state->components) state->compindex = 0; } while (0)
-
-#define save_pixel_value(state, c) (state->prevpixel[0] = (predictor_pixel1b_t)(c))
-
-/* Once the codec function is done with the scanline, we set imaginary left pixel data to zero, and reset row counters to
-zero in order to allow buffering another input scanline. */
-
-#define reset_row(state) state->rowend = 0
-
-#define reset_png_row(state) (memcpy(state->rowup, state->rowsave, state->rowsize), state->predictorbyte = 0, reset_row(state))
-
-#define reset_tiff_row(state) \
- memset(state->prevcomp, 0, state->pixbufsize), \
- state->bitsin = state->bitsout = 0, \
- state->compin = state->compout = 0, \
- reset_row(state), \
- state->sampleindex = state->compindex = 0
-
-/* PNG paeth predictor function; http://www.libpng.org/pub/png/book/chapter09.html
-Compute the base value p := left + up - upleft, then choose that byte the closest
-(of the smallest absolute difference) to the base value. Left byte has a precedence. */
-
-
-static int paeth (predictor_state *state)
-{
- int p, p1, p2, p3;
- p = left_pixel_byte(state) + up_pixel_byte(state) - upleft_pixel_byte(state);
- p1 = p >= left_pixel_byte(state) ? (p - left_pixel_byte(state)) : (left_pixel_byte(state) - p);
- p2 = p >= up_pixel_byte(state) ? (p - up_pixel_byte(state)) : (up_pixel_byte(state) - p);
- p3 = p >= upleft_pixel_byte(state) ? (p - upleft_pixel_byte(state)) : (upleft_pixel_byte(state) - p);
- return (p1 <= p2 && p1 <= p3) ? left_pixel_byte(state) : (p2 <= p3 ? up_pixel_byte(state) : upleft_pixel_byte(state));
-}
-
-/* predictor decoder */
-
-iof_status predictor_decode_state (iof *I, iof *O, predictor_state *state)
-{
- int status, c, d, outbytes;
- while (state->status == STATUS_CONTINUE)
- {
- if (state->default_predictor >= 10) // PNG predictor?
- {
- read_row(state, I, state->rowsize + 1, status);
- if (state->predictorbyte == 0)
- { // we could actually check state->rowin <> state->buffer, but we need this flag for encoder anyway
- state->current_predictor = row_byte(state) + 10;
- state->predictorbyte = 1;
- ++state->rowin;
- }
- }
- else
- {
- read_row(state, I, state->rowsize, status);
- }
- switch (state->current_predictor)
- {
- case NONE_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- iof_set(O, c);
- }
- reset_row(state);
- break;
- case TIFF_PREDICTOR:
- switch (state->compbits)
- {
- case 1:
- outbytes = (state->components + 7) >> 3;
- for ( ; state->sampleindex < state->rowsamples; ++state->sampleindex)
- {
- ensure_output_bytes(O, outbytes);
- while (state->bitsin < state->components)
- {
- state->compin = (state->compin << 8) | row_byte(state);
- state->bitsin += 8;
- ++state->rowindex;
- }
- state->bitsin -= state->components;
- d = state->compin >> state->bitsin;
- state->compin &= (1 << state->bitsin) - 1;
- c = d ^ left_pixel_value(state);
- save_pixel_value(state, c);
- state->compout = (state->compout << state->components) | c;
- state->bitsout += state->components;
- while (state->bitsout >= 8)
- {
- state->bitsout -= 8;
- iof_set(O, state->compout >> state->bitsout);
- state->compout &= (1 << state->bitsout) - 1;
- }
- }
- if (state->bitsout > 0)
- {
- ensure_output_bytes(O, 1);
- iof_set(O, state->compin << (8 - state->bitsout));
- }
- break;
- case 2: case 4:
- for ( ; state->sampleindex < state->rowsamples; ++state->sampleindex)
- {
- for ( ; state->compindex < state->components; ) // state->compindex is ++ed by save_pixel_component()
- {
- ensure_output_bytes(O, 1);
- if (state->bitsin < state->compbits)
- {
- state->compin = (state->compin << 8) | row_byte(state);
- state->bitsin += 8;
- ++state->rowindex;
- }
- state->bitsin -= state->compbits;
- d = state->compin >> state->bitsin;
- state->compin &= (1 << state->bitsin) - 1;
- c = (d + left_pixel_component(state)) & 0xff;
- save_pixel_component(state, c);
- state->compout = (state->compout << state->compbits) | c;
- state->bitsout += state->compbits;
- if (state->bitsout >= 8)
- {
- state->bitsout -= 8;
- iof_set(O, state->compout >> state->bitsout);
- state->compout &= (1 << state->bitsout) - 1;
- }
- }
- }
- if (state->bitsout > 0)
- {
- ensure_output_bytes(O, 1);
- iof_set(O, state->compin << (8 - state->bitsout));
- }
- break;
- case 8:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = (row_byte(state) + left_pixel_component(state)) & 0xff;
- save_pixel_component(state, c);
- iof_set(O, c);
- }
- break;
- case 16:
- for ( ; state->rowindex < state->rowsize - 1; ++state->rowindex)
- {
- ensure_output_bytes(O, 2);
- d = row_byte(state) << 8;
- ++state->rowindex;
- d |= row_byte(state);
- c = (d + left_pixel_component(state)) & 0xffff;
- save_pixel_component(state, c);
- iof_set2(O, c >> 8, c & 0xff);
- }
- break;
- default:
- return IOFERR;
- }
- reset_tiff_row(state);
- break;
- case PNG_NONE_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- save_pixel_byte(state, c); // next row may need it
- iof_set(O, c);
- }
- reset_png_row(state);
- break;
- case PNG_SUB_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = (row_byte(state) + left_pixel_byte(state)) & 0xff;
- save_pixel_byte(state, c);
- iof_set(O, c);
- }
- reset_png_row(state);
- break;
- case PNG_UP_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = (row_byte(state) + up_pixel_byte(state)) & 0xff;
- save_pixel_byte(state, c);
- iof_set(O, c);
- }
- reset_png_row(state);
- break;
- case PNG_AVERAGE_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = (row_byte(state) + ((up_pixel_byte(state) + left_pixel_byte(state)) / 2)) & 0xff;
- save_pixel_byte(state, c);
- iof_set(O, c);
- }
- reset_png_row(state);
- break;
- case PNG_PAETH_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = (row_byte(state) + paeth(state)) & 0xff;
- save_pixel_byte(state, c);
- iof_set(O, c);
- }
- reset_png_row(state);
- break;
- //case PNG_OPTIMUM_PREDICTOR: // valid as default_redictor, but not as algorithm identifier byte
- default:
- return IOFERR;
- }
- }
- return state->status == STATUS_LAST ? IOFERR : IOFEOF;
-}
-
-/* predictor encoder */
-
-iof_status predictor_encode_state (iof *I, iof *O, predictor_state *state)
-{
- int status, c, d, outbytes;
- while (state->status == STATUS_CONTINUE)
- {
- read_row(state, I, state->rowsize, status);
- if (state->current_predictor >= 10 && state->predictorbyte == 0)
- {
- ensure_output_bytes(O, 1);
- iof_set(O, state->current_predictor - 10);
- state->predictorbyte = 1;
- }
- switch (state->current_predictor)
- {
- case NONE_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- iof_set(O, c);
- }
- reset_row(state);
- break;
- case TIFF_PREDICTOR:
- switch (state->compbits)
- {
- case 1:
- outbytes = (state->components + 7) >> 3;
- for ( ; state->sampleindex < state->rowsamples; ++state->sampleindex)
- {
- ensure_output_bytes(O, outbytes);
- while (state->bitsin < state->components)
- {
- state->compin = (state->compin << 8) | row_byte(state);
- state->bitsin += 8;
- ++state->rowindex;
- }
- state->bitsin -= state->components;
- c = state->compin >> state->bitsin;
- state->compin &= (1 << state->bitsin) - 1;
- d = c ^ left_pixel_value(state);
- save_pixel_value(state, c);
- state->compout = (state->compout << state->components) | d;
- state->bitsout += state->components;
- while (state->bitsout >= 8)
- {
- state->bitsout -= 8;
- iof_set(O, state->compout >> state->bitsout);
- state->compout &= (1 << state->bitsout) - 1;
- }
- }
- if (state->bitsout > 0)
- {
- ensure_output_bytes(O, 1);
- iof_set(O, state->compin << (8 - state->bitsout));
- }
- break;
- case 2: case 4:
- for ( ; state->sampleindex < state->rowsamples; ++state->sampleindex)
- {
- for ( ; state->compindex < state->components; )
- {
- ensure_output_bytes(O, 1);
- if (state->bitsin < state->compbits)
- {
- state->compin = (state->compin << 8) | row_byte(state);
- state->bitsin += 8;
- ++state->rowindex;
- }
- state->bitsin -= state->compbits;
- c = state->compin >> state->bitsin;
- state->compin &= (1 << state->bitsin) - 1;
- d = tocomp(c - left_pixel_component(state));
- save_pixel_component(state, c);
- state->compout = (state->compout << state->compbits) | d;
- state->bitsout += state->compbits;
- if (state->bitsout >= 8)
- {
- state->bitsout -= 8;
- iof_set(O, state->compout >> state->bitsout);
- state->compout &= (1 << state->bitsout) - 1;
- }
- }
- }
- if (state->bitsout > 0)
- {
- ensure_output_bytes(O, 1);
- iof_set(O, state->compin << (8 - state->bitsout));
- }
- break;
- case 8:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- d = tobyte(c - left_pixel_component(state));
- save_pixel_component(state, c);
- iof_set(O, d);
- }
- break;
- case 16:
- for ( ; state->rowindex < state->rowsize - 1; ++state->rowindex)
- {
- ensure_output_bytes(O, 2);
- c = row_byte(state) << 8;
- ++state->rowindex;
- c |= row_byte(state);
- d = tocomp(c - left_pixel_component(state));
- save_pixel_component(state, c);
- iof_set2(O, d >> 8, d & 0xff);
- }
- break;
- default:
- return IOFERR;
- }
- reset_tiff_row(state);
- break;
- case PNG_NONE_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- save_pixel_byte(state, c); // next row may need it
- iof_set(O, c);
- }
- reset_png_row(state);
- break;
- case PNG_SUB_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- d = tobyte(c - left_pixel_byte(state));
- save_pixel_byte(state, c);
- iof_set(O, d);
- }
- reset_png_row(state);
- break;
- case PNG_OPTIMUM_PREDICTOR: // not worthy to perform optimization
- case PNG_UP_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- d = tobyte(c - up_pixel_byte(state));
- save_pixel_byte(state, c);
- iof_set(O, d);
- }
- reset_png_row(state);
- break;
- case PNG_AVERAGE_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- d = tobyte(c - ((up_pixel_byte(state) + left_pixel_byte(state)) >> 1));
- save_pixel_byte(state, c);
- iof_set(O, d);
- }
- reset_png_row(state);
- break;
- case PNG_PAETH_PREDICTOR:
- for ( ; state->rowindex < state->rowsize; ++state->rowindex)
- {
- ensure_output_bytes(O, 1);
- c = row_byte(state);
- d = tobyte(c - paeth(state));
- save_pixel_byte(state, c);
- iof_set(O, d);
- }
- reset_png_row(state);
- break;
- default:
- return IOFERR;
- }
- }
- return state->status == STATUS_LAST ? IOFERR : IOFEOF;
-}
-
-iof_status predictor_decode (iof *I, iof *O, int predictor, int rowsamples, int components, int compbits)
-{
- predictor_state state;
- int ret;
- predictor_decoder_init(&state, predictor, rowsamples, components, compbits);
- state.flush = 1;
- ret = predictor_decode_state(I, O, &state);
- predictor_decoder_close(&state);
- return ret;
-}
-
-iof_status predictor_encode (iof *I, iof *O, int predictor, int rowsamples, int components, int compbits)
-{
- predictor_state state;
- int ret;
- predictor_encoder_init(&state, predictor, rowsamples, components, compbits);
- state.flush = 1;
- ret = predictor_encode_state(I, O, &state);
- predictor_encoder_close(&state);
- return ret;
-}
-
-/* filters */
-
-// predictor decoder function
-
-static size_t predictor_decoder (iof *F, iof_mode mode)
-{
- predictor_state *state;
- iof_status status;
- size_t tail;
-
- state = iof_filter_state(predictor_state *, F);
- switch(mode)
- {
- case IOFLOAD:
- case IOFREAD:
- if (F->flags & IOF_STOPPED)
- return 0;
- tail = iof_tail(F);
- F->pos = F->buf + tail;
- F->end = F->buf + F->space;
- do {
- status = predictor_decode_state(F->next, F, state);
- } while (mode == IOFLOAD && status == IOFFULL && iof_resize_buffer(F));
- return iof_decoder_retval(F, "predictor", status);
- case IOFCLOSE:
- predictor_decoder_close(state);
- iof_free(F);
- return 0;
- default:
- break;
- }
- return 0;
-}
-
-// predictor encoder function
-
-static size_t predictor_encoder (iof *F, iof_mode mode)
-{
- predictor_state *state;
- iof_status status;
-
- state = iof_filter_state(predictor_state *, F);
- switch (mode)
- {
- case IOFFLUSH:
- state->flush = 1;
- FALLTHRU // fall through
- case IOFWRITE:
- F->end = F->pos;
- F->pos = F->buf;
- status = predictor_encode_state(F, F->next, state);
- return iof_encoder_retval(F, "predictor", status);
- case IOFCLOSE:
- if (!state->flush)
- predictor_encoder(F, IOFFLUSH);
- predictor_encoder_close(state);
- iof_free(F);
- return 0;
- default:
- break;
- }
- return 0;
-}
-
-iof * iof_filter_predictor_decoder (iof *N, int predictor, int rowsamples, int components, int compbits)
-{
- iof *I;
- predictor_state_pointer P;
- I = iof_filter_reader(predictor_decoder, sizeof(predictor_state), &P.voidstate);
- iof_setup_next(I, N);
- if (predictor_decoder_init(P.predictorstate, predictor, rowsamples, components, compbits) == NULL)
- {
- iof_discard(I);
- return NULL;
- }
- P.predictorstate->flush = 1;
- return I;
-}
-
-iof * iof_filter_predictor_encoder (iof *N, int predictor, int rowsamples, int components, int compbits)
-{
- iof *O;
- predictor_state_pointer P;
- O = iof_filter_writer(predictor_encoder, sizeof(predictor_state), &P.voidstate);
- iof_setup_next(O, N);
- if (predictor_encoder_init(P.predictorstate, predictor, rowsamples, components, compbits) == NULL)
- {
- iof_discard(O);
- return NULL;
- }
- return O;
-}