调整图像亮度、对比度、饱和度

完整代码如下:
1、主要方法编写类
package chapter4;

import java.awt.image.BufferedImage;

public class BSCAdjustFilter extends AbstractBufferedImageOp {
private double brightness;
private double contrast;
private double saturation;

public double getBrightness() {
return brightness;
}

public void setBrightness(double brightness) {
this.brightness = brightness;
}

public double getSaturation() {
return saturation;
}

public void setSaturation(double saturation) {
this.saturation = saturation;
}

public double getContrast() {
return contrast;
}

public void setContrast(double contrast) {
this.contrast = contrast;
}
public BufferedImage filter(BufferedImage src,BufferedImage dest){
handleParameters();//调整各系数取值范围
int width = src.getWidth();
int height = src.getHeight();
if(dest == null){
dest = creatCompatibleDestImage(src,null);
}
int[] inpixels = new int[widthheight];
int[] outpixels = new int[width
height];
getRGB(src,0,0,width,height,inpixels);

int index = 0;
for(int row=0;row<height;row++){
int ta = 0,tr = 0,tg = 0,tb = 0;
for(int col=0;col<width;col++){
index = row*width+col;
ta = (inpixels[index] >> 24) & 0xff;
tr = (inpixels[index] >> 16) & 0xff;
tg = (inpixels[index] >> 8) & 0xff;
tb = inpixels[index] & 0xff;
//RGB转换为HSL色彩空间
double[] hsl = rgb2Hsl(new int[]{tr,tg,tb});

//调整饱和度
hsl[1] = hsl[1]*saturation;
if(hsl[1]<0.0){
hsl[1] = 0.0;
}
if(hsl[1]>255.0){
hsl[1] = 255.0;
}

//调整亮度
hsl[2] = hsl[2]*brightness;
if(hsl[2]<0.0){
hsl[2] = 0.0;
}
if(hsl[2]>255.0){
hsl[2] = 255.0;
}
//HSL转换为rgb空间
int[] rgb = hsl2RGB(hsl);
tr = clamp(rgb[0]);
tg = clamp(rgb[1]);
tb = clamp(rgb[2]);

//调整对比度
double cr = ((tr/255.0d)-0.5d)contrast;
double cg = ((tg/255.0d)-0.5d)
contrast;
double cb = ((tb/255.0d)-0.5d)contrast;
//输出RGB值
tr = (int)((cr+0.5f)
255.0f);
tg = (int)((cg+0.5f)255.0f);
tb = (int)((cb+0.5f)
255.0f);

outpixels[index] = (ta << 24) | (clamp(tr) << 16 ) | (clamp(tg) << 8) | clamp(tb);
}
}
setRGB(dest,0,0,width,height,outpixels);
return dest;
}
public void handleParameters(){
contrast = (1.0+contrast/100.0);
brightness = (1.0 +brightness/100.0);
saturation = (1.0+saturation/100.0);
}
public int clamp(int value){
return value>255 ? 255:((value<0) ? 0:value);
}
}
2、抽象类,集成公有类方法
package chapter4;

import java.awt.image.BufferedImage;

