int srcY = source.getMinY();
// Retrieve format tags.
RasterFormatTag[] formatTags = getFormatTags();
RasterAccessor srcAccessor =
new RasterAccessor(source,
new Rectangle(srcX, srcY,
srcWidth, srcHeight),
formatTags[0], getSourceImage(0).getColorModel());
RasterAccessor dstAccessor =
new RasterAccessor(dest, destRect, formatTags[1], getColorModel());
// Set data type flags.
int srcDataType = srcAccessor.getDataType();
int dstDataType = dstAccessor.getDataType();
// Set pixel and line strides.
int srcPixelStride = srcAccessor.getPixelStride();
int srcScanlineStride = srcAccessor.getScanlineStride();
int dstPixelStride = dstAccessor.getPixelStride();
int dstScanlineStride = dstAccessor.getScanlineStride();
int dstPixelStrideImag = 1;
int dstLineStrideImag = destRect.width;
if(complexDst) {
dstPixelStrideImag = dstPixelStride;
dstLineStrideImag = dstScanlineStride;
}
// Set indices and strides for image bands (real/imaginary).
int srcBandIndex = 0;
int srcBandStride = complexSrc ? 2 : 1;
int dstBandIndex = 0;
int dstBandStride = complexDst ? 2 : 1;
// Get the number of components.
int numComponents = (complexDst ?
dest.getSampleModel().getNumBands() / 2 :
dest.getSampleModel().getNumBands());
// Loop over the components.
for(int comp = 0; comp < numComponents; comp++) {
// Get the real source data for this component.
Object srcReal = srcAccessor.getDataArray(srcBandIndex);
// Get the imaginary source data for this component if present.
Object srcImag = null;
if(complexSrc) {
srcImag = srcAccessor.getDataArray(srcBandIndex+1);
}
// Specify the destination components.
Object dstReal = dstAccessor.getDataArray(dstBandIndex);
Object dstImag = null;
if(complexDst) {
dstImag = dstAccessor.getDataArray(dstBandIndex+1);
} else {
// Need to allocate an array for the entire band anyway
// even though the destination is real because it is needed
// for storage of the result of the row transforms.
if(dstDataType == DataBuffer.TYPE_FLOAT) {
dstImag = new float[destRect.width*destRect.height];
} else {
dstImag = new double[destRect.width*destRect.height];
}
}
if(destRect.width > 1) {
// Set the FFT length.
fft.setLength(getWidth());
// Initialize the source offsets for this component.
int srcOffsetReal =
srcAccessor.getBandOffset(srcBandIndex);
int srcOffsetImag = 0;
if(complexSrc) {
srcOffsetImag =
srcAccessor.getBandOffset(srcBandIndex+1);
}
// Initialize destination offsets and strides.
int dstOffsetReal =
dstAccessor.getBandOffset(dstBandIndex);
int dstOffsetImag = 0;
if(complexDst) {
dstOffsetImag =
dstAccessor.getBandOffset(dstBandIndex+1);
}
// Perform the row transforms.
for(int row = 0; row < srcHeight; row++) {
// Set the input data of the FFT.
fft.setData(srcDataType,
srcReal, srcOffsetReal, srcPixelStride,
srcImag, srcOffsetImag, srcPixelStride,
srcWidth);
// Calculate the DFT of the row.
fft.transform();
// Get the output data of the FFT.
fft.getData(dstDataType,
dstReal, dstOffsetReal, dstPixelStride,
dstImag, dstOffsetImag, dstPixelStrideImag);
// Increment the data offsets.
srcOffsetReal += srcScanlineStride;
srcOffsetImag += srcScanlineStride;
dstOffsetReal += dstScanlineStride;
dstOffsetImag += dstLineStrideImag;
}
}
if(destRect.width == 1) { // destRect.height > 1
// NB 1) destRect.height has to be greater than one or this
// would be the degenerate case of a single point which is
// handled above. 2) There is no need to do setLength() on
// the FFT object here as the length will already have been
// set to the maximum of destRect.width amd destRect.height
// which must be destRect.height.
// Initialize the source offsets for this component.
int srcOffsetReal =
srcAccessor.getBandOffset(srcBandIndex);
int srcOffsetImag = 0;
if(complexSrc) {
srcOffsetImag =
srcAccessor.getBandOffset(srcBandIndex+1);
}
// Initialize destination offsets and strides.
int dstOffsetReal =
dstAccessor.getBandOffset(dstBandIndex);
int dstOffsetImag = 0;
if(complexDst) {
dstOffsetImag =
dstAccessor.getBandOffset(dstBandIndex+1);
}
// Set the input data of the FFT.
fft.setData(srcDataType,
srcReal, srcOffsetReal, srcScanlineStride,
srcImag, srcOffsetImag, srcScanlineStride,
srcHeight);
// Calculate the DFT of the column.
fft.transform();
// Get the output data of the FFT.
fft.getData(dstDataType,
dstReal, dstOffsetReal, dstScanlineStride,
dstImag, dstOffsetImag, dstLineStrideImag);
} else if(destRect.height > 1) { // destRect.width > 1
// Reset the FFT length.
fft.setLength(getHeight());
// Initialize destination offsets and strides.
int dstOffsetReal =
dstAccessor.getBandOffset(dstBandIndex);
int dstOffsetImag = 0;
if(complexDst) {
dstOffsetImag =
dstAccessor.getBandOffset(dstBandIndex+1);
}
// Perform the column transforms.
for(int col = 0; col < destRect.width; col++) {
// Set the input data of the FFT.
fft.setData(dstDataType,
dstReal, dstOffsetReal, dstScanlineStride,
dstImag, dstOffsetImag, dstLineStrideImag,
destRect.height);
// Calculate the DFT of the column.
fft.transform();
// Get the output data of the FFT.
fft.getData(dstDataType,
dstReal, dstOffsetReal, dstScanlineStride,
complexDst ? dstImag : null,
dstOffsetImag, dstLineStrideImag);
// Increment the data offset.
dstOffsetReal += dstPixelStride;
dstOffsetImag += dstPixelStrideImag;
}
}
// Increment the indices of the real bands in both images.
srcBandIndex += srcBandStride;
dstBandIndex += dstBandStride;
}
if (dstAccessor.needsClamping()) {
dstAccessor.clampDataArrays();
}
// Make sure that the output data is copied to the destination.
dstAccessor.copyDataToRaster();
}