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_ImageColormap.h" 77 #include "mlib_ImageAffine.h" 78 79 80 /***************************************************************/ 81 #define BUFF_SIZE 600 82 83 /***************************************************************/ 84 const 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 /***************************************************************/ 96 const 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 /***************************************************************/ 112 const 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 /***************************************************************/ 128 const 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 /***************************************************************/ 147 mlib_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 else 214 return MLIB_FAILURE; /* unknown image type */ 215 216 if (colormap != NULL && filter != MLIB_NEAREST) { 217 if (t_ind != 0 && t_ind != 1) 218 return MLIB_FAILURE; 219 220 if (mlib_ImageGetLutType(colormap) == MLIB_SHORT) 221 t_ind += 2; 222 t_ind = 2 * t_ind; 223 224 if (mlib_ImageGetLutChannels(colormap) == 4) 225 t_ind++; 226 } 227 228 if (type == MLIB_BIT) { 229 mlib_s32 s_bitoff = mlib_ImageGetBitOffset(src); 230 mlib_s32 d_bitoff = mlib_ImageGetBitOffset(dst); 231 232 if (nchan != 1 || filter != MLIB_NEAREST) 233 return MLIB_FAILURE; 234 mlib_ImageAffine_bit_1ch_nn(param, s_bitoff, d_bitoff); 235 } 236 else { 237 switch (filter) { 238 case MLIB_NEAREST: 239 240 if (t_ind >= 3) 241 t_ind -= 2; /* correct types USHORT, FLOAT, DOUBLE; new values: 1, 2, 3 */ 242 243 /* two channels as one channel of next type */ 244 align = (mlib_addr) (param->dstData) | (mlib_addr) lineAddr[0]; 245 align |= param->dstYStride | param->srcYStride; 246 while (((nchan | (align >> t_ind)) & 1) == 0 && t_ind < MAX_T_IND) { 247 nchan >>= 1; 248 t_ind++; 249 } 250 251 res = mlib_AffineFunArr_nn[4 * t_ind + (nchan - 1)] (param); 252 break; 253 254 case MLIB_BILINEAR: 255 256 if (colormap != NULL) { 257 res = mlib_AffineFunArr_bl_i[t_ind] (param, colormap); 258 } 259 else { 260 res = mlib_AffineFunArr_bl[4 * t_ind + (nchan - 1)] (param); 261 } 262 263 break; 264 265 case MLIB_BICUBIC: 266 case MLIB_BICUBIC2: 267 268 if (colormap != NULL) { 269 res = mlib_AffineFunArr_bc_i[t_ind] (param, colormap); 270 } 271 else { 272 res = mlib_AffineFunArr_bc[4 * t_ind + (nchan - 1)] (param); 273 } 274 275 break; 276 } 277 278 if (res != MLIB_SUCCESS) { 279 if (param->buff_malloc != NULL) 280 mlib_free(param->buff_malloc); 281 return res; 282 } 283 } 284 285 if (edge == MLIB_EDGE_SRC_PADDED) 286 edge = MLIB_EDGE_DST_NO_WRITE; 287 288 if (filter != MLIB_NEAREST && edge != MLIB_EDGE_DST_NO_WRITE) { 289 mlib_affine_param param_e[1]; 290 mlib_d64 buff_lcl1[BUFF_SIZE / 8]; 291 292 STORE_PARAM(param_e, lineAddr); 293 STORE_PARAM(param_e, filter); 294 295 res = mlib_AffineEdges(param_e, dst, src, buff_lcl1, BUFF_SIZE, 296 kw, kw, kw1, kw1, -1, mtx, MLIB_SHIFT, MLIB_SHIFT); 297 298 if (res != MLIB_SUCCESS) { 299 if (param->buff_malloc != NULL) 300 mlib_free(param->buff_malloc); 301 return res; 302 } 303 304 switch (edge) { 305 case MLIB_EDGE_DST_FILL_ZERO: 306 mlib_ImageAffineEdgeZero(param, param_e, colormap); 307 break; 308 309 case MLIB_EDGE_OP_NEAREST: 310 mlib_ImageAffineEdgeNearest(param, param_e); 311 break; 312 313 case MLIB_EDGE_SRC_EXTEND: 314 315 if (filter == MLIB_BILINEAR) { 316 res = mlib_ImageAffineEdgeExtend_BL(param, param_e, colormap); 317 } 318 else { 319 res = mlib_ImageAffineEdgeExtend_BC(param, param_e, colormap); 320 } 321 322 break; 323 324 default: 325 /* nothing to do for other edge types. */ 326 break; 327 } 328 329 if (param_e->buff_malloc != NULL) 330 mlib_free(param_e->buff_malloc); 331 } 332 333 if (param->buff_malloc != NULL) 334 mlib_free(param->buff_malloc); 335 336 return res; 337 } 338 339 /***************************************************************/ 340 mlib_status mlib_ImageAffine(mlib_image *dst, 341 const mlib_image *src, 342 const mlib_d64 *mtx, 343 mlib_filter filter, 344 mlib_edge edge) 345 { 346 mlib_type type; 347 348 MLIB_IMAGE_CHECK(src); 349 MLIB_IMAGE_CHECK(dst); 350 351 type = mlib_ImageGetType(dst); 352 353 if (type != MLIB_BIT && type != MLIB_BYTE && 354 type != MLIB_SHORT && type != MLIB_USHORT && type != MLIB_INT) { 355 return MLIB_FAILURE; 356 } 357 358 return mlib_ImageAffine_alltypes(dst, src, mtx, filter, edge, NULL); 359 } 360 361 /***************************************************************/