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 /***************************************************************/ 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 mlib_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 /***************************************************************/