/// <summary> /// Determines if the rescale can be performed as a lookup. /// The dst must be a byte or short type. /// The src must be less than 16 bits. /// All source band sizes must be the same and all dst band sizes /// must be the same. /// </summary> private bool CanUseLookup(Raster src, Raster dst) { // // Check that the src datatype is either a BYTE or SHORT // int datatype = src.DataBuffer.DataType; if (datatype != DataBuffer.TYPE_BYTE && datatype != DataBuffer.TYPE_USHORT) { return(false); } // // Check dst sample sizes. All must be 8 or 16 bits. // SampleModel dstSM = dst.SampleModel; DstNbits = dstSM.GetSampleSize(0); if (!(DstNbits == 8 || DstNbits == 16)) { return(false); } for (int i = 1; i < src.NumBands; i++) { int bandSize = dstSM.GetSampleSize(i); if (bandSize != DstNbits) { return(false); } } // // Check src sample sizes. All must be the same size // SampleModel srcSM = src.SampleModel; SrcNbits = srcSM.GetSampleSize(0); if (SrcNbits > 16) { return(false); } for (int i = 1; i < src.NumBands; i++) { int bandSize = srcSM.GetSampleSize(i); if (bandSize != SrcNbits) { return(false); } } return(true); }
/* color convert a Raster - handles byte, ushort, int, short, float, * or double transferTypes */ private WritableRaster NonICCRasterFilter(Raster src, WritableRaster dst) { if (CSList.Length != 2) { throw new IllegalArgumentException("Destination ColorSpace is undefined"); } if (src.NumBands != CSList[0].NumComponents) { throw new IllegalArgumentException("Numbers of source Raster bands and source color space " + "components do not match"); } if (dst == null) { dst = CreateCompatibleDestRaster(src); } else { if (src.Height != dst.Height || src.Width != dst.Width) { throw new IllegalArgumentException("Width or height of Rasters do not match"); } if (dst.NumBands != CSList[1].NumComponents) { throw new IllegalArgumentException("Numbers of destination Raster bands and destination " + "color space components do not match"); } } if (SrcMinVals == null) { GetMinMaxValsFromColorSpaces(CSList[0], CSList[1]); } SampleModel srcSM = src.SampleModel; SampleModel dstSM = dst.SampleModel; bool srcIsFloat, dstIsFloat; int srcTransferType = src.TransferType; int dstTransferType = dst.TransferType; if ((srcTransferType == DataBuffer.TYPE_FLOAT) || (srcTransferType == DataBuffer.TYPE_DOUBLE)) { srcIsFloat = true; } else { srcIsFloat = false; } if ((dstTransferType == DataBuffer.TYPE_FLOAT) || (dstTransferType == DataBuffer.TYPE_DOUBLE)) { dstIsFloat = true; } else { dstIsFloat = false; } int w = src.Width; int h = src.Height; int srcNumBands = src.NumBands; int dstNumBands = dst.NumBands; float[] srcScaleFactor = null; float[] dstScaleFactor = null; if (!srcIsFloat) { srcScaleFactor = new float[srcNumBands]; for (int i = 0; i < srcNumBands; i++) { if (srcTransferType == DataBuffer.TYPE_SHORT) { srcScaleFactor[i] = (SrcMaxVals[i] - SrcMinVals[i]) / 32767.0f; } else { srcScaleFactor[i] = (SrcMaxVals[i] - SrcMinVals[i]) / ((float)((1 << srcSM.GetSampleSize(i)) - 1)); } } } if (!dstIsFloat) { dstScaleFactor = new float[dstNumBands]; for (int i = 0; i < dstNumBands; i++) { if (dstTransferType == DataBuffer.TYPE_SHORT) { dstScaleFactor[i] = 32767.0f / (DstMaxVals[i] - DstMinVals[i]); } else { dstScaleFactor[i] = ((float)((1 << dstSM.GetSampleSize(i)) - 1)) / (DstMaxVals[i] - DstMinVals[i]); } } } int ys = src.MinY; int yd = dst.MinY; int xs, xd; float sample; float[] color = new float[srcNumBands]; float[] tmpColor; ColorSpace srcColorSpace = CSList[0]; ColorSpace dstColorSpace = CSList[1]; // process each pixel for (int y = 0; y < h; y++, ys++, yd++) { // get src scanline xs = src.MinX; xd = dst.MinX; for (int x = 0; x < w; x++, xs++, xd++) { for (int i = 0; i < srcNumBands; i++) { sample = src.GetSampleFloat(xs, ys, i); if (!srcIsFloat) { sample = sample * srcScaleFactor[i] + SrcMinVals[i]; } color[i] = sample; } tmpColor = srcColorSpace.ToCIEXYZ(color); tmpColor = dstColorSpace.FromCIEXYZ(tmpColor); for (int i = 0; i < dstNumBands; i++) { sample = tmpColor[i]; if (!dstIsFloat) { sample = (sample - DstMinVals[i]) * dstScaleFactor[i]; } dst.SetSample(xd, yd, i, sample); } } } 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); }