/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2016 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.image; import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import org.jwildfire.base.Tools; import org.jwildfire.base.mathlib.GfxMathLib; import org.jwildfire.base.mathlib.MathLib; public class SimpleImage implements WFImage, Cloneable { private int imageWidth = -1; private int imageHeight = -1; private BufferedImage bufferedImg; public SimpleImage(int pWidth, int pHeight) { bufferedImg = new BufferedImage(pWidth, pHeight, BufferedImage.TYPE_INT_ARGB); imageWidth = pWidth; imageHeight = pHeight; } public SimpleImage(BufferedImage pBufferedImg, int pWidth, int pHeight) { setBufferedImage(pBufferedImg, pWidth, pHeight); } public SimpleImage() { } public void setBufferedImage(BufferedImage pBufferedImg, int pWidth, int pHeight) { bufferedImg = pBufferedImg; imageWidth = pWidth; imageHeight = pHeight; } @Override public int getImageWidth() { return imageWidth; } @Override public int getImageHeight() { return imageHeight; } public BufferedImage getBufferedImg() { return bufferedImg; } @Override public double getAspect() { return imageHeight != 0 ? (double) imageWidth / (double) imageHeight : 0.0; } public int getScaledWidth(int pScaledHeight) { return (int) ((double) pScaledHeight * getAspect() + 0.5); } public int getScaledHeight(int pScaledWidth) { return (int) ((double) pScaledWidth / getAspect() + 0.5); } @Override public SimpleImage clone() { SimpleImage res = new SimpleImage(); res.bufferedImg = new BufferedImage(getImageWidth(), getImageHeight(), BufferedImage.TYPE_INT_ARGB); res.imageWidth = getImageWidth(); res.imageHeight = getImageHeight(); Graphics g = res.bufferedImg.getGraphics(); g.drawImage(getBufferedImg(), 0, 0, null); return res; } public Graphics getGraphics() { return bufferedImg.getGraphics(); } public void setRGB(int pX, int pY, int pR, int pG, int pB) { getBufferedImg().setRGB(pX, pY, getARGB(255, pR, pG, pB)); } public void setARGB(int pX, int pY, int pA, int pR, int pG, int pB) { getBufferedImg().setRGB(pX, pY, getARGB(pA, pR, pG, pB)); } private void setARGBValue(int pX, int pY, int pARGBValue) { getBufferedImg().setRGB(pX, pY, pARGBValue); } public void setRGB(int pX, int pY, Pixel pPixel) { getBufferedImg().setRGB(pX, pY, pPixel.getARGBValue()); } public void setARGB(int pX, int pY, int pARGB) { getBufferedImg().setRGB(pX, pY, pARGB); } public int getARGBValue(int pX, int pY) { try { return getBufferedImg().getRGB(pX, pY); } catch (Exception ex) { throw new RuntimeException("(" + pX + ", " + pY + ") is out of bounds (0.." + (imageWidth - 1) + ", 0.." + (imageHeight - 1) + ")", ex); } } public int getAValue(int pX, int pY) { return getA(getARGBValue(pX, pY)); } public int getRValue(int pX, int pY) { return getR(getARGBValue(pX, pY)); } public int getGValue(int pX, int pY) { return getG(getARGBValue(pX, pY)); } public int getBValue(int pX, int pY) { return getB(getARGBValue(pX, pY)); } public int getRGBEValue(int pX, int pY) { try { return convertRGBToRGBE(getRValue(pX, pY), getGValue(pX, pY), getBValue(pX, pY)); } catch (Exception ex) { throw new RuntimeException("(" + pX + ", " + pY + ") is out of bounds (0.." + (imageWidth - 1) + ", 0.." + (imageHeight - 1) + ")", ex); } } private int convertRGBToRGBE(int pR, int pG, int pB) { return SimpleHDRImage.convertRGBToRGBE((float) pR / 255.0f, (float) pG / 255.0f, (float) pB / 255.0f); } public int getARGBValueIgnoreBounds(int pX, int pY) { if ((pX < 0) || (pX >= imageWidth) || (pY < 0) || (pY >= imageHeight)) return 0; else return getBufferedImg().getRGB(pX, pY); } public int getRValueIgnoreBounds(int pX, int pY) { if ((pX < 0) || (pX >= imageWidth) || (pY < 0) || (pY >= imageHeight)) return 0; else return getRValue(pX, pY); } public int getGValueIgnoreBounds(int pX, int pY) { if ((pX < 0) || (pX >= imageWidth) || (pY < 0) || (pY >= imageHeight)) return 0; else return getGValue(pX, pY); } public void fillBackground(int pR, int pG, int pB) { Graphics g = bufferedImg.getGraphics(); g.setColor(new Color(pR, pG, pB)); g.fillRect(0, 0, imageWidth, imageHeight); } public void resetImage(int pWidth, int pHeight) { bufferedImg = new BufferedImage(pWidth, pHeight, BufferedImage.TYPE_INT_RGB); imageWidth = pWidth; imageHeight = pHeight; } public int[] getLine(int pY) { int res[] = new int[imageWidth]; for (int i = 0; i < imageWidth; i++) { res[i] = getARGBValue(i, pY); } return res; } public void setLine(int pY, int[] pLine) { for (int i = 0; i < imageWidth; i++) { setARGBValue(i, pY, pLine[i]); } } public void fillBackground(SimpleImage pImage) { Pixel toolPixel = new Pixel(); if (pImage.getImageWidth() == imageWidth && pImage.getImageHeight() == imageHeight) { for (int i = 0; i < imageHeight; i++) { for (int j = 0; j < imageWidth; j++) { setARGB(j, i, pImage.getARGBValue(j, i)); } } } else { for (int i = 0; i < imageHeight; i++) { for (int j = 0; j < imageWidth; j++) { double xCoord = (double) j * (double) (pImage.getImageWidth() - 1) / (double) (imageWidth - 1); double yCoord = (double) i * (double) (pImage.getImageHeight() - 1) / (double) (imageHeight - 1); toolPixel.setARGBValue(pImage.getARGBValueIgnoreBounds((int) xCoord, (int) yCoord)); int luR = toolPixel.r; int luG = toolPixel.g; int luB = toolPixel.b; toolPixel.setARGBValue(pImage.getARGBValueIgnoreBounds(((int) xCoord) + 1, (int) yCoord)); int ruR = toolPixel.r; int ruG = toolPixel.g; int ruB = toolPixel.b; toolPixel.setARGBValue(pImage.getARGBValueIgnoreBounds((int) xCoord, ((int) yCoord) + 1)); int lbR = toolPixel.r; int lbG = toolPixel.g; int lbB = toolPixel.b; toolPixel.setARGBValue(pImage.getARGBValueIgnoreBounds(((int) xCoord) + 1, ((int) yCoord) + 1)); int rbR = toolPixel.r; int rbG = toolPixel.g; int rbB = toolPixel.b; double x = MathLib.frac(xCoord); double y = MathLib.frac(yCoord); int r = Tools.roundColor(GfxMathLib.blerp(luR, ruR, lbR, rbR, x, y)); int g = Tools.roundColor(GfxMathLib.blerp(luG, ruG, lbG, rbG, x, y)); int b = Tools.roundColor(GfxMathLib.blerp(luB, ruB, lbB, rbB, x, y)); setRGB(j, i, r, g, b); } } } } private int getARGB(int a, int r, int g, int b) { return (a << 24) | (r << 16) | (g << 8) | b; } private int getA(int argb) { return (argb >>> 24) & 0xff; } private int getR(int argb) { return (argb >>> 16) & 0xff; } private int getG(int argb) { return (argb >>> 8) & 0xff; } private int getB(int argb) { return argb & 0xff; } }