/* * Copyright (c) 2013 by Gerrit Grunwald * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package eu.hansolo.enzo.common; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.image.PixelWriter; import javafx.scene.image.WritableImage; import javafx.scene.paint.Color; import javafx.scene.paint.ImagePattern; import javafx.scene.shape.Shape; import java.util.Random; /** * Created by * User: hansolo * Date: 01.03.13 * Time: 11:16 */ public class BrushedMetalPaint { private int radius; private double amount; private int color; private double shine; private boolean monochrome; private Random randomNumbers; // ******************** Constructors ************************************** public BrushedMetalPaint() { this(Color.rgb(136, 136, 136), 5, 0.1, true, 0.3); } public BrushedMetalPaint(final Color COLOR) { this(COLOR, 5, 0.1, true, 0.3); } public BrushedMetalPaint(final Color COLOR, final int RADIUS, final double AMOUNT, final boolean MONOCHROME, final double SHINE) { color = getIntFromColor(COLOR); radius = RADIUS; amount = AMOUNT; monochrome = MONOCHROME; shine = SHINE; } // ******************** Methods ******************************************* public Image getImage(final double W, final double H) { final int WIDTH = (int) W; final int HEIGHT = (int) H; WritableImage DESTINATION = new WritableImage(WIDTH, HEIGHT); final int[] IN_PIXELS = new int[WIDTH]; final int[] OUT_PIXELS = new int[WIDTH]; randomNumbers = new Random(0); final int ALPHA = color & 0xff000000; final int RED = (color >> 16) & 0xff; final int GREEN = (color >> 8) & 0xff; final int BLUE = color & 0xff; for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { int tr = RED; int tg = GREEN; int tb = BLUE; if (shine != 0) { int f = (int) (255 * shine * Math.sin((double) x / WIDTH * Math.PI)); tr += f; tg += f; tb += f; } if (monochrome) { int n = (int) (255 * (2 * randomNumbers.nextFloat() - 1) * amount); IN_PIXELS[x] = ALPHA | (clamp(tr + n) << 16) | (clamp(tg + n) << 8) | clamp(tb + n); } else { IN_PIXELS[x] = ALPHA | (random(tr) << 16) | (random(tg) << 8) | random(tb); } } if (radius != 0) { blur(IN_PIXELS, OUT_PIXELS, WIDTH, radius); setRGB(DESTINATION, 0, y, OUT_PIXELS); } else { setRGB(DESTINATION, 0, y, IN_PIXELS); } } return DESTINATION; } public ImageView getImageView(final double W, final double H, final Shape CLIP) { final Image IMAGE = getImage(W, H); final ImageView IMAGE_VIEW = new ImageView(IMAGE); IMAGE_VIEW.setClip(CLIP); return IMAGE_VIEW; } public ImagePattern apply(final Shape SHAPE) { double x = SHAPE.getLayoutBounds().getMinX(); double y = SHAPE.getLayoutBounds().getMinY(); double width = SHAPE.getLayoutBounds().getWidth(); double height = SHAPE.getLayoutBounds().getHeight(); return new ImagePattern(getImage(width, height), x, y, width, height, false); } public void blur(final int[] IN, final int[] OUT, final int WIDTH, final int RADIUS) { final int WIDTH_MINUS_1 = WIDTH - 1; final int R2 = 2 * RADIUS + 1; int tr = 0, tg = 0, tb = 0; for (int i = -RADIUS; i <= RADIUS; i++) { int rgb = IN[mod(i, WIDTH)]; tr += (rgb >> 16) & 0xff; tg += (rgb >> 8) & 0xff; tb += rgb & 0xff; } for (int x = 0; x < WIDTH; x++) { OUT[x] = 0xff000000 | ((tr / R2) << 16) | ((tg / R2) << 8) | (tb / R2); int i1 = x + RADIUS + 1; if (i1 > WIDTH_MINUS_1) { i1 = mod(i1, WIDTH); } int i2 = x - RADIUS; if (i2 < 0) { i2 = mod(i2, WIDTH); } int rgb1 = IN[i1]; int rgb2 = IN[i2]; tr += ((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16; tg += ((rgb1 & 0xff00) - (rgb2 & 0xff00)) >> 8; tb += (rgb1 & 0xff) - (rgb2 & 0xff); } } public void setRadius(final int RADIUS) { radius = RADIUS; } public int getRadius() { return radius; } public void setAmount(final double AMOUNT) { amount = AMOUNT; } public double getAmount() { return amount; } public void setColor(final int COLOR) { color = COLOR; } public int getColor() { return color; } public void setMonochrome(final boolean MONOCHROME) { monochrome = MONOCHROME; } public boolean isMonochrome() { return monochrome; } public void setShine(final double SHINE) { shine = SHINE; } public double getShine() { return shine; } private int random(int x) { x += (int) (255 * (2 * randomNumbers.nextFloat() - 1) * amount); if (x < 0) { x = 0; } else if (x > 0xff) { x = 0xff; } return x; } private int clamp(final int C) { int ret = C; if (C < 0) { ret = 0; } if (C > 255) { ret = 255; } return ret; } private int mod(int a, final int B) { final int N = a / B; a -= N * B; if (a < 0) { return a + B; } return a; } private void setRGB(final WritableImage IMAGE, final int X, final int Y, final int[] PIXELS) { final PixelWriter RASTER = IMAGE.getPixelWriter(); for (int x = 0 ; x < PIXELS.length ; x++) { RASTER.setColor(X + x, Y, Color.rgb((PIXELS[x] >> 16) & 0xFF, (PIXELS[x] >> 8) & 0xFF, (PIXELS[x] &0xFF))); } } private int getIntFromColor(final Color COLOR) { String hex = COLOR.toString(); StringBuilder intValue = new StringBuilder(10); intValue.append(hex.substring(8, 10)); intValue.append(hex.substring(2, 8)); return (int) Long.parseLong(intValue.toString(), 16); } }