如何更改图像的亮度

时间:2012-10-19 19:02:22

标签: java swing image-manipulation brightness imageicon

我的问题:我希望能够更改资源图片的亮度,并将其三个实例作为ImageIcons。一个亮度为50%(如此暗),另一个亮度为75%(亮度稍高),最后另一个亮度为100%(与原始图像相同)。我也希望保持透明度。

我尝试了什么:我一直在搜索,看起来最好的解决方案是使用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));
}

电话会是这样的:

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).

该代码会发生什么:图像显示为“隐形”我知道它就在那里,因为它位于JLabel上,上面有鼠标点击事件,并且工作得很好。如果我只是跳过亮度变化部分并说setRegularIcon(new ImageIcon(Button.class.getResource(imageLocation));它工作正常,但显然它不是更暗。

我认为我需要什么:有些人可以帮助了解offsetscaleFactorfilter方法的意思/做法,以及提供的数字对于亮度变量。

任何帮助将不胜感激!谢谢!

4 个答案:

答案 0 :(得分:5)

医生说:

重新缩放操作的伪代码如下:

for each pixel from Source object {
    for each band/component of the pixel {
        dstElement = (srcElement*scaleFactor) + offset
    }
}

这只是每个像素的线性变换。该转换的参数为scaleFactoroffset。如果您想要100%亮度,则此变换必须是标识,即dstElement = srcElement。设置scaleFactor = 1offset = 0可以解决问题。

现在假设你想让图像变暗,像你说的那样亮度为75%。这相当于将像素值乘以0.75。你想要:dstElement = 0.75 * srcElement。因此,设置scaleFactor = 0.75offset = 0应该可以解决问题。您的值的问题是它们从0到100,您需要使用0到1之间的值。

答案 1 :(得分:4)

我建议用半透明的黑色书写图像。

假设您想直接在图像上书写:

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());

或者,如果您只是将图像用于显示目的,请使用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);
    }
}

修改

假设代码与上面相同,你可以通过搞乱光栅化器来操纵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);
            }
        }

答案 2 :(得分:1)

还有一些研究的例子:

  • AlphaTest仅重新调整图像的alpha透明度,介于0和1之间,没有偏移。巧合的是,它还将图像重新采样为四分之三大小。

  • RescaleOpTest使用固定比例并且没有偏移来做同样的事情。

  • RescaleTest在0到2之间缩放图像的所有波段,没有偏移。

API所述,比例和偏移分别作为线性函数的斜率和 y - 截距应用于每个波段。

dstElement = (srcElement*scaleFactor) + offset

答案 3 :(得分:0)

基本逻辑是取每个像素的RGB值,为它添加一些因子,再次将其设置为resulltant矩阵(缓冲图像)

    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);
    }
     }}