2012-10-19 12 views
9

La mia domanda: Desidero poter modificare la luminosità di un'immagine di risorsa e avere tre istanze di essa come ImageIcons. Uno al 50% di luminosità (quindi più scuro), un altro al 75% di luminosità (un po 'più luminoso) e infine un altro al 100% di luminosità (lo stesso dell'immagine originale). Voglio anche preservare la trasparenza.Come modificare la luminosità di un'immagine

Quello che ho provato: Ho cercato in giro e sembra che la soluzione migliore sta utilizzando RescaleOp, ma non riesco proprio a capirlo. Non so cosa sia il fattore di scala e l'offset. Ecco il mio codice per quello che ho provato.

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

La chiamata sarebbe qualcosa di simile a questo:

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

Che cosa succede con quel codice: L'immagine appare "invisibile" So che è lì perché è su una JLabel con un evento del mouse cliccato su di esso e che funziona bene. Se salterò la parte che cambia luminosità e dico setRegularIcon(new ImageIcon(Button.class.getResource(imageLocation)); funziona perfettamente, ma ovviamente non è più scura.

Quello che penso che ho bisogno: Qualche aiuto capire cosa offset, scaleFactor, e il metodo filter significano/fanno, e di conseguenza quello che i numeri per dare per la variabile della luminosità.

Qualsiasi aiuto sarebbe molto apprezzato! Grazie!

+1

vedono questa domanda simile: http: // StackOverflow. it/questions/3433275/adjust-brightness-and-contrast-of-bufferedimage-in-java –

risposta

5

Il dottore dice:

Il codice pseudo per l'operazione di ridimensionamento è il seguente:

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

'solo una trasformazione lineare su ogni pixel. I parametri per quella trasformazione sono scaleFactor e offset. Se si desidera una luminosità del 100%, questa trasformazione deve essere un'identità, ad esempio dstElement = srcElement. L'impostazione scaleFactor = 1 e offset = 0 fa il trucco.

Ora supponiamo di voler rendere l'immagine più scura, al 75% di luminosità come dici tu. Ciò equivale a moltiplicare i valori dei pixel per 0,75. Vuoi: dstElement = 0.75 * srcElement. Quindi impostare scaleFactor = 0.75 e offset = 0 dovrebbe fare il trucco. Il problema con i tuoi valori è che vanno da 0 a 100, devi usare valori compresi tra 0 e 1.

+0

Grazie per la spiegazione. Sfortunatamente quando cambio la luminosità a 1.0f e il mio offset a 0, è ancora invisibile. Se cambio la mia chiamata 'filter' per essere' filter (bufferedImage, bufferedImage) 'piuttosto che' filter (bufferedImage, null) 'è un divertente colore blu. Qualche idea? – kentcdodds

+0

Sono queste immagini RGB o in scala di grigi? Questo è rilevante. Controlla [questo link] (http://www.exampledepot.com/egs/java.awt.image/Bright.html) –

+0

Queste sono immagini RGB. – kentcdodds

4

Suggerirei di scrivere sull'immagine con un nero semitrasparente.

Supponendo che si desidera scrivere direttamente sull'immagine:

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

Se stai usando solo l'immagine per la visualizzazione, farlo nel metodo paintComponent. Ecco uno 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

Ipotizzando lo stesso codice di cui sopra, è possibile manipolare tutto ciò oltre alla Alpha scherzi con il rasterizer.Ecco un esempio (vernice shadedImage anziché img se si utilizza questo exmaple). Si prega di notare che questo non cattura i casi limite di RGB valori superiori a 256 e meno di 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); 
      } 
     } 
+0

Questo influisce sullo sfondo se l'immagine aveva trasparenza? Penso che lo farebbe. Non sarebbe? – kentcdodds

+0

@kentcdodds Touche - Ero convinto che quando hai detto "Voglio anche preservare la trasparenza". Intendevi solo che dovrebbe essere ancora trasparente (ma più scuro). Quindi se dovrebbe essere solo trasparente, è diverso. –

+0

Sì, ma il tuo SSCCE ha funzionato benissimo e mi ha aiutato a capire cosa stava succedendo. Vorrei che funzionasse per il mio caso d'uso! – kentcdodds

1

Alcuni altri esempi di studio:

  • AlphaTest ridimensiona solo la trasparenza alfa di un'immagine tra zero e uno senza offset. Per coincidenza, ricampiona l'immagine a una dimensione di tre quarti.

  • RescaleOpTest esegue lo stesso utilizzando una scala fissa e senza offset.

  • RescaleTest bilance tutte bande di un'immagine tra zero e due senza offset.

Come indicato nella API, la scala e l'offset vengono applicate a ciascuna banda come la pendenza e y intercetta, rispettivamente, di una funzione lineare.

dstElement = (srcElement*scaleFactor) + offset 
0

logica di base è prendere valore RGB di ogni pixel, aggiungere qualche fattore ad esso, impostare nuovamente alla matrice resulltant (Immagine Buffered)

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