代码展示
ImageEFF
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ImageEFF {
public int[][] ImageToArray(String imgpath){
File imgfile=new File(imgpath);
BufferedImage img=null;
try {
img=ImageIO.read(imgfile);
}catch(java.io.IOException e) {
e.printStackTrace();
System.err.println("图像读取失败");
}
int w=img.getWidth();
int h=img.getHeight();
int [][] imgArr=new int [w][h];
for(int i=0;i<w;i++) {
for(int j=0;j<h;j++) {
imgArr[i][j]=img.getRGB(i, j);
}
}
return imgArr;
}
//油画融合
public BufferedImage drawImagenmd(int [][]imgArr1,int [][]imgArr2,Graphics g) { //用返回值保存
BufferedImage buffimg=new BufferedImage(imgArr1.length,imgArr1[0].length,BufferedImage.TYPE_INT_ARGB);
//TYPE_INT_ARGB代表颜色为int(4个字节),红色通道道在16-23,绿色在8-15和蓝色在0-7
// 将所有的像素值存入缓冲图片- 操作- 内存操作
for(int i=0;i<imgArr1.length;i++) {
for(int j=0;j<imgArr1[i].length;j++) {
int value=imgArr1[i][j];
//Color color=new Color(value);
//g.setColor(color);//相当于在重绘每个像素点 所以要给画笔每个像素的颜色再填充
//g.fillRect(50+i, 50+j, 1, 1);
int value1=imgArr2[i][j];
buffimg.setRGB(i, j, (value+value1)/2);//全部初始化缓冲在内存的BufferedImage中 还未画
}
}
//将整张图片一次性绘制
g.drawImage(buffimg, 0,0,null);
return buffimg;
}
//马赛克瓷砖
public BufferedImage drawImage0(int [][]imgArr,Graphics g) {
BufferedImage buffimg=new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg.getGraphics();
for(int i=0;i<imgArr.length;i+=10) {
for(int j=0;j<imgArr[i].length;j+=10) {
int value=imgArr[i][j];
Color color=new Color(value);
buffg.setColor(color);//相当于在重绘每个像素点 所以要给画笔每个像素的颜色再填充
buffg.fillRect(i, j, 8, 8);
}
}
g.drawImage(buffimg, 0, 0, null);
return buffimg;
}
/**
* 灰度
* @param path 图片路径
* @param g 图形类 功能 绘制像素点
*/
public BufferedImage drawImage1(int [][]imgArr,Graphics g) {
BufferedImage buffimg=new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg.getGraphics();
for (int i=0;i<imgArr.length;i++) {
for(int j=0;j<imgArr[i].length;j++) {
int value=imgArr[i][j];
int red=(value>>16)&0xFF;
int green=(value>>8)&0xFF;
int blue=(value>>0)&0xFF;
int gray=(int)(red*0.6+green*0.3+blue*0.1);
Color color=new Color(gray,gray,gray);
buffg.setColor(color);
buffg.fillRect(i, j, 1, 1);
}
}
g.drawImage(buffimg, 0, 0, null);
return buffimg;
}
/**
* 二值化的手绘效果
* @param path 图片路径
* @param g 图形类 功能 绘制像素点
*/
public BufferedImage drawImage2(int [][]imgArr,Graphics g) {
BufferedImage buffimg = new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg.getGraphics();
for(int i=0;i<imgArr.length;i++) {
for(int j=0;j<imgArr[i].length;j++) {
int value=imgArr[i][j];
int red=(value>>16)&0xFF;
int green=(value>>8)&0xFF;
int blue=(value>>0)&0xFF;
int gray=(int)(red*0.4+green*0.3+blue*0.3);
if(gray<127) {
buffg.setColor(Color.BLACK);
}else {
buffg.setColor(Color.white);
}
buffg.fillRect(i, j, 1, 1);
}
}
g.drawImage(buffimg, 0, 0, null);
return buffimg;
}
/**
* 轮廓检测
* 相邻之间的像素颜色进行比较
* @param path 图片路径
* @param g 图形类 功能 绘制像素点
*/
public BufferedImage drawImage3(int [][]imgArr,Graphics g) {
BufferedImage buffimg = new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg.getGraphics();
for(int i=0;i<imgArr.length-2;i++) {
for(int j=0;j<imgArr[i].length-2;j++) {//注意减2
int value=imgArr[i][j];
int red=(value>>16)&0xFF;
int green=(value>>8)&0xFF;
int blue=(value>>0)&0xFF;
int gray=(int)(red*0.4+green*0.3+blue*0.3);
int valueN=imgArr[i+2][j+2];
int redN=(valueN>>16)&0xFF;
int greenN=(value>>8)&0xFF;
int blueN=(value>>0)&0xFF;
int grayN=(int)(redN*0.4+greenN*0.3+blueN*0.3);
if(Math.abs(gray-grayN)>15) {//Math.abs绝对值
buffg.setColor(Color.red);
}else {
buffg.setColor(Color.white);
}
buffg.fillRect(i, j, 1, 1);
}
}
g.drawImage(buffimg, 0, 0, null);
return buffimg;
}
//马赛克
public BufferedImage drawImage5(int [][]imgArr,Graphics g) {
BufferedImage buffimg=new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg.getGraphics(); //直接画在缓冲区 不到GPU 是内存操作
for(int i=0;i<imgArr.length;i+=10) {
for(int j=0;j<imgArr[i].length;j+=10) {
int value=imgArr[i][j];
Color color=new Color(value);
buffg.setColor(color);//相当于在重绘每个像素点 所以要给画笔每个像素的颜色再填充
buffg.fillRect(i, j, 10, 10);//坐标以从50往后移 drawImage中坐标不用为0就好
}
}
g.drawImage(buffimg, 0, 0, null);//将buffimg内存缓冲区中的取出一次性绘制
return buffimg;
}
//原图缩小
public void drawImage6(int [][]imgArr,Graphics g) {
BufferedImage buffimg=new BufferedImage(imgArr.length,imgArr[0].length,BufferedImage.TYPE_INT_ARGB);
//TYPE_INT_ARGB代表颜色为int(4个字节),红色通道道在16-23,绿色在8-15和蓝色在0-7
// 将所有的像素值存入缓冲图片- 操作- 内存操作
for(int i=0;i<imgArr.length;i++) {
for(int j=0;j<imgArr[i].length;j++) {
int value=imgArr[i][j];
//Color color=new Color(value);
//g.setColor(color);//相当于在重绘每个像素点 所以要给画笔每个像素的颜色再填充
//g.fillRect(50+i, 50+j, 1, 1);
buffimg.setRGB(i, j, value);//全部初始化缓冲在内存的BufferedImage中 还未画
}
}
//将整张图片一次性绘制
g.drawImage(buffimg, 50,50,200,200,null);//通过200 200 缩小
}
//原图
public BufferedImage drawImagelaozi(int [][]imgArr,Graphics g) { //用返回值保存
BufferedImage buffimg=new BufferedImage(imgArr.length,imgArr[0].length,BufferedImage.TYPE_INT_ARGB);
//TYPE_INT_ARGB代表颜色为int(4个字节),红色通道道在16-23,绿色在8-15和蓝色在0-7
// 将所有的像素值存入缓冲图片- 操作- 内存操作
for(int i=0;i<imgArr.length;i++) {
for(int j=0;j<imgArr[i].length;j++) {
int value=imgArr[i][j];
//Color color=new Color(value);
//g.setColor(color);//相当于在重绘每个像素点 所以要给画笔每个像素的颜色再填充
//g.fillRect(50+i, 50+j, 1, 1);
buffimg.setRGB(i, j, value);//全部初始化缓冲在内存的BufferedImage中 还未画
}
}
//将整张图片一次性绘制
g.drawImage(buffimg, 0,0,null);
return buffimg;
}
}
ImageListene
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.Stack;
public class ImageListener extends ListenerUtils {
public Graphics g;
JPanel jp;
String path="F:\\自己填\\作业\\1.png";
String path1="F:\\自己填\\作业\\2.jpg";
String path2="F:\\自己填\\作业\\3.jpg";
public String btnstrs;
BufferedImage [] buffimgs=new BufferedImage[100];//存返回值对象的数组
Stack<BufferedImage> buffstack= new Stack<BufferedImage>();
int index=0;//计数器
int indexmsk=0;
int x1,y1,x2,y2;
int x3,y3;
// 1)构造出来一个类的实例 (2)对构造出来个一个类的实例(对象)初始化
//构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有
int[][] imgArr;
int[][] imgArr1;
int[][] imgArr2;
ImageEFF imgeff;
//类构造方法
//就是类构造对象时调用的方法,主要用来实例化对象。
ImageListener(){
imgeff = new ImageEFF();
imgArr=imgeff.ImageToArray(path);
imgArr1=imgeff.ImageToArray(path1);
imgArr2=imgeff.ImageToArray(path2);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
btnstrs =e.getActionCommand();
if(btnstrs.equals("原图")) {
BufferedImage img=imgeff.drawImagelaozi(imgArr, g);//img 存返回值对象(内存缓冲池中已画好的内容)
buffimgs[index++]=img;
indexmsk++;
System.out.println("index"+index);
}
else if(btnstrs.equals("马赛克")) {
BufferedImage img=imgeff.drawImage5(imgArr, g);
buffimgs[index++]=img;
indexmsk++;
System.out.println("index"+index);
}
else if(btnstrs.equals("马赛克瓷砖")) {
BufferedImage img=imgeff.drawImage0(imgArr, g);
buffimgs[index++]=img;
indexmsk++;
buffstack.push(img);
}
else if(btnstrs.equals("灰度")) {
BufferedImage img=imgeff.drawImage1(imgArr, g);
buffimgs[index++]=img;
indexmsk++;
System.out.println("index"+index);
}
else if(btnstrs.equals("轮廓检测")) {
BufferedImage img=imgeff.drawImage3(imgArr, g);
buffimgs[index++]=img;
indexmsk++;
buffstack.push(img);
}
else if(btnstrs.equals("二值化")) {
BufferedImage img=imgeff.drawImage2(imgArr, g);
buffimgs[index++]=img;
indexmsk++;
buffstack.push(img);
}
else if(btnstrs.equals("缩小")) {
//取当前图片
BufferedImage buffimg=buffimgs[indexmsk-1];
//创建一个新的空缓冲区
BufferedImage buffimg1=new BufferedImage(buffimg.getWidth(), buffimg.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg1.getGraphics();
for(int i=0;i<buffimg.getWidth();i++) {
for(int j=0;j<buffimg.getHeight();j++) {
int rgbvalue=buffimg.getRGB(i,j);
Color color=new Color(rgbvalue);
buffimg1.setRGB(i, j, rgbvalue);
}
}
g.drawImage(buffimg, 0,0,200,200,null);
buffimgs[index++]=buffimg1;
indexmsk++;
}
else if(btnstrs.equals("撤回")) {
if(index==0)
{
return;
}
else
{
// 删除数据
buffimgs[index-1]=null;
index--;
}
jp.repaint();//调用repaint 就相当于在调用jp的paint方法
}
else if(btnstrs.equals("油画融合")) {
BufferedImage img=imgeff.drawImagenmd(imgArr1,imgArr2, g);
buffimgs[index++]=img;
indexmsk++;
}
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
super.mousePressed(e);
if(btnstrs.equals("选择截屏区域")) {
x1=e.getX();
y1=e.getY();
}
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
super.mouseReleased(e);
if(btnstrs.equals("选择截屏区域")) {
x2=e.getX();
y2=e.getY();
}
}
@Override
public void mouseDragged(MouseEvent e) {
// 鼠标拖动 局部马赛克
System.out.println("拖动");
int oldx=0;
int oldy=0;
if("局部马赛克".equals(btnstrs)) {
//取当前图片
BufferedImage buffimg=buffimgs[indexmsk-1];
//创建一个新的空缓冲区
BufferedImage buffimg1=new BufferedImage(buffimg.getWidth(), buffimg.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics buffg1=buffimg1.getGraphics();
int x=e.getX();
int y=e.getY();
//获取像素点太快了
if((Math.abs(x-oldx)*Math.abs(y-oldy))<100) {
return;
}
else {
oldx=x;
oldy=y;
}
//根据坐标获取当前像素点的像素值
int rgbvalue=buffimg.getRGB(x, y);
//转成颜色 设置画笔 绘制方块
Color color=new Color(rgbvalue);
//g.setColor(color);
//g.fillRect(x, y, 10, 10);
//将处理后的 存储在buffimg中
//buffg.setColor(color);
buffg1.setColor(color);
//System.out.println("color="+color);
buffg1.fillRect(x, y, 10, 10);
g.drawImage(buffimg1, 0, 0, null);
//jp.repaint();//修改数据后使用paint刷新
buffimgs[index++]=buffimg1;
System.out.println("index="+index);
//比如说我在原图画了一道局部马赛克 原图就变成带一道马赛克的了被覆盖了 局部马赛克与原图对应的是同一个对象
//不断覆盖原来的 index(1-10++)全是一张图 需要使用新的bufferedimage
}
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
if(btnstrs.equals("截屏放置区域")) {
x3=e.getX();
y3=e.getY();
//取当前图片
BufferedImage buffimg=buffimgs[indexmsk-1];
//创建一个新的空缓冲区
BufferedImage buffimg1=new BufferedImage(buffimg.getWidth(), buffimg.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics buffg=buffimg1.getGraphics();
for(int i=x1;i<=x2;i++) {
for(int j=y1;j<=y2;j++) {
int rgbvalue=buffimg.getRGB(i,j);
Color color=new Color(rgbvalue);
//buffimg1.setRGB(i, j, rgbvalue);
buffg.setColor(color);
buffg.fillRect(i, j, 1, 1);
}
}
g.drawImage(buffimg1,x3,y3,x2-x1,y2-y1,null);
buffimgs[index++]=buffimg1;
indexmsk++;
}
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
super.keyPressed(e);
}
}
ListenerUtils
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ListenerUtils implements ActionListener,MouseListener,MouseMotionListener,KeyListener,ChangeListener{
@Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
ImageUI
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class ImageUI extends JPanel{
String [] btnstrs= {"原图","马赛克","灰度","二值化","马赛克瓷砖","轮廓检测","手绘风格","怀旧","油画融合","局部马赛克","缩小","截屏放置区域","选择截屏区域","撤回"};
static final ImageListener imageListener=new ImageListener();
//对于变量,表示一旦给值就不可修改,并且通过类名可以访问。
//对于方法,表示不可覆盖,并且可以通过类名直接访问。
public static void main(String[] args) {
new ImageUI().initUI();
}
public void initUI() {
JFrame jf=new JFrame("图形编程");
jf.setSize(800,600);
jf.setDefaultCloseOperation(3);
jf.setLocationRelativeTo(null);
// 按钮功能区面板 JPanel
JPanel jp1= new JPanel();
jp1.setBackground(Color.DARK_GRAY);
Dimension dim=new Dimension(120,0);
jp1.setPreferredSize(dim);
Dimension btndim=new Dimension(110,35);
for(int i=0;i<btnstrs.length;i++) {
JButton btn=new JButton(btnstrs[i]);
btn.setBackground(Color.white);
btn.setPreferredSize(btndim);
btn.addActionListener(imageListener);
jp1.add(btn);
}
//绘图区
//JPanel jp2=new JPanel();
this.setBackground(Color.BLACK);
this.addMouseListener(imageListener);
this.addMouseMotionListener(imageListener);
this.addKeyListener(imageListener);
jf.add(jp1,BorderLayout.EAST);
jf.add(this);
jf.setVisible(true);
Graphics g=this.getGraphics();
imageListener.g=g;
imageListener.jp=this;
}
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
//paint(g)函数会重绘图像,要加上super.paint(g),表示在原来图像的基础上,再画图。
//如果不加super.paint(g),重绘时,会将原有的绘制清空,再根据paing(g)函数绘制。
super.paint(g);//你改变界面的状态它就要重新画一次 在JPanel重画一次
BufferedImage []imgs=imageListener.buffimgs;
for(int i=0;i<imgs.length;i++) {
//g.drawImage(imgs[i], 0, 0, null);
if(imgs[i]==null) {
return;
}
//创建新空缓冲图片对象
g.drawImage(imgs[i], 0, 0,this.getWidth(),this.getHeight(), null);
BufferedImage buffimg1=new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics buffg1=buffimg1.getGraphics();
//将发大后的缓冲图片放入新缓冲图片对象
buffg1.drawImage(imgs[imageListener.index-1], 0, 0,this.getWidth(),this.getHeight(), null);
//用放大后的图片替换
imgs[imageListener.index-1]=buffimg1;
//绘制新缓冲图片
g.drawImage(buffimg1, 0, 0, null);
System.out.println("i="+i);
}
}
}