有没有办法让 Java 中的 ImageIcon 的一部分变灰?
Is there a way to gray out a portion of an ImageIcon in Java?
我正在尝试将图片的一部分变灰。 normalImage 是 100% 彩色的,而 grayedImage 是 0% 彩色的。我怎样才能生成 grayedImage,比方说,左边 50% 着色,右边 50% 变灰,反之亦然?
import javax.swing.*;
import java.awt.*;
public class TestPicture {
public static void main(String[] args) {
JFrame jf = new JFrame("Test Picture");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLayout(new BorderLayout());
jf.setPreferredSize(new Dimension(600, 300));
jf.setVisible(true);
jf.pack();
JPanel jp = new JPanel();
JLabel jl1 = new JLabel();
JLabel jl2 = new JLabel();
ImageIcon normalImage = new ImageIcon("normalImage.png");
ImageIcon grayedImage = new ImageIcon(GrayFilter.createDisabledImage(normalImage.getImage()));
jl1.setIcon(normalImage);
jl2.setIcon(grayedImage);
jp.add(jl1);
jp.add(jl2);
jf.add(jp);
jf.repaint();
jf.revalidate();
}
}
What if I wanted to do something more complex, such as graying out an image in a clock form? Are you familiar with League of Legends? In the game, there are skills that have cool down. As time passes, it undarkens itself going clockwise
你可以...
使用 BufferedImage#subImage
生成彩色图像的“进度”切片并将其绘制在灰度图像的顶部,但这只会给你一个线性进展,而不是......
你可以...
使用 AlphaComposite
生成进度蒙版,将其绘制在灰度图像的顶部
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.LinearGradientPaint;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage color;
private BufferedImage gray;
private Duration duration = Duration.ofSeconds(5);
private Instant startedAt;
private double progress;
public TestPane() throws IOException {
color = ImageIO.read(getClass().getResource("Progress.png"));
// You don't need to do this, but my original image was transparent
// and it was hard to see the fill effect
color = fillImage(color);
gray = ImageIO.read(getClass().getResource("Progress.png"));
gray = fillImage(gray);
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter(gray, gray);
Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (startedAt == null) {
startedAt = Instant.now();
}
Instant now = Instant.now();
Duration runTime = Duration.between(startedAt, now);
progress = (double) runTime.toMillis() / (double) duration.toMillis();
if (progress >= 1.0) {
((Timer) (e.getSource())).stop();
progress = 1.0;
}
System.out.println(progress);
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setRenderingHints(hints);
g2d.drawImage(progressEffect(), 0, 0, this);
g2d.dispose();
}
protected BufferedImage progressEffect() {
int width = color.getWidth();
int height = color.getHeight();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D og = img.createGraphics();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
og.setRenderingHints(hints);
og.drawImage(gray, 0, 0, this);
og.drawImage(maskedEffect(), 0, 0, this);
og.dispose();
return img;
}
protected BufferedImage maskedEffect() {
int width = color.getWidth();
int height = color.getHeight();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D og = img.createGraphics();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
og.setRenderingHints(hints);
// This will "overfill" the are so it occupies the entire image
Arc2D.Double expose = new Arc2D.Double(-(width / 2d), -(height / 2d), width * 2d, height * 2d, 90, -(360.0d * progress), Arc2D.PIE);
og.fill(expose);
og.setComposite(AlphaComposite.SrcIn);
og.drawImage(color, 0, 0, this);
og.dispose();
return img;
}
protected BufferedImage fillImage(BufferedImage original) {
int width = original.getWidth();
int height = original.getHeight();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setRenderingHints(hints);
LinearGradientPaint lgp = new LinearGradientPaint(
new Point2D.Double(0, 0),
new Point2D.Double(0, height),
new float[]{0f, 1f},
new Color[]{Color.YELLOW, Color.RED});
g2d.setPaint(lgp);
g2d.fillRect(0, 0, width, height);
g2d.drawImage(original, 0, 0, this);
g2d.dispose();
return img;
}
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
public static void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
public static BufferedImage generateMask(BufferedImage imgSource, Color color, float alpha) {
int imgWidth = imgSource.getWidth();
int imgHeight = imgSource.getHeight();
BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = imgMask.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(imgSource, 0, 0, null);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha));
g2.setColor(color);
g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight());
g2.dispose();
return imgMask;
}
}
我正在尝试将图片的一部分变灰。 normalImage 是 100% 彩色的,而 grayedImage 是 0% 彩色的。我怎样才能生成 grayedImage,比方说,左边 50% 着色,右边 50% 变灰,反之亦然?
import javax.swing.*;
import java.awt.*;
public class TestPicture {
public static void main(String[] args) {
JFrame jf = new JFrame("Test Picture");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLayout(new BorderLayout());
jf.setPreferredSize(new Dimension(600, 300));
jf.setVisible(true);
jf.pack();
JPanel jp = new JPanel();
JLabel jl1 = new JLabel();
JLabel jl2 = new JLabel();
ImageIcon normalImage = new ImageIcon("normalImage.png");
ImageIcon grayedImage = new ImageIcon(GrayFilter.createDisabledImage(normalImage.getImage()));
jl1.setIcon(normalImage);
jl2.setIcon(grayedImage);
jp.add(jl1);
jp.add(jl2);
jf.add(jp);
jf.repaint();
jf.revalidate();
}
}
What if I wanted to do something more complex, such as graying out an image in a clock form? Are you familiar with League of Legends? In the game, there are skills that have cool down. As time passes, it undarkens itself going clockwise
你可以...
使用 BufferedImage#subImage
生成彩色图像的“进度”切片并将其绘制在灰度图像的顶部,但这只会给你一个线性进展,而不是......
你可以...
使用 AlphaComposite
生成进度蒙版,将其绘制在灰度图像的顶部
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.LinearGradientPaint;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Arc2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
private BufferedImage color;
private BufferedImage gray;
private Duration duration = Duration.ofSeconds(5);
private Instant startedAt;
private double progress;
public TestPane() throws IOException {
color = ImageIO.read(getClass().getResource("Progress.png"));
// You don't need to do this, but my original image was transparent
// and it was hard to see the fill effect
color = fillImage(color);
gray = ImageIO.read(getClass().getResource("Progress.png"));
gray = fillImage(gray);
ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
op.filter(gray, gray);
Timer timer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (startedAt == null) {
startedAt = Instant.now();
}
Instant now = Instant.now();
Duration runTime = Duration.between(startedAt, now);
progress = (double) runTime.toMillis() / (double) duration.toMillis();
if (progress >= 1.0) {
((Timer) (e.getSource())).stop();
progress = 1.0;
}
System.out.println(progress);
repaint();
}
});
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setRenderingHints(hints);
g2d.drawImage(progressEffect(), 0, 0, this);
g2d.dispose();
}
protected BufferedImage progressEffect() {
int width = color.getWidth();
int height = color.getHeight();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D og = img.createGraphics();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
og.setRenderingHints(hints);
og.drawImage(gray, 0, 0, this);
og.drawImage(maskedEffect(), 0, 0, this);
og.dispose();
return img;
}
protected BufferedImage maskedEffect() {
int width = color.getWidth();
int height = color.getHeight();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D og = img.createGraphics();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
og.setRenderingHints(hints);
// This will "overfill" the are so it occupies the entire image
Arc2D.Double expose = new Arc2D.Double(-(width / 2d), -(height / 2d), width * 2d, height * 2d, 90, -(360.0d * progress), Arc2D.PIE);
og.fill(expose);
og.setComposite(AlphaComposite.SrcIn);
og.drawImage(color, 0, 0, this);
og.dispose();
return img;
}
protected BufferedImage fillImage(BufferedImage original) {
int width = original.getWidth();
int height = original.getHeight();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON
);
g2d.setRenderingHints(hints);
LinearGradientPaint lgp = new LinearGradientPaint(
new Point2D.Double(0, 0),
new Point2D.Double(0, height),
new float[]{0f, 1f},
new Color[]{Color.YELLOW, Color.RED});
g2d.setPaint(lgp);
g2d.fillRect(0, 0, width, height);
g2d.drawImage(original, 0, 0, this);
g2d.dispose();
return img;
}
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
public static void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
public static BufferedImage generateMask(BufferedImage imgSource, Color color, float alpha) {
int imgWidth = imgSource.getWidth();
int imgHeight = imgSource.getHeight();
BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = imgMask.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(imgSource, 0, 0, null);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha));
g2.setColor(color);
g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight());
g2.dispose();
return imgMask;
}
}