BandCombineOppublic class BandCombineOp extends Object implements RasterOpThe BandCombineOp class translates coordinates from coordinates in the source
Raster to coordinates in the destination Raster by an arbitrary linear
combination of the bands in a source Raster, using a specified matrix. The
number of bands in the matrix should equal to the number of bands in the
source Raster plus 1. |
Fields Summary |
---|
static final int[] | offsets3cThe Constant offsets3c. | static final int[] | offsets4acThe Constant offsets4ac. | static final int[] | masks3cThe Constant masks3c. | static final int[] | masks4acThe Constant masks4ac. | private static final int[] | piOffsetsThe Constant piOffsets. | private static final int[] | piInvOffsetsThe Constant piInvOffsets. | private static final int | TYPE_BYTE3CThe Constant TYPE_BYTE3C. | private static final int | TYPE_BYTE4ACThe Constant TYPE_BYTE4AC. | private static final int | TYPE_USHORT3CThe Constant TYPE_USHORT3C. | private static final int | TYPE_SHORT3CThe Constant TYPE_SHORT3C. | private int | mxWidthThe mx width. | private int | mxHeightThe mx height. | private float[] | matrixThe matrix. | private RenderingHints | rHintsThe r hints. |
Constructors Summary |
---|
public BandCombineOp(float[] matrix, RenderingHints hints)Instantiates a new BandCombineOp object with the specified matrix.
// XXX - todo
// System.loadLibrary("imageops");
this.mxHeight = matrix.length;
this.mxWidth = matrix[0].length;
this.matrix = new float[mxHeight][mxWidth];
for (int i = 0; i < mxHeight; i++) {
System.arraycopy(matrix[i], 0, this.matrix[i], 0, mxWidth);
}
this.rHints = hints;
|
Methods Summary |
---|
private final java.awt.image.BandCombineOp$SampleModelInfo | checkSampleModel(java.awt.image.SampleModel sm)Check sample model.
SampleModelInfo ret = new SampleModelInfo();
if (sm instanceof PixelInterleavedSampleModel) {
// Check PixelInterleavedSampleModel
if (sm.getDataType() != DataBuffer.TYPE_BYTE) {
return null;
}
ret.channels = sm.getNumBands();
ret.stride = ((ComponentSampleModel)sm).getScanlineStride();
ret.channelsOrder = ((ComponentSampleModel)sm).getBandOffsets();
} else if (sm instanceof SinglePixelPackedSampleModel) {
// Check SinglePixelPackedSampleModel
SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel)sm;
ret.channels = sppsm1.getNumBands();
if (sppsm1.getDataType() != DataBuffer.TYPE_INT) {
return null;
}
// Check sample models
for (int i = 0; i < ret.channels; i++) {
if (sppsm1.getSampleSize(i) != 8) {
return null;
}
}
ret.channelsOrder = new int[ret.channels];
int bitOffsets[] = sppsm1.getBitOffsets();
for (int i = 0; i < ret.channels; i++) {
if (bitOffsets[i] % 8 != 0) {
return null;
}
ret.channelsOrder[i] = bitOffsets[i] / 8;
}
ret.channels = 4;
ret.stride = sppsm1.getScanlineStride() * 4;
} else {
return null;
}
return ret;
| public java.awt.image.WritableRaster | createCompatibleDestRaster(java.awt.image.Raster src)
int numBands = src.getNumBands();
if (mxWidth != numBands && mxWidth != (numBands + 1) || numBands != mxHeight) {
// awt.254=Number of bands in the source raster ({0}) is
// incompatible with the matrix [{1}x{2}]
throw new IllegalArgumentException(Messages.getString("awt.254", //$NON-NLS-1$
new Object[] {
numBands, mxWidth, mxHeight
}));
}
return src.createCompatibleWritableRaster(src.getWidth(), src.getHeight());
| public java.awt.image.WritableRaster | filter(java.awt.image.Raster src, java.awt.image.WritableRaster dst)
int numBands = src.getNumBands();
if (mxWidth != numBands && mxWidth != (numBands + 1)) {
// awt.254=Number of bands in the source raster ({0}) is
// incompatible with the matrix [{1}x{2}]
throw new IllegalArgumentException(Messages.getString("awt.254", //$NON-NLS-1$
new Object[] {
numBands, mxWidth, mxHeight
}));
}
if (dst == null) {
dst = createCompatibleDestRaster(src);
} else if (dst.getNumBands() != mxHeight) {
// awt.255=Number of bands in the destination raster ({0}) is
// incompatible with the matrix [{1}x{2}]
throw new IllegalArgumentException(Messages.getString("awt.255", //$NON-NLS-1$
new Object[] {
dst.getNumBands(), mxWidth, mxHeight
}));
}
// XXX - todo
// if (ippFilter(src, dst) != 0)
if (verySlowFilter(src, dst) != 0) {
// awt.21F=Unable to transform source
throw new ImagingOpException(Messages.getString("awt.21F")); //$NON-NLS-1$
}
return dst;
| public final java.awt.geom.Rectangle2D | getBounds2D(java.awt.image.Raster src)
return src.getBounds();
| public final float[][] | getMatrix()Gets the matrix associated with this BandCombineOp object.
float res[][] = new float[mxHeight][mxWidth];
for (int i = 0; i < mxHeight; i++) {
System.arraycopy(matrix[i], 0, res[i], 0, mxWidth);
}
return res;
| public final java.awt.geom.Point2D | getPoint2D(java.awt.geom.Point2D srcPoint, java.awt.geom.Point2D dstPoint)
if (dstPoint == null) {
dstPoint = new Point2D.Float();
}
dstPoint.setLocation(srcPoint);
return dstPoint;
| public final java.awt.RenderingHints | getRenderingHints()
return this.rHints;
| private final native int | ippColorTwist(java.lang.Object srcData, int srcWidth, int srcHeight, int srcStride, java.lang.Object dstData, int dstWidth, int dstHeight, int dstStride, float[] ippMatrix, int type, int[] offsets, boolean inPlace)Ipp color twist.
| private int | ippFilter(java.awt.image.Raster src, java.awt.image.WritableRaster dst)Ipp filter.
boolean invertChannels;
boolean inPlace = (src == dst);
int type;
int srcStride, dstStride;
int offsets[] = null;
int srcBands = src.getNumBands();
int dstBands = dst.getNumBands();
if (dstBands != 3
|| (srcBands != 3 && !(srcBands == 4 && matrix[0][3] == 0 && matrix[1][3] == 0 && matrix[2][3] == 0))) {
return slowFilter(src, dst);
}
SampleModel srcSM = src.getSampleModel();
SampleModel dstSM = dst.getSampleModel();
if (srcSM instanceof SinglePixelPackedSampleModel
&& dstSM instanceof SinglePixelPackedSampleModel) {
// Check SinglePixelPackedSampleModel
SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel)srcSM;
SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel)dstSM;
if (sppsm1.getDataType() != DataBuffer.TYPE_INT
|| sppsm2.getDataType() != DataBuffer.TYPE_INT) {
return slowFilter(src, dst);
}
// Check sample models
if (!Arrays.equals(sppsm2.getBitOffsets(), offsets3c)
|| !Arrays.equals(sppsm2.getBitMasks(), masks3c)) {
return slowFilter(src, dst);
}
if (srcBands == 3) {
if (!Arrays.equals(sppsm1.getBitOffsets(), offsets3c)
|| !Arrays.equals(sppsm1.getBitMasks(), masks3c)) {
return slowFilter(src, dst);
}
} else if (srcBands == 4) {
if (!Arrays.equals(sppsm1.getBitOffsets(), offsets4ac)
|| !Arrays.equals(sppsm1.getBitMasks(), masks4ac)) {
return slowFilter(src, dst);
}
}
type = TYPE_BYTE4AC;
invertChannels = true;
srcStride = sppsm1.getScanlineStride() * 4;
dstStride = sppsm2.getScanlineStride() * 4;
} else if (srcSM instanceof PixelInterleavedSampleModel
&& dstSM instanceof PixelInterleavedSampleModel) {
if (srcBands != 3) {
return slowFilter(src, dst);
}
int srcDataType = srcSM.getDataType();
switch (srcDataType) {
case DataBuffer.TYPE_BYTE:
type = TYPE_BYTE3C;
break;
case DataBuffer.TYPE_USHORT:
type = TYPE_USHORT3C;
break;
case DataBuffer.TYPE_SHORT:
type = TYPE_SHORT3C;
break;
default:
return slowFilter(src, dst);
}
// Check PixelInterleavedSampleModel
PixelInterleavedSampleModel pism1 = (PixelInterleavedSampleModel)srcSM;
PixelInterleavedSampleModel pism2 = (PixelInterleavedSampleModel)dstSM;
if (srcDataType != pism2.getDataType() || pism1.getPixelStride() != 3
|| pism2.getPixelStride() != 3
|| !Arrays.equals(pism1.getBandOffsets(), pism2.getBandOffsets())) {
return slowFilter(src, dst);
}
if (Arrays.equals(pism1.getBandOffsets(), piInvOffsets)) {
invertChannels = true;
} else if (Arrays.equals(pism1.getBandOffsets(), piOffsets)) {
invertChannels = false;
} else {
return slowFilter(src, dst);
}
int dataTypeSize = DataBuffer.getDataTypeSize(srcDataType) / 8;
srcStride = pism1.getScanlineStride() * dataTypeSize;
dstStride = pism2.getScanlineStride() * dataTypeSize;
} else { // XXX - todo - IPP allows support for planar data also
return slowFilter(src, dst);
}
// Fill offsets if there's a child raster
if (src.getParent() != null || dst.getParent() != null) {
if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0
|| dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) {
offsets = new int[4];
offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
}
}
Object srcData, dstData;
AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
try {
srcData = dbAccess.getData(src.getDataBuffer());
dstData = dbAccess.getData(dst.getDataBuffer());
} catch (IllegalArgumentException e) {
return -1; // Unknown data buffer type
}
float ippMatrix[] = new float[12];
if (invertChannels) {
// IPP treats big endian integers like BGR, so we have to
// swap columns 1 and 3 and rows 1 and 3
for (int i = 0; i < mxHeight; i++) {
ippMatrix[i * 4] = matrix[2 - i][2];
ippMatrix[i * 4 + 1] = matrix[2 - i][1];
ippMatrix[i * 4 + 2] = matrix[2 - i][0];
if (mxWidth == 4) {
ippMatrix[i * 4 + 3] = matrix[2 - i][3];
} else if (mxWidth == 5) {
ippMatrix[i * 4 + 3] = matrix[2 - i][4];
}
}
} else {
for (int i = 0; i < mxHeight; i++) {
ippMatrix[i * 4] = matrix[i][0];
ippMatrix[i * 4 + 1] = matrix[i][1];
ippMatrix[i * 4 + 2] = matrix[i][2];
if (mxWidth == 4) {
ippMatrix[i * 4 + 3] = matrix[i][3];
} else if (mxWidth == 5) {
ippMatrix[i * 4 + 3] = matrix[i][4];
}
}
}
return ippColorTwist(srcData, src.getWidth(), src.getHeight(), srcStride, dstData, dst
.getWidth(), dst.getHeight(), dstStride, ippMatrix, type, offsets, inPlace);
| private final native int | simpleCombineBands(java.lang.Object srcData, int srcWidth, int srcHeight, int srcStride, int srcChannels, java.lang.Object dstData, int dstStride, int dstChannels, float[] m, int[] offsets)Simple combine bands.
| private final int | slowFilter(java.awt.image.Raster src, java.awt.image.WritableRaster dst)Slow filter.
int res = 0;
SampleModelInfo srcInfo, dstInfo;
int offsets[] = null;
srcInfo = checkSampleModel(src.getSampleModel());
dstInfo = checkSampleModel(dst.getSampleModel());
if (srcInfo == null || dstInfo == null) {
return verySlowFilter(src, dst);
}
// Fill offsets if there's a child raster
if (src.getParent() != null || dst.getParent() != null) {
if (src.getSampleModelTranslateX() != 0 || src.getSampleModelTranslateY() != 0
|| dst.getSampleModelTranslateX() != 0 || dst.getSampleModelTranslateY() != 0) {
offsets = new int[4];
offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
}
}
int rmxWidth = (srcInfo.channels + 1); // width of the reordered matrix
float reorderedMatrix[] = new float[rmxWidth * dstInfo.channels];
for (int j = 0; j < dstInfo.channels; j++) {
if (j >= dstInfo.channelsOrder.length) {
continue;
}
for (int i = 0; i < srcInfo.channels; i++) {
if (i >= srcInfo.channelsOrder.length) {
break;
}
reorderedMatrix[dstInfo.channelsOrder[j] * rmxWidth + srcInfo.channelsOrder[i]] = matrix[j][i];
}
if (mxWidth == rmxWidth) {
reorderedMatrix[(dstInfo.channelsOrder[j] + 1) * rmxWidth - 1] = matrix[j][mxWidth - 1];
}
}
Object srcData, dstData;
AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
try {
srcData = dbAccess.getData(src.getDataBuffer());
dstData = dbAccess.getData(dst.getDataBuffer());
} catch (IllegalArgumentException e) {
return -1; // Unknown data buffer type
}
simpleCombineBands(srcData, src.getWidth(), src.getHeight(), srcInfo.stride,
srcInfo.channels, dstData, dstInfo.stride, dstInfo.channels, reorderedMatrix,
offsets);
return res;
| private int | verySlowFilter(java.awt.image.Raster src, java.awt.image.WritableRaster dst)Very slow filter.
int numBands = src.getNumBands();
int srcMinX = src.getMinX();
int srcY = src.getMinY();
int dstMinX = dst.getMinX();
int dstY = dst.getMinY();
int dX = src.getWidth();// < dst.getWidth() ? src.getWidth() :
// dst.getWidth();
int dY = src.getHeight();// < dst.getHeight() ? src.getHeight() :
// dst.getHeight();
float sample;
int srcPixels[] = new int[numBands * dX * dY];
int dstPixels[] = new int[mxHeight * dX * dY];
srcPixels = src.getPixels(srcMinX, srcY, dX, dY, srcPixels);
if (numBands == mxWidth) {
for (int i = 0, j = 0; i < srcPixels.length; i += numBands) {
for (int dstB = 0; dstB < mxHeight; dstB++) {
sample = 0f;
for (int srcB = 0; srcB < numBands; srcB++) {
sample += matrix[dstB][srcB] * srcPixels[i + srcB];
}
dstPixels[j++] = (int)sample;
}
}
} else {
for (int i = 0, j = 0; i < srcPixels.length; i += numBands) {
for (int dstB = 0; dstB < mxHeight; dstB++) {
sample = 0f;
for (int srcB = 0; srcB < numBands; srcB++) {
sample += matrix[dstB][srcB] * srcPixels[i + srcB];
}
dstPixels[j++] = (int)(sample + matrix[dstB][numBands]);
}
}
}
dst.setPixels(dstMinX, dstY, dX, dY, dstPixels);
return 0;
|
|