2017-10-17 93 views
1

我有以下问题:如何控制图像的亮度?

我想创建一个方法来控制图像的亮度。我想我必须先将它转换为BufferedImage。
如果图像有一个alpha通道,我想用TYPE_INT_RGB将其转换为alpha像素将是黑色的。但它可以很好地与TYPE_INT_ARGB ...
如果图像没有alpha通道,并且我将其转换为TYPE_INT_ARGB,则不起作用。那么不仅亮度变化,还有颜色。当我使图像更明亮时,它会变得更黄,如果我变暗,它会变成蓝色。
我可以用另一种方式转换它,还是有可能检查图像是否有alpha通道?

这里是我的代码:

public static Image brightnessControl(Image image, float brightness) { 

    //First I convert the Image to a BufferedImage 
    BufferedImage bi = new BufferedImage 
      (image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); 
    Graphics bg = bi.getGraphics(); 
    bg.drawImage(image, 0, 0, null); 
    bg.dispose(); 

    //here I brighten/darken the BufferedImage 
    RescaleOp rescaleOp = new RescaleOp(brightness, 0, null); 
    rescaleOp.filter(bi, bi); 

    //I change the BufferedImage back to the Image again! 
    image = bi; 

    //Last but not least I return the Image... 
    return image; 
} 
+0

