Package com.lightcrafts.media.jai.opimage

Source Code of com.lightcrafts.media.jai.opimage.ScaleBicubicOpImage

/*
* $RCSfile: ScaleBicubicOpImage.java,v $
*
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
*
* Use is subject to license terms.
*
* $Revision: 1.1 $
* $Date: 2005/02/11 04:56:42 $
* $State: Exp $
*/
package com.lightcrafts.media.jai.opimage;
import java.awt.Rectangle;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import com.lightcrafts.mediax.jai.BorderExtender;
import com.lightcrafts.mediax.jai.ImageLayout;
import com.lightcrafts.mediax.jai.Interpolation;
import com.lightcrafts.mediax.jai.InterpolationTable;
import com.lightcrafts.mediax.jai.RasterAccessor;
import com.lightcrafts.mediax.jai.RasterFormatTag;
import com.lightcrafts.mediax.jai.ScaleOpImage;
import java.util.Map;
import com.lightcrafts.media.jai.util.Rational;
// import com.lightcrafts.media.jai.test.OpImageTester;

/**
* An <code>OpImage</code> that performs bicubic interpolation scaling.
*
*/
final class ScaleBicubicOpImage extends ScaleOpImage {

    /* The number of subsampleBits */
    private int subsampleBits;

    /* 2 ^ subsampleBits */
    private int one;

    /** The horizontal coefficient data in fixed-point format. */
    private int[] tableDataHi = null;

    /** The vertical coefficient data in fixed-point format. */
    private int[] tableDataVi = null;

    /** The horizontal coefficient data in floating-point format. */
    private float[] tableDataHf = null;

    /** The vertical coefficient data in floating-point format. */
    private float[] tableDataVf = null;

    /** The horizontal coefficient data in double format. */
    private double[] tableDataHd = null;

    /** The vertical coefficient data in double format. */
    private double[] tableDataVd = null;

    /** Number of fractional bits used to described filter coefficients. */
    private int precisionBits;

    /** The number 1/2 with precisionBits of fractional precision. */
    private int round;

    private Rational half = new Rational(1, 2);

    // The InterpolationTable superclass.
    InterpolationTable interpTable;

    long invScaleYInt, invScaleYFrac;
    long invScaleXInt, invScaleXFrac;

    /**
     * Constructs a ScaleBicubicOpImage from a RenderedImage source,
     *
     * @param source a RenderedImage.
     * @param extender a BorderExtender, or null.
     * @param layout an ImageLayout optionally containing the tile grid layout,
     *        SampleModel, and ColorModel, or null.
     * @param xScale scale factor along x axis.
     * @param yScale scale factor along y axis.
     * @param xTrans translation factor along x axis.
     * @param yTrans translation factor along y axis.
     * @param interp a Interpolation object to use for resampling.
     */
    public ScaleBicubicOpImage(RenderedImage source,
                               BorderExtender extender,
             Map config,
                               ImageLayout layout,
             float xScale,
             float yScale,
             float xTrans,
             float yTrans,
             Interpolation interp) {
        super(source,
              layout,
              config,
              true,
              extender,
              interp,
              xScale,
              yScale,
              xTrans,
              yTrans);

  subsampleBits = interp.getSubsampleBitsH();
  interpTable = (InterpolationTable)interp;

  // Number of subsample positions
  one = 1 << subsampleBits;
  precisionBits = interpTable.getPrecisionBits();
  if (precisionBits > 0) {
      round = 1<< (precisionBits - 1);
  }

  if (invScaleYRational.num > invScaleYRational.denom) {
      invScaleYInt = invScaleYRational.num / invScaleYRational.denom;
      invScaleYFrac = invScaleYRational.num % invScaleYRational.denom;
  } else {
      invScaleYInt = 0;
      invScaleYFrac = invScaleYRational.num;
  }

  if (invScaleXRational.num > invScaleXRational.denom) {
      invScaleXInt = invScaleXRational.num / invScaleXRational.denom;
      invScaleXFrac = invScaleXRational.num % invScaleXRational.denom;
  } else {
      invScaleXInt = 0;
      invScaleXFrac = invScaleXRational.num;
  }
    }

