11

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.

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.

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.

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.

Any help would be greatly appreciated! Thanks!

kentcdodds
  • 27,113
  • 32
  • 108
  • 187
  • 1
    see this similar question : http://stackoverflow.com/questions/3433275/adjust-brightness-and-contrast-of-bufferedimage-in-java – David Kroukamp Oct 19 '12 at 22:05

4 Answers4

5

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.

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.

dario_ramos
  • 7,118
  • 9
  • 61
  • 108
  • 1
    Thanks for the explanation. Unfortunately when I change my brightness to 1.0f and my offset to 0, it's still invisible. If I change my `filter` call to be `filter(bufferedImage, bufferedImage)` rather than `filter(bufferedImage, null)` it is a funny blue color. Any idea? – kentcdodds Oct 19 '12 at 19:19
  • Are these RGB or grayscale images? That is relevant. Check [this link](http://www.exampledepot.com/egs/java.awt.image/Bright.html) – dario_ramos Oct 19 '12 at 19:31
  • Your code is just like the example, should be OK. Is some other manipulation done with the icon before displaying it? Try saving it to disk right after calling `filter` and look at the saved image. – dario_ramos Oct 19 '12 at 19:45
  • 1
    if bufferedImage.getType()==BufferedImage.TYPE_INT_ARGB then how about to use new RescaleOp(new float[]{1.2f,1.2f,1.2f,1.0f},new float[] {0f,0f,0f,0f},null); instead of new RescaleOp(1.2f, 0f, null); – aterai Oct 19 '12 at 19:57
  • @dario_ramos, I just tried saving it to disk. It's invisible... So weird! – kentcdodds Oct 19 '12 at 20:07
  • I'm going to say this is the right answer even though I haven't quite gotten it to work on my machine because I think there must be something else wrong with my program. Thanks for the help. – kentcdodds Oct 20 '12 at 22:13
4

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:

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.

        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);
            }
        }
Nick Rippe
  • 6,465
  • 14
  • 30
  • Would this effect the background if the image had transparency? I think it would. Wouldn't it? – kentcdodds Oct 19 '12 at 20:53
  • @kentcdodds Touche - I was under the assumption that when you said "I also want to preserve transparency." You meant just that it should still be transparent (but darker). So if it's supposed to just be transparent, that's different. – Nick Rippe Oct 19 '12 at 20:56
  • Yeah, but your SSCCE worked great and helped me understand what was going on. Wish it would work for my use case! – kentcdodds Oct 19 '12 at 20:57
  • @kentcdodds Added update which addresses the transparency issue. Might have been better as a separate answer - maybe I'll remove my first answer (let me know what you think). – Nick Rippe Oct 19 '12 at 22:02
  • If the percentage is 0f, this will encounter an exception because the color would then be created with an alpha component of 256. The brightness should be `(int) (256 - 256 * percentage)`. – FThompson Oct 19 '12 at 22:08
1

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 all bands of an image between zero and two with no offsets.

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.

dstElement = (srcElement*scaleFactor) + offset
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
0

Basic logic is take RGB value of each pixel ,add some factor to it,set it again to resulltant matrix(Buffered Image)

    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);
    }
     }}
Tarun Rawat
  • 244
  • 3
  • 9