/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2011 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.variation; import org.jwildfire.base.Tools; import org.jwildfire.create.tina.base.Layer; import org.jwildfire.create.tina.base.XForm; import org.jwildfire.create.tina.base.XYZPoint; import org.jwildfire.image.Pixel; import org.jwildfire.image.SimpleHDRImage; import org.jwildfire.image.SimpleImage; import org.jwildfire.image.WFImage; public class PostBumpMapWFFunc extends VariationFunc { private static final long serialVersionUID = 1L; private static final String PARAM_SCALEX = "scale_x"; private static final String PARAM_SCALEY = "scale_y"; private static final String PARAM_SCALEZ = "scale_z"; private static final String PARAM_OFFSETX = "offset_x"; private static final String PARAM_OFFSETY = "offset_y"; private static final String PARAM_OFFSETZ = "offset_z"; private static final String PARAM_RESETZ = "reset_z"; private static final String RESSOURCE_IMAGE_FILENAME = "image_filename"; private static final String RESSOURCE_INLINED_IMAGE = "inlined_image"; private static final String[] paramNames = { PARAM_SCALEX, PARAM_SCALEY, PARAM_SCALEZ, PARAM_OFFSETX, PARAM_OFFSETY, PARAM_OFFSETZ, PARAM_RESETZ }; private static final String[] ressourceNames = { RESSOURCE_IMAGE_FILENAME, RESSOURCE_INLINED_IMAGE }; private double scaleX = 1.0; private double scaleY = 1.0; private double scaleZ = 0.2; private double offsetX = 0.0; private double offsetY = 0.0; private double offsetZ = 0.0; private int resetZ = 0; private String imageFilename = null; private byte[] inlinedImage = null; private int inlinedImageHash = 0; // derived params private int imgWidth, imgHeight; private Pixel toolPixel = new Pixel(); private float[] rgbArray = new float[3]; @Override public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) { double x = (pAffineTP.x - offsetX + 1.0) / scaleX * 0.5 * (double) (imgWidth - 1); double y = (pAffineTP.y - offsetY + 1.0) / scaleY * 0.5 * (double) (imgHeight - 1); double dz = offsetZ; int ix = Tools.FTOI(x); int iy = Tools.FTOI(y); if (ix >= 0 && ix < imgWidth && iy >= 0 && iy < imgHeight) { double intensity; if (bumpMap instanceof SimpleImage) { toolPixel.setARGBValue(((SimpleImage) bumpMap).getARGBValue(ix, iy)); double r = toolPixel.r; double g = toolPixel.g; double b = toolPixel.b; intensity = (0.299 * r + 0.588 * g + 0.113 * b) / 255.0; } else { ((SimpleHDRImage) bumpMap).getRGBValues(rgbArray, ix, iy); double r = rgbArray[0]; double g = rgbArray[0]; double b = rgbArray[0]; intensity = (0.299 * r + 0.588 * g + 0.113 * b); } dz += scaleZ * intensity; if (resetZ != 0) { pVarTP.z = dz; } else { pVarTP.z += dz; } } } @Override public String[] getParameterNames() { return paramNames; } @Override public Object[] getParameterValues() { return new Object[] { scaleX, scaleY, scaleZ, offsetX, offsetY, offsetZ, resetZ }; } @Override public void setParameter(String pName, double pValue) { if (PARAM_SCALEX.equalsIgnoreCase(pName)) scaleX = pValue; else if (PARAM_SCALEY.equalsIgnoreCase(pName)) scaleY = pValue; else if (PARAM_SCALEZ.equalsIgnoreCase(pName)) scaleZ = pValue; else if (PARAM_OFFSETX.equalsIgnoreCase(pName)) offsetX = pValue; else if (PARAM_OFFSETY.equalsIgnoreCase(pName)) offsetY = pValue; else if (PARAM_OFFSETZ.equalsIgnoreCase(pName)) offsetZ = pValue; else if (PARAM_RESETZ.equalsIgnoreCase(pName)) resetZ = Tools.FTOI(pValue); else throw new IllegalArgumentException(pName); } @Override public String getName() { return "post_bumpmap_wf"; } private WFImage bumpMap; @Override public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) { bumpMap = null; if (inlinedImage != null) { try { bumpMap = RessourceManager.getImage(inlinedImageHash, inlinedImage); } catch (Exception e) { e.printStackTrace(); } } else if (imageFilename != null && imageFilename.length() > 0) { try { bumpMap = RessourceManager.getImage(imageFilename); } catch (Exception e) { e.printStackTrace(); } } if (bumpMap == null) { bumpMap = new SimpleImage(320, 256); } imgWidth = bumpMap.getImageWidth(); imgHeight = bumpMap.getImageHeight(); } @Override public String[] getRessourceNames() { return ressourceNames; } @Override public byte[][] getRessourceValues() { return new byte[][] { (imageFilename != null ? imageFilename.getBytes() : null), inlinedImage }; } @Override public void setRessource(String pName, byte[] pValue) { if (RESSOURCE_IMAGE_FILENAME.equalsIgnoreCase(pName)) { imageFilename = pValue != null ? new String(pValue) : ""; bumpMap = null; } else if (RESSOURCE_INLINED_IMAGE.equalsIgnoreCase(pName)) { inlinedImage = pValue; inlinedImageHash = RessourceManager.calcHashCode(inlinedImage); bumpMap = null; } else throw new IllegalArgumentException(pName); } @Override public RessourceType getRessourceType(String pName) { if (RESSOURCE_IMAGE_FILENAME.equalsIgnoreCase(pName)) { return RessourceType.IMAGE_FILENAME; } else if (RESSOURCE_INLINED_IMAGE.equalsIgnoreCase(pName)) { return RessourceType.IMAGE_FILE; } else throw new IllegalArgumentException(pName); } }