/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2013 Andreas Maschke
This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
This software 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this software;
if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.create.tina.randomflame;
import static org.jwildfire.base.mathlib.MathLib.fabs;
import org.jwildfire.base.Prefs;
import org.jwildfire.create.tina.base.Flame;
import org.jwildfire.create.tina.base.Layer;
import org.jwildfire.create.tina.palette.RGBPalette;
import org.jwildfire.create.tina.randomgradient.RandomGradientGenerator;
import org.jwildfire.create.tina.randomsymmetry.RandomSymmetryGenerator;
import org.jwildfire.create.tina.render.FlameRenderer;
import org.jwildfire.create.tina.render.RenderInfo;
import org.jwildfire.create.tina.render.RenderMode;
import org.jwildfire.create.tina.render.RenderedFlame;
import org.jwildfire.create.tina.swing.RandomBatchQuality;
import org.jwildfire.image.Pixel;
import org.jwildfire.image.SimpleImage;
import org.jwildfire.transform.ConvolveTransformer;
import org.jwildfire.transform.ConvolveTransformer.KernelType;
import org.jwildfire.transform.PixelizeTransformer;
public class RandomFlameGeneratorSampler {
private final int imageWidth;
private final int imageHeight;
private final Prefs prefs;
private final int paletteSize;
private final boolean fadePaletteColors;
private RandomFlameGenerator randGen;
private RandomSymmetryGenerator randSymmGen;
private RandomGradientGenerator randGradientGen;
private final RandomBatchQuality quality;
public RandomFlameGeneratorSampler(int pImageWidth, int pImageHeight, Prefs pPrefs, RandomFlameGenerator pRandGen, RandomSymmetryGenerator pRandSymmGen, RandomGradientGenerator pRandGradientGen, int pPaletteSize, boolean pFadePaletteColors, RandomBatchQuality pQuality) {
imageWidth = pImageWidth;
imageHeight = pImageHeight;
prefs = pPrefs;
randGen = pRandGen;
randSymmGen = pRandSymmGen;
randGradientGen = pRandGradientGen;
paletteSize = pPaletteSize;
fadePaletteColors = pFadePaletteColors;
quality = pQuality;
}
public static double calculateCoverage(SimpleImage pImg, int bgRed, int bgGreen, int bgBlue, boolean useFilter) {
SimpleImage img;
if (useFilter) {
SimpleImage filteredImg = new SimpleImage(pImg.getBufferedImg(), pImg.getImageWidth(), pImg.getImageHeight());
ConvolveTransformer transformer = new ConvolveTransformer();
transformer.initDefaultParams(filteredImg);
transformer.setKernelType(KernelType.SOBEL_3X3);
transformer.transformImage(filteredImg);
img = filteredImg;
}
else {
img = pImg;
}
long maxCoverage = img.getImageWidth() * img.getImageHeight();
long coverage = 0;
Pixel pixel = new Pixel();
if (bgRed == 0 && bgGreen == 0 && bgBlue == 0) {
for (int k = 0; k < img.getImageHeight(); k++) {
for (int l = 0; l < img.getImageWidth(); l++) {
pixel.setARGBValue(img.getARGBValue(l, k));
if (pixel.r > 29 || pixel.g > 15 || pixel.b > 78) {
coverage++;
}
}
}
}
else {
for (int k = 0; k < img.getImageHeight(); k++) {
for (int l = 0; l < img.getImageWidth(); l++) {
pixel.setARGBValue(img.getARGBValue(l, k));
if (Math.abs(pixel.r - bgRed) > 29.0 && Math.abs(pixel.g - bgGreen) > 15.0 && Math.abs(pixel.b - bgBlue) > 78.0) {
coverage++;
}
}
}
}
return (double) coverage / (double) maxCoverage;
}
public RandomFlameGeneratorSample createSample() {
RenderInfo info = new RenderInfo(imageWidth, imageHeight, RenderMode.PREVIEW);
Flame bestFlame = null;
int bgRed = prefs.getTinaRandomBatchBGColorRed();
int bgGreen = prefs.getTinaRandomBatchBGColorGreen();
int bgBlue = prefs.getTinaRandomBatchBGColorBlue();
RandomFlameGeneratorState randGenState = randGen.initState(prefs, randGradientGen);
double bestCoverage = 0.0;
for (int j = 0; j < quality.getMaxSamples(); j++) {
// create flame
Flame flame;
try {
flame = randGen.createFlame(prefs, randGenState);
randSymmGen.addSymmetry(flame);
}
catch (Exception ex) {
flame = new Flame();
ex.printStackTrace();
}
flame.setWidth(imageWidth);
flame.setHeight(imageHeight);
flame.setPixelsPerUnit(10);
flame.setSpatialFilterRadius(0.0);
for (Layer layer : flame.getLayers()) {
RGBPalette palette = randGradientGen.generatePalette(paletteSize, fadePaletteColors);
layer.setPalette(palette);
}
flame = randGen.postProcessFlame(randGenState, flame);
// render it
flame.setSampleDensity(25);
RenderedFlame renderedFlame;
flame.setAntialiasAmount(0.0);
try {
FlameRenderer renderer = new FlameRenderer(flame, prefs, false, true);
renderedFlame = renderer.renderFlame(info);
}
finally {
flame.setAntialiasAmount(prefs.getTinaDefaultAntialiasingAmount());
}
if (j == quality.getMaxSamples() - 1) {
renderedFlame = new FlameRenderer(bestFlame, prefs, false, true).renderFlame(info);
return new RandomFlameGeneratorSample(bestFlame, renderedFlame.getImage());
}
else {
double fCoverage = calculateCoverage(renderedFlame.getImage(), bgRed, bgGreen, bgBlue, randGen.isUseFilter(randGenState));
if (fCoverage >= quality.getCoverage()) {
return new RandomFlameGeneratorSample(flame, renderedFlame.getImage());
}
else {
if (bestFlame == null || fCoverage > bestCoverage) {
bestFlame = flame;
bestCoverage = fCoverage;
}
}
}
}
throw new IllegalStateException();
}
public static SimpleImage createSimplifiedRefImage(SimpleImage pImg) {
SimpleImage img = pImg.clone();
PixelizeTransformer pT = new PixelizeTransformer();
pT.setCentre(false);
pT.setGridSize(5);
pT.transformImage(img);
return img;
}
public static double calculateDiffCoverage(SimpleImage pImg, SimpleImage pSimplifiedRefImg) {
SimpleImage img = createSimplifiedRefImage(pImg);
long maxCoverage = img.getImageWidth() * img.getImageHeight();
long coverage = 0;
Pixel pixel = new Pixel();
Pixel refPixel = new Pixel();
for (int k = 0; k < img.getImageHeight(); k++) {
for (int l = 0; l < img.getImageWidth(); l++) {
pixel.setARGBValue(img.getARGBValue(l, k));
refPixel.setARGBValue(pSimplifiedRefImg.getARGBValue(l, k));
if (fabs(pixel.r - refPixel.r) > 29.0 || fabs(pixel.g - refPixel.g) > 15.0 || fabs(pixel.b - refPixel.b) > 78.0) {
coverage++;
}
}
}
// System.out.println((double) coverage / (double) maxCoverage);
return (double) coverage / (double) maxCoverage;
}
}