/**

  • Created by LENOVO on 18-1-29.
    */
    public class AbstractBufferedImageOp {
    public static final double clo60 = 1.0/60.0;
    public static final double clo255 = 1.0/255.0;
    public int tr = 0,tg = 0,tb = 0;

    public AbstractBufferedImageOp(){}
    //读取像素数据
    public int[] getRGB(BufferedImage image,int x, int y, int width, int height,int[] pixels){
    int type = image.getType();
    if(type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB){
    return (int[]) image.getRaster().getDataElements(x,y,width,height,pixels);
    }else{
    return image.getRGB(x,y,width,height,pixels,0,width);
    }
    }
    //写入像素数据
    public void setRGB(BufferedImage image,int x, int y, int width, int height, int[] pixels){
    int type = image.getType();
    if(type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB){
    image.getRaster().setDataElements(x,y,width,height,pixels);
    }else {
    image.setRGB(x,y,width,height,pixels,0,width);
    }
    }
    public BufferedImage creatCompatibleDestImage(BufferedImage src,BufferedImage dest){

    return new BufferedImage(src.getWidth(),src.getHeight(),BufferedImage.TYPE_INT_RGB);
    }
    //RGB色彩空间转换为HSL色彩空间
    public double[] rgb2Hsl(int[] hsl){
    double min,max,dif,sum;
    double f1,f2;
    double h,s,l;//HSL色彩空间的三个分量
    double hsl1[]={0.0,0.0,0.0};
    tr = hsl[0];
    tg = hsl[1];
    tb = hsl[2];
    min = tr;
    if(tg<min)
    min = tg;
    if(tb<min)
    min = tb;
    max = tr;
    f1 = 0.0;
    f2 = tg-tb;
    if(tg>max){
    max = tg;
    f1 = 120.0;
    f2 = tb-tr;
    }
    if(tb >max){
    max = tb;
    f1 = 240.0;
    f2 = tr-tg;
    }
    dif = max-min;
    sum = max+min;
    l =0.5sum;//亮度仅与图像的最多颜色成分和最少的颜色成分的总量有关。亮度越小,图像越趋于黑色。亮度越高图像越趋于明亮的白色。
    if(dif == 0){//最大值与最小值相同,则表示为灰色,那么s定义为0,h未定义通常也写为0
    h = 0.0;
    s = 0.0;
    } else if(l<127.5){//根据亮度l计算饱和度
    s = 255.0
    dif/sum;
    } else{
    s = 255.0dif/(510.0-sum);
    }
    h = (f1 +60.0
    f2)/dif;//计算色调h
    if(h<0.0){
    h+=360.0;
    }
    if(h>360.0){
    h-=360.0;
    }
    hsl1[0] = h;
    hsl1[1] = s;
    hsl1[2] = l;
    return hsl1;
    }
    //HSL色彩空间转换为RGB色彩空间
    public int[] hsl2RGB(double[] hsl){
    double h,s,l;//HSL色彩空间的三个分量
    h = hsl[0];
    s = hsl[1];
    l = hsl[2];
    int[] rgb1={0,0,0};//RGB数组初始化
    double v1,v2,v3,h1;
    //HSL 转换为 RGB
    if(s == 0){//表示灰色,R,G,B定义为0
    tr = (int)l;
    tg = (int)l;
    tb = (int)l;
    }else{
    if(l<127.5){
    v2 = clo255 l(255+s);
    }else{
    v2 = l+s-clo255sl;
    }
    v1 = 2*l-v2;
    v3 = v2-v1;
    h1 = h+120.0;
    if(h1>=360.0)
    h1 -=360.0;
    //计算tr
    if(h1<60){
    tr = (int)(v1 +v3 h1 clo60);
    }else if(h1<180.0){
    tr = (int)v2;
    }else if(h1<240.0){
    tr = (int)(v1+v3
    (4-h1
    clo60));
    }else{
    tr = (int)v1;
    }
    //计算tg
    h1 = h;
    if(h1<60.0){
    tg = (int)(v1 +v3 h1 clo60);
    }else if(h1 <180.0){
    tg = (int)v2;
    }else if(h1<240.0){
    tg = (int)(v1+v3
    (4-h1
    clo60));
    }else {
    tg = (int)v1;
    }
    //计算tb
    h1 = h-120.0;
    if(h1 <0.0){
    h1 += 360.0;
    }
    if(h1<60.0){
    tb = (int)(v1 +v3 h1 clo60);
    }else if(h1<180.0){
    tb = (int)v2;
    }else if(h1<240.0){
    tb = (int)(v1+v3
    (4-h1
    clo60));
    }else{
    tb = (int)v1;
    }

    }
    rgb1[0] = tr;
    rgb1[1] = tg;
    rgb1[2] = tb;
    return rgb1;
    }
    }
    3、图像面板类
    package chapter4;

import javax.swing.;
import java.awt.
;
import java.awt.image.BufferedImage;

