/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.jai.opimage;
import com.bc.ceres.jai.operator.InterpretationType;
import com.bc.ceres.jai.operator.ReinterpretDescriptor;
import com.bc.ceres.jai.operator.ScalingType;
import org.junit.Ignore;
import org.junit.Test;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import javax.media.jai.operator.ConstantDescriptor;
import java.awt.RenderingHints;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import static com.bc.ceres.jai.operator.ReinterpretDescriptor.AWT;
import static com.bc.ceres.jai.operator.ReinterpretDescriptor.EXPONENTIAL;
import static com.bc.ceres.jai.operator.ReinterpretDescriptor.INTERPRET_BYTE_SIGNED;
import static com.bc.ceres.jai.operator.ReinterpretDescriptor.INTERPRET_INT_UNSIGNED;
import static com.bc.ceres.jai.operator.ReinterpretDescriptor.LINEAR;
import static com.bc.ceres.jai.operator.ReinterpretDescriptor.LOGARITHMIC;
import static org.junit.Assert.assertEquals;
public class ReinterpretOpImageTest {
private static final int W = 10;
private static final int H = 10;
@Test
public void testRescaleByte() {
testRescale(new Byte[]{-1}, 11.0, 1.0, LINEAR, AWT,
DataBuffer.TYPE_FLOAT, 255 * 11.0 + 1.0);
}
@Test
public void testRescaleSByte() {
testRescale(new Byte[]{-1}, 11.0, 1.0, LINEAR, INTERPRET_BYTE_SIGNED,
DataBuffer.TYPE_FLOAT, -1 * 11.0 + 1.0);
}
@Test
public void testRescaleInt() {
testRescale(new Integer[]{-1}, 11.0, 1.0, LINEAR, AWT,
DataBuffer.TYPE_DOUBLE, -1 * 11.0 + 1.0);
}
@Test
public void testRescaleUInt() {
testRescale(new Integer[]{-1}, 11.0, 1.0, LINEAR, INTERPRET_INT_UNSIGNED,
DataBuffer.TYPE_DOUBLE, (((long) 1 << 32) - 1) * 11.0 + 1.0);
}
@Test
public void testRescaleFloatLin() {
testRescale(new Float[]{0.1f}, 11.0, 1.0, LINEAR, AWT,
DataBuffer.TYPE_FLOAT, 0.1f * 11.0 + 1.0);
}
@Test
public void testRescaleFloatExp10() {
testRescale(new Float[]{0.1f}, 11.0, 1.0, EXPONENTIAL, AWT,
DataBuffer.TYPE_FLOAT, Math.pow(10, 0.1f * 11.0 + 1.0));
}
@Test
public void testRescaleFloatLog10() {
testRescale(new Float[]{0.1f}, 11.0, 1.0, LOGARITHMIC, AWT,
DataBuffer.TYPE_FLOAT, Math.log10(0.1 * 11.0 + 1.0));
}
@Test
public void testRescaleByteExp10() {
testRescale(new Byte[]{-1}, 1.0 / 255.0, 1.0, EXPONENTIAL, AWT,
DataBuffer.TYPE_FLOAT, Math.pow(10, 1.0 + 1.0));
testRescale(new Byte[]{-1}, 1.0 / 255.0, 1.0, EXPONENTIAL, INTERPRET_BYTE_SIGNED,
DataBuffer.TYPE_FLOAT, Math.pow(10, -1.0 / 255.0 + 1.0));
}
@Test
public void testRescaleByteLog10() {
testRescale(new Byte[]{-1}, 1.0 / 255.0, 1.0, LOGARITHMIC, AWT,
DataBuffer.TYPE_FLOAT, Math.log10(1.0 + 1.0));
testRescale(new Byte[]{-1}, 1.0 / 255.0, 1.0, LOGARITHMIC, INTERPRET_BYTE_SIGNED,
DataBuffer.TYPE_FLOAT, Math.log10(-1.0 / 255.0 + 1.0));
}
private void testRescale(Number[] sourcePixelValue, double factor, double offset, ScalingType scalingType, InterpretationType interpretationType, int expectedDataType, double expectedPixelValue) {
final RenderedImage target = ReinterpretOpImage.create(createSourceImage(sourcePixelValue), factor, offset, scalingType, interpretationType, null);
assertEquals(expectedDataType, target.getSampleModel().getDataType());
final Raster targetData = target.getData();
assertEquals(expectedPixelValue, targetData.getSampleDouble(0, 0, 0), expectedDataType == DataBuffer.TYPE_DOUBLE ? 1e-10 : 1e-5);
}
@Test
@Ignore
public void testScalingTypePerformance() {
testScalingTypePerformance(LINEAR);
testScalingTypePerformance(EXPONENTIAL);
testScalingTypePerformance(LOGARITHMIC);
}
private void testScalingTypePerformance(ScalingType scalingType) {
int size = 2 * 1024; // = 4 mega-pixels
RenderedOp sourceImage = ConstantDescriptor.create((float) size, (float) size, new Byte[]{1}, null);
RenderedImage renderedImage = ReinterpretOpImage.create(sourceImage, 1.1, 0.1, scalingType, AWT, null);
int n = 10;
double sum = 0;
for (int i = 0; i < n; i++) {
long t0 = System.currentTimeMillis();
renderedImage.getData();
long t1 = System.currentTimeMillis();
sum += t1 - t0;
}
System.out.println(scalingType + ": " + sum/n + " ms for " + size*size + " pixels");
}
@Test
public void testImageLayout() {
int w = 1121;
int h = 2000;
final RenderedImage source = createSourceImage(w, h, w, 64, new Integer[]{0});
final SampleModel sampleModel = source.getSampleModel().createCompatibleSampleModel(w, h);
final ImageLayout imageLayout = ReinterpretDescriptor.createTargetImageLayout(source, sampleModel);
final RenderedImage target = ReinterpretDescriptor.create(source, 11.0, 1.0, LINEAR, AWT, new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout));
assertEquals(w, target.getWidth());
assertEquals(h, target.getHeight());
assertEquals(w, target.getTileWidth());
assertEquals(64, target.getTileHeight());
}
static RenderedImage createSourceImage(Number[] v) {
return ConstantDescriptor.create((float) W, (float) H, v, null);
}
static RenderedImage createSourceImage(int w, int h, int tw, int th, Number[] v) {
ImageLayout imageLayout = new ImageLayout(0, 0, w, h);
imageLayout.setTileWidth(tw);
imageLayout.setTileHeight(th);
return ConstantDescriptor.create((float) w, (float) h, v, new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout));
}
}