1/*
2 * Copyright (c) 2003, 2011, 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/***************************************************************/
302mlib_status mlib_ImageAffine(mlib_image       *dst,
303                             const mlib_image *src,
304                             const mlib_d64   *mtx,
305                             mlib_filter      filter,
306                             mlib_edge        edge)
307{
308  mlib_type type;
309
310  MLIB_IMAGE_CHECK(src);
311  MLIB_IMAGE_CHECK(dst);
312
313  type = mlib_ImageGetType(dst);
314
315  if (type != MLIB_BIT && type != MLIB_BYTE &&
316      type != MLIB_SHORT && type != MLIB_USHORT && type != MLIB_INT) {
317    return MLIB_FAILURE;
318  }
319
320  return mlib_ImageAffine_alltypes(dst, src, mtx, filter, edge);
321}
322
323/***************************************************************/
324