Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: siinterp.c,v 1.7 2004/12/08 21:35:13 stefan Exp $ */
18
/* Image interpolation filter */
19
#include "memory_.h"
20
#include <assert.h>
21
#include "gxfixed.h"		/* for gxdda.h */
22
#include "gxdda.h"
23
#include "gxfrac.h"
24
#include "strimpl.h"
25
#include "siinterp.h"
26
 
27
/* ImageInterpolateEncode state */
28
typedef struct gx_dda_int_s {
29
    dda_state_struct(ia_, int, uint) state;
30
    dda_step_struct(ie_, int, uint) step;
31
} gx_dda_int_t;
32
typedef enum {
33
    SCALE_SAME = 0,
34
    SCALE_SAME_ALIGNED,
35
    SCALE_8_8,
36
    SCALE_8_8_ALIGNED,
37
    SCALE_8_16_BYTE2FRAC,
38
    SCALE_8_16_BYTE2FRAC_ALIGNED,
39
    SCALE_8_16_BYTE2FRAC_3,
40
    SCALE_8_16_BYTE2FRAC_3_ALIGNED,
41
    SCALE_8_16_GENERAL,
42
    SCALE_8_16_GENERAL_ALIGNED,
43
    SCALE_16_8,
44
    SCALE_16_8_ALIGNED,
45
    SCALE_16_16,
46
    SCALE_16_16_ALIGNED
47
} scale_case_t;
48
typedef struct stream_IIEncode_state_s {
49
    /* The client sets the params values before initialization. */
50
    stream_image_scale_state_common;  /* = state_common + params */
51
    /* The init procedure sets the following. */
52
    int sizeofPixelIn;		/* bytes per input pixel, 1 or 2 * Colors */
53
    int sizeofPixelOut;		/* bytes per output pixel, 1 or 2 * Colors */
54
    uint src_size;		/* bytes per row of input */
55
    uint dst_size;		/* bytes per row of output */
56
    void /*PixelOut */ *prev;	/* previous row of input data in output fmt, */
57
				/* [WidthIn * sizeofPixelOut] */
58
    void /*PixelOut */ *cur;	/* current row of input data in output fmt, */
59
				/* [WidthIn * sizeofPixelOut] */
60
    scale_case_t scale_case;
61
    /* The following are updated dynamically. */
62
    int dst_x;
63
    gx_dda_int_t dda_x;		/* DDA for dest X in current scan line */
64
    gx_dda_int_t dda_x_init;	/* initial setting of dda_x */
65
    int src_y, dst_y;
66
    gx_dda_int_t dda_y;		/* DDA for dest Y */
67
    int src_offset, dst_offset;
68
} stream_IIEncode_state;
69
 
70
gs_private_st_ptrs2(st_IIEncode_state, stream_IIEncode_state,
71
    "ImageInterpolateEncode state",
72
    iiencode_state_enum_ptrs, iiencode_state_reloc_ptrs,
73
    prev, cur);
74
 
75
/* Forward references */
76
private void s_IIEncode_release(stream_state * st);
77
 
78
/* Initialize the filter. */
79
private int
80
s_IIEncode_init(stream_state * st)
81
{
82
    stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
83
    gs_memory_t *mem = ss->memory;
84
 
85
    ss->sizeofPixelIn =
86
	ss->params.BitsPerComponentIn / 8 * ss->params.Colors;
87
    ss->sizeofPixelOut =
88
	ss->params.BitsPerComponentOut / 8 * ss->params.Colors;
89
    ss->src_size = ss->sizeofPixelIn * ss->params.WidthIn;
90
    ss->dst_size = ss->sizeofPixelOut * ss->params.WidthOut;
91
 
92
    /* Initialize destination DDAs. */
93
    ss->dst_x = 0;
94
    ss->src_offset = ss->dst_offset = 0;
95
    dda_init(ss->dda_x, 0, ss->params.WidthIn, ss->params.WidthOut);
96
    ss->dda_x_init = ss->dda_x;
97
    ss->src_y = ss->dst_y = 0;
98
    dda_init(ss->dda_y, 0, ss->params.HeightOut, ss->params.HeightIn);
99
 
100
    /* Allocate buffers for 2 rows of input data. */
101
    ss->prev = gs_alloc_byte_array(mem, ss->params.WidthIn,
102
				   ss->sizeofPixelOut, "IIEncode prev");
103
    ss->cur = gs_alloc_byte_array(mem, ss->params.WidthIn,
104
				  ss->sizeofPixelOut, "IIEncode cur");
105
    if (ss->prev == 0 || ss->cur == 0) {
106
	s_IIEncode_release(st);
107
	return ERRC;	/****** WRONG ******/
108
    }
109
 
110
    /* Determine the case for the inner loop. */
111
    ss->scale_case =
112
	(ss->params.BitsPerComponentIn == 8 ?
113
	 (ss->params.BitsPerComponentOut == 8 ?
114
	  (ss->params.MaxValueIn == ss->params.MaxValueOut ?
115
	   SCALE_SAME : SCALE_8_8) :
116
	  (ss->params.MaxValueIn == 255 && ss->params.MaxValueOut == frac_1 ?
117
	   (ss->params.Colors == 3 ? SCALE_8_16_BYTE2FRAC_3 :
118
	    SCALE_8_16_BYTE2FRAC) :
119
	   SCALE_8_16_GENERAL)) :
120
	 (ss->params.BitsPerComponentOut == 8 ? SCALE_16_8 :
121
	  ss->params.MaxValueIn == ss->params.MaxValueOut ?
122
	  SCALE_SAME : SCALE_16_16));
123
 
124
    return 0;
125
}
126
 