/**

  • Created by LENOVO on 18-1-29.
    */
    public class ImageJPanel extends JPanel {
    private static final long serialVersionUID = 1L;
    private BufferedImage sourceImage;
    private BufferedImage destImage;

    public ImageJPanel(){}
    public BufferedImage getSourceImage() {
    return sourceImage;
    }

    public void setSourceImage(BufferedImage sourceImage) {
    this.sourceImage = sourceImage;
    }

    public BufferedImage getDestImage() {
    return destImage;
    }

    public void setDestImage(BufferedImage destImage) {
    this.destImage = destImage;
    }

    public void process(){
    //SepiaToneFilter filter = new SepiaToneFilter();
    //SaturationFilter filter = new SaturationFilter();
    //BrightFilter filter = new BrightFilter();
    //ContrastFilter filter = new ContrastFilter();
    // destImage = filter.filter(sourceImage,null);
    //BrightContrastSatUI bcsUI = new BrightContrastSatUI(this);
    }
    public void process(double bcs[]){
    double s = 0.0,b = 0.0,c = 0.0;
    BSCAdjustFilter filter = new BSCAdjustFilter();
    filter.setSaturation(bcs[0]);
    filter.setBrightness(bcs[1]);
    filter.setContrast(bcs[2]);

    destImage = filter.filter(sourceImage,null);
    }

    public void paintComponent(Graphics g){
    Graphics2D g2d = (Graphics2D) g.create();
    g2d.clearRect(0,0,this.getWidth(),this.getHeight());

    if(sourceImage != null){
    g2d.drawImage(sourceImage,0,0,sourceImage.getWidth(),sourceImage.getHeight(),null);
    if(destImage != null){
    g2d.drawImage(destImage,sourceImage.getWidth()+10,0,destImage.getWidth(),destImage.getHeight(),null);
    }
    }

    }

}
4、滑动窗口面板类
package chapter4;

import javax.swing.;
import java.awt.
;
import java.awt.event.ActionListener;

/**

  • Created by LENOVO on 18-1-29.
    */
    public class BrightContrastSatUI extends JDialog {
    private static final long serialVersionUID = 1L;
    private JButton okBtn;
    private JLabel bLabel;
    private JLabel cLabel;
    private JLabel sLabel;

    private JSlider bSlider;
    private JSlider cSlider;
    private JSlider sSlider;

    public BrightContrastSatUI(JFrame parent){
    super(parent,"调整图像亮度、对比度、饱和度");
    initComponent();
    }
    public void initComponent(){
    okBtn = new JButton("确定");
    bLabel = new JLabel("亮度");
    cLabel = new JLabel("对比度");
    sLabel = new JLabel("饱和度");
    bSlider = new JSlider(JSlider.HORIZONTAL,-100,100,0);//滑块最大值最小值与初始值
    bSlider.setMajorTickSpacing(40);//主刻度标记之间间隔
    bSlider.setMinorTickSpacing(10);//次刻度标记之间间隔
    bSlider.setPaintLabels(true);//确定是否绘制标签
    bSlider.setPaintTicks(true);//确定是否在滑块上绘制刻度标记
    bSlider.setPaintTrack(true);//确定是否在滑道上绘制滑道

    cSlider = new JSlider(JSlider.HORIZONTAL,-100,100,0);
    cSlider.setMajorTickSpacing(40);
    cSlider.setMinorTickSpacing(10);
    cSlider.setPaintTicks(true);
    cSlider.setPaintLabels(true);
    cSlider.setPaintTrack(true);

    sSlider = new JSlider(JSlider.HORIZONTAL,-100,100,0);
    sSlider.setMajorTickSpacing(40);
    sSlider.setMinorTickSpacing(10);
    sSlider.setPaintTicks(true);
    sSlider.setPaintLabels(true);
    sSlider.setPaintTrack(true);

    this.getContentPane().setLayout(new BorderLayout());

    JPanel bPanel = new JPanel();
    bPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
    bPanel.add(bLabel);
    bPanel.add(bSlider);

    JPanel cPanel = new JPanel();
    cPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
    cPanel.add(cLabel);
    cPanel.add(cSlider);

    JPanel sPanel = new JPanel();
    sPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
    sPanel.add(sLabel);
    sPanel.add(sSlider);

    JPanel contentPanel = new JPanel();
    contentPanel.setLayout(new GridLayout(3,1));
    contentPanel.add(bPanel);
    contentPanel.add(cPanel);
    contentPanel.add(sPanel);

    JPanel btnPanel = new JPanel();
    btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
    btnPanel.add(okBtn);

    this.getContentPane().add(contentPanel,BorderLayout.CENTER);
    this.getContentPane().add(btnPanel,BorderLayout.SOUTH);
    this.pack();
    }

    public static void centre(Window w){//调整窗口位置
    Dimension us = w.getSize();
    Dimension them = Toolkit.getDefaultToolkit().getScreenSize();
    int newX = (them.width-us.width)/2;
    int newY = (them.height-us.height)/2;
    w.setLocation(newX,newY);
    }

    public int getBright(){
    return bSlider.getValue();//返回滑块的当前亮度值
    }
    public int getContrast(){
    return cSlider.getValue();//返回滑块当前对比度值
    }
    public int getSat(){
    return sSlider.getValue();//返回滑块当前饱和度值
    }
    public void showUI(){
    centre(this);
    this.setVisible(true);
    }

    public void setActionListener(ActionListener l){
    this.okBtn.addActionListener(l);
    }
    }
    5、测试类
    package chapter4;