    /**
     * Performs a scale operation on a specified rectangle. The sources are
     * cobbled.
     *
     * @param sources  an array of source Rasters, guaranteed to provide all
     *                 necessary source data for computing the output.
     * @param dest     a WritableRaster containing the area to be computed.
     * @param destRect the rectangle within dest to be processed.
     */
    protected void computeRect(Raster [] sources,
                               WritableRaster dest,
                               Rectangle destRect) {
        // Retrieve format tags.
        RasterFormatTag[] formatTags = getFormatTags();

        Raster source = sources[0];
  // Get the source rectangle
        Rectangle srcRect = source.getBounds();

  int srcRectX = srcRect.x;
  int srcRectY = srcRect.y;

        RasterAccessor srcAccessor =
            new RasterAccessor(source, srcRect, 
                               formatTags[0], getSource(0).getColorModel());

        RasterAccessor dstAccessor =
            new RasterAccessor(dest, destRect, formatTags[1], getColorModel());

  // Loop variables based on the destination rectangle to be calculated.
  int dx = destRect.x;
  int dy = destRect.y;
  int dwidth = destRect.width;
  int dheight = destRect.height;
        int srcPixelStride = srcAccessor.getPixelStride();
  int srcScanlineStride = srcAccessor.getScanlineStride();

  int[] ypos = new int[dheight];
  int[] xpos = new int[dwidth];

  // Precalculate the y positions and store them in an array.
  int[] yfracvalues = new int[dheight];
  // Precalculate the x positions and store them in an array.
  int[] xfracvalues = new int[dwidth];

  long syNum = dy, syDenom = 1;

  // Subtract the X translation factor sy -= transY
  syNum = syNum * transYRationalDenom - transYRationalNum * syDenom;
  syDenom *= transYRationalDenom;
 
  // Add 0.5
  syNum = 2 * syNum + syDenom;
  syDenom *= 2;

  // Multply by invScaleX
  syNum *= invScaleYRationalNum;
  syDenom *= invScaleYRationalDenom;

  // Subtract 0.5
  syNum = 2 * syNum - syDenom;
  syDenom *= 2;

  // Separate the x source coordinate into integer and fractional part
  int srcYInt = Rational.floor(syNum , syDenom);
  long srcYFrac = syNum % syDenom;
  if (srcYInt < 0) {
      srcYFrac = syDenom + srcYFrac;
  }

  // Normalize - Get a common denominator for the fracs of
  // src and invScaleY
  long commonYDenom = syDenom * invScaleYRationalDenom;
  srcYFrac *= invScaleYRationalDenom;
  long newInvScaleYFrac = invScaleYFrac * syDenom;

  long sxNum = dx, sxDenom = 1;

  // Subtract the X translation factor sx -= transX
  sxNum = sxNum * transXRationalDenom - transXRationalNum * sxDenom;
  sxDenom *= transXRationalDenom;
 
  // Add 0.5
  sxNum = 2 * sxNum + sxDenom;
  sxDenom *= 2;

  // Multply by invScaleX
  sxNum *= invScaleXRationalNum;
  sxDenom *= invScaleXRationalDenom;

  // Subtract 0.5
  sxNum = 2 * sxNum - sxDenom;
  sxDenom *= 2;

  // Separate the x source coordinate into integer and fractional part
  // int part is floor(sx), frac part is sx - floor(sx)
  int srcXInt = Rational.floor(sxNum , sxDenom);
  long srcXFrac = sxNum % sxDenom;
  if (srcXInt < 0) {
      srcXFrac = sxDenom + srcXFrac;
  }
 
  // Normalize - Get a common denominator for the fracs of
  // src and invScaleX
  long commonXDenom = sxDenom * invScaleXRationalDenom;
  srcXFrac *= invScaleXRationalDenom;
  long newInvScaleXFrac = invScaleXFrac * sxDenom;

  for (int i=0; i<dwidth; i++) {
       xpos[i] = (srcXInt - srcRectX) * srcPixelStride;
      xfracvalues[i] = (int)(((float)srcXFrac/(float)commonXDenom) * one);

      // Move onto the next source pixel.

      // Add the integral part of invScaleX to the integral part
      // of srcX
      srcXInt += invScaleXInt;

      // Add the fractional part of invScaleX to the fractional part
      // of srcX
      srcXFrac += newInvScaleXFrac;

      // If the fractional part is now greater than equal to the
      // denominator, divide so as to reduce the numerator to be less
      // than the denominator and add the overflow to the integral part.
      if (srcXFrac >= commonXDenom) {
    srcXInt += 1;
    srcXFrac -= commonXDenom;
      }
  }

  for (int i = 0; i < dheight; i++) {

      // Calculate the source position in the source data array.
      ypos[i] = (srcYInt - srcRectY) * srcScanlineStride;

      // Calculate the yfrac value
      yfracvalues[i] = (int)(((float)srcYFrac/(float)commonYDenom) * one);

      // Move onto the next source pixel.

      // Add the integral part of invScaleY to the integral part
      // of srcY
      srcYInt += invScaleYInt;

      // Add the fractional part of invScaleY to the fractional part
      // of srcY
      srcYFrac += newInvScaleYFrac;

      // If the fractional part is now greater than equal to the
      // denominator, divide so as to reduce the numerator to be less
      // than the denominator and add the overflow to the integral part.
      if (srcYFrac >= commonYDenom) {
    srcYInt += 1;
    srcYFrac -= commonYDenom;
      }
  }

        switch (dstAccessor.getDataType()) {

        case DataBuffer.TYPE_BYTE:
      initTableDataI();
            byteLoop(srcAccessor, destRect, dstAccessor,
      xpos, ypos, xfracvalues, yfracvalues);
            break;

        case DataBuffer.TYPE_SHORT:
      initTableDataI();
      shortLoop(srcAccessor, destRect, dstAccessor,
      xpos, ypos, xfracvalues, yfracvalues);
            break;

        case DataBuffer.TYPE_USHORT:
      initTableDataI();
      ushortLoop(srcAccessor, destRect, dstAccessor,
      xpos, ypos, xfracvalues, yfracvalues);
            break;

        case DataBuffer.TYPE_INT:
      initTableDataI();
      intLoop(srcAccessor, destRect, dstAccessor,
      xpos, ypos, xfracvalues, yfracvalues);
            break;

  case DataBuffer.TYPE_FLOAT:
      initTableDataF();
      floatLoop(srcAccessor, destRect, dstAccessor,
      xpos, ypos, xfracvalues, yfracvalues);
      break;

  case DataBuffer.TYPE_DOUBLE:
      initTableDataD();
      doubleLoop(srcAccessor, destRect, dstAccessor,
      xpos, ypos, xfracvalues, yfracvalues);
      break;

        default:
      throw
    new RuntimeException(JaiI18N.getString("OrderedDitherOpImage0"));
        }

        // If the RasterAccessor object set up a temporary buffer for the
        // op to write to, tell the RasterAccessor to write that data
        // to the raster no that we're done with it.
        if (dstAccessor.isDataCopy()) {
            dstAccessor.clampDataArrays();
            dstAccessor.copyDataToRaster();
        }
    }