你可以试试'image = rescaleOp.filter(bi,null);'而不是'rescaleOp。filter(bi,bi);'(参见[Javadoc](https://docs.oracle.com/javase/8/docs/api/java/awt/image/RescaleOp.html#filter-java.awt.image。 BufferedImage的-java.awt.image.BufferedImage-))? – howlger

+0

@howlger如果我这样做,我不能使用alpha通道使图像变亮。但它修复了奇怪的颜色问题! – Andy

回答

2

看看下面的代码。

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class Test { 

    public static void main(String[] args) throws IOException { 

     Image img = ImageIO.read(new File("image.jpeg")); 

     new JFrame(){ 
      { 
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       setSize(800, 600); 
       setLocationRelativeTo(null); 
       add(new JPanel(){ 
        @Override 
        protected void paintComponent(Graphics g) { 

         super.paintComponent(g); 

         int imgWidth = img.getWidth(null); 
         int imgHeight = img.getHeight(null); 
         int lines = 4; 
         int columns = 6; 
         int count = 1; 

         for (int i = 0; i < lines; i++) { 
          for (int j = 0; j < columns; j++) { 
           g.drawImage(newBrightness(img, 1f/(lines*columns)*count), imgWidth * j, imgHeight * i, null); 
           count++; 
          } 
         } 
        } 
       }); 
      } 
     }.setVisible(true); 

    } 

    public static Image newBrightness(Image source, float brightnessPercentage) { 

     BufferedImage bi = new BufferedImage( 
       source.getWidth(null), 
       source.getHeight(null), 
       BufferedImage.TYPE_INT_ARGB); 

     int[] pixel = { 0, 0, 0, 0 }; 
     float[] hsbvals = { 0, 0, 0 }; 

     bi.getGraphics().drawImage(source, 0, 0, null); 

     // recalculare every pixel, changing the brightness 
     for (int i = 0; i < bi.getHeight(); i++) { 
      for (int j = 0; j < bi.getWidth(); j++) { 

       // get the pixel data 
       bi.getRaster().getPixel(j, i, pixel); 

       // converts its data to hsb to change brightness 
       Color.RGBtoHSB(pixel[0], pixel[1], pixel[2], hsbvals); 

       // create a new color with the changed brightness 
       Color c = new Color(Color.HSBtoRGB(hsbvals[0], hsbvals[1], hsbvals[2] * brightnessPercentage)); 

       // set the new pixel 
       bi.getRaster().setPixel(j, i, new int[]{ c.getRed(), c.getGreen(), c.getBlue(), pixel[3] }); 

      } 

     } 

     return bi; 

    } 

} 

它会读取图像,并创建一个新的图像矩阵与新的亮度。这是我的个人资料图片的结果。

enter image description here

编辑:

现在支持alpha过。在之前的代码中,新像素的alpha分量在255中被修复。我改变了使用原始像素的alpha分量(pixel[3])。

enter image description here

编辑2:

每个像素将具有如果此成分推断值1 0是改变到1的亮度分量,象素将具有“陌生”颜色。你希望有比原来更亮的东西,因此,你需要验证新的亮度值是否外推1。您将有一个滑块来控制将计算到新像素亮度分量的最大百分比。如果该值超过最大值(1),则将使用最大值。我希望现在它终于可以帮助你:D

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class ChangeImageBrightnessExample2 { 

    public static void main(String[] args) throws IOException { 
     new ChangeImageBrightnessExample2().createUI(); 
    } 

    public void createUI() throws IOException { 

     Image img = ImageIO.read(new File("image.jpeg")); 

     new JFrame(){ 
      { 
       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       setSize(800, 600); 
       setLocationRelativeTo(null); 

       CustomPanel panel = new CustomPanel(); 
       panel.setImage(img); 

       JSlider slider = new JSlider(0, 400, 100); 
       slider.setMinorTickSpacing(10); 
       slider.setMajorTickSpacing(50); 
       slider.setPaintLabels(true); 
       slider.setPaintTicks(true); 
       slider.setSnapToTicks(true); 
       slider.addChangeListener(new ChangeListener() { 
        @Override 
        public void stateChanged(ChangeEvent evt) { 
         JSlider s = ((JSlider) evt.getSource()); 
         if (s.getValueIsAdjusting()) { 
          panel.setMaximumBrightnessPercentage(s.getValue()/100f); 
          panel.repaint(); 
         } 

        } 
       }); 

       add(panel, BorderLayout.CENTER); 
       add(slider, BorderLayout.SOUTH); 

      } 
     }.setVisible(true); 

    } 

    public static Image newBrightness(Image source, float brightnessPercentage) { 

     BufferedImage bi = new BufferedImage( 
       source.getWidth(null), 
       source.getHeight(null), 
       BufferedImage.TYPE_INT_ARGB); 

     int[] pixel = { 0, 0, 0, 0 }; 
     float[] hsbvals = { 0, 0, 0 }; 

     bi.getGraphics().drawImage(source, 0, 0, null); 

     // recalculare every pixel, changing the brightness 
     for (int i = 0; i < bi.getHeight(); i++) { 
      for (int j = 0; j < bi.getWidth(); j++) { 

       // get the pixel data 
       bi.getRaster().getPixel(j, i, pixel); 

       // converts its data to hsb to change brightness 
       Color.RGBtoHSB(pixel[0], pixel[1], pixel[2], hsbvals); 

       // calculates the brightness component. 
       float newBrightness = hsbvals[2] * brightnessPercentage; 
       if (newBrightness > 1f) { 
        newBrightness = 1f; 
       } 

       // create a new color with the new brightness 
       Color c = new Color(Color.HSBtoRGB(hsbvals[0], hsbvals[1], newBrightness)); 

       // set the new pixel 
       bi.getRaster().setPixel(j, i, new int[]{ c.getRed(), c.getGreen(), c.getBlue(), pixel[3] }); 

      } 

     } 

     return bi; 

    } 

    private class CustomPanel extends JPanel { 

     private float maximumBrightnessPercentage = 1f; 
     private Image image; 

     @Override 
     protected void paintComponent(Graphics g) { 

      super.paintComponent(g); 

      int imgWidth = image.getWidth(null); 
      int imgHeight = image.getHeight(null); 
      int lines = 4; 
      int columns = 6; 
      int count = 1; 

      for (int i = 0; i < lines; i++) { 
       for (int j = 0; j < columns; j++) { 
        float newBrightness = maximumBrightnessPercentage/(lines*columns)*count; 
        g.drawImage(newBrightness(image, newBrightness), imgWidth * j, imgHeight * i, null); 
        g.drawString(String.format("%.2f%%", newBrightness*100), imgWidth * j, imgHeight * i + 10); 
        count++; 
       } 
      } 

     } 

     public void setMaximumBrightnessPercentage(float maximumBrightnessPercentage) { 
      this.maximumBrightnessPercentage = maximumBrightnessPercentage; 
     } 

     public void setImage(Image image) { 
      this.image = image; 
     } 

    } 

} 

看一看下图。

enter image description here

现在我想你会明白的。如果没有,我会放弃:D

+0

谢谢!这就是我期待的! – Andy

+0

我试用过PNG-File,出于任何原因Alpha通道变成黑色......为什么? – Andy

+1

@安迪现在它支持阿尔法。 – davidbuzatto

2

要在BufferedImage检查alpha通道,使用BufferedImage.getColorModel().hasAlpha();

public static Image brightnessControl(Image image, float brightness) { 
    // First I convert the Image to a BufferedImage 
    BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); 
    Graphics bg = bi.getGraphics(); 

    if (bi.getColorModel().hasAlpha()) { // This will output true because you have just applied TYPE_INT_ARGB! 
     System.out.println("Image has got an alpha channel"); 
    } 

    bg.drawImage(image, 0, 0, null); 
    bg.dispose(); 

    // here I brighten/darken the BufferedImage 
    RescaleOp rescaleOp = new RescaleOp(brightness, 0, null); 
    rescaleOp.filter(bi, bi); 

    // I change the BufferedImage back to the Image again! 
    image = bi; 

    // Last but not least I return the Image... 
    return bi; 
} 

您需要在参数传递的Image转换为BufferedImage使用.getColorModel().hasAlpha()方法。