Path: blob/master/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c
41152 views
/*1* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/242526/*27* FUNCTION28* mlib_ImageAffine - image affine transformation with edge condition29*30* SYNOPSIS31* mlib_status mlib_ImageAffine(mlib_image *dst,32* const mlib_image *src,33* const mlib_d64 *mtx,34* mlib_filter filter,35* mlib_edge edge)36*37* ARGUMENTS38* dst Pointer to destination image39* src Pointer to source image40* mtx Transformation matrix, where41* mtx[0] holds a; mtx[1] holds b;42* mtx[2] holds tx; mtx[3] holds c;43* mtx[4] holds d; mtx[5] holds ty.44* filter Type of resampling filter.45* edge Type of edge condition.46*47* DESCRIPTION48* xd = a*xs + b*ys + tx49* yd = c*xs + d*ys + ty50*51* The upper-left corner pixel of an image is located at (0.5, 0.5).52*53* The resampling filter can be one of the following:54* MLIB_NEAREST55* MLIB_BILINEAR56* MLIB_BICUBIC57* MLIB_BICUBIC258*59* The edge condition can be one of the following:60* MLIB_EDGE_DST_NO_WRITE (default)61* MLIB_EDGE_DST_FILL_ZERO62* MLIB_EDGE_OP_NEAREST63* MLIB_EDGE_SRC_EXTEND64* MLIB_EDGE_SRC_PADDED65*66* RESTRICTION67* src and dst must be the same type and the same number of channels.68* They can have 1, 2, 3 or 4 channels. They can be in MLIB_BIT, MLIB_BYTE,69* MLIB_SHORT, MLIB_USHORT or MLIB_INT data type.70*71* src image can not have width or height larger than 32767.72*/7374#include "mlib_ImageCheck.h"75#include "mlib_ImageAffine.h"767778/***************************************************************/79#define BUFF_SIZE 6008081/***************************************************************/82const type_affine_fun mlib_AffineFunArr_nn[] = {83mlib_ImageAffine_u8_1ch_nn, mlib_ImageAffine_u8_2ch_nn,84mlib_ImageAffine_u8_3ch_nn, mlib_ImageAffine_u8_4ch_nn,85mlib_ImageAffine_s16_1ch_nn, mlib_ImageAffine_s16_2ch_nn,86mlib_ImageAffine_s16_3ch_nn, mlib_ImageAffine_s16_4ch_nn,87mlib_ImageAffine_s32_1ch_nn, mlib_ImageAffine_s32_2ch_nn,88mlib_ImageAffine_s32_3ch_nn, mlib_ImageAffine_s32_4ch_nn,89mlib_ImageAffine_d64_1ch_nn, mlib_ImageAffine_d64_2ch_nn,90mlib_ImageAffine_d64_3ch_nn, mlib_ImageAffine_d64_4ch_nn,91};9293/***************************************************************/94const type_affine_fun mlib_AffineFunArr_bl[] = {95mlib_ImageAffine_u8_1ch_bl, mlib_ImageAffine_u8_2ch_bl,96mlib_ImageAffine_u8_3ch_bl, mlib_ImageAffine_u8_4ch_bl,97mlib_ImageAffine_s16_1ch_bl, mlib_ImageAffine_s16_2ch_bl,98mlib_ImageAffine_s16_3ch_bl, mlib_ImageAffine_s16_4ch_bl,99mlib_ImageAffine_s32_1ch_bl, mlib_ImageAffine_s32_2ch_bl,100mlib_ImageAffine_s32_3ch_bl, mlib_ImageAffine_s32_4ch_bl,101mlib_ImageAffine_u16_1ch_bl, mlib_ImageAffine_u16_2ch_bl,102mlib_ImageAffine_u16_3ch_bl, mlib_ImageAffine_u16_4ch_bl,103mlib_ImageAffine_f32_1ch_bl, mlib_ImageAffine_f32_2ch_bl,104mlib_ImageAffine_f32_3ch_bl, mlib_ImageAffine_f32_4ch_bl,105mlib_ImageAffine_d64_1ch_bl, mlib_ImageAffine_d64_2ch_bl,106mlib_ImageAffine_d64_3ch_bl, mlib_ImageAffine_d64_4ch_bl107};108109/***************************************************************/110const type_affine_fun mlib_AffineFunArr_bc[] = {111mlib_ImageAffine_u8_1ch_bc, mlib_ImageAffine_u8_2ch_bc,112mlib_ImageAffine_u8_3ch_bc, mlib_ImageAffine_u8_4ch_bc,113mlib_ImageAffine_s16_1ch_bc, mlib_ImageAffine_s16_2ch_bc,114mlib_ImageAffine_s16_3ch_bc, mlib_ImageAffine_s16_4ch_bc,115mlib_ImageAffine_s32_1ch_bc, mlib_ImageAffine_s32_2ch_bc,116mlib_ImageAffine_s32_3ch_bc, mlib_ImageAffine_s32_4ch_bc,117mlib_ImageAffine_u16_1ch_bc, mlib_ImageAffine_u16_2ch_bc,118mlib_ImageAffine_u16_3ch_bc, mlib_ImageAffine_u16_4ch_bc,119mlib_ImageAffine_f32_1ch_bc, mlib_ImageAffine_f32_2ch_bc,120mlib_ImageAffine_f32_3ch_bc, mlib_ImageAffine_f32_4ch_bc,121mlib_ImageAffine_d64_1ch_bc, mlib_ImageAffine_d64_2ch_bc,122mlib_ImageAffine_d64_3ch_bc, mlib_ImageAffine_d64_4ch_bc123};124125/***************************************************************/126#ifdef i386 /* do not perform the coping by mlib_d64 data type for x86 */127#define MAX_T_IND 2128#else129#define MAX_T_IND 3130#endif /* i386 ( do not perform the coping by mlib_d64 data type for x86 ) */131132/***************************************************************/133mlib_status mlib_ImageAffine_alltypes(mlib_image *dst,134const mlib_image *src,135const mlib_d64 *mtx,136mlib_filter filter,137mlib_edge edge)138{139mlib_affine_param param[1];140mlib_status res;141mlib_type type;142mlib_s32 nchan, t_ind, kw, kw1;143mlib_addr align;144mlib_d64 buff_lcl[BUFF_SIZE / 8];145mlib_u8 **lineAddr = NULL;146147/* check for obvious errors */148MLIB_IMAGE_TYPE_EQUAL(src, dst);149MLIB_IMAGE_CHAN_EQUAL(src, dst);150151type = mlib_ImageGetType(dst);152nchan = mlib_ImageGetChannels(dst);153154switch (filter) {155case MLIB_NEAREST:156kw = 1;157kw1 = 0;158break;159160case MLIB_BILINEAR:161kw = 2;162kw1 = 0;163break;164165case MLIB_BICUBIC:166case MLIB_BICUBIC2:167kw = 4;168kw1 = 1;169break;170171default:172return MLIB_FAILURE;173}174175STORE_PARAM(param, lineAddr);176STORE_PARAM(param, filter);177178res = mlib_AffineEdges(param, dst, src, buff_lcl, BUFF_SIZE,179kw, kw, kw1, kw1, edge, mtx, MLIB_SHIFT, MLIB_SHIFT);180181if (res != MLIB_SUCCESS)182return res;183184lineAddr = param->lineAddr;185186if (type == MLIB_BYTE)187t_ind = 0;188else if (type == MLIB_SHORT)189t_ind = 1;190else if (type == MLIB_INT)191t_ind = 2;192else if (type == MLIB_USHORT)193t_ind = 3;194else if (type == MLIB_FLOAT)195t_ind = 4;196else if (type == MLIB_DOUBLE)197t_ind = 5;198else199return MLIB_FAILURE; /* unknown image type */200201if (type == MLIB_BIT) {202mlib_s32 s_bitoff = mlib_ImageGetBitOffset(src);203mlib_s32 d_bitoff = mlib_ImageGetBitOffset(dst);204205if (nchan != 1 || filter != MLIB_NEAREST)206return MLIB_FAILURE;207mlib_ImageAffine_bit_1ch_nn(param, s_bitoff, d_bitoff);208}209else {210switch (filter) {211case MLIB_NEAREST:212213if (t_ind >= 3)214t_ind -= 2; /* correct types USHORT, FLOAT, DOUBLE; new values: 1, 2, 3 */215216/* two channels as one channel of next type */217align = (mlib_addr) (param->dstData) | (mlib_addr) lineAddr[0];218align |= param->dstYStride | param->srcYStride;219while (((nchan | (align >> t_ind)) & 1) == 0 && t_ind < MAX_T_IND) {220nchan >>= 1;221t_ind++;222}223224res = mlib_AffineFunArr_nn[4 * t_ind + (nchan - 1)] (param);225break;226227case MLIB_BILINEAR:228229res = mlib_AffineFunArr_bl[4 * t_ind + (nchan - 1)] (param);230break;231232case MLIB_BICUBIC:233case MLIB_BICUBIC2:234235res = mlib_AffineFunArr_bc[4 * t_ind + (nchan - 1)] (param);236break;237}238239if (res != MLIB_SUCCESS) {240if (param->buff_malloc != NULL)241mlib_free(param->buff_malloc);242return res;243}244}245246if (edge == MLIB_EDGE_SRC_PADDED)247edge = MLIB_EDGE_DST_NO_WRITE;248249if (filter != MLIB_NEAREST && edge != MLIB_EDGE_DST_NO_WRITE) {250mlib_affine_param param_e[1];251mlib_d64 buff_lcl1[BUFF_SIZE / 8];252253STORE_PARAM(param_e, lineAddr);254STORE_PARAM(param_e, filter);255256res = mlib_AffineEdges(param_e, dst, src, buff_lcl1, BUFF_SIZE,257kw, kw, kw1, kw1, -1, mtx, MLIB_SHIFT, MLIB_SHIFT);258259if (res != MLIB_SUCCESS) {260if (param->buff_malloc != NULL)261mlib_free(param->buff_malloc);262return res;263}264265switch (edge) {266case MLIB_EDGE_DST_FILL_ZERO:267mlib_ImageAffineEdgeZero(param, param_e);268break;269270case MLIB_EDGE_OP_NEAREST:271mlib_ImageAffineEdgeNearest(param, param_e);272break;273274case MLIB_EDGE_SRC_EXTEND:275276if (filter == MLIB_BILINEAR) {277res = mlib_ImageAffineEdgeExtend_BL(param, param_e);278}279else {280res = mlib_ImageAffineEdgeExtend_BC(param, param_e);281}282283break;284285default:286/* nothing to do for other edge types. */287break;288}289290if (param_e->buff_malloc != NULL)291mlib_free(param_e->buff_malloc);292}293294if (param->buff_malloc != NULL)295mlib_free(param->buff_malloc);296297return res;298}299300/***************************************************************/301JNIEXPORT302mlib_status mlib_ImageAffine(mlib_image *dst,303const mlib_image *src,304const mlib_d64 *mtx,305mlib_filter filter,306mlib_edge edge)307{308mlib_type type;309310MLIB_IMAGE_CHECK(src);311MLIB_IMAGE_CHECK(dst);312313type = mlib_ImageGetType(dst);314315if (type != MLIB_BIT && type != MLIB_BYTE &&316type != MLIB_SHORT && type != MLIB_USHORT && type != MLIB_INT) {317return MLIB_FAILURE;318}319320return mlib_ImageAffine_alltypes(dst, src, mtx, filter, edge);321}322323/***************************************************************/324325326