jdk/src/share/native/sun/awt/medialib/mlib_ImageAffine.c
changeset 2 90ce3da70b43
child 5506 202f599c92aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/awt/medialib/mlib_ImageAffine.c	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc.  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.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * FUNCTION
+ *      mlib_ImageAffine - image affine transformation with edge condition
+ *
+ * SYNOPSIS
+ *      mlib_status mlib_ImageAffine(mlib_image       *dst,
+ *                                   const mlib_image *src,
+ *                                   const mlib_d64   *mtx,
+ *                                   mlib_filter      filter,
+ *                                   mlib_edge        edge)
+ *
+ * ARGUMENTS
+ *      dst       Pointer to destination image
+ *      src       Pointer to source image
+ *      mtx       Transformation matrix, where
+ *                  mtx[0] holds a;  mtx[1] holds b;
+ *                  mtx[2] holds tx; mtx[3] holds c;
+ *                  mtx[4] holds d;  mtx[5] holds ty.
+ *      filter    Type of resampling filter.
+ *      edge      Type of edge condition.
+ *
+ * DESCRIPTION
+ *                      xd = a*xs + b*ys + tx
+ *                      yd = c*xs + d*ys + ty
+ *
+ *  The upper-left corner pixel of an image is located at (0.5, 0.5).
+ *
+ *  The resampling filter can be one of the following:
+ *      MLIB_NEAREST
+ *      MLIB_BILINEAR
+ *      MLIB_BICUBIC
+ *      MLIB_BICUBIC2
+ *
+ *  The edge condition can be one of the following:
+ *      MLIB_EDGE_DST_NO_WRITE  (default)
+ *      MLIB_EDGE_DST_FILL_ZERO
+ *      MLIB_EDGE_OP_NEAREST
+ *      MLIB_EDGE_SRC_EXTEND
+ *      MLIB_EDGE_SRC_PADDED
+ *
+ * RESTRICTION
+ *      src and dst must be the same type and the same number of channels.
+ *      They can have 1, 2, 3 or 4 channels. They can be in MLIB_BIT, MLIB_BYTE,
+ *      MLIB_SHORT, MLIB_USHORT or MLIB_INT data type.
+ *
+ *      src image can not have width or height larger than 32767.
+ */
+
+#include "mlib_ImageCheck.h"
+#include "mlib_ImageColormap.h"
+#include "mlib_ImageAffine.h"
+
+
+/***************************************************************/
+#define BUFF_SIZE  600
+
+/***************************************************************/
+const type_affine_fun mlib_AffineFunArr_nn[] = {
+  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,
+  mlib_ImageAffine_s32_1ch_nn, mlib_ImageAffine_s32_2ch_nn,
+  mlib_ImageAffine_s32_3ch_nn, mlib_ImageAffine_s32_4ch_nn,
+  mlib_ImageAffine_d64_1ch_nn, mlib_ImageAffine_d64_2ch_nn,
+  mlib_ImageAffine_d64_3ch_nn, mlib_ImageAffine_d64_4ch_nn,
+};
+
+/***************************************************************/
+const type_affine_fun mlib_AffineFunArr_bl[] = {
+  mlib_ImageAffine_u8_1ch_bl,  mlib_ImageAffine_u8_2ch_bl,
+  mlib_ImageAffine_u8_3ch_bl,  mlib_ImageAffine_u8_4ch_bl,
+  mlib_ImageAffine_s16_1ch_bl, mlib_ImageAffine_s16_2ch_bl,
+  mlib_ImageAffine_s16_3ch_bl, mlib_ImageAffine_s16_4ch_bl,
+  mlib_ImageAffine_s32_1ch_bl, mlib_ImageAffine_s32_2ch_bl,
+  mlib_ImageAffine_s32_3ch_bl, mlib_ImageAffine_s32_4ch_bl,
+  mlib_ImageAffine_u16_1ch_bl, mlib_ImageAffine_u16_2ch_bl,
+  mlib_ImageAffine_u16_3ch_bl, mlib_ImageAffine_u16_4ch_bl,
+  mlib_ImageAffine_f32_1ch_bl, mlib_ImageAffine_f32_2ch_bl,
+  mlib_ImageAffine_f32_3ch_bl, mlib_ImageAffine_f32_4ch_bl,
+  mlib_ImageAffine_d64_1ch_bl, mlib_ImageAffine_d64_2ch_bl,
+  mlib_ImageAffine_d64_3ch_bl, mlib_ImageAffine_d64_4ch_bl
+};
+
+/***************************************************************/
+const type_affine_fun mlib_AffineFunArr_bc[] = {
+  mlib_ImageAffine_u8_1ch_bc,  mlib_ImageAffine_u8_2ch_bc,
+  mlib_ImageAffine_u8_3ch_bc,  mlib_ImageAffine_u8_4ch_bc,
+  mlib_ImageAffine_s16_1ch_bc, mlib_ImageAffine_s16_2ch_bc,
+  mlib_ImageAffine_s16_3ch_bc, mlib_ImageAffine_s16_4ch_bc,
+  mlib_ImageAffine_s32_1ch_bc, mlib_ImageAffine_s32_2ch_bc,
+  mlib_ImageAffine_s32_3ch_bc, mlib_ImageAffine_s32_4ch_bc,
+  mlib_ImageAffine_u16_1ch_bc, mlib_ImageAffine_u16_2ch_bc,
+  mlib_ImageAffine_u16_3ch_bc, mlib_ImageAffine_u16_4ch_bc,
+  mlib_ImageAffine_f32_1ch_bc, mlib_ImageAffine_f32_2ch_bc,
+  mlib_ImageAffine_f32_3ch_bc, mlib_ImageAffine_f32_4ch_bc,
+  mlib_ImageAffine_d64_1ch_bc, mlib_ImageAffine_d64_2ch_bc,
+  mlib_ImageAffine_d64_3ch_bc, mlib_ImageAffine_d64_4ch_bc
+};
+
+/***************************************************************/
+const type_affine_i_fun mlib_AffineFunArr_bc_i[] = {
+  mlib_ImageAffineIndex_U8_U8_3CH_BC,
+  mlib_ImageAffineIndex_U8_U8_4CH_BC,
+  mlib_ImageAffineIndex_S16_U8_3CH_BC,
+  mlib_ImageAffineIndex_S16_U8_4CH_BC,
+  mlib_ImageAffineIndex_U8_S16_3CH_BC,
+  mlib_ImageAffineIndex_U8_S16_4CH_BC,
+  mlib_ImageAffineIndex_S16_S16_3CH_BC,
+  mlib_ImageAffineIndex_S16_S16_4CH_BC
+};
+
+/***************************************************************/
+#ifdef i386 /* do not perform the coping by mlib_d64 data type for x86 */
+#define MAX_T_IND  2
+#else
+#define MAX_T_IND  3
+#endif /* i386 ( do not perform the coping by mlib_d64 data type for x86 ) */
+
+/***************************************************************/
+mlib_status mlib_ImageAffine_alltypes(mlib_image       *dst,
+                                      const mlib_image *src,
+                                      const mlib_d64   *mtx,
+                                      mlib_filter      filter,
+                                      mlib_edge        edge,
+                                      const void       *colormap)
+{
+  mlib_affine_param param[1];
+  mlib_status res;
+  mlib_type type;
+  mlib_s32 nchan, t_ind, kw, kw1;
+  mlib_addr align;
+  mlib_d64 buff_lcl[BUFF_SIZE / 8];
+  mlib_u8 **lineAddr = NULL;
+
+  /* check for obvious errors */
+  MLIB_IMAGE_TYPE_EQUAL(src, dst);
+  MLIB_IMAGE_CHAN_EQUAL(src, dst);
+
+  type = mlib_ImageGetType(dst);
+  nchan = mlib_ImageGetChannels(dst);
+
+  switch (filter) {
+    case MLIB_NEAREST:
+      kw = 1;
+      kw1 = 0;
+      break;
+
+    case MLIB_BILINEAR:
+      kw = 2;
+      kw1 = 0;
+      break;
+
+    case MLIB_BICUBIC:
+    case MLIB_BICUBIC2:
+      kw = 4;
+      kw1 = 1;
+      break;
+
+    default:
+      return MLIB_FAILURE;
+  }
+
+  STORE_PARAM(param, lineAddr);
+  STORE_PARAM(param, filter);
+
+  res = mlib_AffineEdges(param, dst, src, buff_lcl, BUFF_SIZE,
+                         kw, kw, kw1, kw1, edge, mtx, MLIB_SHIFT, MLIB_SHIFT);
+
+  if (res != MLIB_SUCCESS)
+    return res;
+
+  lineAddr = param->lineAddr;
+
+  if (type == MLIB_BYTE)
+    t_ind = 0;
+  else if (type == MLIB_SHORT)
+    t_ind = 1;
+  else if (type == MLIB_INT)
+    t_ind = 2;
+  else if (type == MLIB_USHORT)
+    t_ind = 3;
+  else if (type == MLIB_FLOAT)
+    t_ind = 4;
+  else if (type == MLIB_DOUBLE)
+    t_ind = 5;
+
+  if (colormap != NULL && filter != MLIB_NEAREST) {
+    if (t_ind != 0 && t_ind != 1)
+      return MLIB_FAILURE;
+
+    if (mlib_ImageGetLutType(colormap) == MLIB_SHORT)
+      t_ind += 2;
+    t_ind = 2 * t_ind;
+
+    if (mlib_ImageGetLutChannels(colormap) == 4)
+      t_ind++;
+  }
+
+  if (type == MLIB_BIT) {
+    mlib_s32 s_bitoff = mlib_ImageGetBitOffset(src);
+    mlib_s32 d_bitoff = mlib_ImageGetBitOffset(dst);
+
+    if (nchan != 1 || filter != MLIB_NEAREST)
+      return MLIB_FAILURE;
+    mlib_ImageAffine_bit_1ch_nn(param, s_bitoff, d_bitoff);
+  }
+  else {
+    switch (filter) {
+      case MLIB_NEAREST:
+
+        if (t_ind >= 3)
+          t_ind -= 2;                                      /* correct types USHORT, FLOAT, DOUBLE; new values: 1, 2, 3 */
+
+        /* two channels as one channel of next type */
+        align = (mlib_addr) (param->dstData) | (mlib_addr) lineAddr[0];
+        align |= param->dstYStride | param->srcYStride;
+        while (((nchan | (align >> t_ind)) & 1) == 0 && t_ind < MAX_T_IND) {
+          nchan >>= 1;
+          t_ind++;
+        }
+
+        res = mlib_AffineFunArr_nn[4 * t_ind + (nchan - 1)] (param);
+        break;
+
+      case MLIB_BILINEAR:
+
+        if (colormap != NULL) {
+          res = mlib_AffineFunArr_bl_i[t_ind] (param, colormap);
+        }
+        else {
+          res = mlib_AffineFunArr_bl[4 * t_ind + (nchan - 1)] (param);
+        }
+
+        break;
+
+      case MLIB_BICUBIC:
+      case MLIB_BICUBIC2:
+
+        if (colormap != NULL) {
+          res = mlib_AffineFunArr_bc_i[t_ind] (param, colormap);
+        }
+        else {
+          res = mlib_AffineFunArr_bc[4 * t_ind + (nchan - 1)] (param);
+        }
+
+        break;
+    }
+
+    if (res != MLIB_SUCCESS) {
+      if (param->buff_malloc != NULL)
+        mlib_free(param->buff_malloc);
+      return res;
+    }
+  }
+
+  if (edge == MLIB_EDGE_SRC_PADDED)
+    edge = MLIB_EDGE_DST_NO_WRITE;
+
+  if (filter != MLIB_NEAREST && edge != MLIB_EDGE_DST_NO_WRITE) {
+    mlib_affine_param param_e[1];
+    mlib_d64 buff_lcl1[BUFF_SIZE / 8];
+
+    STORE_PARAM(param_e, lineAddr);
+    STORE_PARAM(param_e, filter);
+
+    res = mlib_AffineEdges(param_e, dst, src, buff_lcl1, BUFF_SIZE,
+                           kw, kw, kw1, kw1, -1, mtx, MLIB_SHIFT, MLIB_SHIFT);
+
+    if (res != MLIB_SUCCESS) {
+      if (param->buff_malloc != NULL)
+        mlib_free(param->buff_malloc);
+      return res;
+    }
+
+    switch (edge) {
+      case MLIB_EDGE_DST_FILL_ZERO:
+        mlib_ImageAffineEdgeZero(param, param_e, colormap);
+        break;
+
+      case MLIB_EDGE_OP_NEAREST:
+        mlib_ImageAffineEdgeNearest(param, param_e);
+        break;
+
+      case MLIB_EDGE_SRC_EXTEND:
+
+        if (filter == MLIB_BILINEAR) {
+          res = mlib_ImageAffineEdgeExtend_BL(param, param_e, colormap);
+        }
+        else {
+          res = mlib_ImageAffineEdgeExtend_BC(param, param_e, colormap);
+        }
+
+        break;
+    }
+
+    if (param_e->buff_malloc != NULL)
+      mlib_free(param_e->buff_malloc);
+  }
+
+  if (param->buff_malloc != NULL)
+    mlib_free(param->buff_malloc);
+
+  return res;
+}
+
+/***************************************************************/
+mlib_status mlib_ImageAffine(mlib_image       *dst,
+                             const mlib_image *src,
+                             const mlib_d64   *mtx,
+                             mlib_filter      filter,
+                             mlib_edge        edge)
+{
+  mlib_type type;
+
+  MLIB_IMAGE_CHECK(src);
+  MLIB_IMAGE_CHECK(dst);
+
+  type = mlib_ImageGetType(dst);
+
+  if (type != MLIB_BIT && type != MLIB_BYTE &&
+      type != MLIB_SHORT && type != MLIB_USHORT && type != MLIB_INT) {
+    return MLIB_FAILURE;
+  }
+
+  return mlib_ImageAffine_alltypes(dst, src, mtx, filter, edge, NULL);
+}
+
+/***************************************************************/