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