java中有drawLine的功能,当drawLine的起始点和终止点在同一点时,画出来的就是一个点,当你通过setColor的方法为其赋予颜色时,它画到屏幕上就是一个有颜色的像素点了,当你画出很多的点,便可以组成一幅图片了。获取图片数据的方法就是以二维数组的形式获取图片上点的RGB并保存起来,当你要画的时候,只要遍历数组然后取出颜色画到屏幕上即可。所以,如果我们要处理图片,并为其加上一些特殊效果,首先就要把它转化为一个二维数组。
public static int[][] img2color(String imgfile) {
File file = new File(imgfile);
BufferedImage bi = null;
try {
bi = ImageIO.read(file);
} catch (Exception e) {
e.printStackTrace();
}
int width = bi.getWidth();
int height = bi.getHeight();
int minx = bi.getMinX();
int miny = bi.getMinY();
int[][] allcolor = new int[height - miny][width - minx];
for (int j = miny; j < height; j++) {
for (int i = minx; i < width; i++) {
int pixel = bi.getRGB(i, j);// 将一个数字转换为RGB数字
allcolor[j - miny][i - minx] = pixel;
}
}
return allcolor;
}
public static Color[][] img3color(String imgfile){
File file = new File(imgfile);
BufferedImage bi = null;
try {
bi = ImageIO.read(file);
} catch (Exception e) {
e.printStackTrace();
}
int width = bi.getWidth();
int height = bi.getHeight();
int minx = bi.getMinX();
int miny = bi.getMinY();
Color[][] allcolor=new Color[height-miny][width-minx];
for (int j = miny; j < height; j++) {
for (int i = minx; i < width; i++) {
int pixel = bi.getRGB(i, j); // 将一个数字转换为RGB数字
allcolor[j-miny][i-minx] = new Color(pixel);
}
}
return allcolor;
}
这里有两种方法可以选择,第一种方法是把每一个像素点的转化为一个用int表示的参数,它的好处是可以通过对参数做一些判断,获得一些条件的限定然后为画笔的RGB参数赋值,实现类似黑白化的效果。第二种方法是获取Color值,存入数组,调用时可直接为画笔颜色赋值。
数组中存的是一个int值参数,使用时需要先试着输出数组的值,判断它的大致范围,然后在其中选择一个合适的值来做判断。我们这里是t大于10599121把像素点赋为黑色,其余不画。
if ("黑白".equals(e.getActionCommand()))
{
g.setColor(Color.white);
g.fillRect(0, 0, 1500, 1000);
System.out.println("黑白");
int[][] allcolor = img2color("E:\\workspace\\mayifan\\src\\com\\myf\\ps1110\\图片\\1.jpg");
for (int i=0;i<allcolor.length;i++)
{
for (int j=0;j<allcolor[i].length;j++)
{
int t=-allcolor[i][j];
if(t>10599121)
{
Color c= new Color(0,0,0);
g.setColor(c);
g.drawLine(j+300,i+150, j+300, i+150);
}
}
}
}
马赛克的实现思路就是把画面的像素点数量减少,降低画面的分辨率。我们隔10个点取一色,然后fill这10*10的区域,这样就形成马赛克的方块了,我们可以根据取样的间隔来调整画面的可辨识度。
else if ("马赛克".equals(e.getActionCommand()))
{
g.setColor(Color.white);
g.fillRect(0, 0, 1500, 1000);
System.out.println("马赛克");
Color[][] allcolor=img3color("E:\\workspace\\mayifan\\src\\com\\myf\\ps1110\\图片\\1.jpg");
for (int i=0;i<allcolor.length;i=i+10)
{
for (int j=0;j<allcolor[i].length;j=j+10)
{
//System.out.println(color);
Color c=allcolor[i][j];
g.setColor(c);
g.fillRect(j+300,i+150, 10, 10);
}
}
}
这里用到了一个sin函数,这里我们要注意参数的类型,int会被取整为0,另外还要注意函数的放大,不然效果会不明显哦。
else if ("波纹化".equals(e.getActionCommand()))
{
g.setColor(Color.white);
g.fillRect(0, 0, 1500, 1000);
System.out.println("波纹化");
Color[][] allcolor=img3color("E:\\workspace\\mayifan\\src\\com\\myf\\ps1110\\图片\\1.jpg");
for (int i=0;i<allcolor.length;i++)
{
for (int j=0;j<allcolor[i].length;j++)
{
Color c=allcolor[i][j];
g.setColor(c);
int y=(int)(12*Math.sin((double)j/10));
g.drawLine(j+300,i+150-y, j+300, i+150-y);
}
}
}
这里我们贴上把图片转为蓝色调的代码。红色,绿色等处理方法都同理,核心就是对RGB参数的赋值。
else if ("蓝色".equals(e.getActionCommand()))
{
g.setColor(Color.white);
g.fillRect(0, 0, 1500, 1000);
System.out.println("蓝色");
int[][] allcolor = img2color("E:\\workspace\\mayifan\\src\\com\\myf\\ps1110\\图片\\1.jpg");
for (int i=0;i<allcolor.length;i++)
{
for (int j=0;j<allcolor[i].length;j++)
{
int t=-allcolor[i][j];
Color c= new Color(0,0,t/100000);
g.setColor(c);
g.drawLine(j+300,i+150, j+300, i+150);
}
}
}
这里的效果是,当按下“分散”按钮时,让图片化为许多的碎片向四周散落,再按下“恢复”按钮时,图片又重新聚拢恢复成原来的样子,这段代码思路我的总结就是:让图片化为若干独立的有自己属性的对象,记录初始坐标,在线程内修改坐标让他们运动,聚拢时即寻找每个小图片的x0和y0(初始坐标)。
监听器类:
public class Listener implements ActionListener {
private Graphics g;
private ArrayList<Picture> array = new ArrayList<Picture>();
private PictureJpanel cp;
private ThreadPicture tp;
public int flag=0;
private Listener listener;
public void setg(Graphics g) {
this.g = g;
}
public void actionPerformed(ActionEvent e)
{
if ("分散".equals(e.getActionCommand()))
{
flag=1;
g.setColor(Color.white);
g.fillRect(0, 0, 1500, 1000);
System.out.println("分散");
Color[][] allcolor=img3color("E:\\workspace\\mayifan\\src\\com\\myf\\ps1110\\图片\\1.jpg");
for (int i=0;i<allcolor.length;i++)
{
for (int j=0;j<allcolor[i].length;j++)
{
Color c=allcolor[i][j];
g.setColor(c);
g.drawLine(j+300,i+150, j+300, i+150);
}
}
for (int i=0;i<allcolor.length;i=i+50)
{
for (int j=0;j<allcolor[i].length;j=j+50)
{
File file = new File("E:\\workspace\\mayifan\\src\\com\\myf\\ps1110\\图片\\1.jpg");
BufferedImage bi = null;
try {
bi = ImageIO.read(file);
} catch (Exception e1) {
e1.printStackTrace();
}
Color[][] allcolor1=new Color[50][50];
for (int n = i; n < i+50; n++)
{
for (int m = j; m < j+50; m++)
{
int pixel = bi.getRGB(m, n);// 下面三行代码将一个数字转换为RGB数字
allcolor1[n-i][m-j] = new Color(pixel);
}
}
int rand=(int)(1+Math.random()*(4-1+1));
Picture pic= new Picture(j+300,i+150,50,50,allcolor1,j+300,i+150,rand);
array.add(pic);
//System.out.println(array.size());
}
}
if(tp==null)
{
ThreadPicture tp= new ThreadPicture();
tp.start();
tp.setcp(cp);
tp.setArray(array);
tp.setlistener(listener);
}
}
else if ("恢复".equals(e.getActionCommand()))
{
System.out.println("恢复");
flag=2;
}
}
public static Color[][] img3color(String imgfile){
File file = new File(imgfile);
BufferedImage bi = null;
try {
bi = ImageIO.read(file);
} catch (Exception e) {
e.printStackTrace();
}
int width = bi.getWidth();
int height = bi.getHeight();
int minx = bi.getMinX();
int miny = bi.getMinY();
Color[][] allcolor=new Color[height-miny][width-minx];
for (int j = miny; j < height; j++) {
for (int i = minx; i < width; i++) {
int pixel = bi.getRGB(i, j); ///将一个数字转换为RGB数字
allcolor[j-miny][i-minx] = new Color(pixel);
}
}
return allcolor;
}
public void setcp(PictureJpanel cp) {
// TODO Auto-generated method stub
this.cp=cp;
cp.setarray(array);
}
public void setlistener(Listener listener) {
// TODO Auto-generated method stub
this.listener=listener;
}
}
图片类:
public class Picture {
public int x0;
public int y0;
public int height;
public int width;
public Color[][] allcolor=new Color[height][width];
public int x;
public int y;
public int direct;
public Picture(int x0,int y0,int height, int width, Color[][] allcolor, int x,int y , int direct)
{
this.x0=x0;
this.y0=y0;
this.height=height;
this.width=width;
this.allcolor=allcolor;
this.x=x;
this.y=y;
this.direct=direct;
}
画板重绘:
public class PictureJpanel extends JPanel{
private ArrayList<Picture> array;
public void paint(Graphics g)
{
super.paint(g);
for(int i=0;i<array.size();i++)
{
Picture pic= array.get(i);
for (int k=0;k<50;k++)
{
for (int j=0;j<50;j++)
{
Color c=pic.allcolor[k][j];
g.setColor(c);
g.drawLine(pic.x+j,pic.y+k,pic.x+j,pic.y+k);
}
}
}
}
public void setarray(ArrayList<Picture> array) {
// TODO Auto-generated method stub
this.array=array;
}
}
图片线程:
public class ThreadPicture extends Thread {
private PictureJpanel cp;
private ArrayList<Picture> array;
private Listener listener;
public void run(){
while(true){
for(int i=0;i<array.size();i++)
{
int randx =(int)(1+Math.random()*(2-1+1));
Picture pic= array.get(i);
if(listener.flag==2&&Math.abs(pic.x-pic.x0)<5)
{
pic.x=pic.x0;
continue;
}
if(listener.flag==1)
{
switch(pic.direct)
{
case 1:
pic.x+=randx;
break;
case 2:
pic.x-=randx;
break;
case 3:
pic.x+=randx;
break;
case 4:
pic.x-=randx;
break;
}
}
else if(listener.flag==2)
{
switch(pic.direct)
{
case 1:
pic.x-=randx;
break;
case 2:
pic.x+=randx;
break;
case 3:
pic.x-=randx;
break;
case 4:
pic.x+=randx;
break;
}
}
//System.out.println(pic.x);
}
for(int i=0;i<array.size();i++)
{
int randy =(int)(1+Math.random()*(2-1+1));
Picture pic= array.get(i);
if(listener.flag==2&&Math.abs(pic.y-pic.y0)<5)
{
pic.y=pic.y0;
continue;
}
if(listener.flag==1)
{
switch(pic.direct)
{
case 1:
pic.y+=randy;
break;
case 2:
pic.y-=randy;
break;
case 3:
pic.y-=randy;
break;
case 4:
pic.y+=randy;
break;
}
}
else if(listener.flag==2)
{
switch(pic.direct)
{
case 1:
pic.y-=randy;
break;
case 2:
pic.y+=randy;
break;
case 3:
pic.y+=randy;
break;
case 4:
pic.y-=randy;
break;
}
}
//System.out.println(pic.x);
}
cp.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void setcp(PictureJpanel cp) {
// TODO Auto-generated method stub
this.cp=cp;
}
public void setArray(ArrayList<Picture> array) {
// TODO Auto-generated method stub
this.array=array;
}
public void setlistener(Listener listener) {
// TODO Auto-generated method stub
this.listener=listener;
}
}
基于以上思路我们还可以对图像做很多处理,加各种有趣的特效!