1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: siinterp.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* Image interpolation filter */
17
#include "gxfixed.h" /* for gxdda.h */
23
/* ImageInterpolateEncode state */
30
SCALE_8_16_BYTE2FRAC_ALIGNED,
31
SCALE_8_16_BYTE2FRAC_3,
32
SCALE_8_16_BYTE2FRAC_3_ALIGNED,
34
SCALE_8_16_GENERAL_ALIGNED,
40
typedef struct stream_IIEncode_state_s {
41
/* The client sets the params values before initialization. */
42
stream_image_scale_state_common; /* = state_common + params */
43
/* The init procedure sets the following. */
44
int sizeofPixelIn; /* bytes per input pixel, 1 or 2 * Colors */
45
int sizeofPixelOut; /* bytes per output pixel, 1 or 2 * Colors */
46
uint src_size; /* bytes per row of input */
47
uint dst_size; /* bytes per row of output */
48
void /*PixelOut */ *prev; /* previous row of input data in output fmt, */
49
/* [WidthIn * sizeofPixelOut] */
50
void /*PixelOut */ *cur; /* current row of input data in output fmt, */
51
/* [WidthIn * sizeofPixelOut] */
52
scale_case_t scale_case;
53
/* The following are updated dynamically. */
55
gx_dda_int_t dda_x; /* DDA for dest X in current scan line */
56
gx_dda_int_t dda_x_init; /* initial setting of dda_x */
58
gx_dda_int_t dda_y; /* DDA for dest Y */
59
int src_offset, dst_offset;
60
} stream_IIEncode_state;
62
gs_private_st_ptrs2(st_IIEncode_state, stream_IIEncode_state,
63
"ImageInterpolateEncode state",
64
iiencode_state_enum_ptrs, iiencode_state_reloc_ptrs,
67
/* Forward references */
68
static void s_IIEncode_release(stream_state * st);
70
/* Initialize the filter. */
72
s_IIEncode_init(stream_state * st)
74
stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
75
gs_memory_t *mem = ss->memory;
78
ss->params.BitsPerComponentIn / 8 * ss->params.Colors;
80
ss->params.BitsPerComponentOut / 8 * ss->params.Colors;
81
ss->src_size = ss->sizeofPixelIn * ss->params.WidthIn;
82
ss->dst_size = ss->sizeofPixelOut * ss->params.WidthOut;
84
/* Initialize destination DDAs. */
86
ss->src_offset = ss->dst_offset = 0;
87
dda_init(ss->dda_x, 0, ss->params.WidthIn, ss->params.WidthOut);
88
ss->dda_x_init = ss->dda_x;
89
ss->src_y = ss->dst_y = 0;
90
dda_init(ss->dda_y, 0, ss->params.HeightOut, ss->params.HeightIn);
92
/* Allocate buffers for 2 rows of input data. */
93
ss->prev = gs_alloc_byte_array(mem, ss->params.WidthIn,
94
ss->sizeofPixelOut, "IIEncode prev");
95
ss->cur = gs_alloc_byte_array(mem, ss->params.WidthIn,
96
ss->sizeofPixelOut, "IIEncode cur");
97
if (ss->prev == 0 || ss->cur == 0) {
98
s_IIEncode_release(st);
99
return ERRC; /****** WRONG ******/
102
/* Determine the case for the inner loop. */
104
(ss->params.BitsPerComponentIn == 8 ?
105
(ss->params.BitsPerComponentOut == 8 ?
106
(ss->params.MaxValueIn == ss->params.MaxValueOut ?
107
SCALE_SAME : SCALE_8_8) :
108
(ss->params.MaxValueIn == 255 && ss->params.MaxValueOut == frac_1 ?
109
(ss->params.Colors == 3 ? SCALE_8_16_BYTE2FRAC_3 :
110
SCALE_8_16_BYTE2FRAC) :
111
SCALE_8_16_GENERAL)) :
112
(ss->params.BitsPerComponentOut == 8 ? SCALE_16_8 :
113
ss->params.MaxValueIn == ss->params.MaxValueOut ?
114
SCALE_SAME : SCALE_16_16));
119
/* Process a buffer. */
121
s_IIEncode_process(stream_state * st, stream_cursor_read * pr,
122
stream_cursor_write * pw, bool last)
124
stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
125
const scale_case_t scale_case = ss->scale_case +
126
ALIGNMENT_MOD(pw->ptr, 2); /* ptr odd => buffer is aligned */
127
byte *out = pw->ptr + 1;
128
/****** WRONG, requires an entire output pixel ******/
129
byte *limit = pw->limit + 1 - ss->sizeofPixelOut;
131
/* Check whether we need to deliver any output. */
134
if (dda_current(ss->dda_y) > ss->dst_y) {
135
/* Deliver some or all of the current scaled row. */
136
while (ss->dst_x < ss->params.WidthOut) {
137
uint sx = dda_current(ss->dda_x) * ss->sizeofPixelIn;
138
const byte *in = (const byte *)ss->cur + sx;
145
switch (scale_case) {
147
case SCALE_SAME_ALIGNED:
148
memcpy(out, in, ss->sizeofPixelIn);
149
out += ss->sizeofPixelIn;
152
case SCALE_8_8_ALIGNED:
153
for (c = ss->params.Colors; --c >= 0; ++in, ++out)
154
*out = (byte)(*in * ss->params.MaxValueOut /
155
ss->params.MaxValueIn);
157
case SCALE_8_16_BYTE2FRAC:
158
case SCALE_8_16_BYTE2FRAC_ALIGNED: /* could be optimized */
159
case SCALE_8_16_BYTE2FRAC_3: /* could be optimized */
160
for (c = ss->params.Colors; --c >= 0; ++in, out += 2) {
162
uint value = byte2frac(b);
164
out[0] = (byte)(value >> 8), out[1] = (byte)value;
167
case SCALE_8_16_BYTE2FRAC_3_ALIGNED:
171
((bits16 *)out)[0] = byte2frac(b);
173
((bits16 *)out)[1] = byte2frac(b);
175
((bits16 *)out)[2] = byte2frac(b);
179
case SCALE_8_16_GENERAL:
180
case SCALE_8_16_GENERAL_ALIGNED: /* could be optimized */
181
for (c = ss->params.Colors; --c >= 0; ++in, out += 2) {
182
uint value = *in * ss->params.MaxValueOut /
183
ss->params.MaxValueIn;
185
out[0] = (byte)(value >> 8), out[1] = (byte)value;
189
case SCALE_16_8_ALIGNED:
190
for (c = ss->params.Colors; --c >= 0; in += 2, ++out)
191
*out = (byte)(*(const bits16 *)in *
192
ss->params.MaxValueOut /
193
ss->params.MaxValueIn);
196
case SCALE_16_16_ALIGNED: /* could be optimized */
197
for (c = ss->params.Colors; --c >= 0; in += 2, out += 2) {
198
uint value = *(const bits16 *)in *
199
ss->params.MaxValueOut / ss->params.MaxValueIn;
201
out[0] = (byte)(value >> 8), out[1] = (byte)value;
209
ss->dda_x = ss->dda_x_init;
213
if (ss->dst_y >= ss->params.HeightOut)
216
if (ss->src_offset < ss->src_size) {
217
uint count = min(ss->src_size - ss->src_offset, pr->limit - pr->ptr);
221
memcpy((byte *)ss->cur + ss->src_offset, pr->ptr + 1, count);
222
ss->src_offset += count;
224
if (ss->src_offset < ss->src_size)
229
ss->dda_x = ss->dda_x_init;
234
/* Release the filter's storage. */
236
s_IIEncode_release(stream_state * st)
238
stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
239
gs_memory_t *mem = ss->memory;
241
gs_free_object(mem, ss->cur, "IIEncode cur");
243
gs_free_object(mem, ss->prev, "IIEncode prev");
247
/* Stream template */
248
const stream_template s_IIEncode_template = {
249
&st_IIEncode_state, s_IIEncode_init, s_IIEncode_process, 1, 1,