/* JAI-Ext - OpenSource Java Advanced Image Extensions Library * http://www.geo-solutions.it/ * Copyright 2014 GeoSolutions * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.geosolutions.jaiext.convolve; import it.geosolutions.jaiext.range.Range; import java.awt.RenderingHints; import java.awt.image.DataBuffer; import java.awt.image.RenderedImage; import javax.media.jai.BorderExtender; import javax.media.jai.ImageLayout; import javax.media.jai.KernelJAI; import javax.media.jai.ROI; import javax.media.jai.RasterAccessor; import javax.media.jai.iterator.RandomIter; import com.sun.media.jai.util.ImageUtil; public class Convolve3x3OpImage extends ConvolveOpImage { float tables[][] = new float[9][256]; public Convolve3x3OpImage(RenderedImage source, BorderExtender extender, RenderingHints hints, ImageLayout l, KernelJAI kernel, ROI roi, Range noData, double destinationNoData, boolean skipNoData) { super(source, extender, hints, l, kernel, roi, noData, destinationNoData, skipNoData); this.kernel = kernel; if ((kernel.getWidth() != 3) || (kernel.getHeight() != 3) || (kernel.getXOrigin() != 1) || (kernel.getYOrigin() != 1)) { throw new RuntimeException(JaiI18N.getString("Convolve3x3OpImage0")); } if (sampleModel.getDataType() == DataBuffer.TYPE_BYTE) { float kdata[] = kernel.getKernelData(); float k0 = kdata[0], k1 = kdata[1], k2 = kdata[2], k3 = kdata[3], k4 = kdata[4], k5 = kdata[5], k6 = kdata[6], k7 = kdata[7], k8 = kdata[8]; for (int j = 0; j < 256; j++) { byte b = (byte) j; float f = (float) j; // noData Check tables[0][b + 128] = hasNoData && noData.contains(b) ? 0.5f : k0 * f + 0.5f; tables[1][b + 128] = hasNoData && noData.contains(b) ? 0 : k1 * f; tables[2][b + 128] = hasNoData && noData.contains(b) ? 0 : k2 * f; tables[3][b + 128] = hasNoData && noData.contains(b) ? 0 : k3 * f; tables[4][b + 128] = hasNoData && noData.contains(b) ? 0 : k4 * f; tables[5][b + 128] = hasNoData && noData.contains(b) ? 0 : k5 * f; tables[6][b + 128] = hasNoData && noData.contains(b) ? 0 : k6 * f; tables[7][b + 128] = hasNoData && noData.contains(b) ? 0 : k7 * f; tables[8][b + 128] = hasNoData && noData.contains(b) ? 0 : k8 * f; } } } @Override protected void byteLoop(RasterAccessor src, RasterAccessor dst, RandomIter roiIter, boolean roiContainsTile) { int dwidth = dst.getWidth(); int dheight = dst.getHeight(); int dnumBands = dst.getNumBands(); // cache these out to avoid an array access per kernel value float t0[] = tables[0], t1[] = tables[1], t2[] = tables[2], t3[] = tables[3], t4[] = tables[4], t5[] = tables[5], t6[] = tables[6], t7[] = tables[7], t8[] = tables[8]; byte dstDataArrays[][] = dst.getByteDataArrays(); int dstBandOffsets[] = dst.getBandOffsets(); int dstPixelStride = dst.getPixelStride(); int dstScanlineStride = dst.getScanlineStride(); byte srcDataArrays[][] = src.getByteDataArrays(); int srcBandOffsets[] = src.getBandOffsets(); int srcPixelStride = src.getPixelStride(); int srcScanlineStride = src.getScanlineStride(); // precalculate offsets int centerScanlineOffset = srcScanlineStride; int bottomScanlineOffset = srcScanlineStride * 2; int middlePixelOffset = dnumBands; int rightPixelOffset = dnumBands * 2; // X,Y positions int x0 = 0; int y0 = 0; int srcX = src.getX(); int srcY = src.getY(); // ROI And NoData Check if (hasROI) { for (int k = 0; k < dnumBands; k++) { byte dstData[] = dstDataArrays[k]; byte srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; y0 = srcY + j; for (int i = 0; i < dwidth; i++) { x0 = srcX + i; // ROI Check boolean inROI = false; for (int y = 0; y < kh && !inROI; y++) { int yI = y0 + y; for (int x = 0; x < kw && !inROI; x++) { int xI = x0 + x; if (roiBounds.contains(xI, yI) && roiIter.getSample(xI, yI, 0) > 0) { inROI = true; } } } byte b0 = srcData[srcPixelOffset]; byte b1 = srcData[srcPixelOffset + middlePixelOffset]; byte b2 = srcData[srcPixelOffset + rightPixelOffset]; byte b3 = srcData[srcPixelOffset + centerScanlineOffset]; byte b4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; byte b5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; byte b6 = srcData[srcPixelOffset + bottomScanlineOffset]; byte b7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; byte b8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; float f = t0[128 + b0] + t1[128 + b1] + t2[128 + b2] + t3[128 + b3] + t4[128 + b4] + t5[128 + b5] + t6[128 + b6] + t7[128 + b7] + t8[128 + b8]; boolean isValid = true; // Check if nodata must be skipped if (skipNoData) { isValid = lut[b0] && lut[b1] && lut[b2] && lut[b3] && lut[b4] && lut[b5] && lut[b6] && lut[b7] && lut[b8]; } if (isValid && inROI) { // Clamping data dstData[dstPixelOffset] = ImageUtil.clampRoundByte(f); } else { dstData[dstPixelOffset] = destNoDataByte; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // Only NoData Check } else { for (int k = 0; k < dnumBands; k++) { byte dstData[] = dstDataArrays[k]; byte srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; for (int i = 0; i < dwidth; i++) { byte b0 = srcData[srcPixelOffset]; byte b1 = srcData[srcPixelOffset + middlePixelOffset]; byte b2 = srcData[srcPixelOffset + rightPixelOffset]; byte b3 = srcData[srcPixelOffset + centerScanlineOffset]; byte b4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; byte b5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; byte b6 = srcData[srcPixelOffset + bottomScanlineOffset]; byte b7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; byte b8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; float f = t0[128 + b0] + t1[128 + b1] + t2[128 + b2] + t3[128 + b3] + t4[128 + b4] + t5[128 + b5] + t6[128 + b6] + t7[128 + b7] + t8[128 + b8]; boolean isValid = true; // Check if nodata must be skipped if (skipNoData) { isValid = lut[b0] && lut[b1] && lut[b2] && lut[b3] && lut[b4] && lut[b5] && lut[b6] && lut[b7] && lut[b8]; } if (isValid) { // Clamping data dstData[dstPixelOffset] = ImageUtil.clampRoundByte(f); } else { dstData[dstPixelOffset] = destNoDataByte; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } } } @Override protected void shortLoop(RasterAccessor src, RasterAccessor dst, RandomIter roiIter, boolean roiContainsTile) { int dwidth = dst.getWidth(); int dheight = dst.getHeight(); int dnumBands = dst.getNumBands(); short dstDataArrays[][] = dst.getShortDataArrays(); int dstBandOffsets[] = dst.getBandOffsets(); int dstPixelStride = dst.getPixelStride(); int dstScanlineStride = dst.getScanlineStride(); short srcDataArrays[][] = src.getShortDataArrays(); int srcBandOffsets[] = src.getBandOffsets(); int srcPixelStride = src.getPixelStride(); int srcScanlineStride = src.getScanlineStride(); // precalcaculate offsets int centerScanlineOffset = srcScanlineStride; int bottomScanlineOffset = srcScanlineStride * 2; int middlePixelOffset = dnumBands; int rightPixelOffset = dnumBands * 2; float kdata[] = kernel.getKernelData(); float k0 = kdata[0], k1 = kdata[1], k2 = kdata[2], k3 = kdata[3], k4 = kdata[4], k5 = kdata[5], k6 = kdata[6], k7 = kdata[7], k8 = kdata[8]; // X,Y positions int x0 = 0; int y0 = 0; int srcX = src.getX(); int srcY = src.getY(); // Valid data if (caseA || (caseB && roiContainsTile)) { for (int k = 0; k < dnumBands; k++) { short dstData[] = dstDataArrays[k]; short srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; for (int i = 0; i < dwidth; i++) { short s0 = srcData[srcPixelOffset]; short s1 = srcData[srcPixelOffset + middlePixelOffset]; short s2 = srcData[srcPixelOffset + rightPixelOffset]; short s3 = srcData[srcPixelOffset + centerScanlineOffset]; short s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; short s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; short s6 = srcData[srcPixelOffset + bottomScanlineOffset]; short s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; short s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; float f = k0 * s0 + k1 * s1 + k2 * s2 + k3 * s3 + k4 * s4 + k5 * s5 + k6 * s6 + k7 * s7 + k8 * s8; dstData[dstPixelOffset] = ImageUtil.clampRoundShort(f); srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // ROI Check } else if (caseB) { for (int k = 0; k < dnumBands; k++) { short dstData[] = dstDataArrays[k]; short srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; y0 = srcY + j; for (int i = 0; i < dwidth; i++) { x0 = srcX + i; boolean inROI = false; // ROI Check for (int y = 0; y < kh && !inROI; y++) { int yI = y0 + y; for (int x = 0; x < kw && !inROI; x++) { int xI = x0 + x; if (roiBounds.contains(xI, yI) && roiIter.getSample(xI, yI, 0) > 0) { inROI = true; } } } short s0 = srcData[srcPixelOffset]; short s1 = srcData[srcPixelOffset + middlePixelOffset]; short s2 = srcData[srcPixelOffset + rightPixelOffset]; short s3 = srcData[srcPixelOffset + centerScanlineOffset]; short s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; short s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; short s6 = srcData[srcPixelOffset + bottomScanlineOffset]; short s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; short s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; float f = k0 * s0 + k1 * s1 + k2 * s2 + k3 * s3 + k4 * s4 + k5 * s5 + k6 * s6 + k7 * s7 + k8 * s8; if (inROI) { dstData[dstPixelOffset] = ImageUtil.clampRoundShort(f); } else { dstData[dstPixelOffset] = destNoDataShort; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // NoData Check } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { for (int k = 0; k < dnumBands; k++) { short dstData[] = dstDataArrays[k]; short srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; for (int i = 0; i < dwidth; i++) { short s0 = srcData[srcPixelOffset]; short s1 = srcData[srcPixelOffset + middlePixelOffset]; short s2 = srcData[srcPixelOffset + rightPixelOffset]; short s3 = srcData[srcPixelOffset + centerScanlineOffset]; short s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; short s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; short s6 = srcData[srcPixelOffset + bottomScanlineOffset]; short s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; short s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; boolean isValid = true; // Boolean indicating NoData values boolean nod0 = noData.contains(s0); boolean nod1 = noData.contains(s1); boolean nod2 = noData.contains(s2); boolean nod3 = noData.contains(s3); boolean nod4 = noData.contains(s4); boolean nod5 = noData.contains(s5); boolean nod6 = noData.contains(s6); boolean nod7 = noData.contains(s7); boolean nod8 = noData.contains(s8); // Check if nodata must be skipped if (skipNoData) { isValid = !(nod0 || nod1 || nod2 || nod3 || nod4 || nod5 || nod6 || nod7 || nod8); } // NoData Check if (isValid) { float f = k0 * (nod0 ? 0 : s0) + k1 * (nod1 ? 0 : s1) + k2 * (nod2 ? 0 : s2) + k3 * (nod3 ? 0 : s3) + k4 * (nod4 ? 0 : s4) + k5 * (nod5 ? 0 : s5) + k6 * (nod6 ? 0 : s6) + k7 * (nod7 ? 0 : s7) + k8 * (nod8 ? 0 : s8); // Clamping data dstData[dstPixelOffset] = ImageUtil.clampRoundShort(f); } else { dstData[dstPixelOffset] = destNoDataShort; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // ROI and NoData Check } else { for (int k = 0; k < dnumBands; k++) { short dstData[] = dstDataArrays[k]; short srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; y0 = srcY + j; for (int i = 0; i < dwidth; i++) { x0 = srcX + i; boolean inROI = false; // ROI Check for (int y = 0; y < kh && !inROI; y++) { int yI = y0 + y; for (int x = 0; x < kw && !inROI; x++) { int xI = x0 + x; if (roiBounds.contains(xI, yI) && roiIter.getSample(xI, yI, 0) > 0) { inROI = true; } } } short s0 = srcData[srcPixelOffset]; short s1 = srcData[srcPixelOffset + middlePixelOffset]; short s2 = srcData[srcPixelOffset + rightPixelOffset]; short s3 = srcData[srcPixelOffset + centerScanlineOffset]; short s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; short s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; short s6 = srcData[srcPixelOffset + bottomScanlineOffset]; short s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; short s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; boolean isValid = true; // Boolean indicating NoData values boolean nod0 = noData.contains(s0); boolean nod1 = noData.contains(s1); boolean nod2 = noData.contains(s2); boolean nod3 = noData.contains(s3); boolean nod4 = noData.contains(s4); boolean nod5 = noData.contains(s5); boolean nod6 = noData.contains(s6); boolean nod7 = noData.contains(s7); boolean nod8 = noData.contains(s8); // Check if nodata must be skipped if (skipNoData) { isValid = !(nod0 || nod1 || nod2 || nod3 || nod4 || nod5 || nod6 || nod7 || nod8); } if (inROI && isValid) { float f = k0 * (nod0 ? 0 : s0) + k1 * (nod1 ? 0 : s1) + k2 * (nod2 ? 0 : s2) + k3 * (nod3 ? 0 : s3) + k4 * (nod4 ? 0 : s4) + k5 * (nod5 ? 0 : s5) + k6 * (nod6 ? 0 : s6) + k7 * (nod7 ? 0 : s7) + k8 * (nod8 ? 0 : s8); // Clamping data dstData[dstPixelOffset] = ImageUtil.clampRoundShort(f); } else { dstData[dstPixelOffset] = destNoDataShort; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } } } @Override protected void intLoop(RasterAccessor src, RasterAccessor dst, RandomIter roiIter, boolean roiContainsTile) { int dwidth = dst.getWidth(); int dheight = dst.getHeight(); int dnumBands = dst.getNumBands(); int dstDataArrays[][] = dst.getIntDataArrays(); int dstBandOffsets[] = dst.getBandOffsets(); int dstPixelStride = dst.getPixelStride(); int dstScanlineStride = dst.getScanlineStride(); int srcDataArrays[][] = src.getIntDataArrays(); int srcBandOffsets[] = src.getBandOffsets(); int srcPixelStride = src.getPixelStride(); int srcScanlineStride = src.getScanlineStride(); // precalcaculate offsets int centerScanlineOffset = srcScanlineStride; int bottomScanlineOffset = srcScanlineStride * 2; int middlePixelOffset = dnumBands; int rightPixelOffset = dnumBands * 2; float kdata[] = kernel.getKernelData(); float k0 = kdata[0], k1 = kdata[1], k2 = kdata[2], k3 = kdata[3], k4 = kdata[4], k5 = kdata[5], k6 = kdata[6], k7 = kdata[7], k8 = kdata[8]; // X,Y positions int x0 = 0; int y0 = 0; int srcX = src.getX(); int srcY = src.getY(); // Valid data if (caseA || (caseB && roiContainsTile)) { for (int k = 0; k < dnumBands; k++) { int dstData[] = dstDataArrays[k]; int srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; for (int i = 0; i < dwidth; i++) { int s0 = srcData[srcPixelOffset]; int s1 = srcData[srcPixelOffset + middlePixelOffset]; int s2 = srcData[srcPixelOffset + rightPixelOffset]; int s3 = srcData[srcPixelOffset + centerScanlineOffset]; int s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; int s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; int s6 = srcData[srcPixelOffset + bottomScanlineOffset]; int s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; int s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; float f = k0 * s0 + k1 * s1 + k2 * s2 + k3 * s3 + k4 * s4 + k5 * s5 + k6 * s6 + k7 * s7 + k8 * s8; dstData[dstPixelOffset] = ImageUtil.clampRoundInt(f); srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // ROI Check } else if (caseB) { for (int k = 0; k < dnumBands; k++) { int dstData[] = dstDataArrays[k]; int srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; y0 = srcY + j; for (int i = 0; i < dwidth; i++) { x0 = srcX + i; boolean inROI = false; // ROI Check for (int y = 0; y < kh && !inROI; y++) { int yI = y0 + y; for (int x = 0; x < kw && !inROI; x++) { int xI = x0 + x; if (roiBounds.contains(xI, yI) && roiIter.getSample(xI, yI, 0) > 0) { inROI = true; } } } int s0 = srcData[srcPixelOffset]; int s1 = srcData[srcPixelOffset + middlePixelOffset]; int s2 = srcData[srcPixelOffset + rightPixelOffset]; int s3 = srcData[srcPixelOffset + centerScanlineOffset]; int s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; int s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; int s6 = srcData[srcPixelOffset + bottomScanlineOffset]; int s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; int s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; float f = k0 * s0 + k1 * s1 + k2 * s2 + k3 * s3 + k4 * s4 + k5 * s5 + k6 * s6 + k7 * s7 + k8 * s8; if (inROI) { dstData[dstPixelOffset] = ImageUtil.clampRoundInt(f); } else { dstData[dstPixelOffset] = destNoDataInt; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // NoData Check } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { for (int k = 0; k < dnumBands; k++) { int dstData[] = dstDataArrays[k]; int srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; for (int i = 0; i < dwidth; i++) { int s0 = srcData[srcPixelOffset]; int s1 = srcData[srcPixelOffset + middlePixelOffset]; int s2 = srcData[srcPixelOffset + rightPixelOffset]; int s3 = srcData[srcPixelOffset + centerScanlineOffset]; int s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; int s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; int s6 = srcData[srcPixelOffset + bottomScanlineOffset]; int s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; int s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; boolean isValid = true; // Boolean indicating NoData values boolean nod0 = noData.contains(s0); boolean nod1 = noData.contains(s1); boolean nod2 = noData.contains(s2); boolean nod3 = noData.contains(s3); boolean nod4 = noData.contains(s4); boolean nod5 = noData.contains(s5); boolean nod6 = noData.contains(s6); boolean nod7 = noData.contains(s7); boolean nod8 = noData.contains(s8); // Check if nodata must be skipped if (skipNoData) { isValid = !(nod0 || nod1 || nod2 || nod3 || nod4 || nod5 || nod6 || nod7 || nod8); } if (isValid) { float f = k0 * (nod0 ? 0 : s0) + k1 * (nod1 ? 0 : s1) + k2 * (nod2 ? 0 : s2) + k3 * (nod3 ? 0 : s3) + k4 * (nod4 ? 0 : s4) + k5 * (nod5 ? 0 : s5) + k6 * (nod6 ? 0 : s6) + k7 * (nod7 ? 0 : s7) + k8 * (nod8 ? 0 : s8); // Clamping data dstData[dstPixelOffset] = ImageUtil.clampRoundInt(f); } else { dstData[dstPixelOffset] = destNoDataInt; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } // ROI and No Data Check } else { for (int k = 0; k < dnumBands; k++) { int dstData[] = dstDataArrays[k]; int srcData[] = srcDataArrays[k]; int srcScanlineOffset = srcBandOffsets[k]; int dstScanlineOffset = dstBandOffsets[k]; for (int j = 0; j < dheight; j++) { int srcPixelOffset = srcScanlineOffset; int dstPixelOffset = dstScanlineOffset; y0 = srcY + j; for (int i = 0; i < dwidth; i++) { x0 = srcX + i; boolean inROI = false; // ROI Check for (int y = 0; y < kh && !inROI; y++) { int yI = y0 + y; for (int x = 0; x < kw && !inROI; x++) { int xI = x0 + x; if (roiBounds.contains(xI, yI) && roiIter.getSample(xI, yI, 0) > 0) { inROI = true; } } } int s0 = srcData[srcPixelOffset]; int s1 = srcData[srcPixelOffset + middlePixelOffset]; int s2 = srcData[srcPixelOffset + rightPixelOffset]; int s3 = srcData[srcPixelOffset + centerScanlineOffset]; int s4 = srcData[srcPixelOffset + centerScanlineOffset + middlePixelOffset]; int s5 = srcData[srcPixelOffset + centerScanlineOffset + rightPixelOffset]; int s6 = srcData[srcPixelOffset + bottomScanlineOffset]; int s7 = srcData[srcPixelOffset + bottomScanlineOffset + middlePixelOffset]; int s8 = srcData[srcPixelOffset + bottomScanlineOffset + rightPixelOffset]; boolean isValid = true; // Boolean indicating NoData values boolean nod0 = noData.contains(s0); boolean nod1 = noData.contains(s1); boolean nod2 = noData.contains(s2); boolean nod3 = noData.contains(s3); boolean nod4 = noData.contains(s4); boolean nod5 = noData.contains(s5); boolean nod6 = noData.contains(s6); boolean nod7 = noData.contains(s7); boolean nod8 = noData.contains(s8); // Check if nodata must be skipped if (skipNoData) { isValid = !(nod0 || nod1 || nod2 || nod3 || nod4 || nod5 || nod6 || nod7 || nod8); } if (inROI && isValid) { float f = k0 * (nod0 ? 0 : s0) + k1 * (nod1 ? 0 : s1) + k2 * (nod2 ? 0 : s2) + k3 * (nod3 ? 0 : s3) + k4 * (nod4 ? 0 : s4) + k5 * (nod5 ? 0 : s5) + k6 * (nod6 ? 0 : s6) + k7 * (nod7 ? 0 : s7) + k8 * (nod8 ? 0 : s8); // Clamping data dstData[dstPixelOffset] = ImageUtil.clampRoundInt(f); } else { dstData[dstPixelOffset] = destNoDataInt; } srcPixelOffset += srcPixelStride; dstPixelOffset += dstPixelStride; } srcScanlineOffset += srcScanlineStride; dstScanlineOffset += dstScanlineStride; } } } } @Override protected void ushortLoop(RasterAccessor src, RasterAccessor dst, RandomIter roiIter, boolean roiContainsTile) { throw new UnsupportedOperationException(JaiI18N.getString("Convolve3x3OpImage1")); } @Override protected void floatLoop(RasterAccessor src, RasterAccessor dst, RandomIter roiIter, boolean roiContainsTile) { throw new UnsupportedOperationException(JaiI18N.getString("Convolve3x3OpImage1")); } @Override protected void doubleLoop(RasterAccessor src, RasterAccessor dst, RandomIter roiIter, boolean roiContainsTile) { throw new UnsupportedOperationException(JaiI18N.getString("Convolve3x3OpImage1")); } }