blob: 9680aa0d976a317fc7bebaa97494c1d956214000 [file] [log] [blame]
/*
* Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* FUNCTION
* mlib_ImageAffine_u8_1ch_nn
* mlib_ImageAffine_u8_2ch_nn
* mlib_ImageAffine_u8_3ch_nn
* mlib_ImageAffine_u8_4ch_nn
* mlib_ImageAffine_s16_1ch_nn
* mlib_ImageAffine_s16_2ch_nn
* mlib_ImageAffine_s16_3ch_nn
* mlib_ImageAffine_s16_4ch_nn
* - image affine transformation with Nearest Neighbor filtering
*
*/
#include "vis_proto.h"
#include "mlib_image.h"
#include "mlib_ImageCopy.h"
#include "mlib_ImageAffine.h"
#define BUFF_SIZE 256
/***************************************************************/
#define sp srcPixelPtr
#define dp dstPixelPtr
/***************************************************************/
#undef DTYPE
#define DTYPE mlib_u8
#define LD_U8(sp, x) vis_read_lo(vis_ld_u8_i(sp, ((x) >> MLIB_SHIFT)))
/***************************************************************/
mlib_status mlib_ImageAffine_u8_1ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
mlib_s32 i, size;
#ifndef _NO_LONGLONG
mlib_s64 Y0, Y1, dYl;
#endif /* _NO_LONGLONG */
for (j = yStart; j <= yFinish; j++) {
mlib_d64 s0, s1;
CLIP(1);
size = xRight - xLeft + 1;
while (((mlib_s32)dp & 3) && (size > 0)) {
*dp = *(S_PTR(Y) + (X >> MLIB_SHIFT));
dp++;
X += dX;
Y += dY;
size--;
}
#ifdef _NO_LONGLONG
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
mlib_u8 *sp0, *sp1, *sp2, *sp3;
sp0 = S_PTR(Y);
sp1 = S_PTR(Y + dY);
sp2 = S_PTR(Y + 2*dY);
sp3 = S_PTR(Y + 3*dY);
s0 = vis_fpmerge(LD_U8(sp0, X), LD_U8(sp2, X + 2*dX));
s1 = vis_fpmerge(LD_U8(sp1, X + dX), LD_U8(sp3, X + 3*dX));
s0 = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s1));
*(mlib_f32*)dp = vis_read_lo(s0);
dp += 4;
X += 4*dX;
Y += 4*dY;
}
#else
Y0 = ((mlib_s64)(Y + dY) << 32) | Y;
if (dY >= 0) {
dYl = ((mlib_s64)dY << 33) | (dY << 1);
} else {
dYl = -(((mlib_s64)(-dY) << 33) | ((-dY) << 1));
}
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
mlib_u8 *sp0, *sp1, *sp2, *sp3;
Y1 = Y0 + dYl;
sp0 = S_PTRl(Y0, 16);
sp1 = S_PTRl(Y0, 48);
sp2 = S_PTRl(Y1, 16);
sp3 = S_PTRl(Y1, 48);
s0 = vis_fpmerge(LD_U8(sp0, X), LD_U8(sp2, X + 2*dX));
s1 = vis_fpmerge(LD_U8(sp1, X + dX), LD_U8(sp3, X + 3*dX));
s0 = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s1));
*(mlib_f32*)dp = vis_read_lo(s0);
dp += 4;
X += 4*dX;
Y0 += 2*dYl;
}
Y = Y0 & ((1u << 31) - 1);
#endif /* _NO_LONGLONG */
for (i = 0; i < (size & 3); i++) {
dp[i] = *(S_PTR(Y) + (X >> MLIB_SHIFT));
X += dX;
Y += dY;
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
#undef LD_U8
#define LD_U8(sp, x) vis_read_lo(vis_ld_u8_i(sp, x))
/***************************************************************/
#define GET_POINTERS_2CH \
sp0 = S_PTR(Y) + 2*(X >> MLIB_SHIFT); \
sp1 = S_PTR(Y + dY) + 2*((X + dX) >> MLIB_SHIFT); \
sp2 = S_PTR(Y + 2*dY) + 2*((X + 2*dX) >> MLIB_SHIFT); \
sp3 = S_PTR(Y + 3*dY) + 2*((X + 3*dX) >> MLIB_SHIFT); \
X += 4*dX; \
Y += 4*dY
/***************************************************************/
#define AFFINE_U8_2CH \
s0 = vis_fpmerge(LD_U8(sp0, 0), LD_U8(sp2, 0)); \
s1 = vis_fpmerge(LD_U8(sp0, 1), LD_U8(sp2, 1)); \
s2 = vis_fpmerge(LD_U8(sp1, 0), LD_U8(sp3, 0)); \
s3 = vis_fpmerge(LD_U8(sp1, 1), LD_U8(sp3, 1)); \
\
s0 = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s2)); \
s1 = vis_fpmerge(vis_read_lo(s1), vis_read_lo(s3)); \
dd = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s1))
/***************************************************************/
mlib_status mlib_ImageAffine_u8_2ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
DTYPE *dstLineEnd;
mlib_s32 i, size;
for (j = yStart; j <= yFinish; j++) {
mlib_u8 *sp0, *sp1, *sp2, *sp3;
mlib_d64 *da, s0, s1, s2, s3, dd, d_old;
mlib_s32 emask;
CLIP(2);
dstLineEnd = (DTYPE*)dstData + 2 * xRight;
size = xRight - xLeft + 1;
dstLineEnd++;
if (((mlib_s32)dp & 7) == 0) {
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
GET_POINTERS_2CH;
AFFINE_U8_2CH;
*(mlib_d64*)dp = dd;
dp += 8;
}
if (i < size) {
sp0 = sp1 = sp2 = sp3 = S_PTR(Y) + 2*(X >> MLIB_SHIFT);
if (i + 1 < size) sp1 = S_PTR(Y + dY) + 2*((X + dX) >> MLIB_SHIFT);
if (i + 2 < size) sp2 = S_PTR(Y + 2*dY) + 2*((X + 2*dX) >> MLIB_SHIFT);
if (i + 3 < size) sp3 = S_PTR(Y + 3*dY) + 2*((X + 3*dX) >> MLIB_SHIFT);
AFFINE_U8_2CH;
emask = vis_edge8(dp, dstLineEnd);
vis_pst_8(dd, dp, emask);
}
} else {
da = vis_alignaddr(dp, 0);
d_old = vis_faligndata(da[0], da[0]);
vis_alignaddr((void*)0, (mlib_u8*)da - dp);
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
GET_POINTERS_2CH;
AFFINE_U8_2CH;
*da++ = vis_faligndata(d_old, dd);
d_old = dd;
}
if (i < size) {
sp0 = sp1 = sp2 = sp3 = S_PTR(Y) + 2*(X >> MLIB_SHIFT);
if (i + 1 < size) sp1 = S_PTR(Y + dY) + 2*((X + dX) >> MLIB_SHIFT);
if (i + 2 < size) sp2 = S_PTR(Y + 2*dY) + 2*((X + 2*dX) >> MLIB_SHIFT);
if (i + 3 < size) sp3 = S_PTR(Y + 3*dY) + 2*((X + 3*dX) >> MLIB_SHIFT);
AFFINE_U8_2CH;
}
emask = vis_edge8(da, dstLineEnd);
vis_pst_8(vis_faligndata(d_old, dd), da++, emask);
if ((mlib_u8*)da <= dstLineEnd) {
emask = vis_edge8(da, dstLineEnd);
vis_pst_8(vis_faligndata(dd, dd), da, emask);
}
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
#undef LD_U8
#define LD_U8(sp, x) vis_read_lo(vis_ld_u8(sp + x))
/***************************************************************/
mlib_status mlib_ImageAffine_u8_3ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
DTYPE *srcPixelPtr;
mlib_s32 i, size;
for (j = yStart; j <= yFinish; j++) {
mlib_d64 s0, s1, s2, s3, s4, s5;
CLIP(3);
size = xRight - xLeft + 1;
while (((mlib_s32)dp & 3) && (size > 0)) {
sp = S_PTR(Y) + 3*(X >> MLIB_SHIFT);
dp[0] = sp[0];
dp[1] = sp[1];
dp[2] = sp[2];
dp += 3;
X += dX;
Y += dY;
size--;
}
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
mlib_u8 *sp0, *sp1, *sp2, *sp3;
sp0 = S_PTR(Y);
sp1 = S_PTR(Y + dY);
sp2 = S_PTR(Y + 2*dY);
sp3 = S_PTR(Y + 3*dY);
sp0 += 3*(X >> MLIB_SHIFT);
sp1 += 3*((X + dX) >> MLIB_SHIFT);
sp2 += 3*((X + 2*dX) >> MLIB_SHIFT);
sp3 += 3*((X + 3*dX) >> MLIB_SHIFT);
s0 = vis_fpmerge(LD_U8(sp0, 0), LD_U8(sp0, 2));
s1 = vis_fpmerge(LD_U8(sp0, 1), LD_U8(sp1, 0));
s0 = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s1));
s2 = vis_fpmerge(LD_U8(sp1, 1), LD_U8(sp2, 0));
s3 = vis_fpmerge(LD_U8(sp1, 2), LD_U8(sp2, 1));
s2 = vis_fpmerge(vis_read_lo(s2), vis_read_lo(s3));
s4 = vis_fpmerge(LD_U8(sp2, 2), LD_U8(sp3, 1));
s5 = vis_fpmerge(LD_U8(sp3, 0), LD_U8(sp3, 2));
s4 = vis_fpmerge(vis_read_lo(s4), vis_read_lo(s5));
((mlib_f32*)dp)[0] = vis_read_lo(s0);
((mlib_f32*)dp)[1] = vis_read_lo(s2);
((mlib_f32*)dp)[2] = vis_read_lo(s4);
dp += 12;
X += 4*dX;
Y += 4*dY;
}
for (i = 0; i < (size & 3); i++) {
sp = S_PTR(Y) + 3*(X >> MLIB_SHIFT);
dp[0] = sp[0];
dp[1] = sp[1];
dp[2] = sp[2];
dp += 3;
X += dX;
Y += dY;
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
#undef LD_U8
#define LD_U8(sp, x) vis_read_lo(vis_ld_u8_i(sp, x))
/***************************************************************/
#define AFFINE_U8_4x2 \
sp0 = S_PTR(Y) + 4*(X >> MLIB_SHIFT); \
sp1 = S_PTR(Y + dY) + 4*((X + dX) >> MLIB_SHIFT); \
\
s0 = vis_fpmerge(LD_U8(sp0, 0), LD_U8(sp1, 0)); \
s1 = vis_fpmerge(LD_U8(sp0, 1), LD_U8(sp1, 1)); \
s2 = vis_fpmerge(LD_U8(sp0, 2), LD_U8(sp1, 2)); \
s3 = vis_fpmerge(LD_U8(sp0, 3), LD_U8(sp1, 3)); \
\
s0 = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s2)); \
s1 = vis_fpmerge(vis_read_lo(s1), vis_read_lo(s3)); \
dd = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s1)); \
\
X += 2*dX; \
Y += 2*dY
/***************************************************************/
#define AFFINE_U8_4x1 \
sp0 = S_PTR(Y) + 4*(X >> MLIB_SHIFT); \
\
s0 = vis_fpmerge(LD_U8(sp0, 0), LD_U8(sp0, 2)); \
s1 = vis_fpmerge(LD_U8(sp0, 1), LD_U8(sp0, 3)); \
s0 = vis_fpmerge(vis_read_lo(s0), vis_read_lo(s1)); \
dd = vis_freg_pair(vis_read_lo(s0), vis_fzeros())
/***************************************************************/
mlib_status mlib_ImageAffine_u8_4ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
DTYPE *dstLineEnd;
mlib_s32 i, size;
for (j = yStart; j <= yFinish; j++) {
mlib_u8 *sp0, *sp1;
mlib_d64 *da, s0, s1, s2, s3, dd, d_old;
mlib_s32 emask;
CLIP(4);
dstLineEnd = (DTYPE*)dstData + 4 * xRight;
size = xRight - xLeft + 1;
if (((mlib_s32)dp & 7) == 0) {
#pragma pipeloop(0)
for (i = 0; i <= (size - 2); i += 2) {
AFFINE_U8_4x2;
*(mlib_d64*)dp = dd;
dp += 8;
}
if (i < size) {
AFFINE_U8_4x1;
*(mlib_f32*)dp = vis_read_hi(dd);
}
} else {
da = vis_alignaddr(dp, 0);
d_old = vis_faligndata(da[0], da[0]);
vis_alignaddr((void*)0, (mlib_u8*)da - dp);
#pragma pipeloop(0)
for (i = 0; i <= (size - 2); i += 2) {
AFFINE_U8_4x2;
*da++ = vis_faligndata(d_old, dd);
d_old = dd;
}
if (i < size) {
AFFINE_U8_4x1;
}
dstLineEnd += 3;
emask = vis_edge8(da, dstLineEnd);
vis_pst_8(vis_faligndata(d_old, dd), da++, emask);
if ((mlib_u8*)da <= dstLineEnd) {
emask = vis_edge8(da, dstLineEnd);
vis_pst_8(vis_faligndata(dd, dd), da, emask);
}
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
#undef DTYPE
#define DTYPE mlib_u16
#define SHIFT1(x) (((x) >> (MLIB_SHIFT - 1)) &~ 1)
/***************************************************************/
mlib_status mlib_ImageAffine_s16_1ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
mlib_s32 i, size;
vis_alignaddr((void*)0, 6);
for (j = yStart; j <= yFinish; j++) {
mlib_d64 ss;
CLIP(1);
size = xRight - xLeft + 1;
while (((mlib_s32)dp & 7) && (size > 0)) {
*dp = *(S_PTR(Y) + (X >> MLIB_SHIFT));
dp++;
X += dX;
Y += dY;
size--;
}
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
mlib_u16 *sp0, *sp1, *sp2, *sp3;
sp0 = S_PTR(Y);
sp1 = S_PTR(Y + dY);
sp2 = S_PTR(Y + 2*dY);
sp3 = S_PTR(Y + 3*dY);
ss = vis_faligndata(vis_ld_u16_i(sp3, SHIFT1(X + 3*dX)), ss);
ss = vis_faligndata(vis_ld_u16_i(sp2, SHIFT1(X + 2*dX)), ss);
ss = vis_faligndata(vis_ld_u16_i(sp1, SHIFT1(X + dX)), ss);
ss = vis_faligndata(vis_ld_u16_i(sp0, SHIFT1(X)), ss);
*(mlib_d64*)dp = ss;
dp += 4;
X += 4*dX;
Y += 4*dY;
}
for (i = 0; i < (size & 3); i++) {
dp[i] = *(S_PTR(Y) + (X >> MLIB_SHIFT));
X += dX;
Y += dY;
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
mlib_status mlib_ImageAffine_s16_2ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
DTYPE *srcPixelPtr;
DTYPE *dstLineEnd;
for (j = yStart; j <= yFinish; j++) {
CLIP(2);
dstLineEnd = (DTYPE*)dstData + 2 * xRight;
#pragma pipeloop(0)
for (; dp <= dstLineEnd; dp += 2) {
sp = S_PTR(Y) + 2*(X >> MLIB_SHIFT);
dp[0] = sp[0];
dp[1] = sp[1];
X += dX;
Y += dY;
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
#undef LD_U16
#define LD_U16(sp, x) vis_ld_u16(sp + x)
/***************************************************************/
mlib_status mlib_ImageAffine_s16_3ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
DTYPE *srcPixelPtr;
mlib_s32 i, size;
vis_alignaddr((void*)0, 6);
for (j = yStart; j <= yFinish; j++) {
mlib_d64 s0, s1, s2;
CLIP(3);
size = xRight - xLeft + 1;
while (((mlib_s32)dp & 7) && (size > 0)) {
sp = S_PTR(Y) + 3*(X >> MLIB_SHIFT);
dp[0] = sp[0];
dp[1] = sp[1];
dp[2] = sp[2];
dp += 3;
X += dX;
Y += dY;
size--;
}
#pragma pipeloop(0)
for (i = 0; i <= (size - 4); i += 4) {
mlib_u16 *sp0, *sp1, *sp2, *sp3;
sp0 = S_PTR(Y);
sp1 = S_PTR(Y + dY);
sp2 = S_PTR(Y + 2*dY);
sp3 = S_PTR(Y + 3*dY);
sp0 += 3*(X >> MLIB_SHIFT);
sp1 += 3*((X + dX) >> MLIB_SHIFT);
sp2 += 3*((X + 2*dX) >> MLIB_SHIFT);
sp3 += 3*((X + 3*dX) >> MLIB_SHIFT);
s2 = vis_faligndata(LD_U16(sp3, 2), s2);
s2 = vis_faligndata(LD_U16(sp3, 1), s2);
s2 = vis_faligndata(LD_U16(sp3, 0), s2);
s2 = vis_faligndata(LD_U16(sp2, 2), s2);
s1 = vis_faligndata(LD_U16(sp2, 1), s1);
s1 = vis_faligndata(LD_U16(sp2, 0), s1);
s1 = vis_faligndata(LD_U16(sp1, 2), s1);
s1 = vis_faligndata(LD_U16(sp1, 1), s1);
s0 = vis_faligndata(LD_U16(sp1, 0), s0);
s0 = vis_faligndata(LD_U16(sp0, 2), s0);
s0 = vis_faligndata(LD_U16(sp0, 1), s0);
s0 = vis_faligndata(LD_U16(sp0, 0), s0);
((mlib_d64*)dp)[0] = s0;
((mlib_d64*)dp)[1] = s1;
((mlib_d64*)dp)[2] = s2;
dp += 12;
X += 4*dX;
Y += 4*dY;
}
for (i = 0; i < (size & 3); i++) {
sp = S_PTR(Y) + 3*(X >> MLIB_SHIFT);
dp[0] = sp[0];
dp[1] = sp[1];
dp[2] = sp[2];
dp += 3;
X += dX;
Y += dY;
}
}
return MLIB_SUCCESS;
}
/***************************************************************/
#define AFFINE_S16_4ch \
sp = S_PTR(Y) + 4*(X >> MLIB_SHIFT); \
\
dd = vis_faligndata(LD_U16(sp, 3), dd); \
dd = vis_faligndata(LD_U16(sp, 2), dd); \
dd = vis_faligndata(LD_U16(sp, 1), dd); \
dd = vis_faligndata(LD_U16(sp, 0), dd); \
\
X += dX; \
Y += dY
/***************************************************************/
mlib_status mlib_ImageAffine_s16_4ch_nn(mlib_affine_param *param)
{
DECLAREVAR();
DTYPE *srcPixelPtr;
mlib_s32 i, size, max_xsize = param -> max_xsize;
mlib_d64 buff[BUFF_SIZE], *pbuff = buff;
if (max_xsize > BUFF_SIZE) {
pbuff = mlib_malloc(sizeof(mlib_d64)*max_xsize);
}
for (j = yStart; j <= yFinish; j++) {
mlib_d64 *da, dd;
vis_alignaddr((void*)0, 6);
CLIP(4);
size = xRight - xLeft + 1;
if ((mlib_s32)dp & 7) {
da = buff;
} else {
da = (mlib_d64*)dp;
}
#pragma pipeloop(0)
for (i = 0; i < size; i++) {
AFFINE_S16_4ch;
da[i] = dd;
}
if ((mlib_s32)dp & 7) {
mlib_ImageCopy_na((mlib_u8*)buff, (mlib_u8*)dp, 8*size);
}
}
if (pbuff != buff) {
mlib_free(pbuff);
}
return MLIB_SUCCESS;
}
/***************************************************************/