127
/* Process a buffer. */
128
private int
129
s_IIEncode_process(stream_state * st, stream_cursor_read * pr,
130
		   stream_cursor_write * pw, bool last)
131
{
132
    stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
133
    const scale_case_t scale_case = ss->scale_case +
134
	ALIGNMENT_MOD(pw->ptr, 2); /* ptr odd => buffer is aligned */
135
    byte *out = pw->ptr + 1;
136
    /****** WRONG, requires an entire output pixel ******/
137
    byte *limit = pw->limit + 1 - ss->sizeofPixelOut;
138
 
139
    /* Check whether we need to deliver any output. */
140
 
141
top:
142
    if (dda_current(ss->dda_y) > ss->dst_y) {
143
	/* Deliver some or all of the current scaled row. */
144
	while (ss->dst_x < ss->params.WidthOut) {
145
	    uint sx = dda_current(ss->dda_x) * ss->sizeofPixelIn;
146
	    const byte *in = (const byte *)ss->cur + sx;
147
	    int c;
148
 
149
	    if (out > limit) {
150
		pw->ptr = out - 1;
151
		return 1;
152
	    }
153
	    switch (scale_case) {
154
	    case SCALE_SAME:
155
	    case SCALE_SAME_ALIGNED:
156
		memcpy(out, in, ss->sizeofPixelIn);
157
		out += ss->sizeofPixelIn;
158
		break;
159
	    case SCALE_8_8:
160
	    case SCALE_8_8_ALIGNED:
161
		for (c = ss->params.Colors; --c >= 0; ++in, ++out)
162
		    *out = (byte)(*in * ss->params.MaxValueOut /
163
				  ss->params.MaxValueIn);
164
		break;
165
	    case SCALE_8_16_BYTE2FRAC:
166
	    case SCALE_8_16_BYTE2FRAC_ALIGNED: /* could be optimized */
167
	    case SCALE_8_16_BYTE2FRAC_3: /* could be optimized */
168
		for (c = ss->params.Colors; --c >= 0; ++in, out += 2) {
169
		    uint b = *in;
170
		    uint value = byte2frac(b);
171
 
172
		    out[0] = (byte)(value >> 8), out[1] = (byte)value;
173
		}
174
		break;
175
	    case SCALE_8_16_BYTE2FRAC_3_ALIGNED:
176
		{
177
		    uint b = in[0];
178
 
179
		    ((bits16 *)out)[0] = byte2frac(b);
180
		    b = in[1];
181
		    ((bits16 *)out)[1] = byte2frac(b);
182
		    b = in[2];
183
		    ((bits16 *)out)[2] = byte2frac(b);
184
		}
185
		out += 6;
186
		break;
187
	    case SCALE_8_16_GENERAL:
188
	    case SCALE_8_16_GENERAL_ALIGNED: /* could be optimized */
189
		for (c = ss->params.Colors; --c >= 0; ++in, out += 2) {
190
		    uint value = *in * ss->params.MaxValueOut /
191
			ss->params.MaxValueIn;
192
 
193
		    out[0] = (byte)(value >> 8), out[1] = (byte)value;
194
		}
195
		break;
196
	    case SCALE_16_8:
197
	    case SCALE_16_8_ALIGNED:
198
		for (c = ss->params.Colors; --c >= 0; in += 2, ++out)
199
		    *out = (byte)(*(const bits16 *)in *
200
				  ss->params.MaxValueOut /
201
				  ss->params.MaxValueIn);
202
		break;
203
	    case SCALE_16_16:
204
	    case SCALE_16_16_ALIGNED: /* could be optimized */
205
		for (c = ss->params.Colors; --c >= 0; in += 2, out += 2) {
206
		    uint value = *(const bits16 *)in *
207
			ss->params.MaxValueOut / ss->params.MaxValueIn;
208
 
209
		    out[0] = (byte)(value >> 8), out[1] = (byte)value;
210
		}
211
	    }
212
	    dda_next(ss->dda_x);
213
	    ss->dst_x++;
214
	}
215
	ss->dst_x = 0;
216
	ss->dst_y++;
217
	ss->dda_x = ss->dda_x_init;
218
	goto top;
219
    }
220
    pw->ptr = out - 1;
221
    if (ss->dst_y >= ss->params.HeightOut)
222
	return EOFC;
223
 
224
    if (ss->src_offset < ss->src_size) {
225
	uint count = min(ss->src_size - ss->src_offset, pr->limit - pr->ptr);
226
 
227
	if (count == 0)
228
	    return 0;
229
	memcpy((byte *)ss->cur + ss->src_offset, pr->ptr + 1, count);
230
	ss->src_offset += count;
231
	pr->ptr += count;
232
	if (ss->src_offset < ss->src_size)
233
	    return 0;
234
    }
235
    ss->src_offset = 0;
236
    ss->dst_x = 0;
237
    ss->dda_x = ss->dda_x_init;
238
    dda_next(ss->dda_y);
239
    goto top;
240
}
241
 
242
/* Release the filter's storage. */
243
private void
244
s_IIEncode_release(stream_state * st)
245
{
246
    stream_IIEncode_state *const ss = (stream_IIEncode_state *) st;
247
    gs_memory_t *mem = ss->memory;
248
 
249
    gs_free_object(mem, ss->cur, "IIEncode cur");
250
    ss->cur = 0;
251
    gs_free_object(mem, ss->prev, "IIEncode prev");
252
    ss->prev = 0;
253
}
254
 
255
/* Stream template */
256
const stream_template s_IIEncode_template = {
257
    &st_IIEncode_state, s_IIEncode_init, s_IIEncode_process, 1, 1,
258
    s_IIEncode_release
259
};