    private void byteLoop(RasterAccessor src, Rectangle destRect,
        RasterAccessor dst, int xpos[], int ypos[],
        int xfracvalues[], int yfracvalues[]) {

        int srcPixelStride = src.getPixelStride();
  int srcScanlineStride = src.getScanlineStride();

  int dwidth = destRect.width;
  int dheight = destRect.height;
        int dnumBands = dst.getNumBands();
        byte dstDataArrays[][] = dst.getByteDataArrays();
        int dstBandOffsets[] = dst.getBandOffsets();
        int dstPixelStride = dst.getPixelStride();
        int dstScanlineStride = dst.getScanlineStride();
 
        byte srcDataArrays[][] = src.getByteDataArrays();
  int bandOffsets[] = src.getBandOffsets();
 
  int posy, posylow, posyhigh, posyhigh2;
  int posx, posxlow, posxhigh, posxhigh2;
  int xfrac, yfrac;
  int s__, s_0, s_1, s_2;
  int s0_, s00, s01, s02;
  int s1_, s10, s11, s12;
  int s2_, s20, s21, s22;
  int s, dstOffset = 0

  // Putting band loop outside
  for (int k = 0; k < dnumBands; k++)  {
            byte dstData[] = dstDataArrays[k];
            byte srcData[] = srcDataArrays[k];
      int dstScanlineOffset = dstBandOffsets[k];
      int bandOffset = bandOffsets[k];
     
      for (int j = 0; j < dheight; j++) {
                int dstPixelOffset = dstScanlineOffset;
    yfrac = yfracvalues[j];
    posy = ypos[j] + bandOffset;
    posylow = posy - srcScanlineStride;
    posyhigh = posy + srcScanlineStride;
    posyhigh2 = posyhigh + srcScanlineStride;
    for (int i = 0; i < dwidth; i++) {
        xfrac = xfracvalues[i];
        posx = xpos[i];
        posxlow = posx - srcPixelStride;
        posxhigh = posx + srcPixelStride;
        posxhigh2 = posxhigh + srcPixelStride;
       
        // Get the sixteen surrounding pixel values
        s__ = srcData[posxlow + posylow] & 0xff;
        s_0 = srcData[posx + posylow] & 0xff;
        s_1 = srcData[posxhigh + posylow] & 0xff;
        s_2 = srcData[posxhigh2 + posylow] & 0xff;

        s0_ = srcData[posxlow + posy] & 0xff;
        s00 = srcData[posx + posy] & 0xff;
        s01 = srcData[posxhigh + posy] & 0xff;
        s02 = srcData[posxhigh2 + posy] & 0xff;
       
        s1_ = srcData[posxlow + posyhigh] & 0xff;
        s10 = srcData[posx + posyhigh] & 0xff;
        s11 = srcData[posxhigh + posyhigh] & 0xff;
        s12 = srcData[posxhigh2 + posyhigh] & 0xff;

        s2_ = srcData[posxlow + posyhigh2] & 0xff;
        s20 = srcData[posx + posyhigh2] & 0xff;
        s21 = srcData[posxhigh + posyhigh2] & 0xff;
        s22 = srcData[posxhigh2 + posyhigh2] & 0xff;

        // Interpolate in X
        int offsetX = 4*xfrac;
        int offsetX1 = offsetX + 1;
        int offsetX2 = offsetX + 2;
        int offsetX3 = offsetX + 3;

        long sum_ = (long)tableDataHi[offsetX]*s__;
        sum_ += (long)tableDataHi[offsetX1]*s_0;
        sum_ += (long)tableDataHi[offsetX2]*s_1;
        sum_ += (long)tableDataHi[offsetX3]*s_2;
       
        long sum0 = (long)tableDataHi[offsetX]*s0_;
        sum0 += (long)tableDataHi[offsetX1]*s00;
        sum0 += (long)tableDataHi[offsetX2]*s01;
        sum0 += (long)tableDataHi[offsetX3]*s02;
       
        long sum1 = (long)tableDataHi[offsetX]*s1_;
        sum1 += (long)tableDataHi[offsetX1]*s10;
        sum1 += (long)tableDataHi[offsetX2]*s11;
        sum1 += (long)tableDataHi[offsetX3]*s12;
       
        long sum2 = (long)tableDataHi[offsetX]*s2_;
        sum2 += (long)tableDataHi[offsetX1]*s20;
        sum2 += (long)tableDataHi[offsetX2]*s21;
        sum2 += (long)tableDataHi[offsetX3]*s22;
       
        // Intermediate rounding
        sum_ = (sum_ + round) >> precisionBits;
        sum0 = (sum0 + round) >> precisionBits;
        sum1 = (sum1 + round) >> precisionBits;
        sum2 = (sum2 + round) >> precisionBits;
       
        // Interpolate in Y
        int offsetY = 4*yfrac;
        long sum = (long)tableDataVi[offsetY]*sum_;
        sum += (long)tableDataVi[offsetY + 1]*sum0;
        sum += (long)tableDataVi[offsetY + 2]*sum1;
        sum += (long)tableDataVi[offsetY + 3]*sum2;
       
        s = (int)((sum + round) >> precisionBits);
     
        // clamp the value to byte range
        if (s > 255) {
      s = 255;
        } else if (s < 0) {
      s = 0;
        }
       
        dstData[dstPixelOffset] = (byte)(s&0xff);
                    dstPixelOffset += dstPixelStride;
    }
                dstScanlineOffset += dstScanlineStride;
            }
        }
    }

