/*
* 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;
import static com.bc.ceres.jai.DFTTestMain.showImage;
import com.bc.ceres.jai.operator.DFTConvolveDescriptor;
import com.bc.ceres.jai.opimage.DFTConvolveRIF;
import com.bc.ceres.jai.tilecache.SwappingTileCache;
import com.bc.ceres.jai.tilecache.DefaultSwapSpace;
import javax.media.jai.BorderExtender;
import javax.media.jai.JAI;
import javax.media.jai.KernelJAI;
import javax.media.jai.RenderedOp;
import javax.media.jai.operator.ConvolveDescriptor;
import javax.media.jai.operator.FileLoadDescriptor;
import javax.media.jai.operator.MultiplyConstDescriptor;
import javax.media.jai.operator.SubtractDescriptor;
import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import java.io.File;
import java.util.logging.Logger;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
public class DFTConvolveTestMain {
private static final long M = 1024L*1024L;
public static void main(String[] args) {
final File swapDir = new File("swap");
swapDir.mkdir();
final Logger logger = Logger.getAnonymousLogger();
final ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.ALL);
logger.addHandler(consoleHandler);
logger.setLevel(Level.ALL);
final DefaultSwapSpace swapSpace = new DefaultSwapSpace(swapDir, logger);
final SwappingTileCache tileCache = new SwappingTileCache(64 * M, swapSpace);
JAI.getDefaultInstance().setTileCache(tileCache);
RenderedImage sourceImage;
if (args.length == 0) {
sourceImage = DFTTestMain.createTestImage(512, 512);
} else {
sourceImage = FileLoadDescriptor.create(args[0], null, false, null);
}
sourceImage = DFTConvolveRIF.toFloat(sourceImage, null);
BorderExtender extender = BorderExtender.createInstance(BorderExtender.BORDER_COPY);
RenderingHints hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER, extender);
KernelJAI kernel = createBlurrKernel(33);
RenderedOp convolvedImage = ConvolveDescriptor.create(sourceImage, kernel, hints);
RenderedOp dftConvolvedImage = DFTConvolveDescriptor.create(sourceImage, kernel, null, hints);
RenderedOp deltaImage = MultiplyConstDescriptor.create(SubtractDescriptor.create(convolvedImage, dftConvolvedImage, null), new double[]{2}, null);
showImage(sourceImage, "sourceImage");
showImage(convolvedImage, "convolvedImage");
showImage(dftConvolvedImage, "dftConvolvedImage");
showImage(deltaImage, "deltaImage");
final Object o = dftConvolvedImage.getProperty("kernelFT");
System.out.println("o = " + o);
System.out.println("Kernel\tConvolve\tDFTConvolve\tPerfGain");
for (int i = 3; i <= 201; i += 2) {
KernelJAI k = createBlurrKernel(i);
double t1 = getRenderTime(ConvolveDescriptor.create(sourceImage, k, hints));
double t2 = getRenderTime(DFTConvolveDescriptor.create(sourceImage, k, null, hints));
System.out.println(i + "\t" + t1 + "\t" + t2 + "\t" + t1 / t2);
}
}
private static double getRenderTime(RenderedOp op) {
long t0 = System.nanoTime();
op.getAsBufferedImage();
long t1 = System.nanoTime();
return (t1 - t0) / (1000.0 * 1000.0);
}
private static KernelJAI createBlurrKernel(int size) {
float[] data = new float[size * size];
for (int j = 0; j < size; j++) {
for (int i = 0; i < size; i++) {
float dx = i / (size - 1.0f) - 0.5f;
float dy = j / (size - 1.0f) - 0.5f;
float v = 1.0f - (float) Math.sqrt(dx * dx + dy * dy);
data[j * size + i] = v < 0 ? 0 : v;
}
}
float sum = 0;
for (int i = 0; i < data.length; i++) {
sum += data[i];
}
for (int i = 0; i < data.length; i++) {
data[i] /= sum;
}
return new KernelJAI(size, size, data);
}
private static KernelJAI createIdentityKernel(int size) {
float[] data = new float[size * size];
data[size / 2 * size + size / 2] = 1;
return new KernelJAI(size, size, data);
}
}