如何控制图像的亮度?
How can I control the brightness of an Image?
我有以下问题:
我想创建一种方法来控制图像的亮度。我想我必须先将它转换为 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;
}
要检查 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()
方法。
看看下面的代码。
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;
}
}
它将读取图像并使用具有新亮度的新图像创建矩阵。这是我的个人资料图片的结果。
编辑:
现在它也支持 alpha。之前的代码中,新像素的alpha分量固定为255,我改为使用原像素的alpha分量(pixel[3]
)。
编辑 2:
每个像素都有一个从 0 到 1 不等的亮度分量。如果此分量外推值为 1,则该像素将具有 "strange" 颜色。你想要一些看起来比原来的更亮的东西,所以,你需要验证新的亮度值是否推断为 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;
}
}
}
看看下图。
我想你现在就明白了。如果不行我就放弃了:D
我有以下问题:
我想创建一种方法来控制图像的亮度。我想我必须先将它转换为 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;
}
要检查 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()
方法。
看看下面的代码。
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;
}
}
它将读取图像并使用具有新亮度的新图像创建矩阵。这是我的个人资料图片的结果。
编辑:
现在它也支持 alpha。之前的代码中,新像素的alpha分量固定为255,我改为使用原像素的alpha分量(pixel[3]
)。
编辑 2:
每个像素都有一个从 0 到 1 不等的亮度分量。如果此分量外推值为 1,则该像素将具有 "strange" 颜色。你想要一些看起来比原来的更亮的东西,所以,你需要验证新的亮度值是否推断为 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;
}
}
}
看看下图。
我想你现在就明白了。如果不行我就放弃了:D