/* * Copyright 2009 Rodrigo Reyes reyes.rr at gmail dot com * * 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 net.kornr.swit.wicket.border.graphics; import java.awt.AlphaComposite; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ConvolveOp; import java.awt.image.Kernel; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; /** * Some Graphics effects * * @author Rodrigo Reyes * */ public class GfxEffects { public static BufferedImage createSimilar(BufferedImage img) { BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType()); return result; } static public BufferedImage newBuffer(int width, int height) { return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } public static BufferedImage addMargin(BufferedImage img, int left, int right, int top, int bottom) { BufferedImage result = new BufferedImage(img.getWidth()+left+right, img.getHeight()+top+bottom, img.getType()); Graphics2D g = createInitializedGraphics2DQuality(result); g.drawImage(img, left, top, null); return result; } public static BufferedImage getClipped(BufferedImage img, int x, int y, int width, int height) { BufferedImage result = new BufferedImage(width, height, img.getType()); Graphics2D g = createInitializedGraphics2DQuality(result); g.translate(-x, -y); g.drawImage(img, 0, 0, null); return result; } // public static BufferedImage convertEmbossToMask(BufferedImage org) // { // BufferedImage result = new BufferedImage(org.getWidth(), org.getHeight(), BufferedImage.TYPE_INT_ARGB); // for (int x = 0; x < org.getWidth(); x++) // { // for (int y = 0; y < org.getHeight(); y++) // { // int p = org.getRGB(x,y); // int shade = convertARGBToGrey(p) & 0xFF; // // if (shade == 0x7F ) // result.setRGB(x, y, 0); // else // result.setRGB(x, y, 0xFF000000 + (shade<<16) + (shade<<8) + shade); // } // } // return result; // } // static public BufferedImage createAlphaMaskFromColor(BufferedImage org, Color col, int threshold) // { // BufferedImage result = new BufferedImage(org.getWidth(), org.getHeight(), BufferedImage.TYPE_INT_ARGB); // // for (int x = 0; x < org.getWidth(); x++) // { // for (int y = 0; y < org.getHeight(); y++) // { // int p = org.getRGB(x,y); // int a = (p>>24)&0xFF; // int r = (p>>16)&0xFF; // int g = (p>>8)&0xFF; // int b = (p)&0xFF; // // if (a > 0 && areSimilar(p, col.getRGB(), 1)) // result.setRGB(x,y, 0xFFFFFFFF); // else // result.setRGB(x,y, 0xFF000000); // } // } // return result; // // } public static BufferedImage getAlphaMask(BufferedImage org, float brightness, Color color) { BufferedImage result = new BufferedImage(org.getWidth(), org.getHeight(), BufferedImage.TYPE_INT_ARGB); int basecolor = color.getRGB() & 0xFFFFFF; for (int x = 0; x < org.getWidth(); x++) { for (int y = 0; y < org.getHeight(); y++) { int p = org.getRGB(x,y); result.setRGB(x, y, (p&0xFF000000) + basecolor); } } return result; } public static BufferedImage blurFixed(BufferedImage org, int size) { BufferedImage tempbuf = new BufferedImage(org.getWidth()+size*2, org.getHeight()+size*2, BufferedImage.TYPE_INT_ARGB_PRE); Graphics2D tg = createInitializedGraphics2DQuality(tempbuf); tg.drawImage(org, size, size, null); BufferedImage result = createSimilar(tempbuf); result = blur(tempbuf, result, size); return getClipped(result, size, size, org.getWidth(), org.getHeight()); } public static BufferedImage blur(BufferedImage org, BufferedImage target, int size) { int size2 = size*size; float[] matrix = new float[size2]; for (int i = 0; i < (size2); i++) matrix[i] = (1.0f/(float)size2); ConvolveOp op = new ConvolveOp(new Kernel(size,size,matrix), ConvolveOp.EDGE_ZERO_FILL, null); return op.filter(org, target); } // public static BufferedImage emboss(BufferedImage img, int size) // { // int size2 = size*size; // float[] matrix = new float[] { // 1, 1 ,1, // 1, 0.f, -1, // -1, -1, -1 // }; // ConvolveOp op = new ConvolveOp(new Kernel((int)Math.sqrt(matrix.length),(int)Math.sqrt(matrix.length),matrix), ConvolveOp.EDGE_NO_OP, null); // return op.filter(img, null); // } // public static BufferedImage shift(BufferedImage img, int x, int y) // { // BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); // result.createGraphics().drawImage(img, x, y, new Color(0,0,0,0), null); // return result; // } // public static BufferedImage invertBrightness(BufferedImage img) // { // BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); // // for (int x = 0; x < img.getWidth(); x++) // { // for (int y = 0; y < img.getHeight(); y++) // { // int p = img.getRGB(x,y); // int val = 0xFFFFFF-(p&0xFFFFFF) + (p&0xFF000000); // int shade = 0xFF - (convertARGBToGrey(p)&0xFF); // result.setRGB(x, y, (p&0xFF000000) + (shade<<16)+(shade<<8)+shade); // } // } // return result; // } // public static BufferedImage modifyBrightness(BufferedImage img, float ratio) // { // float[] matrix = new float[9]; // matrix[4] = ratio; // // ConvolveOp op = new ConvolveOp(new Kernel(3,3,matrix), ConvolveOp.EDGE_NO_OP, null); // // return op.filter(img, null); // } // public static BufferedImage mixOnGray(BufferedImage target, BufferedImage mask, int gray) // { // BufferedImage result = new BufferedImage(target.getWidth(), target.getHeight(), BufferedImage.TYPE_INT_ARGB); // for (int x = 0; x < result.getWidth(); x++) // { // for (int y = 0; y < result.getHeight(); y++) // { // int col = target.getRGB(x, y); // int maskval = convertARGBToGrey(mask.getRGB(x, y)) & 0xFF; // int diff = maskval - 0x7F; // float ratio = ((float)maskval/255f) + 0.5f; // // int nc = darken(col, ratio*ratio); // // result.setRGB(x, y, nc); // } // } // // return result; // } public static void mixOn(BufferedImage img1, BufferedImage target, float ratio) { for (int x = 0; x < img1.getWidth() && x < target.getWidth(); x++) { for (int y = 0; y < img1.getHeight() && y<target.getHeight(); y++) { int p1 = img1.getRGB(x,y); int p2 = target.getRGB(x, y); int a1 = (p1>>24)&0xFF; int shade = GfxEffects.convertARGBToGrey(p1) & 0xFF; // int alpha = (((p1&0xFF000000)>>24)&0xFF+((p2&0xFF000000)>>24)&0xFF); // alpha = Math.max((((p1&0xFF000000)>>24)&0xFF), ((p2&0xFF000000)>>24)&0xFF); // int red = (((p1&0xFF0000)>>16)+((p2&0xFF0000)>>16)); // int green = (((p1&0xFF00)>>8)+((p2&0xFF00)>>8)); // int blue = (((p1&0xFF))+((p2&0xFF))); int red = (p2&0xFF0000)>>16; int green = (p2&0xFF00)>>8; int blue = p2&0xFF; red += (int)((float)a1*ratio); green += (int)((float)a1*ratio); blue += (int)((float)a1*ratio); red = Math.max(0, Math.min(255, red)); green = Math.max(0, Math.min(255, green)); blue = Math.max(0, Math.min(255, blue)); target.setRGB(x, y, (p2 & 0xFF000000) + (red<<16) + (green<<8) + blue); // target.setRGB(x, y, p1); } } } public static BufferedImage mix(BufferedImage img1, BufferedImage img2, int alphaMix) { BufferedImage result = new BufferedImage(img1.getWidth(), img1.getHeight(), BufferedImage.TYPE_INT_ARGB); for (int x = 0; x < img1.getWidth() && x < img2.getWidth(); x++) { for (int y = 0; y < img1.getHeight() && y<img2.getWidth(); y++) { int p1 = img1.getRGB(x,y); int p2 = img2.getRGB(x, y); // int alpha = (((p1&0xFF000000)>>24)&0xFF+((p2&0xFF000000)>>24)&0xFF)/2; // alpha = Math.max((((p1&0xFF000000)>>24)&0xFF), ((p2&0xFF000000)>>24)&0xFF); // int red = (((p1&0xFF0000)>>16)+((p2&0xFF0000)>>16))/2; // int green = (((p1&0xFF00)>>8)+((p2&0xFF00)>>8))/2; // int blue = (((p1&0xFF))+((p2&0xFF)))/2; // // result.setRGB(x, y, (alpha<<24) + (red<<16) + (green<<8) + blue); result.setRGB(x, y, mixColor(p1,p2)); } } return result; } public static int mixColor(int p1, int p2) { int alpha = (((p1&0xFF000000)>>24)&0xFF+((p2&0xFF000000)>>24)&0xFF)/2; // alpha = Math.max((((p1&0xFF000000)>>24)&0xFF), ((p2&0xFF000000)>>24)&0xFF); int red = (((p1&0xFF0000)>>16)+((p2&0xFF0000)>>16))/2; int green = (((p1&0xFF00)>>8)+((p2&0xFF00)>>8))/2; int blue = (((p1&0xFF))+((p2&0xFF)))/2; return (alpha<<24) + (red<<16) + (green<<8) + blue; } public static BufferedImage applyConvolution(BufferedImage img, float[]matrix) { ConvolveOp op = new ConvolveOp(new Kernel((int)Math.sqrt(matrix.length),(int)Math.sqrt(matrix.length),matrix), ConvolveOp.EDGE_NO_OP, null); return op.filter(img, null); } public static void fill(BufferedImage img, Color c) { Graphics2D g = img.createGraphics(); g.setColor(c); g.fillRect(0, 0, img.getWidth(), img.getHeight()); } public static void clear(BufferedImage img) { Graphics2D g = img.createGraphics(); g.setColor(new Color(0,0,0,0)); g.setComposite(AlphaComposite.Clear); g.fillRect(0, 0, img.getWidth(), img.getHeight()); } public static void copyOn(BufferedImage source, BufferedImage target, Color background) { if (background == null) background = new Color(0,0,0,0); Graphics2D g = target.createGraphics(); g.setComposite(AlphaComposite.SrcOver); g.drawImage(source, 0, 0, background, null); } static public int convertARGBToGrey(int color) { int result = color&0xFF000000; // Respect the brightness of each color component float red = 0.299f * (float)((color>>16)&(int)0xFF); float green = 0.587f * (float)((color>>8)&(int)0xFF); float blue = 0.114f * (float)((color)&(int)0xFF); int brightness = (int)(red+green+blue) & 0xFF; return result + (brightness<<16) + (brightness<<8) + brightness; } public static int getColorTransition(int color1, int color2, float ratio) { float alpha = ((float)((color1>>24)&(int)0xFF)*(1.0f-ratio)) + ((float)((color2>>24)&(int)0xFF)*ratio); float red = ((float)((color1>>16)&(int)0xFF)*(1.0f-ratio)) + ((float)((color2>>16)&(int)0xFF)*ratio); float green = ((float)((color1>>8)&(int)0xFF)*(1.0f-ratio)) + ((float)((color2>>8)&(int)0xFF)*ratio); float blue = ((float)(color1&0xFF)*(1.0f-ratio)) + ((float)(color2&0xFF)*ratio); int a = (int)alpha; int r = (int)red; int g = (int)green; int b = (int)blue; int result = (a<<24)&0xFF000000 + ((r<<16)&0xFF0000) + ((g<<8)&0xFF00) + (b&0xFF); return result; } public static Color getColorTransition(Color color1, Color color2, float ratio) { float alpha = ((float)((color1.getAlpha())&(int)0xFF)*(1.0f-ratio)) + ((float)((color2.getAlpha())&(int)0xFF)*ratio); float red = ((float)((color1.getRed())&(int)0xFF)*(1.0f-ratio)) + ((float)((color2.getRed())&(int)0xFF)*ratio); float green = ((float)((color1.getGreen())&(int)0xFF)*(1.0f-ratio)) + ((float)((color2.getGreen())&(int)0xFF)*ratio); float blue = ((float)(color1.getBlue()&0xFF)*(1.0f-ratio)) + ((float)(color2.getBlue()&0xFF)*ratio); int a = (int)alpha; int r = (int)red; int g = (int)green; int b = (int)blue; return new Color(r,g,b,a); } public static int adjustBrightness(int col, float ratio) { float red = (float)((col>>16)&0xFF) * ratio; float green = (float)((col>>8)&0xFF) * ratio; float blue = (float)(col&0xFF) * ratio; if (red > 255) red=255; if (green > 255) green=255; if (blue > 255) blue=255; return (col&0xFF000000) + ((int)red<<16) + ((int)green<<8) + (int)blue; } public static Color adjustBrightness(Color col, float ratio) { float red = (float)col.getRed() * ratio; float green = (float)col.getGreen() * ratio; float blue = (float)col.getBlue() * ratio; red = Math.min(red, 255.0f); green = Math.min(green, 255.0f); blue = Math.min(blue, 255.0f); return new Color((int)red, (int)green, (int)blue, col.getAlpha()); } static public void main(String[]args) { Color col1 = new Color(10,50,100); Color col2 = new Color(200,180, 160); float ratio = 0.5f; Color col3 = getColorTransition(col1, col2, ratio); } /** * Replace the alpha value of each pixel of the first image with the corresponding alpha value of the pixels of the second image. * @param org * @param alphaMask * @return an image identical to org, but with the alpha value of each pixel substituted with the alpha values of alphaMask */ public static BufferedImage substituteAlpha(BufferedImage org, BufferedImage alphaMask) { BufferedImage result = new BufferedImage(org.getWidth(), org.getHeight(), BufferedImage.TYPE_INT_ARGB); for (int x = 0; x < org.getWidth() && x < alphaMask.getWidth(); x++) { for (int y = 0; y < org.getHeight() && y<alphaMask.getHeight(); y++) { int p1 = org.getRGB(x,y); int p2 = alphaMask.getRGB(x, y); int a1 = p1&0xFF000000; int a2 = p2&0xFF000000; if (a1!=0) // Only apply the alpha mask if the pixel from the source is not transparent { int resultpixel = (p1 & 0xFFFFFF) | a2; result.setRGB(x, y, resultpixel); } } } return result; } static public boolean areSimilar(Color c1, Color c2, int thres) { int r = Math.abs(c1.getRed()-c2.getRed()); int g = Math.abs(c1.getGreen()-c2.getGreen()); int b = Math.abs(c1.getBlue()-c2.getBlue()); return (r<=thres) && (g<=thres) && (b<=thres); } static public boolean areSimilar(int c1, int c2, int thres) { int r = Math.abs((c1>>16&0xFF)-(c2>>16&0xFF)); int g = Math.abs((c1>>8&0xFF)-(c2>>8&0xFF)); int b = Math.abs((c1&0xFF)-(c2&0xFF)); return (r<=thres) && (g<=thres) && (b<=thres); } static public Graphics2D createInitializedGraphics2DQuality(BufferedImage img) { Graphics2D g = img.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); return g; } static public void displayDebug(BufferedImage img, String title) { JFrame frame = new JFrame("title"); frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(new JLabel(title, new ImageIcon(img), JLabel.CENTER)); frame.setVisible(true); } static public BufferedImage createShadow(BufferedImage img, float size, Color shadowColor) { BufferedImage buffer = GfxEffects.addMargin(img, (int)size, (int)size, (int)size, (int)size); Graphics2D g = createInitializedGraphics2DQuality(buffer); g.drawImage(img, 0, 0, null); buffer = GfxEffects.getAlphaMask(buffer, 1.0f, shadowColor); int size2 = (int)(size*size); float[] matrix = new float[size2]; for (int i = 0; i < (size2); i++) matrix[i] = (1.0f/(float)size2); ConvolveOp op = new ConvolveOp(new Kernel((int)size,(int)size,matrix), ConvolveOp.EDGE_ZERO_FILL, null); BufferedImage target = createSimilar(buffer); return op.filter(buffer, target); } }