public void transform( FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount, double pInputX, double pInputY) { double x = (pInputX - (offsetX + 0.5) + 1.0) / scaleX * (double) (imgWidth - 1); double y = (pInputY - (offsetY + 0.5) + 1.0) / scaleY * (double) (imgHeight - 1); int ix = Tools.FTOI(x); int iy = Tools.FTOI(y); if (this.tileX == 1) { if (ix < 0) { int nx = ix / imgWidth - 1; ix -= nx * imgWidth; } else if (ix >= imgWidth) { int nx = ix / imgWidth; ix -= nx * imgWidth; } } if (this.tileY == 1) { if (iy < 0) { int ny = iy / imgHeight - 1; iy -= ny * imgHeight; } else if (iy >= imgHeight) { int ny = iy / imgHeight; iy -= ny * imgHeight; } } double r, g, b; if (ix >= 0 && ix < imgWidth && iy >= 0 && iy < imgHeight) { if (colorMap instanceof SimpleImage) { toolPixel.setARGBValue(((SimpleImage) colorMap).getARGBValue(ix, iy)); r = (double) toolPixel.r / 255.0; g = (double) toolPixel.g / 255.0; b = (double) toolPixel.b / 255.0; } else { ((SimpleHDRImage) colorMap).getRGBValues(rgbArray, ix, iy); r = rgbArray[0]; g = rgbArray[0]; b = rgbArray[0]; } } else { return; } switch (mode) { case MODE_TRANSLATE: { double amountX = (r - 0.5) * pAmount; double amountY = (g - 0.5) * pAmount; pVarTP.x += amountX; pVarTP.y += amountY; } break; case MODE_SCALE: { double intensity = calcIntensity(r, g, b) - bias; if (intensity > 0.0) { double scl = 1.0 + (intensity - 0.5) * pAmount; pVarTP.x *= scl; pVarTP.y *= scl; } } break; case MODE_SCISSOR: { double amountX = (r - 0.5) * pAmount; double amountY = (g - 0.5) * pAmount; double newx = pVarTP.x * amountX * amountY + pVarTP.y * amountY; double newy = pVarTP.x * amountY - pVarTP.y * amountX * amountY; pVarTP.x = newx; pVarTP.y = newy; } break; case MODE_ROTATE: default: { double intensity = calcIntensity(r, g, b) - bias; if (intensity > 0.0) { double angle = intensity * M_2PI * pAmount; double sina = sin(angle); double cosa = cos(angle); double xnew = pVarTP.x * cosa - pVarTP.y * sina; double ynew = pVarTP.x * sina + pVarTP.y * cosa; pVarTP.x = xnew; pVarTP.y = ynew; } } } switch (colorMode) { case COLOR_MODE_INHERIT: { pVarTP.rgbColor = true; pVarTP.redColor = r; pVarTP.greenColor = g; pVarTP.blueColor = b; pVarTP.color = getColorIdx(r, g, b); } break; } }
@Override protected void fillImage(SimpleImage res) { int width = res.getImageWidth(); int height = res.getImageHeight(); Random rnd = new Random(); rnd.setSeed(this.seed); double cover = 1.0 - this.cover; double aspect = (double) width / (double) height; int frequency = this.initialFrequency; int frequencyX = (int) (frequency * aspect + 0.5); int frequencyY = (int) (frequency * aspect + 0.5); double alphaInt = 1.0f; BufferedImage mainImage = res.getBufferedImg(); Graphics2D mainGr = mainImage.createGraphics(); for (int i = 0; i < this.octaves; i++) { // create a small random image BufferedImage rndMap = new BufferedImage(frequencyX, frequencyY, BufferedImage.TYPE_INT_ARGB); { Graphics2D g = rndMap.createGraphics(); try { switch (colorMode) { case COLOR: for (int x = 0; x < frequencyX; x++) { for (int y = 0; y < frequencyY; y++) { int rVal = rnd.nextInt(255); int gVal = rnd.nextInt(255); int bVal = rnd.nextInt(255); g.setColor(new Color(rVal, gVal, bVal, (int) (255.0 * alphaInt + 0.5))); g.fillRect(x, y, 1, 1); } } break; case GREY: for (int x = 0; x < frequencyX; x++) { for (int y = 0; y < frequencyY; y++) { int val = rnd.nextInt(255); g.setColor(new Color(val, val, val, (int) (255.0 * alphaInt + 0.5))); g.fillRect(x, y, 1, 1); } } break; case BASE_COLOR: int rBase = this.cloudColor.getRed(); int gBase = this.cloudColor.getGreen(); int bBase = this.cloudColor.getBlue(); for (int x = 0; x < frequencyX; x++) { for (int y = 0; y < frequencyY; y++) { int val = rnd.nextInt(255); int rVal = (rBase * val) / 255; int gVal = (gBase * val) / 255; int bVal = (bBase * val) / 255; g.setColor(new Color(rVal, gVal, bVal, (int) (255.0 * alphaInt + 0.5))); g.fillRect(x, y, 1, 1); } } break; } } finally { g.dispose(); } } // scale up the image using Java-built-in interpolation { BufferedImage scaledRndMap = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = scaledRndMap.createGraphics(); try { g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g.drawImage(rndMap, 0, 0, width, height, 0, 0, frequencyX, frequencyY, null); } finally { g.dispose(); } mainGr.drawImage(scaledRndMap, null, 0, 0); } alphaInt *= this.persistence; frequency += frequency; frequencyX = (int) (frequency * aspect + 0.5); frequencyY = (int) (frequency * aspect + 0.5); } // apply an exponential filter to let the noise more look like clouds if (mode == Mode.CLOUDS) { final double rWeight = 0.2990; final double gWeight = 0.5880; final double bWeight = 0.1130; SimpleImage bgImg = (this.backgroundImg != null) ? backgroundImg.getImage() : null; Pixel pixel = new Pixel(); Pixel bgPixel = new Pixel(); for (int i = 0; i < mainImage.getWidth(); i++) { for (int j = 0; j < mainImage.getHeight(); j++) { pixel.setARGBValue(res.getARGBValue(i, j)); double lum = pixel.r * rWeight + pixel.g * gWeight + pixel.b * bWeight; double c = lum - (cover * 255); if (c < 0) c = 0; int iVal = Tools.roundColor(255.0 - (Math.pow(this.sharpness, c) * 255.0)); int bgRed = 0, bgGreen = 0, bgBlue = 0; switch (bgMode) { case IMAGE: if (bgImg != null) { bgPixel.setARGBValue(bgImg.getARGBValueIgnoreBounds(i, j)); bgRed = bgPixel.r; bgGreen = bgPixel.g; bgBlue = bgPixel.b; } break; case COLOR: bgRed = this.bgColor.getRed(); bgGreen = this.bgColor.getGreen(); bgBlue = this.bgColor.getBlue(); break; } switch (colorMode) { case GREY: pixel.r = expose(iVal + 1.5 * bgRed); pixel.g = expose(iVal + 1.5 * bgGreen); pixel.b = expose(iVal + 1.5 * bgBlue); break; default: pixel.r = expose((iVal * pixel.r) / 255 + 1.5 * bgRed); pixel.g = expose((iVal * pixel.g) / 255 + 1.5 * bgGreen); pixel.b = expose((iVal * pixel.b) / 255 + 1.5 * bgBlue); break; } res.setRGB(i, j, pixel); } } } }