昨天晚上在科学松鼠会上看到一篇题为“计算机原来要晃一晃才好用”的文章,里面提到了一种计算机处理数字信号时常用的抖动技术,觉得蛮有意思的所以今天就用万恶的JAVA写了生成二直图像的小程序。
截图:
程序中使用的acm jtf包在http://jtf.acm.org/可以下到,推荐刚开始学java的同学去看Eric S. Roberts的《the art and Science of Java》(影印版),很好的入门教材,还可以顺便提高英语阅读能力。
主程序代码:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import acm.program.*;
import acm.graphics.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class test_filter extends GraphicsProgram{
public void init()
{
setBackground(Color.gray);
slider = new JSlider(0,100,50);
add(new JButton("Open Image"),SOUTH);
add(new JButton("Process"),SOUTH);
add(new JLabel("Dark "),SOUTH);
add(slider,SOUTH);
add(new JLabel("Bright"),SOUTH);
add(new JButton("Save"),SOUTH);
addActionListeners();
}
public void actionPerformed(ActionEvent e)
{
String cmd = e.getActionCommand();
if(cmd.equals("Open Image")) openTarget();
if(cmd.equals("Process")) process();
if(cmd.equals("Save")) save();
}
private void openTarget()
{
JFileChooser chooser = new JFileChooser();
int fid = chooser.showOpenDialog(this);
if(fid == chooser.APPROVE_OPTION)
{
File file = chooser.getSelectedFile();
if(file.getName().endsWith(".jpg") || file.getName().endsWith(".JPG"))
{
target = null;
target = new GImage(file.getPath());
setScale(target);
is_target_ready = true;
target_thumbnail = thumbnail(target);
pic_width = target_thumbnail.getWidth();
pic_height = target_thumbnail.getHeight();
removeAll();
add(target_thumbnail,0,0);
}
}
}
private void process()
{
if(!is_target_ready) return ;
double factor = slider.getValue()/50.0;
result = dsp.actBwFilter(target,factor);
GImage result_thumbnail = thumbnail(result);
add(result_thumbnail,pic_width,0);
is_result_ready = true;
}
private void save()
{
if(!is_result_ready) return ;
try {
JFileChooser chooser = new JFileChooser();
int fid = chooser.showSaveDialog(this);
if(fid==JFileChooser.APPROVE_OPTION)
{
File file = chooser.getSelectedFile();
ImageIO.write(toBufferedImage(result), "jpg", file);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private BufferedImage toBufferedImage(GImage image)
{
int[][] array = image.getPixelArray();
int width = array[0].length;
int height = array.length;
BufferedImage bimg = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++) bimg.setRGB(j, i, array[i][j]);
}
return bimg;
}
private GImage thumbnail(GImage image)
{
GImage thumbnail = dsp.imageSampleAve(image, scale);
return thumbnail;
}
private void setScale(GImage image)
{
if(image.getWidth()>image.getHeight())
{
scale = (int)(calcuScale(image,1,2)+0.5);
}
else scale = (int)(calcuScale(image,2,1)+0.5);
}
private double calcuScale(GImage image,int row,int column)
{
int width = getWidth()/column;
int height = getHeight()/row;
double ws = image.getWidth()/width;
double hs = image.getHeight()/height;
if(ws>hs) return ws;
return hs;
}
public static void main(String args[])
{
new test_filter().start(args);
}
public static final int APPLICATION_WIDTH = 600;
public static final int APPLICATION_HEIGHT = 300;
private int scale;
private GImage target;
private GImage result;
private GImage target_thumbnail;
private double pic_width;
private double pic_height;
private JSlider slider;
private boolean is_target_ready;
private boolean is_result_ready;
}
二值图生成函数:
public static GImage actBwFilter(GImage image)
{
return actBwFilter(image,1);
}
public static GImage actBwFilter(GImage image,double factor)
{
image = bwFilter(image);
int[][] array = image.getPixelArray();
RandomGenerator rgen = RandomGenerator.getInstance();
int width = array[0].length;
int height = array.length;
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
int color=array[i][j]&0xFF;
double p = (double)color/0xFF;
if(rgen.nextBoolean(p*factor)) color=0xFF;
else color=0x00;
array[i][j]=(0xFF<<24)|(color<<16)|(color<<8)|color;
}
}
GImage img = new GImage(array);
return img;
}