    private void shortLoop(RasterAccessor src, Rectangle destRect,
         RasterAccessor dst, int xpos[], int ypos[],
         int xfracvalues[], int yfracvalues[]) {

        int srcPixelStride = src.getPixelStride();
  int srcScanlineStride = src.getScanlineStride();

  int dwidth = destRect.width;
  int dheight = destRect.height;
        int dnumBands = dst.getNumBands();
  short dstDataArrays[][] = dst.getShortDataArrays();
        int dstBandOffsets[] = dst.getBandOffsets();
        int dstPixelStride = dst.getPixelStride();
        int dstScanlineStride = dst.getScanlineStride();
 
        short srcDataArrays[][] = src.getShortDataArrays();
  int bandOffsets[] = src.getBandOffsets();
 
  int dstOffset = 0;
 
  int posy, posylow, posyhigh, posyhigh2;
  int posx, posxlow, posxhigh, posxhigh2;
  int xfrac, yfrac;
  int s__, s_0, s_1, s_2;
  int s0_, s00, s01, s02;
  int s1_, s10, s11, s12;
  int s2_, s20, s21, s22;
  int s; 

  // Putting band loop outside
  for (int k = 0; k < dnumBands; k++)  {
            short dstData[] = dstDataArrays[k];
            short srcData[] = srcDataArrays[k];
      int dstScanlineOffset = dstBandOffsets[k];
      int bandOffset = bandOffsets[k];
     
      for (int j = 0; j < dheight; j++) {
                int dstPixelOffset = dstScanlineOffset;
    yfrac = yfracvalues[j];
    posy = ypos[j] + bandOffset;
    posylow = posy - srcScanlineStride;
    posyhigh = posy + srcScanlineStride;
    posyhigh2 = posyhigh + srcScanlineStride;
    for (int i = 0; i < dwidth; i++) {
        xfrac = xfracvalues[i];
        posx = xpos[i];
        posxlow = posx - srcPixelStride;
        posxhigh = posx + srcPixelStride;
        posxhigh2 = posxhigh + srcPixelStride;
       
        // Get the sixteen surrounding pixel values
        s__ = srcData[posxlow + posylow];
        s_0 = srcData[posx + posylow];
        s_1 = srcData[posxhigh + posylow];
        s_2 = srcData[posxhigh2 + posylow];

        s0_ = srcData[posxlow + posy];
        s00 = srcData[posx + posy];
        s01 = srcData[posxhigh + posy];
        s02 = srcData[posxhigh2 + posy];
       
        s1_ = srcData[posxlow + posyhigh];
        s10 = srcData[posx + posyhigh];
        s11 = srcData[posxhigh + posyhigh];
        s12 = srcData[posxhigh2 + posyhigh];

        s2_ = srcData[posxlow + posyhigh2];
        s20 = srcData[posx + posyhigh2];
        s21 = srcData[posxhigh + posyhigh2];
        s22 = srcData[posxhigh2 + posyhigh2];

        // Interpolate in X
        int offsetX = 4*xfrac;
        int offsetX1 = offsetX + 1;
        int offsetX2 = offsetX + 2;
        int offsetX3 = offsetX + 3;

        long sum_ = (long)tableDataHi[offsetX]*s__;
        sum_ += (long)tableDataHi[offsetX1]*s_0;
        sum_ += (long)tableDataHi[offsetX2]*s_1;
        sum_ += (long)tableDataHi[offsetX3]*s_2;
       
        long sum0 = (long)tableDataHi[offsetX]*s0_;
        sum0 += (long)tableDataHi[offsetX1]*s00;
        sum0 += (long)tableDataHi[offsetX2]*s01;
        sum0 += (long)tableDataHi[offsetX3]*s02;
       
        long sum1 = (long)tableDataHi[offsetX]*s1_;
        sum1 += (long)tableDataHi[offsetX1]*s10;
        sum1 += (long)tableDataHi[offsetX2]*s11;
        sum1 += (long)tableDataHi[offsetX3]*s12;
       
        long sum2 = (long)tableDataHi[offsetX]*s2_;
        sum2 += (long)tableDataHi[offsetX1]*s20;
        sum2 += (long)tableDataHi[offsetX2]*s21;
        sum2 += (long)tableDataHi[offsetX3]*s22;
       
        // Intermediate rounding
        sum_ = (sum_ + round) >> precisionBits;
        sum0 = (sum0 + round) >> precisionBits;
        sum1 = (sum1 + round) >> precisionBits;
        sum2 = (sum2 + round) >> precisionBits;
       
        // Interpolate in Y
        int offsetY = 4*yfrac;
        long sum = (long)tableDataVi[offsetY]*sum_;
        sum += (long)tableDataVi[offsetY + 1]*sum0;
        sum += (long)tableDataVi[offsetY + 2]*sum1;
        sum += (long)tableDataVi[offsetY + 3]*sum2;
       
        s = (int)((sum + round) >> precisionBits);
     
        // clamp the value to short range
        if (s > Short.MAX_VALUE) {
      s = Short.MAX_VALUE;
        } else if (s < Short.MIN_VALUE) {
      s = Short.MIN_VALUE;
        }
       
        dstData[dstPixelOffset] = (short)s;
                    dstPixelOffset += dstPixelStride;
    }
                dstScanlineOffset += dstScanlineStride;
            }
        }
    }

