/// <summary> /// Transforms the source <CODE>Raster</CODE> and stores the results in /// the destination <CODE>Raster</CODE>. This operation performs the /// transform band by band. /// <para> /// If the destination <CODE>Raster</CODE> is null, a new /// <CODE>Raster</CODE> is created. /// An <CODE>IllegalArgumentException</CODE> may be thrown if the source is /// the same as the destination or if the number of bands in /// the source is not equal to the number of bands in the /// destination. /// </para> /// <para> /// The coordinates of the rectangle returned by /// <code>getBounds2D(Raster)</code> /// are not necessarily the same as the coordinates of the /// <code>WritableRaster</code> returned by this method. If the /// upper-left corner coordinates of rectangle are negative then /// this part of the rectangle is not drawn. If the coordinates /// of the rectangle are positive then the filtered image is drawn at /// that position in the destination <code>Raster</code>. /// </para> /// <para> /// </para> /// </summary> /// <param name="src"> The <CODE>Raster</CODE> to transform. </param> /// <param name="dst"> The <CODE>Raster</CODE> in which to store the results of the /// transformation. /// </param> /// <returns> The transformed <CODE>Raster</CODE>. /// </returns> /// <exception cref="ImagingOpException"> if the raster cannot be transformed /// because of a data-processing error that might be /// caused by an invalid image format, tile format, or /// image-processing operation, or any other unsupported /// operation. </exception> public WritableRaster Filter(Raster src, WritableRaster dst) { if (src == null) { throw new NullPointerException("src image is null"); } if (dst == null) { dst = CreateCompatibleDestRaster(src); } if (src == dst) { throw new IllegalArgumentException("src image cannot be the " + "same as the dst image"); } if (src.NumBands != dst.NumBands) { throw new IllegalArgumentException("Number of src bands (" + src.NumBands + ") does not match number of " + " dst bands (" + dst.NumBands + ")"); } if (ImagingLib.filter(this, src, dst) == null) { throw new ImagingOpException("Unable to transform src image"); } return(dst); }
/// <summary> /// Rescales the pixel data in the source Raster. /// If the destination Raster is null, a new Raster will be created. /// The source and destination must have the same number of bands. /// Otherwise, an IllegalArgumentException is thrown. /// Note that the number of scaling factors/offsets in this object must /// meet the restrictions stated in the class comments above. /// Otherwise, an IllegalArgumentException is thrown. </summary> /// <param name="src"> the <code>Raster</code> to be filtered </param> /// <param name="dst"> the destination for the filtering operation /// or <code>null</code> </param> /// <returns> the filtered <code>WritableRaster</code>. </returns> /// <exception cref="IllegalArgumentException"> if <code>src</code> and /// <code>dst</code> do not have the same number of bands, /// or if the number of scaling factors and offsets in this /// <code>RescaleOp</code> do not meet the requirements /// stated in the class comments. </exception> public WritableRaster Filter(Raster src, WritableRaster dst) { int numBands = src.NumBands; int width = src.Width; int height = src.Height; int[] srcPix = null; int step = 0; int tidx = 0; // Create a new destination Raster, if needed if (dst == null) { dst = CreateCompatibleDestRaster(src); } else if (height != dst.Height || width != dst.Width) { throw new IllegalArgumentException("Width or height of Rasters do not " + "match"); } else if (numBands != dst.NumBands) { // Make sure that the number of bands are equal throw new IllegalArgumentException("Number of bands in src " + numBands + " does not equal number of bands in dest " + dst.NumBands); } // Make sure that the arrays match // Make sure that the low/high/constant arrays match if (Length != 1 && Length != src.NumBands) { throw new IllegalArgumentException("Number of scaling constants " + "does not equal the number of" + " of bands in the src raster"); } // // Try for a native raster rescale first // if (ImagingLib.filter(this, src, dst) != null) { return(dst); } // // Native raster rescale failed. // Try to see if a lookup operation can be used // if (CanUseLookup(src, dst)) { int srcNgray = (1 << SrcNbits); int dstNgray = (1 << DstNbits); if (dstNgray == 256) { ByteLookupTable lut = CreateByteLut(ScaleFactors, Offsets, numBands, srcNgray); LookupOp op = new LookupOp(lut, Hints); op.Filter(src, dst); } else { ShortLookupTable lut = CreateShortLut(ScaleFactors, Offsets, numBands, srcNgray); LookupOp op = new LookupOp(lut, Hints); op.Filter(src, dst); } } else { // // Fall back to the slow code // if (Length > 1) { step = 1; } int sminX = src.MinX; int sY = src.MinY; int dminX = dst.MinX; int dY = dst.MinY; int sX; int dX; // // Determine bits per band to determine maxval for clamps. // The min is assumed to be zero. // REMIND: This must change if we ever support signed data types. // int nbits; int[] dstMax = new int[numBands]; int[] dstMask = new int[numBands]; SampleModel dstSM = dst.SampleModel; for (int z = 0; z < numBands; z++) { nbits = dstSM.GetSampleSize(z); dstMax[z] = (1 << nbits) - 1; dstMask[z] = ~(dstMax[z]); } int val; for (int y = 0; y < height; y++, sY++, dY++) { dX = dminX; sX = sminX; for (int x = 0; x < width; x++, sX++, dX++) { // Get data for all bands at this x,y position srcPix = src.GetPixel(sX, sY, srcPix); tidx = 0; for (int z = 0; z < numBands; z++, tidx += step) { val = (int)(srcPix[z] * ScaleFactors[tidx] + Offsets[tidx]); // Clamp if ((val & dstMask[z]) != 0) { if (val < 0) { val = 0; } else { val = dstMax[z]; } } srcPix[z] = val; } // Put it back for all bands dst.SetPixel(dX, dY, srcPix); } } } return(dst); }
/// <summary> /// Transforms the source <CODE>BufferedImage</CODE> and stores the results /// in the destination <CODE>BufferedImage</CODE>. /// If the color models for the two images do not match, a color /// conversion into the destination color model is performed. /// If the destination image is null, /// a <CODE>BufferedImage</CODE> is created with the source /// <CODE>ColorModel</CODE>. /// <para> /// The coordinates of the rectangle returned by /// <code>getBounds2D(BufferedImage)</code> /// are not necessarily the same as the coordinates of the /// <code>BufferedImage</code> returned by this method. If the /// upper-left corner coordinates of the rectangle are /// negative then this part of the rectangle is not drawn. If the /// upper-left corner coordinates of the rectangle are positive /// then the filtered image is drawn at that position in the /// destination <code>BufferedImage</code>. /// </para> /// <para> /// An <CODE>IllegalArgumentException</CODE> is thrown if the source is /// the same as the destination. /// /// </para> /// </summary> /// <param name="src"> The <CODE>BufferedImage</CODE> to transform. </param> /// <param name="dst"> The <CODE>BufferedImage</CODE> in which to store the results /// of the transformation. /// </param> /// <returns> The filtered <CODE>BufferedImage</CODE>. </returns> /// <exception cref="IllegalArgumentException"> if <code>src</code> and /// <code>dst</code> are the same </exception> /// <exception cref="ImagingOpException"> if the image cannot be transformed /// because of a data-processing error that might be /// caused by an invalid image format, tile format, or /// image-processing operation, or any other unsupported /// operation. </exception> public BufferedImage Filter(BufferedImage src, BufferedImage dst) { if (src == null) { throw new NullPointerException("src image is null"); } if (src == dst) { throw new IllegalArgumentException("src image cannot be the " + "same as the dst image"); } bool needToConvert = false; ColorModel srcCM = src.ColorModel; ColorModel dstCM; BufferedImage origDst = dst; if (dst == null) { dst = CreateCompatibleDestImage(src, null); dstCM = srcCM; origDst = dst; } else { dstCM = dst.ColorModel; if (srcCM.ColorSpace.Type != dstCM.ColorSpace.Type) { int type = Xform.Type; bool needTrans = ((type & (Xform.TYPE_MASK_ROTATION | Xform.TYPE_GENERAL_TRANSFORM)) != 0); if (!needTrans && type != Xform.TYPE_TRANSLATION && type != Xform.TYPE_IDENTITY) { double[] mtx = new double[4]; Xform.GetMatrix(mtx); // Check out the matrix. A non-integral scale will force ARGB // since the edge conditions can't be guaranteed. needTrans = (mtx[0] != (int)mtx[0] || mtx[3] != (int)mtx[3]); } if (needTrans && srcCM.Transparency == java.awt.Transparency_Fields.OPAQUE) { // Need to convert first ColorConvertOp ccop = new ColorConvertOp(Hints); BufferedImage tmpSrc = null; int sw = src.Width; int sh = src.Height; if (dstCM.Transparency == java.awt.Transparency_Fields.OPAQUE) { tmpSrc = new BufferedImage(sw, sh, BufferedImage.TYPE_INT_ARGB); } else { WritableRaster r = dstCM.CreateCompatibleWritableRaster(sw, sh); tmpSrc = new BufferedImage(dstCM, r, dstCM.AlphaPremultiplied, null); } src = ccop.Filter(src, tmpSrc); } else { needToConvert = true; dst = CreateCompatibleDestImage(src, null); } } } if (InterpolationType_Renamed != TYPE_NEAREST_NEIGHBOR && dst.ColorModel is IndexColorModel) { dst = new BufferedImage(dst.Width, dst.Height, BufferedImage.TYPE_INT_ARGB); } if (ImagingLib.filter(this, src, dst) == null) { throw new ImagingOpException("Unable to transform src image"); } if (needToConvert) { ColorConvertOp ccop = new ColorConvertOp(Hints); ccop.Filter(dst, origDst); } else if (origDst != dst) { java.awt.Graphics2D g = origDst.CreateGraphics(); try { g.Composite = AlphaComposite.Src; g.DrawImage(dst, 0, 0, null); } finally { g.Dispose(); } } return(origDst); }
/// <summary> /// Rescales the source BufferedImage. /// If the color model in the source image is not the same as that /// in the destination image, the pixels will be converted /// in the destination. If the destination image is null, /// a BufferedImage will be created with the source ColorModel. /// An IllegalArgumentException may be thrown if the number of /// scaling factors/offsets in this object does not meet the /// restrictions stated in the class comments above, or if the /// source image has an IndexColorModel. </summary> /// <param name="src"> the <code>BufferedImage</code> to be filtered </param> /// <param name="dst"> the destination for the filtering operation /// or <code>null</code> </param> /// <returns> the filtered <code>BufferedImage</code>. </returns> /// <exception cref="IllegalArgumentException"> if the <code>ColorModel</code> /// of <code>src</code> is an <code>IndexColorModel</code>, /// or if the number of scaling factors and offsets in this /// <code>RescaleOp</code> do not meet the requirements /// stated in the class comments. </exception> public BufferedImage Filter(BufferedImage src, BufferedImage dst) { ColorModel srcCM = src.ColorModel; ColorModel dstCM; int numBands = srcCM.NumColorComponents; if (srcCM is IndexColorModel) { throw new IllegalArgumentException("Rescaling cannot be " + "performed on an indexed image"); } if (Length != 1 && Length != numBands && Length != srcCM.NumComponents) { throw new IllegalArgumentException("Number of scaling constants " + "does not equal the number of" + " of color or color/alpha " + " components"); } bool needToConvert = false; // Include alpha if (Length > numBands && srcCM.HasAlpha()) { Length = numBands + 1; } int width = src.Width; int height = src.Height; if (dst == null) { dst = CreateCompatibleDestImage(src, null); dstCM = srcCM; } else { if (width != dst.Width) { throw new IllegalArgumentException("Src width (" + width + ") not equal to dst width (" + dst.Width + ")"); } if (height != dst.Height) { throw new IllegalArgumentException("Src height (" + height + ") not equal to dst height (" + dst.Height + ")"); } dstCM = dst.ColorModel; if (srcCM.ColorSpace.Type != dstCM.ColorSpace.Type) { needToConvert = true; dst = CreateCompatibleDestImage(src, null); } } BufferedImage origDst = dst; // // Try to use a native BI rescale operation first // if (ImagingLib.filter(this, src, dst) == null) { // // Native BI rescale failed - convert to rasters // WritableRaster srcRaster = src.Raster; WritableRaster dstRaster = dst.Raster; if (srcCM.HasAlpha()) { if (numBands - 1 == Length || Length == 1) { int minx = srcRaster.MinX; int miny = srcRaster.MinY; int[] bands = new int[numBands - 1]; for (int i = 0; i < numBands - 1; i++) { bands[i] = i; } srcRaster = srcRaster.CreateWritableChild(minx, miny, srcRaster.Width, srcRaster.Height, minx, miny, bands); } } if (dstCM.HasAlpha()) { int dstNumBands = dstRaster.NumBands; if (dstNumBands - 1 == Length || Length == 1) { int minx = dstRaster.MinX; int miny = dstRaster.MinY; int[] bands = new int[numBands - 1]; for (int i = 0; i < numBands - 1; i++) { bands[i] = i; } dstRaster = dstRaster.CreateWritableChild(minx, miny, dstRaster.Width, dstRaster.Height, minx, miny, bands); } } // // Call the raster filter method // Filter(srcRaster, dstRaster); } if (needToConvert) { // ColorModels are not the same ColorConvertOp ccop = new ColorConvertOp(Hints); ccop.Filter(dst, origDst); } return(origDst); }