/// <summary> /// Performs a convolution on Rasters. Each band of the source Raster /// will be convolved. /// The source and destination must have the same number of bands. /// If the destination Raster is null, a new Raster will be created. /// The IllegalArgumentException may be thrown if the source is /// the same as the destination. </summary> /// <param name="src"> the source <code>Raster</code> to filter </param> /// <param name="dst"> the destination <code>WritableRaster</code> for the /// filtered <code>src</code> </param> /// <returns> the filtered <code>WritableRaster</code> </returns> /// <exception cref="NullPointerException"> if <code>src</code> is <code>null</code> </exception> /// <exception cref="ImagingOpException"> if <code>src</code> and <code>dst</code> /// do not have the same number of bands </exception> /// <exception cref="ImagingOpException"> if <code>src</code> cannot be filtered </exception> /// <exception cref="IllegalArgumentException"> if <code>src</code> equals /// <code>dst</code> </exception> public WritableRaster Filter(Raster src, WritableRaster dst) { if (dst == null) { dst = CreateCompatibleDestRaster(src); } else if (src == dst) { throw new IllegalArgumentException("src image cannot be the " + "same as the dst image"); } else if (src.NumBands != dst.NumBands) { throw new ImagingOpException("Different number of bands in src " + " and dst Rasters"); } if (ImagingLib.filter(this, src, dst) == null) { throw new ImagingOpException("Unable to convolve src image"); } return(dst); }
/// <summary> /// Performs a convolution on BufferedImages. Each component of the /// source image will be convolved (including the alpha component, if /// present). /// 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. /// The IllegalArgumentException may be thrown if the source is the /// same as the destination. </summary> /// <param name="src"> the source <code>BufferedImage</code> to filter </param> /// <param name="dst"> the destination <code>BufferedImage</code> for the /// filtered <code>src</code> </param> /// <returns> the filtered <code>BufferedImage</code> </returns> /// <exception cref="NullPointerException"> if <code>src</code> is <code>null</code> </exception> /// <exception cref="IllegalArgumentException"> if <code>src</code> equals /// <code>dst</code> </exception> /// <exception cref="ImagingOpException"> if <code>src</code> cannot be filtered </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; // Can't convolve an IndexColorModel. Need to expand it if (srcCM is IndexColorModel) { IndexColorModel icm = (IndexColorModel)srcCM; src = icm.ConvertToIntDiscrete(src.Raster, false); srcCM = src.ColorModel; } if (dst == null) { dst = CreateCompatibleDestImage(src, null); dstCM = srcCM; origDst = dst; } else { dstCM = dst.ColorModel; if (srcCM.ColorSpace.Type != dstCM.ColorSpace.Type) { needToConvert = true; dst = CreateCompatibleDestImage(src, null); dstCM = dst.ColorModel; } else if (dstCM is IndexColorModel) { dst = CreateCompatibleDestImage(src, null); dstCM = dst.ColorModel; } } if (ImagingLib.filter(this, src, dst) == null) { throw new ImagingOpException("Unable to convolve 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.DrawImage(dst, 0, 0, null); } finally { g.Dispose(); } } return(origDst); }
/// <summary> /// Performs a lookup operation on a <code>BufferedImage</code>. /// 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 <code>null</code>, /// a <code>BufferedImage</code> will be created with an appropriate /// <code>ColorModel</code>. An <code>IllegalArgumentException</code> /// might be thrown if the number of arrays in the /// <code>LookupTable</code> does not meet the restrictions /// stated in the class comment above, or if the source image /// has an <code>IndexColorModel</code>. </summary> /// <param name="src"> the <code>BufferedImage</code> to be filtered </param> /// <param name="dst"> the <code>BufferedImage</code> in which to /// store the results of the filter operation </param> /// <returns> the filtered <code>BufferedImage</code>. </returns> /// <exception cref="IllegalArgumentException"> if the number of arrays in the /// <code>LookupTable</code> does not meet the restrictions /// described in the class comments, or if the source image /// has an <code>IndexColorModel</code>. </exception> public BufferedImage Filter(BufferedImage src, BufferedImage dst) { ColorModel srcCM = src.ColorModel; int numBands = srcCM.NumColorComponents; ColorModel dstCM; if (srcCM is IndexColorModel) { throw new IllegalArgumentException("LookupOp cannot be " + "performed on an indexed image"); } int numComponents = Ltable.NumComponents; if (numComponents != 1 && numComponents != srcCM.NumComponents && numComponents != srcCM.NumColorComponents) { throw new IllegalArgumentException("Number of arrays in the " + " lookup table (" + numComponents + " is not compatible with the " + " src image: " + src); } bool needToConvert = false; 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; if (ImagingLib.filter(this, src, dst) == null) { // Do it the slow way WritableRaster srcRaster = src.Raster; WritableRaster dstRaster = dst.Raster; if (srcCM.HasAlpha()) { if (numBands - 1 == numComponents || numComponents == 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 == numComponents || numComponents == 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); } } Filter(srcRaster, dstRaster); } if (needToConvert) { // ColorModels are not the same ColorConvertOp ccop = new ColorConvertOp(Hints); ccop.Filter(dst, origDst); } return(origDst); }
/// <summary> /// Performs a lookup operation on a <code>Raster</code>. /// If the destination <code>Raster</code> is <code>null</code>, /// a new <code>Raster</code> will be created. /// The <code>IllegalArgumentException</code> might be thrown /// if the source <code>Raster</code> and the destination /// <code>Raster</code> do not have the same /// number of bands or if the number of arrays in the /// <code>LookupTable</code> does not meet the /// restrictions stated in the class comment above. </summary> /// <param name="src"> the source <code>Raster</code> to filter </param> /// <param name="dst"> the destination <code>WritableRaster</code> for the /// filtered <code>src</code> </param> /// <returns> the filtered <code>WritableRaster</code>. </returns> /// <exception cref="IllegalArgumentException"> if the source and destinations /// rasters do not have the same number of bands, or the /// number of arrays in the <code>LookupTable</code> does /// not meet the restrictions described in the class comments. /// </exception> public WritableRaster Filter(Raster src, WritableRaster dst) { int numBands = src.NumBands; int dstLength = dst.NumBands; int height = src.Height; int width = src.Width; int[] srcPix = new int[numBands]; // 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"); } dstLength = dst.NumBands; if (numBands != dstLength) { throw new IllegalArgumentException("Number of channels in the src (" + numBands + ") does not match number of channels" + " in the destination (" + dstLength + ")"); } int numComponents = Ltable.NumComponents; if (numComponents != 1 && numComponents != src.NumBands) { throw new IllegalArgumentException("Number of arrays in the " + " lookup table (" + numComponents + " is not compatible with the " + " src Raster: " + src); } if (ImagingLib.filter(this, src, dst) != null) { return(dst); } // Optimize for cases we know about if (Ltable is ByteLookupTable) { ByteFilter((ByteLookupTable)Ltable, src, dst, width, height, numBands); } else if (Ltable is ShortLookupTable) { ShortFilter((ShortLookupTable)Ltable, src, dst, width, height, numBands); } else { // Not one we recognize so do it slowly int sminX = src.MinX; int sY = src.MinY; int dminX = dst.MinX; int dY = dst.MinY; for (int y = 0; y < height; y++, sY++, dY++) { int sX = sminX; int dX = dminX; for (int x = 0; x < width; x++, sX++, dX++) { // Find data for all bands at this x,y position src.GetPixel(sX, sY, srcPix); // Lookup the data for all bands at this x,y position Ltable.LookupPixel(srcPix, srcPix); // Put it back for all bands dst.SetPixel(dX, dY, srcPix); } } } return(dst); }
/// <summary> /// Transforms the <CODE>Raster</CODE> using the matrix specified in the /// constructor. An <CODE>IllegalArgumentException</CODE> may be thrown if /// the number of bands in the source or destination is incompatible with /// the matrix. See the class comments for more details. /// <para> /// If the destination is null, it will be created with a number of bands /// equalling the number of rows in the matrix. No exception is thrown /// if the operation causes a data overflow. /// /// </para> /// </summary> /// <param name="src"> The <CODE>Raster</CODE> to be filtered. </param> /// <param name="dst"> The <CODE>Raster</CODE> in which to store the results /// of the filter operation. /// </param> /// <returns> The filtered <CODE>Raster</CODE>. /// </returns> /// <exception cref="IllegalArgumentException"> If the number of bands in the /// source or destination is incompatible with the matrix. </exception> public virtual WritableRaster Filter(Raster src, WritableRaster dst) { int nBands = src.NumBands; if (Ncols != nBands && Ncols != (nBands + 1)) { throw new IllegalArgumentException("Number of columns in the " + "matrix (" + Ncols + ") must be equal to the number" + " of bands ([+1]) in src (" + nBands + ")."); } if (dst == null) { dst = CreateCompatibleDestRaster(src); } else if (Nrows != dst.NumBands) { throw new IllegalArgumentException("Number of rows in the " + "matrix (" + Nrows + ") must be equal to the number" + " of bands ([+1]) in dst (" + nBands + ")."); } if (ImagingLib.filter(this, src, dst) != null) { return(dst); } int[] pixel = null; int[] dstPixel = new int[dst.NumBands]; float accum; int sminX = src.MinX; int sY = src.MinY; int dminX = dst.MinX; int dY = dst.MinY; int sX; int dX; if (Ncols == nBands) { for (int y = 0; y < src.Height; y++, sY++, dY++) { dX = dminX; sX = sminX; for (int x = 0; x < src.Width; x++, sX++, dX++) { pixel = src.GetPixel(sX, sY, pixel); for (int r = 0; r < Nrows; r++) { accum = 0.0f; for (int c = 0; c < Ncols; c++) { accum += Matrix_Renamed[r][c] * pixel[c]; } dstPixel[r] = (int)accum; } dst.SetPixel(dX, dY, dstPixel); } } } else { // Need to add constant for (int y = 0; y < src.Height; y++, sY++, dY++) { dX = dminX; sX = sminX; for (int x = 0; x < src.Width; x++, sX++, dX++) { pixel = src.GetPixel(sX, sY, pixel); for (int r = 0; r < Nrows; r++) { accum = 0.0f; for (int c = 0; c < nBands; c++) { accum += Matrix_Renamed[r][c] * pixel[c]; } dstPixel[r] = (int)(accum + Matrix_Renamed[r][nBands]); } dst.SetPixel(dX, dY, dstPixel); } } } return(dst); }