    private void ushortLoop(RasterAccessor src, Rectangle destRect,
          RasterAccessor dst, int xpos[], int ypos[],
          int xfracvalues[], int yfracvalues[]) {

        int srcPixelStride = src.getPixelStride();
  int srcScanlineStride = src.getScanlineStride();

  int dwidth = destRect.width;
  int dheight = destRect.height;
        int dnumBands = dst.getNumBands();
        short dstDataArrays[][] = dst.getShortDataArrays();
        int dstBandOffsets[] = dst.getBandOffsets();
        int dstPixelStride = dst.getPixelStride();
        int dstScanlineStride = dst.getScanlineStride();
 
        short srcDataArrays[][] = src.getShortDataArrays();
  int bandOffsets[] = src.getBandOffsets();
 
  int dstOffset = 0;
 
  int posy, posylow, posyhigh, posyhigh2;
  int posx, posxlow, posxhigh, posxhigh2;
  int xfrac, yfrac;
  int s__, s_0, s_1, s_2;
  int s0_, s00, s01, s02;
  int s1_, s10, s11, s12;
  int s2_, s20, s21, s22;
  int s;
 
  // Putting band loop outside
  for (int k = 0; k < dnumBands; k++)  {
            short dstData[] = dstDataArrays[k];
            short srcData[] = srcDataArrays[k];
      int dstScanlineOffset = dstBandOffsets[k];
      int bandOffset = bandOffsets[k];
     
      for (int j = 0; j < dheight; j++) {
                int dstPixelOffset = dstScanlineOffset;
    yfrac = yfracvalues[j];
    posy = ypos[j] + bandOffset;
    posylow = posy - srcScanlineStride;
    posyhigh = posy + srcScanlineStride;
    posyhigh2 = posyhigh + srcScanlineStride;
    for (int i = 0; i < dwidth; i++) {
        xfrac = xfracvalues[i];
        posx = xpos[i];
        posxlow = posx - srcPixelStride;
        posxhigh = posx + srcPixelStride;
        posxhigh2 = posxhigh + srcPixelStride;
       
        // Get the sixteen surrounding pixel values
        s__ = srcData[posxlow + posylow] & 0xffff;
        s_0 = srcData[posx + posylow] & 0xffff;
        s_1 = srcData[posxhigh + posylow] & 0xffff;
        s_2 = srcData[posxhigh2 + posylow] & 0xffff;

        s0_ = srcData[posxlow + posy] & 0xffff;
        s00 = srcData[posx + posy] & 0xffff;
        s01 = srcData[posxhigh + posy] & 0xffff;
        s02 = srcData[posxhigh2 + posy] & 0xffff;
       
        s1_ = srcData[posxlow + posyhigh] & 0xffff;
        s10 = srcData[posx + posyhigh] & 0xffff;
        s11 = srcData[posxhigh + posyhigh] & 0xffff;
        s12 = srcData[posxhigh2 + posyhigh] & 0xffff;

        s2_ = srcData[posxlow + posyhigh2] & 0xffff;
        s20 = srcData[posx + posyhigh2] & 0xffff;
        s21 = srcData[posxhigh + posyhigh2] & 0xffff;
        s22 = srcData[posxhigh2 + posyhigh2] & 0xffff;

        // Interpolate in X
        int offsetX = 4*xfrac;
        int offsetX1 = offsetX + 1;
        int offsetX2 = offsetX + 2;
        int offsetX3 = offsetX + 3;

        long sum_ = (long)tableDataHi[offsetX]*s__;
        sum_ += (long)tableDataHi[offsetX1]*s_0;
        sum_ += (long)tableDataHi[offsetX2]*s_1;
        sum_ += (long)tableDataHi[offsetX3]*s_2;
       
        long sum0 = (long)tableDataHi[offsetX]*s0_;
        sum0 += (long)tableDataHi[offsetX1]*s00;
        sum0 += (long)tableDataHi[offsetX2]*s01;
        sum0 += (long)tableDataHi[offsetX3]*s02;
       
        long sum1 = (long)tableDataHi[offsetX]*s1_;
        sum1 += (long)tableDataHi[offsetX1]*s10;
        sum1 += (long)tableDataHi[offsetX2]*s11;
        sum1 += (long)tableDataHi[offsetX3]*s12;
       
        long sum2 = (long)tableDataHi[offsetX]*s2_;
        sum2 += (long)tableDataHi[offsetX1]*s20;
        sum2 += (long)tableDataHi[offsetX2]*s21;
        sum2 += (long)tableDataHi[offsetX3]*s22;
       
        // Intermediate rounding
        sum_ = (sum_ + round) >> precisionBits;
        sum0 = (sum0 + round) >> precisionBits;
        sum1 = (sum1 + round) >> precisionBits;
        sum2 = (sum2 + round) >> precisionBits;
       
        // Interpolate in Y
        int offsetY = 4*yfrac;
        long sum = (long)tableDataVi[offsetY]*sum_;
        sum += (long)tableDataVi[offsetY + 1]*sum0;
        sum += (long)tableDataVi[offsetY + 2]*sum1;
        sum += (long)tableDataVi[offsetY + 3]*sum2;
       
        s = (int)((sum + round) >> precisionBits);
     
        // clamp the value to ushort range
        if (s > 65536) {
      s = 65536;
        } else if (s < 0) {
      s = 0;
        }
       
        dstData[dstPixelOffset] = (short)(s & 0xffff);
                    dstPixelOffset += dstPixelStride;
    }
                dstScanlineOffset += dstScanlineStride;
            }
        }
    }
   
