/* 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.scale;
import static org.junit.Assert.*;
import it.geosolutions.jaiext.interpolators.InterpolationBicubic;
import it.geosolutions.jaiext.interpolators.InterpolationBilinear;
import it.geosolutions.jaiext.interpolators.InterpolationNearest;
import it.geosolutions.jaiext.scale.ScaleDescriptor;
import it.geosolutions.jaiext.testclasses.TestData;
import it.geosolutions.rendered.viewer.RenderedImageBrowser;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.stream.FileImageInputStream;
import javax.media.jai.BorderExtender;
import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROIShape;
import javax.media.jai.RenderedOp;
import org.junit.Test;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
/**
* This class extends the TestScale class and tests the Scale operation on a RGB image. If the user want to see the result, must set the
* JAI.Ext.Interactive parameter to true, JAI.Ext.TestSelector from 0 to 2 (the 3 interpolation types) and JAI.Ext.InverseScale to 0 or 1
* (Magnification/reduction) to the Console. The ROI is created by the roiCreation() method and its height and width are half of the RGB image height
* and width. The 3 tests with the different interpolation types are executed by calling 3 times the testImage() method and changing each time the
* selected interpolation.
*/
public class ImageRGBTest extends TestScale {
/** RGB image width */
private int imageWidth;
/** RGB image height */
private int imageHeigth;
/** Destination No Data value */
protected double destinationNoData = 255;
@Test
public void testInterpolationScale() throws Throwable {
boolean bicubic2Disabled = true;
boolean useROIAccessor = true;
boolean roiUsed = true;
TIFFImageReader reader = null;
FileImageInputStream stream_in = null;
try {
// Instantiation of the file-reader
reader = (TIFFImageReader) new TIFFImageReaderSpi().createReaderInstance();
//File inputFile = new File("../jt-utilities/src/test/resources/it/geosolutions/jaiext/images/testImageLittle.tif");
File inputFile = TestData.file(this, "testImageLittle.tif");
// Instantiation of the imageinputstream and imageoutputstrem
stream_in = new FileImageInputStream(inputFile);
// Setting the inputstream to the reader
reader.setInput(stream_in);
// Creation of a Renderedimage to store the image
RenderedImage image = reader.readAsRenderedImage(0, null);
imageWidth = image.getWidth();
imageHeigth = image.getHeight();
int dataType = image.getSampleModel().getDataType();
testImage(image, useROIAccessor, roiUsed, bicubic2Disabled, ScaleType.MAGNIFY,
dataType, InterpolationType.NEAREST_INTERP);
testImage(image, useROIAccessor, roiUsed, bicubic2Disabled, ScaleType.MAGNIFY,
dataType, InterpolationType.BILINEAR_INTERP);
testImage(image, useROIAccessor, roiUsed, bicubic2Disabled, ScaleType.MAGNIFY,
dataType, InterpolationType.BICUBIC_INTERP);
testImage(image, useROIAccessor, roiUsed, bicubic2Disabled, ScaleType.REDUCTION,
dataType, InterpolationType.NEAREST_INTERP);
testImage(image, useROIAccessor, roiUsed, bicubic2Disabled, ScaleType.REDUCTION,
dataType, InterpolationType.BILINEAR_INTERP);
testImage(image, useROIAccessor, roiUsed, bicubic2Disabled, ScaleType.REDUCTION,
dataType, InterpolationType.BICUBIC_INTERP);
} finally {
try {
if (reader != null) {
reader.dispose();
}
} catch (Exception e) {
}
try {
if (stream_in != null) {
stream_in.flush();
stream_in.close();
}
} catch (Exception e) {
}
}
}
protected ROIShape roiCreation() {
int roiHeight = imageHeigth / 2;
int roiWidth = imageWidth / 2;
Rectangle roiBound = new Rectangle(0, 0, roiWidth, roiHeight);
ROIShape roi = new ROIShape(roiBound);
return roi;
}
private void testImage(RenderedImage sourceImage, boolean useROIAccessor, boolean roiUsed,
boolean bicubic2Disabled, ScaleType scaleValue, int dataType,
InterpolationType interpType) {
if (scaleValue == ScaleType.REDUCTION) {
scaleX = 0.5f;
scaleY = 0.5f;
} else {
scaleX = 1.5f;
scaleY = 1.5f;
}
// Hints are used only with roiAccessor
RenderingHints hints = null;
// ROI creation
ROIShape roi = null;
if (roiUsed) {
if (useROIAccessor) {
hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
BorderExtender.createInstance(BorderExtender.BORDER_ZERO));
}
roi = roiCreation();
} else {
useROIAccessor = false;
}
// Interpolator initialization
Interpolation interp = null;
// Interpolators
switch (interpType) {
case NEAREST_INTERP:
// Nearest-Neighbor
interp = new javax.media.jai.InterpolationNearest();
break;
case BILINEAR_INTERP:
// Bilinear
interp = new javax.media.jai.InterpolationBilinear(DEFAULT_SUBSAMPLE_BITS);
if (hints != null) {
hints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender
.createInstance(BorderExtender.BORDER_COPY)));
} else {
hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
BorderExtender.createInstance(BorderExtender.BORDER_COPY));
}
break;
case BICUBIC_INTERP:
// Bicubic
interp = new javax.media.jai.InterpolationBicubic(DEFAULT_SUBSAMPLE_BITS);
if (hints != null) {
hints.add(new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender
.createInstance(BorderExtender.BORDER_COPY)));
} else {
hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER,
BorderExtender.createInstance(BorderExtender.BORDER_COPY));
}
break;
default:
throw new IllegalArgumentException("...");
}
// Scale operation
RenderedImage destinationIMG = ScaleDescriptor.create(sourceImage, scaleX, scaleY,
transX, transY, interp, roi, useROIAccessor, null, null, hints);
if (INTERACTIVE && TEST_SELECTOR == interpType.getType()
&& INVERSE_SCALE == scaleValue.getType()) {
RenderedImageBrowser.showChain(destinationIMG, false, roiUsed);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
} else {
// Forcing to retrieve an array of all the image tiles
// image tile calculation for searching possible errors
((PlanarImage) destinationIMG).getTiles();
}
// Check minimum and maximum value for a tile
Raster simpleTile = destinationIMG.getTile(destinationIMG.getMinTileX(),
destinationIMG.getMinTileY());
int tileWidth = simpleTile.getWidth();
int tileHeight = simpleTile.getHeight();
int minValue = Integer.MAX_VALUE;
int maxValue = Integer.MIN_VALUE;
for (int i = 0; i < tileHeight; i++) {
for (int j = 0; j < tileWidth; j++) {
int value = simpleTile.getSample(j, i, 0);
if (value > maxValue) {
maxValue = value;
}
if (value < minValue) {
minValue = value;
}
}
}
// Check if the values are not max and minimum value
assertFalse(minValue == maxValue);
assertFalse(minValue == Integer.MAX_VALUE);
assertFalse(maxValue == Integer.MIN_VALUE);
// Control if the ROI has been expanded
PlanarImage planarIMG = (PlanarImage) destinationIMG;
int imgWidthROI = destinationIMG.getWidth() / 2 - 1;
int imgHeightROI = destinationIMG.getHeight() / 2 - 1;
int tileInROIx = planarIMG.XToTileX(imgWidthROI);
int tileInROIy = planarIMG.YToTileY(imgHeightROI);
Raster testTile = destinationIMG.getTile(tileInROIx, tileInROIy);
int value = testTile.getSample(testTile.getMinX() + 2, testTile.getMinY() + 2, 0);
assertFalse(value == (int) destinationNoData);
// Control if the scale operation has been correctly performed
// width
assertEquals((int) (imageWidth * scaleX), destinationIMG.getWidth());
// height
assertEquals((int) (imageHeigth * scaleY), destinationIMG.getHeight());
//Final Image disposal
if(destinationIMG instanceof RenderedOp){
((RenderedOp)destinationIMG).dispose();
}
}
}