首页javaimageJava Graphics - 如何创建对图像应用可变透明度。

Java Graphics - 如何创建对图像应用可变透明度。

我们想知道如何对图像应用可变透明度。

code revised from http://stackoverflow.com/questions/23056090

User information: http://stackoverflow.com/users/3417524/cvogt8

import java.awt.Color; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; public class Main { public static void main(String[] args) throws Exception { JFrame Main = new JFrame("Gradient Mask"); JLabel imageLayer = new JLabel(); JLabel maskLayer = new JLabel(); BufferedImage image = ImageIO.read(new URL("http://www.w3cschool.cn/style/download.png")); BufferedImage gradientMask = new GradientImage(image.getWidth(), image.getHeight(), new Color[] { new Color(255, 255, 255, 125), Color.BLACK }, GradientImage.RADIAL_FROM_CENTER).getImage(); Main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Main.setBounds(100, 50, image.getWidth(), image.getHeight()); imageLayer.setBounds(0, 0, Main.getWidth(), Main.getHeight()); maskLayer.setBounds(0, 0, Main.getWidth(), Main.getHeight()); imageLayer.setIcon(new ImageIcon((Image) image)); maskLayer.setIcon(new ImageIcon((Image) gradientMask)); Main.getContentPane().add(imageLayer); imageLayer.add(maskLayer); Main.setVisible(true); } } class GradientImage { public final static int LINEAR_LEFT_TO_RIGHT = 1; public final static int LINEAR_RIGHT_TO_LEFT = 2; public final static int LINEAR_TOP_TO_BOTTOM = 3; public final static int LINEAR_BOTTOM_TO_TOP = 4; public final static int LINEAR_DIAGONAL_UP = 5; public final static int LINEAR_DIAGONAL_DOWN = 6; public final static int RADIAL_FROM_TOP_LEFT_CORNER = 7; public final static int RADIAL_FROM_BOTTOM_LEFT_CORNER = 8; public final static int RADIAL_FROM_TOP_RIGHT_CORNER = 9; public final static int RADIAL_FROM_BOTTOM_RIGHT_CORNER = 10; public final static int RADIAL_FROM_CENTER = 11; public final static int RADIAL_FROM_CORNERS = 12; public final static int PATH_FROM_CENTER = 13; public final static int PATH_FROM_TOP_LEFT_CORNER = 14; public final static int PATH_FROM_TOP_RIGHT_CORNER = 15; public final static int PATH_FROM_BOTTOM_LEFT_CORNER = 16; public final static int PATH_FROM_BOTTOM_RIGHT_CORNER = 17; public final static int LINEAR_FROM_TOP_RIGHT_CORNER = 18; public final static int LINEAR_FROM_TOP_LEFT_CORNER = 19; public final static int LINEAR_FROM_BOTTOM_RIGHT_CORNER = 20; public final static int LINEAR_FROM_BOTTOM_LEFT_CORNER = 21; public final static int LINEAR_FROM_CENTER = 22; public final static int LINEAR_FROM_CORNERS = 23; public final static int PATH_FROM_CORNERS = 24; private BufferedImage image = null; private BufferedImage circleImage = null; private int[] pixels; private int[] circlePixels; private int[] positions; private Color[] colors; private int[] rgbs; private int alignment; private int width; private int height; public GradientImage(int width, int height, Color[] colors, int alignment) { image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); this.alignment = alignment; this.width = width; this.height = height; this.colors = colors; rgbs = new int[colors.length]; for (int i = 0; i < rgbs.length; i++) { rgbs[i] = colors[i].getRGB(); } try { renderImage(); } catch (Exception error) { error.printStackTrace(); } } public GradientImage(int width, int height, Color[] colors, int[] positions, int alignment) { image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); this.alignment = alignment; this.width = width; this.height = height; this.colors = colors; this.positions = positions; rgbs = new int[colors.length]; for (int i = 0; i < rgbs.length; i++) { rgbs[i] = colors[i].getRGB(); } try { renderImage(); } catch (Exception error) { error.printStackTrace(); } } public BufferedImage getImage() { return image; } public BufferedImage getImageAsCircle() { if (circleImage == null) { circleImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); circlePixels = ((DataBufferInt) circleImage.getRaster().getDataBuffer()) .getData(); int radius = Math.min(width, height) >> 1; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (Math.sqrt((Math.max(width >> 1, x) - Math.min(width >> 1, x)) * (Math.max(width >> 1, x) - Math.min(width >> 1, x)) + (Math.max(height >> 1, y) - Math.min(height >> 1, y)) * (Math.max(height >> 1, y) - Math.min(height >> 1, y))) <= radius) { circlePixels[x + y * width] = pixels[x + y * width]; } } } } return circleImage; } private void renderImage() throws Exception { if (alignment == LINEAR_LEFT_TO_RIGHT) { int[] rgbRange = loadRGBRange(width, rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = rgbRange[x]; } } } else if (alignment == LINEAR_RIGHT_TO_LEFT) { int[] rgbRange = loadRGBRange(width, rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = rgbRange[width - x - 1]; } } } else if (alignment == LINEAR_BOTTOM_TO_TOP) { int[] rgbRange = loadRGBRange(height, rgbs, positions); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { pixels[x + y * width] = rgbRange[height - y - 1]; } } } else if (alignment == LINEAR_TOP_TO_BOTTOM) { int[] rgbRange = loadRGBRange(height, rgbs, positions); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { pixels[x + y * width] = rgbRange[y]; } } } else if (alignment == RADIAL_FROM_TOP_LEFT_CORNER) { int[] rgbRange = loadRGBRange( (int) Math.sqrt((width - 1) * (width - 1) + (height - 1) * (height - 1)), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = rgbRange[(int) Math.sqrt((x - 1) * (x - 1) + (y - 1) * (y - 1))]; } } } else if (alignment == RADIAL_FROM_BOTTOM_LEFT_CORNER) { int[] rgbRange = loadRGBRange( (int) Math.sqrt((width - 1) * (width - 1) + (height - 1) * (height - 1)), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + (height - y - 1) * width] = rgbRange[(int) Math .sqrt((x - 1) * (x - 1) + (y - 1) * (y - 1))]; } } } else if (alignment == RADIAL_FROM_TOP_RIGHT_CORNER) { int[] rgbRange = loadRGBRange( (int) Math.sqrt((width - 1) * (width - 1) + (height - 1) * (height - 1)), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[(width - x - 1) + y * width] = rgbRange[(int) Math .sqrt((x - 1) * (x - 1) + (y - 1) * (y - 1))]; } } } else if (alignment == RADIAL_FROM_BOTTOM_RIGHT_CORNER) { int[] rgbRange = loadRGBRange( (int) Math.sqrt((width - 1) * (width - 1) + (height - 1) * (height - 1)), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[(width - x - 1) + (height - y - 1) * width] = rgbRange[(int) Math .sqrt((x - 1) * (x - 1) + (y - 1) * (y - 1))]; } } } else if (alignment == RADIAL_FROM_CENTER) { int[] divArray = divideArray(positions, 2); BufferedImage quad1 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_BOTTOM_RIGHT_CORNER).getImage(); BufferedImage quad2 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_BOTTOM_LEFT_CORNER).getImage(); BufferedImage quad3 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_TOP_RIGHT_CORNER).getImage(); BufferedImage quad4 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_TOP_LEFT_CORNER).getImage(); Graphics2D g = image.createGraphics(); g.drawImage(quad1, 0, 0, null); g.drawImage(quad2, width >> 1, 0, null); g.drawImage(quad3, 0, height >> 1, null); g.drawImage(quad4, width >> 1, height >> 1, null); g.dispose(); } else if (alignment == RADIAL_FROM_CORNERS) { int[] divArray = divideArray(positions, 2); BufferedImage quad1 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_TOP_LEFT_CORNER).getImage(); BufferedImage quad2 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_TOP_RIGHT_CORNER).getImage(); BufferedImage quad3 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_BOTTOM_LEFT_CORNER).getImage(); BufferedImage quad4 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.RADIAL_FROM_BOTTOM_RIGHT_CORNER).getImage(); Graphics2D g = image.createGraphics(); g.drawImage(quad1, 0, 0, null); g.drawImage(quad2, width >> 1, 0, null); g.drawImage(quad3, 0, height >> 1, null); g.drawImage(quad4, width >> 1, height >> 1, null); g.dispose(); } else if (alignment == LINEAR_DIAGONAL_UP) { int[] rgbRange = loadRGBRange( (int) Math.sqrt((width - 1) * (width - 1) + (height - 1) * (height - 1)), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + (height - y - 1) * width] = rgbRange[Math .max(y - x, x - y)]; } } } else if (alignment == LINEAR_DIAGONAL_DOWN) { int[] rgbRange = loadRGBRange( (int) Math.sqrt((width - 1) * (width - 1) + (height - 1) * (height - 1)), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = rgbRange[Math.max(y - x, x - y)]; } } } else if (alignment == LINEAR_FROM_TOP_RIGHT_CORNER) { int[] rgbRange = loadRGBRange((width + height) >> 1, rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + (height - y - 1) * width] = rgbRange[rgbRange.length - ((x + y) >> 1) - 1]; } } } else if (alignment == LINEAR_FROM_TOP_LEFT_CORNER) { int[] rgbRange = loadRGBRange((width + height) >> 1, rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[(width - x - 1) + (height - y - 1) * width] = rgbRange[rgbRange.length - ((x + y) >> 1) - 1]; } } } else if (alignment == LINEAR_FROM_BOTTOM_RIGHT_CORNER) { int[] rgbRange = loadRGBRange((width + height) >> 1, rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = rgbRange[rgbRange.length - ((x + y) >> 1) - 1]; } } } else if (alignment == LINEAR_FROM_BOTTOM_LEFT_CORNER) { int[] rgbRange = loadRGBRange((width + height) >> 1, rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[(width - x - 1) + y * width] = rgbRange[rgbRange.length - ((x + y) >> 1) - 1]; } } } else if (alignment == LINEAR_FROM_CENTER) { int[] divArray = divideArray(positions, 2); BufferedImage quad1 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_BOTTOM_RIGHT_CORNER).getImage(); BufferedImage quad2 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_BOTTOM_LEFT_CORNER).getImage(); BufferedImage quad3 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_TOP_RIGHT_CORNER).getImage(); BufferedImage quad4 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_TOP_LEFT_CORNER).getImage(); Graphics2D g = image.createGraphics(); g.drawImage(quad1, 0, 0, null); g.drawImage(quad2, width >> 1, 0, null); g.drawImage(quad3, 0, height >> 1, null); g.drawImage(quad4, width >> 1, height >> 1, null); g.dispose(); } else if (alignment == LINEAR_FROM_CORNERS) { int[] divArray = divideArray(positions, 2); BufferedImage quad1 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_TOP_LEFT_CORNER).getImage(); BufferedImage quad2 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_TOP_RIGHT_CORNER).getImage(); BufferedImage quad3 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_BOTTOM_LEFT_CORNER).getImage(); BufferedImage quad4 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.LINEAR_FROM_BOTTOM_RIGHT_CORNER).getImage(); Graphics2D g = image.createGraphics(); g.drawImage(quad1, 0, 0, null); g.drawImage(quad2, width >> 1, 0, null); g.drawImage(quad3, 0, height >> 1, null); g.drawImage(quad4, width >> 1, height >> 1, null); g.dispose(); } else if (alignment == PATH_FROM_TOP_LEFT_CORNER) { int[] rgbRange = loadRGBRange(Math.max(width, height), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + y * width] = rgbRange[Math.max(x, y)]; } } } else if (alignment == PATH_FROM_TOP_RIGHT_CORNER) { int[] rgbRange = loadRGBRange(Math.max(width, height), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[(width - x - 1) + y * width] = rgbRange[Math.max(x, y)]; } } } else if (alignment == PATH_FROM_BOTTOM_LEFT_CORNER) { int[] rgbRange = loadRGBRange(Math.max(width, height), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[x + (height - y - 1) * width] = rgbRange[Math.max(x, y)]; } } } else if (alignment == PATH_FROM_BOTTOM_RIGHT_CORNER) { int[] rgbRange = loadRGBRange(Math.max(width, height), rgbs, positions); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pixels[(width - x - 1) + (height - y - 1) * width] = rgbRange[Math .max(x, y)]; } } } else if (alignment == PATH_FROM_CENTER) { int[] divArray = divideArray(positions, 2); BufferedImage quad1 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_BOTTOM_RIGHT_CORNER).getImage(); BufferedImage quad2 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_BOTTOM_LEFT_CORNER).getImage(); BufferedImage quad3 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_TOP_RIGHT_CORNER).getImage(); BufferedImage quad4 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_TOP_LEFT_CORNER).getImage(); Graphics2D g = image.createGraphics(); g.drawImage(quad1, 0, 0, null); g.drawImage(quad2, width >> 1, 0, null); g.drawImage(quad3, 0, height >> 1, null); g.drawImage(quad4, width >> 1, height >> 1, null); g.dispose(); } else if (alignment == PATH_FROM_CORNERS) { int[] divArray = divideArray(positions, 2); BufferedImage quad1 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_TOP_LEFT_CORNER).getImage(); BufferedImage quad2 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_TOP_RIGHT_CORNER).getImage(); BufferedImage quad3 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_BOTTOM_LEFT_CORNER).getImage(); BufferedImage quad4 = new GradientImage(width >> 1, height >> 1, colors, divArray, GradientImage.PATH_FROM_BOTTOM_RIGHT_CORNER).getImage(); Graphics2D g = image.createGraphics(); g.drawImage(quad1, 0, 0, null); g.drawImage(quad2, width >> 1, 0, null); g.drawImage(quad3, 0, height >> 1, null); g.drawImage(quad4, width >> 1, height >> 1, null); g.dispose(); } } public int[] divideArray(int[] array, int div) { if (array == null) { return null; } int[] arr = new int[array.length]; if (div == 2) { for (int i = 0; i < arr.length; i++) { arr[i] = array[i] >> 1; } } else { for (int i = 0; i < arr.length; i++) { arr[i] = array[i] / div; } } return arr; } public int[] loadRGBRange(int length, int[] rgbs) throws Exception { if (rgbs == null) { throw new Exception("RGB[]'s cannot be null"); } if (length == 0) { throw new Exception("Length cannot be 0"); } if (rgbs.length == 0) { throw new Exception("RGB[]'s length cannot be 0"); } int[] rgbRange = new int[length]; if (rgbs.length == 1) { for (int i = 0; i < rgbRange.length; i++) { rgbRange[i] = rgbs[0]; } return rgbRange; } int[] positions = new int[rgbs.length]; double pos = 0; double block = (double) length / (rgbs.length - 1); for (int i = 0; i < positions.length; i++) { positions[i] = (int) pos; pos += block; } int[] as = new int[rgbs.length]; int[] rs = new int[rgbs.length]; int[] gs = new int[rgbs.length]; int[] bs = new int[rgbs.length]; for (int i = 0; i < rgbs.length; i++) { as[i] = (rgbs[i] >> 24) & 0xff; rs[i] = (rgbs[i] >> 16) & 0xff; gs[i] = (rgbs[i] >> 8) & 0xff; bs[i] = (rgbs[i]) & 0xff; } int[] adifs = new int[rgbs.length - 1]; int[] rdifs = new int[rgbs.length - 1]; int[] gdifs = new int[rgbs.length - 1]; int[] bdifs = new int[rgbs.length - 1]; for (int i = 0; i < rgbs.length - 1; i++) { adifs[i] = as[i] - as[i + 1]; rdifs[i] = rs[i] - rs[i + 1]; gdifs[i] = gs[i] - gs[i + 1]; bdifs[i] = bs[i] - bs[i + 1]; } double[] ab = new double[rgbs.length - 1]; double[] rb = new double[rgbs.length - 1]; double[] gb = new double[rgbs.length - 1]; double[] bb = new double[rgbs.length - 1]; for (int i = 0; i < rgbs.length - 1; i++) { int l = positions[i + 1] - positions[i]; ab[i] = (double) adifs[i] / l; rb[i] = (double) rdifs[i] / l; gb[i] = (double) gdifs[i] / l; bb[i] = (double) bdifs[i] / l; } double a = as[0]; double r = rs[0]; double g = gs[0]; double b = bs[0]; int color = 0; for (int i = 0; i < rgbRange.length; i++) { rgbRange[i] = ((int) a << 24) | ((int) r << 16) | ((int) g << 8) | ((int) b); if (i + 1 > positions[0] && i + 1 < positions[positions.length - 1]) { if (i == positions[color + 1]) { color++; a = as[color]; r = rs[color]; g = gs[color]; b = bs[color]; } else { a -= ab[color]; r -= rb[color]; g -= gb[color]; b -= bb[color]; } } } return rgbRange; } public int[] loadRGBRange(int length, int[] rgbs, int[] positions) throws Exception { if (positions == null) { return loadRGBRange(length, rgbs); } if (rgbs == null) { throw new Exception("RGB[]'s cannot be null"); } if (length == 0) { throw new Exception("Length cannot be 0"); } if (rgbs.length == 0 || positions.length == 0) { return null; } if (positions.length != rgbs.length) { throw new Exception( "The length of Positions[] must equals the length of RGB[]'s"); } for (int i = 0; i < positions.length; i++) { if (positions[i] > length) { throw new Exception("Any positions cannot be greater than the length"); } } int[] rgbRange = new int[length]; if (rgbs.length == 1) { for (int i = 0; i < rgbRange.length; i++) { rgbRange[i] = rgbs[0]; } return rgbRange; } int[] as = new int[rgbs.length]; int[] rs = new int[rgbs.length]; int[] gs = new int[rgbs.length]; int[] bs = new int[rgbs.length]; for (int i = 0; i < rgbs.length; i++) { as[i] = (rgbs[i] >> 24) & 0xff; rs[i] = (rgbs[i] >> 16) & 0xff; gs[i] = (rgbs[i] >> 8) & 0xff; bs[i] = (rgbs[i]) & 0xff; } int[] adifs = new int[rgbs.length - 1]; int[] rdifs = new int[rgbs.length - 1]; int[] gdifs = new int[rgbs.length - 1]; int[] bdifs = new int[rgbs.length - 1]; for (int i = 0; i < rgbs.length - 1; i++) { adifs[i] = as[i] - as[i + 1]; rdifs[i] = rs[i] - rs[i + 1]; gdifs[i] = gs[i] - gs[i + 1]; bdifs[i] = bs[i] - bs[i + 1]; } double[] ab = new double[rgbs.length - 1]; double[] rb = new double[rgbs.length - 1]; double[] gb = new double[rgbs.length - 1]; double[] bb = new double[rgbs.length - 1]; for (int i = 0; i < rgbs.length - 1; i++) { int l = positions[i + 1] - positions[i]; ab[i] = (double) adifs[i] / l; rb[i] = (double) rdifs[i] / l; gb[i] = (double) gdifs[i] / l; bb[i] = (double) bdifs[i] / l; } double a = as[0]; double r = rs[0]; double g = gs[0]; double b = bs[0]; int color = 0; for (int i = 0; i < rgbRange.length; i++) { rgbRange[i] = ((int) a << 24) | ((int) r << 16) | ((int) g << 8) | ((int) b); if (i + 1 > positions[0] && i + 1 < positions[positions.length - 1]) { if (i == positions[color + 1]) { color++; a = as[color]; r = rs[color]; g = gs[color]; b = bs[color]; } else { a -= ab[color]; r -= rb[color]; g -= gb[color]; b -= bb[color]; } } } return rgbRange; } }