    // identical to byteLoops, except datatypes have changed.  clumsy,
    // but there's no other way in Java
    private void intLoop(RasterAccessor src, Rectangle destRect,
       RasterAccessor dst, int xpos[], int ypos[],
       int xfracvalues[], int yfracvalues[]) {
 
        int srcPixelStride = src.getPixelStride();
  int srcScanlineStride = src.getScanlineStride();

  int dwidth = destRect.width;
  int dheight = destRect.height;
        int dnumBands = dst.getNumBands();
        int dstDataArrays[][] = dst.getIntDataArrays();
        int dstBandOffsets[] = dst.getBandOffsets();
        int dstPixelStride = dst.getPixelStride();
        int dstScanlineStride = dst.getScanlineStride();
 
        int srcDataArrays[][] = src.getIntDataArrays();
  int bandOffsets[] = src.getBandOffsets();
 
  int dstOffset = 0;
 
  int posy, posylow, posyhigh, posyhigh2;
  int posx, posxlow, posxhigh, posxhigh2;
  long xfrac, yfrac;
  int s__, s_0, s_1, s_2;
  int s0_, s00, s01, s02;
  int s1_, s10, s11, s12;
  int s2_, s20, s21, s22;
  int s;

  // Putting band loop outside
  for (int k = 0; k < dnumBands; k++)  {
            int dstData[] = dstDataArrays[k];
            int srcData[] = srcDataArrays[k];
      int dstScanlineOffset = dstBandOffsets[k];
      int bandOffset = bandOffsets[k];
     
      for (int j = 0; j < dheight; j++) {
                int dstPixelOffset = dstScanlineOffset;
    yfrac = yfracvalues[j];
    posy = ypos[j] + bandOffset;
    posylow = posy - srcScanlineStride;
    posyhigh = posy + srcScanlineStride;
    posyhigh2 = posyhigh + srcScanlineStride;
    for (int i = 0; i < dwidth; i++) {
        xfrac = xfracvalues[i];
        posx = xpos[i];
        posxlow = posx - srcPixelStride;
        posxhigh = posx + srcPixelStride;
        posxhigh2 = posxhigh + srcPixelStride;
       
        // Get the sixteen surrounding pixel values
        s__ = srcData[posxlow + posylow];
        s_0 = srcData[posx + posylow];
        s_1 = srcData[posxhigh + posylow];
        s_2 = srcData[posxhigh2 + posylow];

        s0_ = srcData[posxlow + posy];
        s00 = srcData[posx + posy];
        s01 = srcData[posxhigh + posy];
        s02 = srcData[posxhigh2 + posy];
       
        s1_ = srcData[posxlow + posyhigh];
        s10 = srcData[posx + posyhigh];
        s11 = srcData[posxhigh + posyhigh];
        s12 = srcData[posxhigh2 + posyhigh];

        s2_ = srcData[posxlow + posyhigh2];
        s20 = srcData[posx + posyhigh2];
        s21 = srcData[posxhigh + posyhigh2];
        s22 = srcData[posxhigh2 + posyhigh2];

        // Interpolate in X
        int offsetX = (int)(4*xfrac);
        int offsetX1 = offsetX + 1;
        int offsetX2 = offsetX + 2;
        int offsetX3 = offsetX + 3;

        long sum_ = (long)tableDataHi[offsetX]*s__;
        sum_ += (long)tableDataHi[offsetX1]*s_0;
        sum_ += (long)tableDataHi[offsetX2]*s_1;
        sum_ += (long)tableDataHi[offsetX3]*s_2;
       
        long sum0 = (long)tableDataHi[offsetX]*s0_;
        sum0 += (long)tableDataHi[offsetX1]*s00;
        sum0 += (long)tableDataHi[offsetX2]*s01;
        sum0 += (long)tableDataHi[offsetX3]*s02;
       
        long sum1 = (long)tableDataHi[offsetX]*s1_;
        sum1 += (long)tableDataHi[offsetX1]*s10;
        sum1 += (long)tableDataHi[offsetX2]*s11;
        sum1 += (long)tableDataHi[offsetX3]*s12;
       
        long sum2 = (long)tableDataHi[offsetX]*s2_;
        sum2 += (long)tableDataHi[offsetX1]*s20;
        sum2 += (long)tableDataHi[offsetX2]*s21;
        sum2 += (long)tableDataHi[offsetX3]*s22;
       
        // Intermediate rounding
        sum_ = (sum_ + round) >> precisionBits;
        sum0 = (sum0 + round) >> precisionBits;
        sum1 = (sum1 + round) >> precisionBits;
        sum2 = (sum2 + round) >> precisionBits;
       
        // Interpolate in Y
        int offsetY = (int)(4*yfrac);
        long sum = (long)tableDataVi[offsetY]*sum_;
        sum += (long)tableDataVi[offsetY + 1]*sum0;
        sum += (long)tableDataVi[offsetY + 2]*sum1;
        sum += (long)tableDataVi[offsetY + 3]*sum2;
       
        s = (int)((sum + round) >> precisionBits);

        dstData[dstPixelOffset] = s;
                    dstPixelOffset += dstPixelStride;
    }
                dstScanlineOffset += dstScanlineStride;
            }
        }
    }

