1/*
2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * 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_ImageAffine.h"
77
78
79/***************************************************************/
80#define BUFF_SIZE 600
81
82/***************************************************************/
83const type_affine_fun mlib_AffineFunArr_nn[] = {
84 mlib_ImageAffine_u8_1ch_nn, mlib_ImageAffine_u8_2ch_nn,
85 mlib_ImageAffine_u8_3ch_nn, mlib_ImageAffine_u8_4ch_nn,
86 mlib_ImageAffine_s16_1ch_nn, mlib_ImageAffine_s16_2ch_nn,
87 mlib_ImageAffine_s16_3ch_nn, mlib_ImageAffine_s16_4ch_nn,
88 mlib_ImageAffine_s32_1ch_nn, mlib_ImageAffine_s32_2ch_nn,
89 mlib_ImageAffine_s32_3ch_nn, mlib_ImageAffine_s32_4ch_nn,
90 mlib_ImageAffine_d64_1ch_nn, mlib_ImageAffine_d64_2ch_nn,
91 mlib_ImageAffine_d64_3ch_nn, mlib_ImageAffine_d64_4ch_nn,
92};
93
94/***************************************************************/
95const type_affine_fun mlib_AffineFunArr_bl[] = {
96 mlib_ImageAffine_u8_1ch_bl, mlib_ImageAffine_u8_2ch_bl,
97 mlib_ImageAffine_u8_3ch_bl, mlib_ImageAffine_u8_4ch_bl,
98 mlib_ImageAffine_s16_1ch_bl, mlib_ImageAffine_s16_2ch_bl,
99 mlib_ImageAffine_s16_3ch_bl, mlib_ImageAffine_s16_4ch_bl,
100 mlib_ImageAffine_s32_1ch_bl, mlib_ImageAffine_s32_2ch_bl,
101 mlib_ImageAffine_s32_3ch_bl, mlib_ImageAffine_s32_4ch_bl,
102 mlib_ImageAffine_u16_1ch_bl, mlib_ImageAffine_u16_2ch_bl,
103 mlib_ImageAffine_u16_3ch_bl, mlib_ImageAffine_u16_4ch_bl,
104 mlib_ImageAffine_f32_1ch_bl, mlib_ImageAffine_f32_2ch_bl,
105 mlib_ImageAffine_f32_3ch_bl, mlib_ImageAffine_f32_4ch_bl,
106 mlib_ImageAffine_d64_1ch_bl, mlib_ImageAffine_d64_2ch_bl,
107 mlib_ImageAffine_d64_3ch_bl, mlib_ImageAffine_d64_4ch_bl
108};
109
110/***************************************************************/
111const type_affine_fun mlib_AffineFunArr_bc[] = {
112 mlib_ImageAffine_u8_1ch_bc, mlib_ImageAffine_u8_2ch_bc,
113 mlib_ImageAffine_u8_3ch_bc, mlib_ImageAffine_u8_4ch_bc,
114 mlib_ImageAffine_s16_1ch_bc, mlib_ImageAffine_s16_2ch_bc,
115 mlib_ImageAffine_s16_3ch_bc, mlib_ImageAffine_s16_4ch_bc,
116 mlib_ImageAffine_s32_1ch_bc, mlib_ImageAffine_s32_2ch_bc,
117 mlib_ImageAffine_s32_3ch_bc, mlib_ImageAffine_s32_4ch_bc,
118 mlib_ImageAffine_u16_1ch_bc, mlib_ImageAffine_u16_2ch_bc,
119 mlib_ImageAffine_u16_3ch_bc, mlib_ImageAffine_u16_4ch_bc,
120 mlib_ImageAffine_f32_1ch_bc, mlib_ImageAffine_f32_2ch_bc,
121 mlib_ImageAffine_f32_3ch_bc, mlib_ImageAffine_f32_4ch_bc,
122 mlib_ImageAffine_d64_1ch_bc, mlib_ImageAffine_d64_2ch_bc,
123 mlib_ImageAffine_d64_3ch_bc, mlib_ImageAffine_d64_4ch_bc
124};
125
126/***************************************************************/
127#ifdef i386 /* do not perform the coping by mlib_d64 data type for x86 */
128#define MAX_T_IND 2
129#else
130#define MAX_T_IND 3
131#endif /* i386 ( do not perform the coping by mlib_d64 data type for x86 ) */
132
133/***************************************************************/
134mlib_status mlib_ImageAffine_alltypes(mlib_image *dst,
135 const mlib_image *src,
136 const mlib_d64 *mtx,
137 mlib_filter filter,
138 mlib_edge edge)
139{
140 mlib_affine_param param[1];
141 mlib_status res;
142 mlib_type type;
143 mlib_s32 nchan, t_ind, kw, kw1;
144 mlib_addr align;
145 mlib_d64 buff_lcl[BUFF_SIZE / 8];
146 mlib_u8 **lineAddr = NULL;
147
148 /* check for obvious errors */
149 MLIB_IMAGE_TYPE_EQUAL(src, dst);
150 MLIB_IMAGE_CHAN_EQUAL(src, dst);
151
152 type = mlib_ImageGetType(dst);
153 nchan = mlib_ImageGetChannels(dst);
154
155 switch (filter) {
156 case MLIB_NEAREST:
157 kw = 1;
158 kw1 = 0;
159 break;
160
161 case MLIB_BILINEAR:
162 kw = 2;
163 kw1 = 0;
164 break;
165
166 case MLIB_BICUBIC:
167 case MLIB_BICUBIC2:
168 kw = 4;
169 kw1 = 1;
170 break;
171
172 default:
173 return MLIB_FAILURE;
174 }
175
176 STORE_PARAM(param, lineAddr);
177 STORE_PARAM(param, filter);
178
179 res = mlib_AffineEdges(param, dst, src, buff_lcl, BUFF_SIZE,
180 kw, kw, kw1, kw1, edge, mtx, MLIB_SHIFT, MLIB_SHIFT);
181
182 if (res != MLIB_SUCCESS)
183 return res;
184
185 lineAddr = param->lineAddr;
186
187 if (type == MLIB_BYTE)
188 t_ind = 0;
189 else if (type == MLIB_SHORT)
190 t_ind = 1;
191 else if (type == MLIB_INT)
192 t_ind = 2;
193 else if (type == MLIB_USHORT)
194 t_ind = 3;
195 else if (type == MLIB_FLOAT)
196 t_ind = 4;
197 else if (type == MLIB_DOUBLE)
198 t_ind = 5;
199 else
200 return MLIB_FAILURE; /* unknown image type */
201
202 if (type == MLIB_BIT) {
203 mlib_s32 s_bitoff = mlib_ImageGetBitOffset(src);
204 mlib_s32 d_bitoff = mlib_ImageGetBitOffset(dst);
205
206 if (nchan != 1 || filter != MLIB_NEAREST)
207 return MLIB_FAILURE;
208 mlib_ImageAffine_bit_1ch_nn(param, s_bitoff, d_bitoff);
209 }
210 else {
211 switch (filter) {
212 case MLIB_NEAREST:
213
214 if (t_ind >= 3)
215 t_ind -= 2; /* correct types USHORT, FLOAT, DOUBLE; new values: 1, 2, 3 */
216
217 /* two channels as one channel of next type */
218 align = (mlib_addr) (param->dstData) | (mlib_addr) lineAddr[0];
219 align |= param->dstYStride | param->srcYStride;
220 while (((nchan | (align >> t_ind)) & 1) == 0 && t_ind < MAX_T_IND) {
221 nchan >>= 1;
222 t_ind++;
223 }
224
225 res = mlib_AffineFunArr_nn[4 * t_ind + (nchan - 1)] (param);
226 break;
227
228 case MLIB_BILINEAR:
229
230 res = mlib_AffineFunArr_bl[4 * t_ind + (nchan - 1)] (param);
231 break;
232
233 case MLIB_BICUBIC:
234 case MLIB_BICUBIC2:
235
236 res = mlib_AffineFunArr_bc[4 * t_ind + (nchan - 1)] (param);
237 break;
238 }
239
240 if (res != MLIB_SUCCESS) {
241 if (param->buff_malloc != NULL)
242 mlib_free(param->buff_malloc);
243 return res;
244 }
245 }
246
247 if (edge == MLIB_EDGE_SRC_PADDED)
248 edge = MLIB_EDGE_DST_NO_WRITE;
249
250 if (filter != MLIB_NEAREST && edge != MLIB_EDGE_DST_NO_WRITE) {
251 mlib_affine_param param_e[1];
252 mlib_d64 buff_lcl1[BUFF_SIZE / 8];
253
254 STORE_PARAM(param_e, lineAddr);
255 STORE_PARAM(param_e, filter);
256
257 res = mlib_AffineEdges(param_e, dst, src, buff_lcl1, BUFF_SIZE,
258 kw, kw, kw1, kw1, -1, mtx, MLIB_SHIFT, MLIB_SHIFT);
259
260 if (res != MLIB_SUCCESS) {
261 if (param->buff_malloc != NULL)
262 mlib_free(param->buff_malloc);
263 return res;
264 }
265
266 switch (edge) {
267 case MLIB_EDGE_DST_FILL_ZERO:
268 mlib_ImageAffineEdgeZero(param, param_e);
269 break;
270
271 case MLIB_EDGE_OP_NEAREST:
272 mlib_ImageAffineEdgeNearest(param, param_e);
273 break;
274
275 case MLIB_EDGE_SRC_EXTEND:
276
277 if (filter == MLIB_BILINEAR) {
278 res = mlib_ImageAffineEdgeExtend_BL(param, param_e);
279 }
280 else {
281 res = mlib_ImageAffineEdgeExtend_BC(param, param_e);
282 }
283
284 break;
285
286 default:
287 /* nothing to do for other edge types. */
288 break;
289 }
290
291 if (param_e->buff_malloc != NULL)
292 mlib_free(param_e->buff_malloc);
293 }
294
295 if (param->buff_malloc != NULL)
296 mlib_free(param->buff_malloc);
297
298 return res;
299}
300
301/***************************************************************/
302JNIEXPORT
303mlib_status mlib_ImageAffine(mlib_image *dst,
304 const mlib_image *src,
305 const mlib_d64 *mtx,
306 mlib_filter filter,
307 mlib_edge edge)
308{
309 mlib_type type;
310
311 MLIB_IMAGE_CHECK(src);
312 MLIB_IMAGE_CHECK(dst);
313
314 type = mlib_ImageGetType(dst);
315
316 if (type != MLIB_BIT && type != MLIB_BYTE &&
317 type != MLIB_SHORT && type != MLIB_USHORT && type != MLIB_INT) {
318 return MLIB_FAILURE;
319 }
320
321 return mlib_ImageAffine_alltypes(dst, src, mtx, filter, edge);
322}
323
324/***************************************************************/
325