Package com.lightcrafts.media.jai.opimage

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

/*
* $RCSfile: ScaleBilinearBinaryOpImage.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.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferUShort;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import com.lightcrafts.mediax.jai.Interpolation;
import com.lightcrafts.mediax.jai.ImageLayout;
import com.lightcrafts.mediax.jai.ScaleOpImage;
import com.lightcrafts.mediax.jai.BorderExtender;
import com.lightcrafts.media.jai.util.Rational;
import java.util.Map;

/**
* An OpImage subclass that performs bilinear scaling
* for binary images with a MultiPixelPackedSampleModel
* and byte, short, or int DataBuffers.
*
*/

final public class ScaleBilinearBinaryOpImage extends ScaleOpImage
{

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

  /* Subsampling related variables */
  int one, shift2, round2;

  long invScaleXInt, invScaleXFrac;
  long invScaleYInt, invScaleYFrac;
 
  /**
   * Constructs a ScaleBilinearBinaryOpImage from a RenderedImage source,
   *
   * @param source a RenderedImage.
   * @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 an Interpolation object to use for resampling.
   */
 
  public ScaleBilinearBinaryOpImage(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 ();

    // Numnber of subsampling positions
    one = 1 << subsampleBits;

    //Subsampling related variables
    shift2 = 2 * subsampleBits;
    round2 = 1 << (shift2 - 1);

    // Propagate source's ColorModel
    if (layout != null)
    {
      colorModel = layout.getColorModel(source);
    }
    else
    {
      colorModel = source.getColorModel();
    }
   
    sampleModel = source.getSampleModel().createCompatibleSampleModel(tileWidth, tileHeight);
   
    if (invScaleXRational.num > invScaleXRational.denom)
    {
      invScaleXInt = invScaleXRational.num / invScaleXRational.denom;
      invScaleXFrac = invScaleXRational.num % invScaleXRational.denom;
    }
    else
    {
      invScaleXInt = 0;
      invScaleXFrac = invScaleXRational.num;
    }

    if (invScaleYRational.num > invScaleYRational.denom)
    {
      invScaleYInt = invScaleYRational.num / invScaleYRational.denom;
      invScaleYFrac = invScaleYRational.num % invScaleYRational.denom;
    }
    else
    {
      invScaleYInt = 0;
      invScaleYFrac = invScaleYRational.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)
  {
    Raster source = sources[0];

    // Get the source rectangle
    Rectangle srcRect = source.getBounds();

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

    // Destination rectangle dimensions.
    int dx = destRect.x;
    int dy = destRect.y;

    int dwidth = destRect.width;
    int dheight = destRect.height;
   
    // Precalculate the x positions and store them in an array.
    int[] xvalues = new int[dwidth];
    int[] yvalues = new int[dheight];

    int[] xfracvalues = new int[dwidth];
    int[] yfracvalues = new int[dheight];


    long sxNum = dx, sxDenom = 1;
    long syNum = dy, syDenom = 1;

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

    syNum = syNum*transYRationalDenom - transYRationalNum*syDenom;
    syDenom *= transYRationalDenom;
   
    // Add 0.5
    sxNum = 2*sxNum + sxDenom;
    sxDenom *= 2;

    syNum = 2*syNum + syDenom;
    syDenom *= 2;
   
    // Multply by invScaleX & Y

    sxNum *= invScaleXRationalNum;
    sxDenom *= invScaleXRationalDenom;

    syNum *= invScaleYRationalNum;
    syDenom *= invScaleYRationalDenom;


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

    syNum = 2*syNum - syDenom;
    syDenom *= 2;


    // Separate the x source coordinate into integer and fractional part

    int srcXInt = Rational.floor(sxNum , sxDenom);
    long srcXFrac = sxNum % sxDenom;
    if (srcXInt < 0)
    {
      srcXFrac = sxDenom + srcXFrac;
    }
   
    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 invScaleX
    long commonXDenom = sxDenom*invScaleXRationalDenom;
    srcXFrac *= invScaleXRationalDenom;
    long newInvScaleXFrac = invScaleXFrac*sxDenom;

    long commonYDenom = syDenom * invScaleYRationalDenom;
    srcYFrac *= invScaleYRationalDenom;
    long newInvScaleYFrac = invScaleYFrac * syDenom;

    for (int i = 0; i < dwidth; i++)
    {
      // Calculate the position
      // xfracvalues is the fractional part of x position in terms
      // of the nuber of subpixel points

      xvalues[i] = srcXInt;

      // added by jxz; for the case frac is less then 1/2,
      // the previous location is used
      // e.g. 24.25 is between the two half points 23.5 and 24.5
      // thus 23rd and 24th are the pixel rows
      // XXX watch for side effects associated with sfracvalues

      //if(2 * srcXFrac < commonXDenom && xvalues[i] > 0){
      //--xvalues[i];
      //}

      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;
      }
    }

    // Precalculate the y positions and store them in an array.

    for (int i = 0; i < dheight; i++)
    {
      // Calculate the position
      yvalues[i] = srcYInt;
      yfracvalues[i] = (int) ( ( ( float) srcYFrac / (float) commonYDenom) * one );

      // added by jxz; for the case frac is less then 1/2,
      // the previous location is used
      // e.g. 24.25 is between the two half points 23.5 and 24.5
      // thus 23rd and 24th are the pixel rows
      // XXX watch for side effects associated with yfracvalues

      // if(2 * srcYFrac < commonYDenom && yvalues[i] > 0){
      //      --yvalues[i];
      // }


      // 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 (source.getSampleModel().getDataType())
    {
    case DataBuffer.TYPE_BYTE:
      byteLoop(source, dest, dx, dy, dwidth, dheight,
               xvalues, yvalues, xfracvalues, yfracvalues);
      break;
     
    case DataBuffer.TYPE_SHORT:
    case DataBuffer.TYPE_USHORT:
      shortLoop(source, dest, dx, dy, dwidth, dheight,
                xvalues, yvalues, xfracvalues, yfracvalues);
      break;

    case DataBuffer.TYPE_INT:
      intLoop(source, dest, dx, dy, dwidth, dheight,
              xvalues, yvalues, xfracvalues, yfracvalues);
      break;
     
    default:
      throw new
  RuntimeException(JaiI18N.getString("OrderedDitherOpImage0"));
    }
  }

  private void byteLoop(Raster source, WritableRaster dest,
                        int dx, int dy, int dwidth, int dheight,
                        int[] xvalues, int[] yvalues,
                        int[] xfracvalues, int[] yfracvalues) {
    MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel)source.getSampleModel();
    DataBufferByte sourceDB = (DataBufferByte)source.getDataBuffer();
    int sourceTransX = source.getSampleModelTranslateX();
    int sourceTransY = source.getSampleModelTranslateY();
    int sourceDataBitOffset = sourceSM.getDataBitOffset();
    int sourceScanlineStride = sourceSM.getScanlineStride();
   
    MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel)dest.getSampleModel();
    DataBufferByte destDB = (DataBufferByte)dest.getDataBuffer();
    int destMinX = dest.getMinX();
    int destMinY = dest.getMinY();
    int destTransX = dest.getSampleModelTranslateX();
    int destTransY = dest.getSampleModelTranslateY();
    int destDataBitOffset = destSM.getDataBitOffset();
    int destScanlineStride = destSM.getScanlineStride();
   