    private void floatLoop(RasterAccessor src, Rectangle destRect,
         RasterAccessor dst, int xpos[], int ypos[],
         int xfracvalues[], int yfracvalues[]) {

        int srcPixelStride = src.getPixelStride();
  int srcScanlineStride = src.getScanlineStride();

  int dwidth = destRect.width;
  int dheight = destRect.height;
        int dnumBands = dst.getNumBands();
        float dstDataArrays[][] = dst.getFloatDataArrays();
        int dstBandOffsets[] = dst.getBandOffsets();
        int dstPixelStride = dst.getPixelStride();
        int dstScanlineStride = dst.getScanlineStride();
 
        float srcDataArrays[][] = src.getFloatDataArrays();
  int bandOffsets[] = src.getBandOffsets();
 
  int dstOffset = 0;

  int posy, posylow, posyhigh, posyhigh2;
  int posx, posxlow, posxhigh, posxhigh2;
  int xfrac, yfrac;

  float s__, s_0, s_1, s_2;
  float s0_, s00, s01, s02;
  float s1_, s10, s11, s12;
  float s2_, s20, s21, s22;

  // Putting band loop outside
  for (int k = 0; k < dnumBands; k++)  {
            float dstData[] = dstDataArrays[k];
            float srcData[] = srcDataArrays[k];
      int dstScanlineOffset = dstBandOffsets[k];
      int bandOffset = bandOffsets[k];
     
      for (int j = 0; j < dheight; j++) {
                int dstPixelOffset = dstScanlineOffset;
    yfrac = yfracvalues[j];
    posy = ypos[j] + bandOffset;
    posylow = posy - srcScanlineStride;
    posyhigh = posy + srcScanlineStride;
    posyhigh2 = posyhigh + srcScanlineStride;
    for (int i = 0; i < dwidth; i++) {
        xfrac = xfracvalues[i];
        posx = xpos[i];
        posxlow = posx - srcPixelStride;
        posxhigh = posx + srcPixelStride;
        posxhigh2 = posxhigh + srcPixelStride;
       
        // Get the sixteen surrounding pixel values
        s__ = srcData[posxlow + posylow];
        s_0 = srcData[posx + posylow];
        s_1 = srcData[posxhigh + posylow];
        s_2 = srcData[posxhigh2 + posylow];

        s0_ = srcData[posxlow + posy];
        s00 = srcData[posx + posy];
        s01 = srcData[posxhigh + posy];
        s02 = srcData[posxhigh2 + posy];
       
        s1_ = srcData[posxlow + posyhigh];
        s10 = srcData[posx + posyhigh];
        s11 = srcData[posxhigh + posyhigh];
        s12 = srcData[posxhigh2 + posyhigh];

        s2_ = srcData[posxlow + posyhigh2];
        s20 = srcData[posx + posyhigh2];
        s21 = srcData[posxhigh + posyhigh2];
        s22 = srcData[posxhigh2 + posyhigh2];

        // Perform the bicubic interpolation

        // Interpolate in X
        int offsetX = (int)(4 * xfrac);
        int offsetX1 = offsetX + 1;
        int offsetX2 = offsetX + 2;
        int offsetX3 = offsetX + 3;
       
        double sum_ = tableDataHf[offsetX]*s__;
        sum_ += tableDataHf[offsetX1]*s_0;
        sum_ += tableDataHf[offsetX2]*s_1;
        sum_ += tableDataHf[offsetX3]*s_2;
       
        double sum0 = tableDataHf[offsetX]*s0_;
        sum0 += tableDataHf[offsetX1]*s00;
        sum0 += tableDataHf[offsetX2]*s01;
        sum0 += tableDataHf[offsetX3]*s02;
       
        double sum1 = tableDataHf[offsetX]*s1_;
        sum1 += tableDataHf[offsetX1]*s10;
        sum1 += tableDataHf[offsetX2]*s11;
        sum1 += tableDataHf[offsetX3]*s12;
       
        double sum2 = tableDataHf[offsetX]*s2_;
        sum2 += tableDataHf[offsetX1]*s20;
        sum2 += tableDataHf[offsetX2]*s21;
        sum2 += tableDataHf[offsetX3]*s22;
       
        // Interpolate in Y
        int offsetY = (int)(4 * yfrac);

        double sum = tableDataVf[offsetY]*sum_;
        sum += tableDataVf[offsetY + 1]*sum0;
        sum += tableDataVf[offsetY + 2]*sum1;
        sum += tableDataVf[offsetY + 3]*sum2;

        if (sum > Float.MAX_VALUE) {
      sum = Float.MAX_VALUE;
        } else if (sum < -Float.MAX_VALUE) {
      sum = -Float.MAX_VALUE;
        }

        dstData[dstPixelOffset] = (float)sum;
                    dstPixelOffset += dstPixelStride;
    }
                dstScanlineOffset += dstScanlineStride;
            }
        }
    }

