blob: cf393909d5cbc2669d6bffd22afc8cceab7f3cb4 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27/*
28 * FUNCTION
29 * mlib_ImageAffine - image affine transformation with edge condition
30 *
31 * SYNOPSIS
32 * mlib_status mlib_ImageAffine(mlib_image *dst,
33 * const mlib_image *src,
34 * const mlib_d64 *mtx,
35 * mlib_filter filter,
36 * mlib_edge edge)
37 *
38 * ARGUMENTS
39 * dst Pointer to destination image
40 * src Pointer to source image
41 * mtx Transformation matrix, where
42 * mtx[0] holds a; mtx[1] holds b;
43 * mtx[2] holds tx; mtx[3] holds c;
44 * mtx[4] holds d; mtx[5] holds ty.
45 * filter Type of resampling filter.
46 * edge Type of edge condition.
47 *
48 * DESCRIPTION
49 * xd = a*xs + b*ys + tx
50 * yd = c*xs + d*ys + ty
51 *
52 * The upper-left corner pixel of an image is located at (0.5, 0.5).
53 *
54 * The resampling filter can be one of the following:
55 * MLIB_NEAREST
56 * MLIB_BILINEAR
57 * MLIB_BICUBIC
58 * MLIB_BICUBIC2
59 *
60 * The edge condition can be one of the following:
61 * MLIB_EDGE_DST_NO_WRITE (default)
62 * MLIB_EDGE_DST_FILL_ZERO
63 * MLIB_EDGE_OP_NEAREST
64 * MLIB_EDGE_SRC_EXTEND
65 * MLIB_EDGE_SRC_PADDED
66 *
67 * RESTRICTION
68 * src and dst must be the same type and the same number of channels.
69 * They can have 1, 2, 3 or 4 channels. They can be in MLIB_BIT, MLIB_BYTE,
70 * MLIB_SHORT, MLIB_USHORT or MLIB_INT data type.
71 *
72 * src image can not have width or height larger than 32767.
73 */
74
75#include "mlib_ImageCheck.h"
76#include "mlib_ImageColormap.h"
77#include "mlib_ImageAffine.h"
78
79
80/***************************************************************/
81#define BUFF_SIZE 600
82
83/***************************************************************/
84const type_affine_fun mlib_AffineFunArr_nn[] = {
85 mlib_ImageAffine_u8_1ch_nn, mlib_ImageAffine_u8_2ch_nn,
86 mlib_ImageAffine_u8_3ch_nn, mlib_ImageAffine_u8_4ch_nn,
87 mlib_ImageAffine_s16_1ch_nn, mlib_ImageAffine_s16_2ch_nn,
88 mlib_ImageAffine_s16_3ch_nn, mlib_ImageAffine_s16_4ch_nn,
89 mlib_ImageAffine_s32_1ch_nn, mlib_ImageAffine_s32_2ch_nn,
90 mlib_ImageAffine_s32_3ch_nn, mlib_ImageAffine_s32_4ch_nn,
91 mlib_ImageAffine_d64_1ch_nn, mlib_ImageAffine_d64_2ch_nn,
92 mlib_ImageAffine_d64_3ch_nn, mlib_ImageAffine_d64_4ch_nn,
93};
94
95/***************************************************************/
96const type_affine_fun mlib_AffineFunArr_bl[] = {
97 mlib_ImageAffine_u8_1ch_bl, mlib_ImageAffine_u8_2ch_bl,
98 mlib_ImageAffine_u8_3ch_bl, mlib_ImageAffine_u8_4ch_bl,
99 mlib_ImageAffine_s16_1ch_bl, mlib_ImageAffine_s16_2ch_bl,
100 mlib_ImageAffine_s16_3ch_bl, mlib_ImageAffine_s16_4ch_bl,
101 mlib_ImageAffine_s32_1ch_bl, mlib_ImageAffine_s32_2ch_bl,
102 mlib_ImageAffine_s32_3ch_bl, mlib_ImageAffine_s32_4ch_bl,
103 mlib_ImageAffine_u16_1ch_bl, mlib_ImageAffine_u16_2ch_bl,
104 mlib_ImageAffine_u16_3ch_bl, mlib_ImageAffine_u16_4ch_bl,
105 mlib_ImageAffine_f32_1ch_bl, mlib_ImageAffine_f32_2ch_bl,
106 mlib_ImageAffine_f32_3ch_bl, mlib_ImageAffine_f32_4ch_bl,
107 mlib_ImageAffine_d64_1ch_bl, mlib_ImageAffine_d64_2ch_bl,
108 mlib_ImageAffine_d64_3ch_bl, mlib_ImageAffine_d64_4ch_bl
109};
110
111/***************************************************************/
112const type_affine_fun mlib_AffineFunArr_bc[] = {
113 mlib_ImageAffine_u8_1ch_bc, mlib_ImageAffine_u8_2ch_bc,
114 mlib_ImageAffine_u8_3ch_bc, mlib_ImageAffine_u8_4ch_bc,
115 mlib_ImageAffine_s16_1ch_bc, mlib_ImageAffine_s16_2ch_bc,
116 mlib_ImageAffine_s16_3ch_bc, mlib_ImageAffine_s16_4ch_bc,
117 mlib_ImageAffine_s32_1ch_bc, mlib_ImageAffine_s32_2ch_bc,
118 mlib_ImageAffine_s32_3ch_bc, mlib_ImageAffine_s32_4ch_bc,
119 mlib_ImageAffine_u16_1ch_bc, mlib_ImageAffine_u16_2ch_bc,
120 mlib_ImageAffine_u16_3ch_bc, mlib_ImageAffine_u16_4ch_bc,
121 mlib_ImageAffine_f32_1ch_bc, mlib_ImageAffine_f32_2ch_bc,
122 mlib_ImageAffine_f32_3ch_bc, mlib_ImageAffine_f32_4ch_bc,
123 mlib_ImageAffine_d64_1ch_bc, mlib_ImageAffine_d64_2ch_bc,
124 mlib_ImageAffine_d64_3ch_bc, mlib_ImageAffine_d64_4ch_bc
125};
126
127/***************************************************************/
128const type_affine_i_fun mlib_AffineFunArr_bc_i[] = {
129 mlib_ImageAffineIndex_U8_U8_3CH_BC,
130 mlib_ImageAffineIndex_U8_U8_4CH_BC,
131 mlib_ImageAffineIndex_S16_U8_3CH_BC,
132 mlib_ImageAffineIndex_S16_U8_4CH_BC,
133 mlib_ImageAffineIndex_U8_S16_3CH_BC,
134 mlib_ImageAffineIndex_U8_S16_4CH_BC,
135 mlib_ImageAffineIndex_S16_S16_3CH_BC,
136 mlib_ImageAffineIndex_S16_S16_4CH_BC
137};
138
139/***************************************************************/
140#ifdef i386 /* do not perform the coping by mlib_d64 data type for x86 */
141#define MAX_T_IND 2
142#else
143#define MAX_T_IND 3
144#endif /* i386 ( do not perform the coping by mlib_d64 data type for x86 ) */
145
146/***************************************************************/
147mlib_status mlib_ImageAffine_alltypes(mlib_image *dst,
148 const mlib_image *src,
149 const mlib_d64 *mtx,
150 mlib_filter filter,
151 mlib_edge edge,
152 const void *colormap)
153{
154 mlib_affine_param param[1];
155 mlib_status res;
156 mlib_type type;
157 mlib_s32 nchan, t_ind, kw, kw1;
158 mlib_addr align;
159 mlib_d64 buff_lcl[BUFF_SIZE / 8];
160 mlib_u8 **lineAddr = NULL;
161
162 /* check for obvious errors */
163 MLIB_IMAGE_TYPE_EQUAL(src, dst);
164 MLIB_IMAGE_CHAN_EQUAL(src, dst);
165
166 type = mlib_ImageGetType(dst);
167 nchan = mlib_ImageGetChannels(dst);
168
169 switch (filter) {
170 case MLIB_NEAREST:
171 kw = 1;
172 kw1 = 0;
173 break;
174
175 case MLIB_BILINEAR:
176 kw = 2;
177 kw1 = 0;
178 break;
179
180 case MLIB_BICUBIC:
181 case MLIB_BICUBIC2:
182 kw = 4;
183 kw1 = 1;
184 break;
185
186 default:
187 return MLIB_FAILURE;
188 }
189
190 STORE_PARAM(param, lineAddr);
191 STORE_PARAM(param, filter);
192
193 res = mlib_AffineEdges(param, dst, src, buff_lcl, BUFF_SIZE,
194 kw, kw, kw1, kw1, edge, mtx, MLIB_SHIFT, MLIB_SHIFT);
195
196 if (res != MLIB_SUCCESS)
197 return res;
198
199 lineAddr = param->lineAddr;
200
201 if (type == MLIB_BYTE)
202 t_ind = 0;
203 else if (type == MLIB_SHORT)
204 t_ind = 1;
205 else if (type == MLIB_INT)
206 t_ind = 2;
207 else if (type == MLIB_USHORT)
208 t_ind = 3;
209 else if (type == MLIB_FLOAT)
210 t_ind = 4;
211 else if (type == MLIB_DOUBLE)
212 t_ind = 5;
213
214 if (colormap != NULL && filter != MLIB_NEAREST) {
215 if (t_ind != 0 && t_ind != 1)
216 return MLIB_FAILURE;
217
218 if (mlib_ImageGetLutType(colormap) == MLIB_SHORT)
219 t_ind += 2;
220 t_ind = 2 * t_ind;
221
222 if (mlib_ImageGetLutChannels(colormap) == 4)
223 t_ind++;
224 }
225
226 if (type == MLIB_BIT) {
227 mlib_s32 s_bitoff = mlib_ImageGetBitOffset(src);
228 mlib_s32 d_bitoff = mlib_ImageGetBitOffset(dst);
229
230 if (nchan != 1 || filter != MLIB_NEAREST)
231 return MLIB_FAILURE;
232 mlib_ImageAffine_bit_1ch_nn(param, s_bitoff, d_bitoff);
233 }
234 else {
235 switch (filter) {
236 case MLIB_NEAREST:
237
238 if (t_ind >= 3)
239 t_ind -= 2; /* correct types USHORT, FLOAT, DOUBLE; new values: 1, 2, 3 */
240
241 /* two channels as one channel of next type */
242 align = (mlib_addr) (param->dstData) | (mlib_addr) lineAddr[0];
243 align |= param->dstYStride | param->srcYStride;
244 while (((nchan | (align >> t_ind)) & 1) == 0 && t_ind < MAX_T_IND) {
245 nchan >>= 1;
246 t_ind++;
247 }
248
249 res = mlib_AffineFunArr_nn[4 * t_ind + (nchan - 1)] (param);
250 break;
251
252 case MLIB_BILINEAR:
253
254 if (colormap != NULL) {
255 res = mlib_AffineFunArr_bl_i[t_ind] (param, colormap);
256 }
257 else {
258 res = mlib_AffineFunArr_bl[4 * t_ind + (nchan - 1)] (param);
259 }
260
261 break;
262
263 case MLIB_BICUBIC:
264 case MLIB_BICUBIC2:
265
266 if (colormap != NULL) {
267 res = mlib_AffineFunArr_bc_i[t_ind] (param, colormap);
268 }
269 else {
270 res = mlib_AffineFunArr_bc[4 * t_ind + (nchan - 1)] (param);
271 }
272
273 break;
274 }
275
276 if (res != MLIB_SUCCESS) {
277 if (param->buff_malloc != NULL)
278 mlib_free(param->buff_malloc);
279 return res;
280 }
281 }
282
283 if (edge == MLIB_EDGE_SRC_PADDED)
284 edge = MLIB_EDGE_DST_NO_WRITE;
285
286 if (filter != MLIB_NEAREST && edge != MLIB_EDGE_DST_NO_WRITE) {
287 mlib_affine_param param_e[1];
288 mlib_d64 buff_lcl1[BUFF_SIZE / 8];
289
290 STORE_PARAM(param_e, lineAddr);
291 STORE_PARAM(param_e, filter);
292
293 res = mlib_AffineEdges(param_e, dst, src, buff_lcl1, BUFF_SIZE,
294 kw, kw, kw1, kw1, -1, mtx, MLIB_SHIFT, MLIB_SHIFT);
295
296 if (res != MLIB_SUCCESS) {
297 if (param->buff_malloc != NULL)
298 mlib_free(param->buff_malloc);
299 return res;
300 }
301
302 switch (edge) {
303 case MLIB_EDGE_DST_FILL_ZERO:
304 mlib_ImageAffineEdgeZero(param, param_e, colormap);
305 break;
306
307 case MLIB_EDGE_OP_NEAREST:
308 mlib_ImageAffineEdgeNearest(param, param_e);
309 break;
310
311 case MLIB_EDGE_SRC_EXTEND:
312
313 if (filter == MLIB_BILINEAR) {
314 res = mlib_ImageAffineEdgeExtend_BL(param, param_e, colormap);
315 }
316 else {
317 res = mlib_ImageAffineEdgeExtend_BC(param, param_e, colormap);
318 }
319
320 break;
321 }
322
323 if (param_e->buff_malloc != NULL)
324 mlib_free(param_e->buff_malloc);
325 }
326
327 if (param->buff_malloc != NULL)
328 mlib_free(param->buff_malloc);
329
330 return res;
331}
332
333/***************************************************************/
334mlib_status mlib_ImageAffine(mlib_image *dst,
335 const mlib_image *src,
336 const mlib_d64 *mtx,
337 mlib_filter filter,
338 mlib_edge edge)
339{
340 mlib_type type;
341
342 MLIB_IMAGE_CHECK(src);
343 MLIB_IMAGE_CHECK(dst);
344
345 type = mlib_ImageGetType(dst);
346
347 if (type != MLIB_BIT && type != MLIB_BYTE &&
348 type != MLIB_SHORT && type != MLIB_USHORT && type != MLIB_INT) {
349 return MLIB_FAILURE;
350 }
351
352 return mlib_ImageAffine_alltypes(dst, src, mtx, filter, edge, NULL);
353}
354
355/***************************************************************/