java 如何更改图像的亮度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12980780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to change the brightness of an Image
提问by kentcdodds
My Question:I want to be able to change the brightness of a resource image and have three instances of it as ImageIcons. One at 50% brightness (so darker), another at 75% brightness (a little brighter), and finally another at 100% brightness (the same as the original image). I also want to preserve transparency.
我的问题:我希望能够更改资源图像的亮度并将其三个实例作为 ImageIcons。一个亮度为 50%(太暗),另一个亮度为 75%(亮一点),最后另一个亮度为 100%(与原始图像相同)。我也想保持透明度。
What I've tried:I've searched around and it looks like the best solution is using RescaleOp
, but I just can't figure it out. I don't know what the scaleFactor and the offset is all about. Here's my code for what I've tried.
我尝试过的:我四处搜索,看起来最好的解决方案是使用RescaleOp
,但我就是想不通。我不知道 scaleFactor 和偏移量是什么。这是我尝试过的代码。
public void initialize(String imageLocation, float regularBrightness, float focusedBrightness, float pressedBrightness, String borderTitle) throws IOException {
BufferedImage bufferedImage = ImageIO.read(ButtonIcon.class.getResource(imageLocation));
setRegularIcon(getAlteredImageIcon(bufferedImage, regularBrightness));
setFocusedIcon(getAlteredImageIcon(bufferedImage, focusedBrightness));
setPressedIcon(getAlteredImageIcon(bufferedImage, pressedBrightness));
setTitle(borderTitle);
init();
}
private ImageIcon getAlteredImageIcon(BufferedImage bufferedImage, float brightness) {
RescaleOp rescaleOp = new RescaleOp(brightness, 0, null);
return new ImageIcon(rescaleOp.filter(bufferedImage, null));
}
The call would be something like this:
调用将是这样的:
seeATemplateButton.initialize("/resources/templateIcon-regular.png", 100f, 75f, 50f, "See A Template");
//I think my 100f, 75f, 50f variables need to change, but whenever I change them it behaves unexpectedly (changes colors and stuff).
What happens with that code:The image appears "invisible" I know it's there because it's on a JLabel with a mouse clicked event on it and that works just fine. If I just skip the brightness changing part and say setRegularIcon(new ImageIcon(Button.class.getResource(imageLocation));
it works just fine, but obviously it's not any darker.
该代码会发生什么:图像看起来“不可见”我知道它在那里,因为它在一个 JLabel 上,上面有一个鼠标点击事件,而且效果很好。如果我只是跳过亮度变化部分并说它setRegularIcon(new ImageIcon(Button.class.getResource(imageLocation));
工作得很好,但显然它不会更暗。
What I think I need:Some help understanding what offset
, scaleFactor
, and the filter
method mean/do, and consequently what numbers to give for the brightness variable.
我想我需要什么:一些帮助理解什么offset
、什么scaleFactor
和filter
方法意味着/做什么,以及因此为亮度变量提供什么数字。
Any help would be greatly appreciated! Thanks!
任何帮助将不胜感激!谢谢!
采纳答案by dario_ramos
The doc says:
医生说:
The pseudo code for the rescaling operation is as follows:
重新缩放操作的伪代码如下:
for each pixel from Source object {
for each band/component of the pixel {
dstElement = (srcElement*scaleFactor) + offset
}
}
It's just a linear transformation on every pixel. The parameters for that transformation are scaleFactor
and offset
. If you want 100% brightness, this transform must be an identity, i.e. dstElement = srcElement
. Setting scaleFactor = 1
and offset = 0
does the trick.
它只是对每个像素的线性变换。该转换的参数是scaleFactor
和offset
。如果你想要 100% 的亮度,这个变换必须是一个标识,即dstElement = srcElement
。设置scaleFactor = 1
并解决offset = 0
问题。
Now suppose you want to make the image darker, at 75% brightness like you say. That amounts to multiplying the pixel values by 0.75. You want: dstElement = 0.75 * srcElement
. So setting scaleFactor = 0.75
and offset = 0
should do the trick. The problem with your values is that they go from 0 to 100, you need to use values between 0 and 1.
现在假设你想让图像更暗,就像你说的那样,亮度为 75%。这相当于将像素值乘以 0.75。你要:dstElement = 0.75 * srcElement
。因此,设置比例因子=0.75
和offset = 0
应该做的伎俩。您的值的问题在于它们从 0 到 100,您需要使用 0 到 1 之间的值。
回答by Nick Rippe
I would suggest just writing over the image with a semi-transparent black.
我建议只用半透明的黑色写在图像上。
Assuming you want to write directly on the image:
假设你想直接写在图像上:
Graphics g = img.getGraphics();
float percentage = .5f; // 50% bright - change this (or set dynamically) as you feel fit
int brightness = (int)(256 - 256 * percentage);
g.setColor(new Color(0,0,0,brightness));
g.fillRect(0, 0, img.getWidth(), img.getHeight());
Or if you're just using the image for display purposes, do it in the paintComponent
method. Here's an SSCCE:
或者,如果您只是将图像用于显示目的,请在paintComponent
方法中进行。这是一个 SSCCE:
import java.awt.*;
import java.awt.image.*;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class ImageBrightener extends JPanel{
BufferedImage img;
float percentage = 0.5f;
public Dimension getPreferredSize(){
return new Dimension(img.getWidth(), img.getHeight());
}
public ImageBrightener(){
try {
img = ImageIO.read(new URL("http://media.giantbomb.com/uploads/0/1176/230441-thehoff_super.jpeg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(img, 0, 0, this);
int brightness = (int)(256 - 256 * percentage);
g.setColor(new Color(0,0,0,brightness));
g.fillRect(0, 0, getWidth(), getHeight());
}
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ImageBrightener());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
EDIT
编辑
Assuming the same code as above, you can manipulate everything besides the Alpha by messing with the rasterizer. Here's an example (paint shadedImage
instead of img
if using this exmaple). Please note this doesn't catch edge cases of RGB values greater than 256 and less than 0.
假设代码与上面相同,您可以通过弄乱光栅化器来操作除 Alpha 之外的所有内容。这是一个示例(如果使用此示例shadedImage
,img
则绘制而不是)。请注意,这不会捕获 RGB 值大于 256 且小于 0 的边缘情况。
img = ImageIO.read(new URL("http://media.giantbomb.com/uploads/0/1176/230441-thehoff_super.jpeg"));
shadedImage = new BufferedImage(img.getWidth(), img.getWidth(), BufferedImage.TYPE_INT_ARGB);
shadedImage.getGraphics().drawImage(img, 0, 0, this);
WritableRaster wr = shadedImage.getRaster();
int[] pixel = new int[4];
for(int i = 0; i < wr.getWidth(); i++){
for(int j = 0; j < wr.getHeight(); j++){
wr.getPixel(i, j, pixel);
pixel[0] = (int) (pixel[0] * percentage);
pixel[1] = (int) (pixel[1] * percentage);
pixel[2] = (int) (pixel[2] * percentage);
wr.setPixel(i, j, pixel);
}
}
回答by trashgod
A few more examples for study:
再举几个例子供学习:
AlphaTest
rescales just the alpha transparency of an image between zero and one with no offsets. Coincidentally, it also resamples the image to three-quarter size.RescaleOpTest
does the same using a fixed scale and no offsets.RescaleTest
scales allbands of an image between zero and two with no offsets.
AlphaTest
仅在零和一之间重新调整图像的 alpha 透明度,没有偏移。巧合的是,它还将图像重新采样到四分之三大小。RescaleOpTest
使用固定比例和无偏移量做同样的事情。RescaleTest
在零和二之间缩放图像的所有波段,没有偏移。
As noted in the API, the scale and offset are applied to each band as the slope and y-intercept, respectively, of a linear function.
如API中所述,比例和偏移分别作为线性函数的斜率和y截距应用于每个波段。
dstElement = (srcElement*scaleFactor) + offset
回答by Tarun Rawat
Basic logic is take RGB value of each pixel ,add some factor to it,set it again to resulltant matrix(Buffered Image)
基本逻辑是取每个像素的 RGB 值,为其添加一些因子,再次将其设置为结果矩阵(缓冲图像)
import java.io.*;
import java.awt.Color;
import javax.imageio.ImageIO;
import java.io.*;
import java.awt.image.BufferedImage;
class psp{
public static void main(String a[]){
try{
File input=new File("input.jpg");
File output=new File("output1.jpg");
BufferedImage picture1 = ImageIO.read(input); // original
BufferedImage picture2= new BufferedImage(picture1.getWidth(), picture1.getHeight(),BufferedImage.TYPE_INT_RGB);
int width = picture1.getWidth();
int height = picture1.getHeight();
int factor=50;//chose it according to your need(keep it less than 100)
for (int y = 0; y < height ; y++) {//loops for image matrix
for (int x = 0; x < width ; x++) {
Color c=new Color(picture1.getRGB(x,y));
//adding factor to rgb values
int r=c.getRed()+factor;
int b=c.getBlue()+factor;
int g=c.getGreen()+factor;
if (r >= 256) {
r = 255;
} else if (r < 0) {
r = 0;
}
if (g >= 256) {
g = 255;
} else if (g < 0) {
g = 0;
}
if (b >= 256) {
b = 255;
} else if (b < 0) {
b = 0;
}
picture2.setRGB(x, y,new Color(r,g,b).getRGB());
}
}
ImageIO.write(picture2,"jpg",output);
}catch(Exception e){
System.out.println(e);
}
}}