import javax.imageio.ImageIO;
import javax.sound.midi.SysexMessage;
import javax.swing.;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.
;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**

  • Created by LENOVO on 18-1-29.
    */
    public class UI_MainUI extends JFrame implements ActionListener{
    private static final long serialVersionUID = 1L;
    private static final String IMG_CMD = "选择图像...";
    private static final String PROCESS_CMD = "处理";

    private JButton imgBtn;
    private JButton processBtn;
    private ImageJPanel imageJPanel;

    private BufferedImage srcImage;
    public UI_MainUI(){
    setTitle("JFrame UI —演示");
    imgBtn = new JButton(IMG_CMD);
    processBtn = new JButton(PROCESS_CMD);

    JPanel btnJpanel = new JPanel();
    btnJpanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
    btnJpanel.add(imgBtn);
    btnJpanel.add(processBtn);

    imageJPanel = new ImageJPanel();
    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(imageJPanel,BorderLayout.CENTER);
    getContentPane().add(btnJpanel,BorderLayout.SOUTH);

    setupActionListener();

    }

    public void setupActionListener(){
    imgBtn.addActionListener(this);
    processBtn.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
    if(SwingUtilities.isEventDispatchThread()){
    System.out.println("Event Dispatch Thred!!");
    }
    if(srcImage == null){

    try {
    JOptionPane.showMessageDialog(this,"请先选择图像源文件");
    JFileChooser chooser = new JFileChooser();
    chooser.showOpenDialog(null);
    setFileTypeFilter(chooser);
    File f = chooser.getSelectedFile();
    if(f != null){
    srcImage = ImageIO.read(f);
    imageJPanel.setSourceImage(srcImage);//图像面板添加图像
    imageJPanel.repaint();
    }
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    return ;
    }
    if (IMG_CMD.equals(e.getActionCommand())){
    if(srcImage == null){

    try {
    JOptionPane.showMessageDialog(this,"请先选择图像源文件");
    JFileChooser chooser = new JFileChooser();
    chooser.showOpenDialog(null);
    File f = chooser.getSelectedFile();
    if(f != null){
    srcImage = ImageIO.read(f);
    imageJPanel.setSourceImage(srcImage);//图像面板添加图像
    imageJPanel.repaint();
    }
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    }
    }else if(PROCESS_CMD.equals(e.getActionCommand())){
    //如果点击“处理”按钮,则跳出调整图像饱和度,对比度,亮度窗口

    final BrightContrastSatUI bcsUI = new BrightContrastSatUI(this);//调整图像饱和度,对比度,亮度窗口
    //点击“确定”按钮,触发事件
    bcsUI.setActionListener(new ActionListener() {//点击确定按钮后执行
    @Override
    public void actionPerformed(ActionEvent e) {
    bcsUI.setVisible(true);
    double s = bcsUI.getSat();
    double b = bcsUI.getBright();
    double c = bcsUI.getContrast();
    bcsUI.dispose();
    imageJPanel.process(new double[]{s,b,c});
    imageJPanel.repaint();
    //System.out.print("das");
    }
    });
    bcsUI.showUI();
    }
    }
    public void setFileTypeFilter(JFileChooser chooser){
    FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & PNG Images","jpg","png");
    chooser.setFileFilter(filter);
    }
    public void openView(){
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setPreferredSize(new Dimension(800,600));
    pack();
    setVisible(true);
    }
    public static void main(String args[]){
    UI_MainUI ui = new UI_MainUI();
    ui.openView();
    }
    }

posted @ 2018-01-30 15:07  爽朗的sunmeng  阅读(6819)  评论(1)    收藏  举报