summaryrefslogtreecommitdiff
path: root/gs/src/siinterp.c
diff options
context:
space:
mode:
authorHenry Stiles <henry.stiles@artifex.com>1999-05-24 20:03:13 +0000
committerHenry Stiles <henry.stiles@artifex.com>1999-05-24 20:03:13 +0000
commit5e99d00db40250c4aec92e2e7ecaf51f629540ae (patch)
treec59a16131c363a845609bb0786adc205d3f6fddc /gs/src/siinterp.c
parent7ddfba499458819bf0dbf297b084f8b5b51b8690 (diff)
downloadghostpdl-5e99d00db40250c4aec92e2e7ecaf51f629540ae.tar.gz
initial gs5.84 checkin with pcl and xl compiling.
git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@857 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src/siinterp.c')
-rw-r--r--gs/src/siinterp.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/gs/src/siinterp.c b/gs/src/siinterp.c
new file mode 100644
index 000000000..823789f49
--- /dev/null
+++ b/gs/src/siinterp.c
@@ -0,0 +1,261 @@
+/* Copyright (C) 1999 Aladdin Enterprises. All rights reserved.
+
+ This file is part of Aladdin Ghostscript.
+
+ Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
+ or distributor accepts any responsibility for the consequences of using it,
+ or for whether it serves any particular purpose or works at all, unless he
+ or she says so in writing. Refer to the Aladdin Ghostscript Free Public
+ License (the "License") for full details.
+
+ Every copy of Aladdin Ghostscript must include a copy of the License,
+ normally in a plain ASCII text file named PUBLIC. The License grants you
+ the right to copy, modify and redistribute Aladdin Ghostscript, but only
+ under certain conditions described in the License. Among other things, the
+ License requires that the copyright notice and this notice be preserved on
+ all copies.
+ */
+
+
+/* Image interpolation filter */
+#include "memory_.h"
+#include <assert.h>
+#include "gxfixed.h" /* for gxdda.h */
+#include "gxdda.h"
+#include "gxfrac.h"
+#include "strimpl.h"
+#include "siinterp.h"
+
+/* ImageInterpolateEncode state */
+typedef struct gx_dda_int_s {
+ dda_state_struct(ia_, int, uint) state;
+ dda_step_struct(ie_, int, uint) step;
+} gx_dda_int_t;
+typedef enum {
+ SCALE_SAME = 0,
+ SCALE_SAME_ALIGNED,
+ SCALE_8_8,
+ SCALE_8_8_ALIGNED,
+ SCALE_8_16_BYTE2FRAC,
+ SCALE_8_16_BYTE2FRAC_ALIGNED,
+ SCALE_8_16_BYTE2FRAC_3,
+ SCALE_8_16_BYTE2FRAC_3_ALIGNED,
+ SCALE_8_16_GENERAL,
+ SCALE_8_16_GENERAL_ALIGNED,
+ SCALE_16_8,
+ SCALE_16_8_ALIGNED,
+ SCALE_16_16,
+ SCALE_16_16_ALIGNED
+} scale_case_t;
+typedef struct stream_IIEncode_state_s {
+ /* The client sets the params values before initialization. */
+ stream_image_scale_state_common; /* = state_common + params */
+ /* The init procedure sets the following. */
+ int sizeofPixelIn; /* bytes per input pixel, 1 or 2 * Colors */
+ int sizeofPixelOut; /* bytes per output pixel, 1 or 2 * Colors */
+ uint src_size; /* bytes per row of input */
+ uint dst_size; /* bytes per row of output */
+ void /*PixelOut */ *prev; /* previous row of input data in output fmt, */
+ /* [WidthIn * sizeofPixelOut] */
+ void /*PixelOut */ *cur; /* current row of input data in output fmt, */
+ /* [WidthIn * sizeofPixelOut] */
+ scale_case_t scale_case;
+ /* The following are updated dynamically. */
+ int dst_x;
+ gx_dda_int_t dda_x; /* DDA for dest X in current scan line */
+ gx_dda_int_t dda_x_init; /* initial setting of dda_x */
+ int src_y, dst_y;
+ gx_dda_int_t dda_y; /* DDA for dest Y */
+ int src_offset, dst_offset;
+} stream_IIEncode_state;
+
+gs_private_st_ptrs2(st_IIEncode_state, stream_IIEncode_state,
+ "ImageInterpolateEncode state",
+ iiencode_state_enum_ptrs, iiencode_state_reloc_ptrs,
+ prev, cur);
+
+/* Forward references */
+private void s_IIEncode_release(P1(stream_state * st));
+
+/* Initialize the filter. */
+private int
+s_IIEncode_init(stream_state * st)
+{
+ stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
+ gs_memory_t *mem = ss->memory;
+
+ ss->sizeofPixelIn =
+ ss->params.BitsPerComponentIn / 8 * ss->params.Colors;
+ ss->sizeofPixelOut =
+ ss->params.BitsPerComponentOut / 8 * ss->params.Colors;
+ ss->src_size = ss->sizeofPixelIn * ss->params.WidthIn;
+ ss->dst_size = ss->sizeofPixelOut * ss->params.WidthOut;
+
+ /* Initialize destination DDAs. */
+ ss->dst_x = 0;
+ ss->src_offset = ss->dst_offset = 0;
+ dda_init(ss->dda_x, 0, ss->params.WidthIn, ss->params.WidthOut);
+ ss->dda_x_init = ss->dda_x;
+ ss->src_y = ss->dst_y = 0;
+ dda_init(ss->dda_y, 0, ss->params.HeightOut, ss->params.HeightIn);
+
+ /* Allocate buffers for 2 rows of input data. */
+ ss->prev = gs_alloc_byte_array(mem, ss->params.WidthIn,
+ ss->sizeofPixelOut, "IIEncode prev");
+ ss->cur = gs_alloc_byte_array(mem, ss->params.WidthIn,
+ ss->sizeofPixelOut, "IIEncode cur");
+ if (ss->prev == 0 || ss->cur == 0) {
+ s_IIEncode_release(st);
+ return ERRC; /****** WRONG ******/
+ }
+
+ /* Determine the case for the inner loop. */
+ ss->scale_case =
+ (ss->params.BitsPerComponentIn == 8 ?
+ (ss->params.BitsPerComponentOut == 8 ?
+ (ss->params.MaxValueIn == ss->params.MaxValueOut ?
+ SCALE_SAME : SCALE_8_8) :
+ (ss->params.MaxValueIn == 255 && ss->params.MaxValueOut == frac_1 ?
+ (ss->params.Colors == 3 ? SCALE_8_16_BYTE2FRAC_3 :
+ SCALE_8_16_BYTE2FRAC) :
+ SCALE_8_16_GENERAL)) :
+ (ss->params.BitsPerComponentOut == 8 ? SCALE_16_8 :
+ ss->params.MaxValueIn == ss->params.MaxValueOut ?
+ SCALE_SAME : SCALE_16_16));
+
+ return 0;
+}
+
+/* Process a buffer. */
+private int
+s_IIEncode_process(stream_state * st, stream_cursor_read * pr,
+ stream_cursor_write * pw, bool last)
+{
+ stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
+ const scale_case_t scale_case = ss->scale_case +
+ ALIGNMENT_MOD(pw->ptr, 2); /* ptr odd => buffer is aligned */
+ byte *out = pw->ptr + 1;
+ /****** WRONG, requires an entire output pixel ******/
+ byte *limit = pw->limit + 1 - ss->sizeofPixelOut;
+
+ /* Check whether we need to deliver any output. */
+
+top:
+ if (dda_current(ss->dda_y) > ss->dst_y) {
+ /* Deliver some or all of the current scaled row. */
+ while (ss->dst_x < ss->params.WidthOut) {
+ uint sx = dda_current(ss->dda_x) * ss->sizeofPixelIn;
+ const byte *in = (const byte *)ss->cur + sx;
+ int c;
+
+ if (out > limit) {
+ pw->ptr = out - 1;
+ return 1;
+ }
+ switch (scale_case) {
+ case SCALE_SAME:
+ case SCALE_SAME_ALIGNED:
+ memcpy(out, in, ss->sizeofPixelIn);
+ out += ss->sizeofPixelIn;
+ break;
+ case SCALE_8_8:
+ case SCALE_8_8_ALIGNED:
+ for (c = ss->params.Colors; --c >= 0; ++in, ++out)
+ *out = (byte)(*in * ss->params.MaxValueOut /
+ ss->params.MaxValueIn);
+ break;
+ case SCALE_8_16_BYTE2FRAC:
+ case SCALE_8_16_BYTE2FRAC_ALIGNED: /* could be optimized */
+ case SCALE_8_16_BYTE2FRAC_3: /* could be optimized */
+ for (c = ss->params.Colors; --c >= 0; ++in, out += 2) {
+ uint b = *in;
+ uint value = byte2frac(b);
+
+ out[0] = (byte)(value >> 8), out[1] = (byte)value;
+ }
+ break;
+ case SCALE_8_16_BYTE2FRAC_3_ALIGNED:
+ {
+ uint b = in[0];
+
+ ((bits16 *)out)[0] = byte2frac(b);
+ b = in[1];
+ ((bits16 *)out)[1] = byte2frac(b);
+ b = in[2];
+ ((bits16 *)out)[2] = byte2frac(b);
+ }
+ out += 6;
+ break;
+ case SCALE_8_16_GENERAL:
+ case SCALE_8_16_GENERAL_ALIGNED: /* could be optimized */
+ for (c = ss->params.Colors; --c >= 0; ++in, out += 2) {
+ uint value = *in * ss->params.MaxValueOut /
+ ss->params.MaxValueIn;
+
+ out[0] = (byte)(value >> 8), out[1] = (byte)value;
+ }
+ break;
+ case SCALE_16_8:
+ case SCALE_16_8_ALIGNED:
+ for (c = ss->params.Colors; --c >= 0; in += 2, ++out)
+ *out = (byte)(*(const bits16 *)in *
+ ss->params.MaxValueOut /
+ ss->params.MaxValueIn);
+ break;
+ case SCALE_16_16:
+ case SCALE_16_16_ALIGNED: /* could be optimized */
+ for (c = ss->params.Colors; --c >= 0; in += 2, out += 2) {
+ uint value = *(const bits16 *)in *
+ ss->params.MaxValueOut / ss->params.MaxValueIn;
+
+ out[0] = (byte)(value >> 8), out[1] = (byte)value;
+ }
+ }
+ dda_next(ss->dda_x);
+ ss->dst_x++;
+ }
+ ss->dst_x = 0;
+ ss->dst_y++;
+ ss->dda_x = ss->dda_x_init;
+ goto top;
+ }
+ pw->ptr = out - 1;
+ if (ss->dst_y >= ss->params.HeightOut)
+ return EOFC;
+
+ if (ss->src_offset < ss->src_size) {
+ uint count = min(ss->src_size - ss->src_offset, pr->limit - pr->ptr);
+
+ if (count == 0)
+ return 0;
+ memcpy((byte *)ss->cur + ss->src_offset, pr->ptr + 1, count);
+ ss->src_offset += count;
+ pr->ptr += count;
+ if (ss->src_offset < ss->src_size)
+ return 0;
+ }
+ ss->src_offset = 0;
+ ss->dst_x = 0;
+ ss->dda_x = ss->dda_x_init;
+ dda_next(ss->dda_y);
+ goto top;
+}
+
+/* Release the filter's storage. */
+private void
+s_IIEncode_release(stream_state * st)
+{
+ stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
+ gs_memory_t *mem = ss->memory;
+
+ gs_free_object(mem, ss->cur, "IIEncode cur");
+ ss->cur = 0;
+ gs_free_object(mem, ss->prev, "IIEncode prev");
+ ss->prev = 0;
+}
+
+/* Stream template */
+const stream_template s_IIEncode_template = {
+ &st_IIEncode_state, s_IIEncode_init, s_IIEncode_process, 1, 1,
+ s_IIEncode_release
+};