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 | /***************************************************************/ |
83 | const 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 | /***************************************************************/ |
95 | const 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 | /***************************************************************/ |
111 | const 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 | /***************************************************************/ |
134 | mlib_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 | /***************************************************************/ |
302 | JNIEXPORT |
303 | mlib_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 | |