昨天晚上在科学松鼠会上看到一篇题为“计算机原来要晃一晃才好用”的文章,里面提到了一种计算机处理数字信号时常用的抖动技术,觉得蛮有意思的所以今天就用万恶的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; }