    private void doubleLoop(RasterAccessor src, Rectangle destRect,
          RasterAccessor dst, int xpos[], int ypos[],
          int xfracvalues[], int yfracvalues[]) {

        int srcPixelStride = src.getPixelStride();
  int srcScanlineStride = src.getScanlineStride();

  int dwidth = destRect.width;
  int dheight = destRect.height;
        int dnumBands = dst.getNumBands();
        double dstDataArrays[][] = dst.getDoubleDataArrays();
        int dstBandOffsets[] = dst.getBandOffsets();
        int dstPixelStride = dst.getPixelStride();
        int dstScanlineStride = dst.getScanlineStride();
 
        double srcDataArrays[][] = src.getDoubleDataArrays();
  int bandOffsets[] = src.getBandOffsets();
 
  int dstOffset = 0;
  int posy, posylow, posyhigh, posyhigh2;
  int posx, posxlow, posxhigh, posxhigh2;

  double s__, s_0, s_1, s_2;
  double s0_, s00, s01, s02;
  double s1_, s10, s11, s12;
  double s2_, s20, s21, s22;
  double s;
  int xfrac, yfrac;

  // Putting band loop outside
  for (int k = 0; k < dnumBands; k++)  {
            double dstData[] = dstDataArrays[k];
            double srcData[] = srcDataArrays[k];
      int dstScanlineOffset = dstBandOffsets[k];
      int bandOffset = bandOffsets[k];
     
      for (int j = 0; j < dheight; j++) {
                int dstPixelOffset = dstScanlineOffset;
    yfrac = yfracvalues[j];
    posy = ypos[j] + bandOffset;
    posylow = posy - srcScanlineStride;
    posyhigh = posy + srcScanlineStride;
    posyhigh2 = posyhigh + srcScanlineStride;
    for (int i = 0; i < dwidth; i++) {
        xfrac = xfracvalues[i];
        posx = xpos[i];
        posxlow = posx - srcPixelStride;
        posxhigh = posx + srcPixelStride;
        posxhigh2 = posxhigh + srcPixelStride;
       
        // Get the sixteen surrounding pixel values
        s__ = srcData[posxlow + posylow];
        s_0 = srcData[posx + posylow];
        s_1 = srcData[posxhigh + posylow];
        s_2 = srcData[posxhigh2 + posylow];

        s0_ = srcData[posxlow + posy];
        s00 = srcData[posx + posy];
        s01 = srcData[posxhigh + posy];
        s02 = srcData[posxhigh2 + posy];
       
        s1_ = srcData[posxlow + posyhigh];
        s10 = srcData[posx + posyhigh];
        s11 = srcData[posxhigh + posyhigh];
        s12 = srcData[posxhigh2 + posyhigh];

        s2_ = srcData[posxlow + posyhigh2];
        s20 = srcData[posx + posyhigh2];
        s21 = srcData[posxhigh + posyhigh2];
        s22 = srcData[posxhigh2 + posyhigh2];

        // Perform the bicubic interpolation

        // Interpolate in X
        int offsetX = (int)(4 * xfrac);
        int offsetX1 = offsetX + 1;
        int offsetX2 = offsetX + 2;
        int offsetX3 = offsetX + 3;
       
        double sum_ = tableDataHd[offsetX]*s__;
        sum_ += tableDataHd[offsetX1]*s_0;
        sum_ += tableDataHd[offsetX2]*s_1;
        sum_ += tableDataHd[offsetX3]*s_2;
       
        double sum0 = tableDataHd[offsetX]*s0_;
        sum0 += tableDataHd[offsetX1]*s00;
        sum0 += tableDataHd[offsetX2]*s01;
        sum0 += tableDataHd[offsetX3]*s02;
       
        double sum1 = tableDataHd[offsetX]*s1_;
        sum1 += tableDataHd[offsetX1]*s10;
        sum1 += tableDataHd[offsetX2]*s11;
        sum1 += tableDataHd[offsetX3]*s12;
       
        double sum2 = tableDataHd[offsetX]*s2_;
        sum2 += tableDataHd[offsetX1]*s20;
        sum2 += tableDataHd[offsetX2]*s21;
        sum2 += tableDataHd[offsetX3]*s22;
       
        // Interpolate in Y
        int offsetY = (int)(4 * yfrac);
        s = tableDataVd[offsetY]*sum_;
        s += tableDataVd[offsetY + 1]*sum0;
        s += tableDataVd[offsetY + 2]*sum1;
        s += tableDataVd[offsetY + 3]*sum2;

        dstData[dstPixelOffset] = s;
                    dstPixelOffset += dstPixelStride;
    }
                dstScanlineOffset += dstScanlineStride;
            }
        }
    }

    private synchronized void initTableDataI() {
  if (tableDataHi == null || tableDataVi == null) {
      tableDataHi = interpTable.getHorizontalTableData();
      tableDataVi = interpTable.getVerticalTableData();
  }
    }

    private synchronized void initTableDataF() {
  if (tableDataHf == null || tableDataVf == null) {
      tableDataHf = interpTable.getHorizontalTableDataFloat();
      tableDataVf = interpTable.getVerticalTableDataFloat();
  }
    }

    private synchronized void initTableDataD() {
  if (tableDataHd == null || tableDataVd == null) {
      tableDataHd = interpTable.getHorizontalTableDataDouble();
      tableDataVd = interpTable.getVerticalTableDataDouble();
  }
    }

//     public static OpImage createTestImage(OpImageTester oit) {
//         Interpolation interp =
//             Interpolation.getInstance(Interpolation.INTERP_BICUBIC);
//         return new ScaleBicubicOpImage(oit.getSource(), null, null,
//                                        new ImageLayout(oit.getSource()),
//                                        2.5F, 2.5F, 0.0F, 0.0F,
//                                        interp);
//     }
   
//     public static void main(String args[]) {

//   String classname = "com.lightcrafts.media.jai.opimage.ScaleBicubicOpImage";
//   OpImageTester.performDiagnostics(classname,args);
//   System.exit(1);
 
//   System.out.println("ScaleOpImage Test");
//         ImageLayout layout;
//         OpImage src, dst;
//         Rectangle rect = new Rectangle(2, 2, 5, 5);
 
//   InterpolationBicubic interp = new InterpolationBicubic(8);
 
//         System.out.println("1. PixelInterleaved short 3-band");
//         layout = OpImageTester.createImageLayout(0, 0, 200, 200, 0, 0,
//              64, 64, DataBuffer.TYPE_SHORT,
//              3, false);
//         src = OpImageTester.createRandomOpImage(layout);
//         dst = new ScaleBicubicOpImage(src, null, null, null,
//                                       2.0F, 2.0F, 0.0F, 0.0F, interp);
//         OpImageTester.testOpImage(dst, rect);
//         OpImageTester.timeOpImage(dst, 10);
 
//   System.out.println("2. PixelInterleaved ushort 3-band");
//         layout = OpImageTester.createImageLayout(0, 0, 512, 512, 0, 0,
//              200, 200,
//              DataBuffer.TYPE_USHORT,
//              3, false);
//         src = OpImageTester.createRandomOpImage(layout);
//         dst = new ScaleBicubicOpImage(src, null, null, null,
//                                       2.0F, 2.0F, 0.0F, 0.0F, interp);
//         OpImageTester.testOpImage(dst, rect);
//         OpImageTester.timeOpImage(dst, 10);
//     }
}
TOP

Related Classes of com.lightcrafts.media.jai.opimage.ScaleBicubicOpImage

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.