    byte[] sourceData = sourceDB.getData();
    int sourceDBOffset = sourceDB.getOffset();
   
    byte[] destData = destDB.getData();
    int destDBOffset = destDB.getOffset();
   
    int[] sbytenum = new int[dwidth];
    int[] sshift = new int[dwidth];
  

    // Since the source data is MultiPixel packed
    // precalculate the byte no and the and the shift
    // after masking required to extract a single pixel
    // sample from a byte

    for (int i = 0; i < dwidth; i++)
    {
      int x = xvalues[i];
      int sbitnum = sourceDataBitOffset + (x - sourceTransX);
      sbytenum[i] = sbitnum >> 3;
      sshift[i] = 7 - (sbitnum & 7);
    }
     

    int sourceYOffset;
     
    int s00, s01, s10, s11, s0, s1, s;
    int x =0, y = 0;
    int yfrac, xfrac;
   
    int xNextBitNo;
    int xNextByteNo;
    int xNextShiftNo;

    int destYOffset = (dy - destTransY) * destScanlineStride + destDBOffset;
    int dbitnum = destDataBitOffset + (dx - destTransX);

    int destByteNum;
    int destBitShift;

 
    int i = 0, j = 0;

    // Loop through height of image
    for ( j = 0; j < dheight; j++)
    {

      y = yvalues[j];
      yfrac = yfracvalues[j];
     
      sourceYOffset = (y - sourceTransY) * sourceScanlineStride + sourceDBOffset;
      dbitnum = destDataBitOffset + ( dx - destTransX );


      // loop through one scan line
      for ( i = 0; i < dwidth; i ++ )
      {
  xfrac = xfracvalues[i];
  x = xvalues[i];
  xNextBitNo = sourceDataBitOffset + (x + 1 - sourceTransX);
  xNextByteNo = xNextBitNo >> 3;
  xNextShiftNo = 7 - ( xNextBitNo & 7);

  /* Four surrounding pixels are needed for Bilinear interpolation.
   * If the dest pixel to be calculated is at (dx, dy) then the
   * actual source pixel (sx, sy) required is (dx/scaleX, dy/scaleY).
   * The four pixels that surround it are at the positions:
   * s00 = src(sxlow, sylow)
   * s01 = src(sxhigh, sylow)
   * s10 = src(sxlow, syhigh)
   * s11 = src(sxhigh, syhigh)
   * where sxlow = Math.floor(sx), sxhigh = Math.ceil(sx)
   * and   sylow = Math.floor(sy), syhigh = Math.ceil(sy)
   *
   * The value of the destination pixel can now be calculated as:
   * s0 = (s01 - s00)*xfrac + s00;
   * s1 = (s11 - s10)*xfrac + s10;
   * dst(x,y) = (s1 - s0)*yfrac + s0;
   */


  //Obtain sample values for 4 adjacent pixels in the source
  s00 = (sourceData[sourceYOffset + sbytenum[i]] >> sshift[i]) & 0x01;
  s01 = (sourceData[sourceYOffset + xNextByteNo] >> xNextShiftNo ) & 0x01;
  s10 = (sourceData[sourceYOffset + sourceScanlineStride + sbytenum[i]] >> sshift[i]) & 0x01;
  s11 = (sourceData[sourceYOffset + sourceScanlineStride + xNextByteNo] >> xNextShiftNo ) & 0x01;

  // perform the bilinear interpolation
  s0 = ( s01 - s00 ) * xfrac + (s00 << subsampleBits);
  s1 = ( s11 - s10 ) * xfrac + (s10 << subsampleBits);

  // The bilinear intrerpolated value
  s = ( ( s1 - s0  ) * yfrac + ( (s0 << subsampleBits) + round2) ) >> shift2;


  destByteNum = dbitnum >> 3;
  destBitShift = 7 - (dbitnum & 7);

  if ( s == 1 )
  {
    //the destBit must be set
    destData[destYOffset + destByteNum] |= ( 0x01 << destBitShift );
  }
  else
  {
    //the destBit must be cleared
    destData[destYOffset + destByteNum] &= ( 0xff - ( 0x01 << destBitShift ) );
  }
  dbitnum ++;   
      }
      destYOffset += destScanlineStride;
    }
  }
 
 
  private void shortLoop(Raster source, WritableRaster dest,
                        int dx, int dy, int dwidth, int dheight,
                        int[] xvalues, int[] yvalues,
                        int[] xfracvalues, int[] yfracvalues)
  {
    MultiPixelPackedSampleModel sourceSM =  (MultiPixelPackedSampleModel)source.getSampleModel();
    int sourceTransX = source.getSampleModelTranslateX();
    int sourceTransY = source.getSampleModelTranslateY();
    int sourceDataBitOffset = sourceSM.getDataBitOffset();
    int sourceScanlineStride = sourceSM.getScanlineStride();
   
    MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest.getSampleModel();
    int destMinX = dest.getMinX();
    int destMinY = dest.getMinY();
    int destTransX = dest.getSampleModelTranslateX();
    int destTransY = dest.getSampleModelTranslateY();
    int destDataBitOffset = destSM.getDataBitOffset();
    int destScanlineStride = destSM.getScanlineStride();
   
    DataBufferUShort sourceDB = (DataBufferUShort) source.getDataBuffer();
    short[] sourceData = sourceDB.getData();
    int sourceDBOffset = sourceDB.getOffset();
   
    DataBufferUShort destDB = (DataBufferUShort) dest.getDataBuffer();
    short[] destData = destDB.getData();
    int destDBOffset = destDB.getOffset();
   
    int[] sshortnum = new int[dwidth];
    int[] sshift = new int[dwidth];
   
    for (int i = 0; i < dwidth; i++)
    {
      int x = xvalues[i];
      int sbitnum = sourceDataBitOffset + (x - sourceTransX);
      sshortnum[i] = sbitnum >> 4;
      sshift[i] = 15 - (sbitnum & 15);
    }
   
    int sourceYOffset;

    int s00, s01, s10, s11, s0, s1, s;

    int x, y;
    int yfrac, xfrac;
   
    int xNextBitNo;
    int xNextShortNo;
    int xNextShiftNo;

    int destYOffset = (dy - destTransY) * destScanlineStride + destDBOffset;
    int dbitnum = destDataBitOffset + (dx - destTransX);

    int destShortNum;
    int destBitShift;
   
    for (int j = 0; j < dheight; j++)
    {
      y = yvalues[j];
      yfrac = yfracvalues[j];

      sourceYOffset = (y - sourceTransY)*sourceScanlineStride + sourceDBOffset;
      dbitnum = destDataBitOffset + (dx - destTransX);

      for ( int i = 0; i < dwidth; i++)
      {
  xfrac = xfracvalues[i];
  x = xvalues[i];
  xNextBitNo = sourceDataBitOffset + (x + 1 - sourceTransX);
  xNextShortNo = xNextBitNo >> 4;
  xNextShiftNo = 15 - (xNextBitNo & 15);

  s00 = (sourceData[sourceYOffset + sshortnum[i]] >> sshift[i]) & 0x01;
  s01 = (sourceData[sourceYOffset + xNextShortNo] >> xNextShiftNo ) & 0x01;
  s10 = (sourceData[sourceYOffset + sourceScanlineStride + sshortnum[i]] >> sshift[i]) & 0x01;
  s11 = (sourceData[sourceYOffset + sourceScanlineStride + xNextShortNo] >> xNextShiftNo ) & 0x01;

  s0 = ( s01 - s00 ) * xfrac + (s00 << subsampleBits);
  s1 = ( s11 - s10 ) * xfrac + (s10 << subsampleBits);
  s = ( ( s1 - s0  ) * yfrac + (s0 << subsampleBits) + round2 ) >> shift2;

  destShortNum = dbitnum >> 4;
  destBitShift = 15 - (dbitnum & 15);
 
  if ( s == 1)
  {
    destData [destYOffset + destShortNum] |= ( 0x01 << destBitShift );
  }
  else
  {
    destData [destYOffset + destShortNum] &= ( 0xffff - ( 0x01 << destBitShift ) );
  }
  dbitnum ++;
      }
      destYOffset += destScanlineStride;
    }
  }
 
  private void intLoop(Raster source, WritableRaster dest,
                        int dx, int dy, int dwidth, int dheight,
                        int[] xvalues, int[] yvalues,
                        int[] xfracvalues, int[] yfracvalues)
  {
    MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel)source.getSampleModel();
    DataBufferInt sourceDB = (DataBufferInt)source.getDataBuffer();
    int sourceTransX = source.getSampleModelTranslateX();
    int sourceTransY = source.getSampleModelTranslateY();
    int sourceDataBitOffset = sourceSM.getDataBitOffset();
    int sourceScanlineStride = sourceSM.getScanlineStride();
   
    MultiPixelPackedSampleModel destSM =  (MultiPixelPackedSampleModel)dest.getSampleModel();
    DataBufferInt destDB = (DataBufferInt)dest.getDataBuffer();
    int destMinX = dest.getMinX();
    int destMinY = dest.getMinY();
    int destTransX = dest.getSampleModelTranslateX();
    int destTransY = dest.getSampleModelTranslateY();
    int destDataBitOffset = destSM.getDataBitOffset();
    int destScanlineStride = destSM.getScanlineStride();
   
    int[] sourceData = sourceDB.getData();
    int sourceDBOffset = sourceDB.getOffset();
   
    int[] destData = destDB.getData();
    int destDBOffset = destDB.getOffset();
   
    int[] sintnum = new int[dwidth];
    int[] sshift = new int[dwidth];
   
    for (int i = 0; i < dwidth; i++)
    {
      int x = xvalues[i];
      int sbitnum = sourceDataBitOffset + (x - sourceTransX);
      sintnum[i] = sbitnum >> 5;
      sshift[i] = 31 - (sbitnum & 31);
    }
   
    int sourceYOffset;
     
    int s00, s01, s10, s11, s0, s1, s;
    int x, y;
    int yfrac, xfrac;
   
    int xNextBitNo;
    int xNextIntNo;
    int xNextShiftNo;

    int destYOffset = (dy - destTransY) * destScanlineStride + destDBOffset;
    int dbitnum = destDataBitOffset + (dx - destTransX);

    int destIntNum;
    int destBitShift;
   
    for (int j = 0; j < dheight; j++)
    {
      y = yvalues[j];
      yfrac = yfracvalues[j];

      sourceYOffset = (y - sourceTransY)*sourceScanlineStride + sourceDBOffset;
      dbitnum = destDataBitOffset + ( dx - destTransX );

      for ( int i = 0; i < dwidth; i ++)
      {
  xfrac = xfracvalues[i];
  x = xvalues[i];
 
  xNextBitNo = sourceDataBitOffset + (x + 1 - sourceTransX);
  xNextIntNo = xNextBitNo >> 5;
  xNextShiftNo = 31 - ( xNextBitNo & 31 );

  s00 = (sourceData[sourceYOffset + sintnum[i]] >> sshift[i]) & 0x01;
  s01 = (sourceData[sourceYOffset + xNextIntNo] >> xNextShiftNo ) & 0x01;
  s10 = (sourceData[sourceYOffset + sourceScanlineStride + sintnum[i]] >> sshift[i]) & 0x01;
  s11 = (sourceData[sourceYOffset + sourceScanlineStride + xNextIntNo] >> xNextShiftNo ) & 0x01;

  s0 = ( s01 - s00 ) * xfrac + (s00 << subsampleBits);
  s1 = ( s11 - s10 ) * xfrac + (s10 << subsampleBits);
  s = ( ( s1 - s0  ) * yfrac + (s0 << subsampleBits) + round2 ) >> shift2;

  destIntNum = dbitnum >> 5;
  destBitShift = 31 - ( dbitnum & 31 );

  if ( s == 1 )
  {
    //Is above the threshold, the destBit must be set
    destData [destYOffset + destIntNum] |= ( 0x01 << destBitShift );
  }
  else
  {
    destData [destYOffset + destIntNum] &= ( 0xff - ( 0x01 << destBitShift ) );
  }
  dbitnum ++;   
      }
      destYOffset += destScanlineStride;
    }

  }
}
TOP

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

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.