Java实现图片渲染

  • 方法改进
  • ImageUI
  • ImageListener
  • ImageUtils
  • 演示动画

github源代码下载: 图片渲染源代码.

方法改进

紧接上一篇实现图片渲染链接: 图片渲染(图像编码原理).

可以发现:只前在绘画图片的时候速度非常的慢。那是因为每次只要一获得像素就立即将其绘画出来。

g.setColor(color);
g.fillRect(i, j,1, 1)

在内存中执行代码后,会向GPU请求刷新屏幕,一张图片有成千上万个像素,那么屏幕就会连续刷新很多次,速度非常慢。例如,如果电脑屏幕的刷新率是60赫兹的话,意味着一秒钟屏幕会刷新60次,放到这里来讲的话,一秒钟最多显示60个像素,对于分辨率极高的图片,要加载出来,可想而知等的时间也就会越久。

所以,就要用一种方法一次性将所有的像素画出来。BufferedImage是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片)

在请求刷新屏幕之前,现将所有的像素设置完毕,然后一次性将缓冲区的像素全部画出来(刷新一次屏幕)。有两种方法来设置缓冲区。
第一:直接设置缓冲区相应位置像素的RGB值。
实现如下:

//绘画原图改进方法public BufferedImage paint1(Graphics g,int[][] arrpixel){     BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);for(int i=0;i<arrpixel.length;i++){for(int j=0;j<arrpixel[0].length;j++){int value=arrpixel[i][j];                buffimage.setRGB(i, j, value);//一次性将所有像素存储完成}}              g.drawImage(buffimage, 0, 0, null);//一次性画完return buffimage;}

第二:通过缓冲区获得画笔,将画笔赋相应的RGB值,然后通过fillRect方法来填充矩形小像素。这种方法还可以方便我们实现渲染(如后面的马赛克等)
实现如下:

//原图改进方法
public BufferedImage paint1(Graphics g,int[][] arrpixel){     BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);Graphics ng=buffimage.getGraphics();for(int i=0;i<arrpixel.length;i++){for(int j=0;j<arrpixel[0].length;j++){int value=arrpixel[i][j];if(i==0&&j==0){ System.out.println("arrpixel:"+value);}ng.setColor(new Color(value));ng.fillRect(i, j, 1, 1);              }}                g.drawImage(buffimage, 0, 0, null);               }

之后就可以把其他的渲染方法逐个改进。以下是图片渲染程序的源代码。

ImageUI

public class ImageUI extends JPanel {String []bt= {"原图","方形马赛克","灰度","二值化","轮廓检测","油画绘制","拖动原图马赛克","拖动彩色马赛克","截图","放大","缩小","撤回上一步","清空图片"};ImageListener listener=new ImageListener();//什么时候static finalJFrame nj=new JFrame();//截图确认窗口public void initUI(){JFrame jf=new JFrame();jf.setSize(1500,780);jf.setTitle("图片处理");jf.setDefaultCloseOperation(3);jf.setLocationRelativeTo(null);//按钮功能区面板JPanel jp1=new JPanel();jp1.setBackground(new Color(0xafeeee));Dimension dm=new Dimension(200,780);jp1.setPreferredSize(dm);Dimension btdm=new Dimension(190,40);        for(int i=0;i<bt.length;i++){JButton jb =new JButton(bt[i]);jb.setPreferredSize(btdm);jb.setBackground(Color.white);Font font= new Font("黑体",Font.BOLD,20);jb.setFont(font);jb.setForeground(new Color(0x000080));jb.setBackground(new Color(0xf0fff0));jb.addActionListener(listener);jp1.add(jb);}//绘图区jframe默认边框布局this.setBackground(new Color(0xffffe0));jf.add(jp1,BorderLayout.EAST); jf.add(this,BorderLayout.CENTER);this.addMouseListener(listener);this.addMouseMotionListener(listener);this.addKeyListener(listener);jf.setVisible(true);//从jp2 获得画笔Graphics g=jf.getRootPane().getGraphics();listener.setgraphics(g);listener.setjpanel(this);nj.setTitle("提示");nj.setSize(300, 150);//nj.setDefaultCloseOperation(3);//这里弹出窗口点叉不能设置关闭程序,否则主界面也会跟着关闭nj.setLocationRelativeTo(jf);nj.setResizable(false);JLabel txt =new JLabel("是否确认截图",JLabel.CENTER);Font fnt= new Font("黑体",Font.BOLD,30);txt.setFont(fnt);nj.setLayout(new FlowLayout());nj.add(txt);Font fnt2=new Font("黑体", Font.CENTER_BASELINE, 15);JButton bt =new JButton("确认");bt.addActionListener(listener);bt.setPreferredSize(new Dimension(100, 30));bt.setFont(fnt2);nj.add(bt);JButton bt2=new JButton("取消");bt2.addActionListener(listener);bt2.setPreferredSize(new Dimension(100, 30));bt2.setFont(fnt2);nj.add(bt2);nj.addWindowListener(listener);}@Overridepublic void paint(Graphics g) {// TODO Auto-generated method stubsuper.paint(g);              System.out.println("fresh"+!listener.freshbuff.isEmpty());if( !listener.freshbuff.isEmpty()){BufferedImage top=( BufferedImage)listener.freshbuff.peek();g.drawImage(top,0,0,top.getWidth(),top.getHeight() ,null);     System.out.println("调用paint");}}public void clear(Graphics g){super.paint(g);}public static void main(String[] args) {new ImageUI().initUI();}}

ImageListener

#前提说明:
如果一个类需要的接口太多,且接口中的方法又有很
多,且大部分无用,而这个类又不需要继承,那么就可以考虑做一个工具类——实现所有的接口。 然后用所需的类继承这个工具类,选择性的重写方法。
这里监听器类为ImageListener,继承监听器工具类ListenerUtils ,选择性重写接口方法:

  public class ImageListener extends ListenerUtils
{//选择性重写... ...
}public class ListenerUtils implements ActionListener,MouseListener,MouseMotionListener
,KeyListener,ChangeListener,WindowListener{@Overridepublic void stateChanged(ChangeEvent e) {// TODO Auto-generated method stub}... ... ... ... ..

为了更好得实现返回上一步功能,定义了两个BufferedImage栈,考虑到,窗口改变执行的peek()操作,返回上一步执行的是pop()操作,所以用一个栈不容易将功能正确实现。(读者也可以自己定义不同的数据类型存储BufferedImage,可能会更加方便)
刷新栈:
窗口改变大小实现图片重绘。

public Stack<BufferedImage> freshbuff=new Stack<BufferedImage>();

操作栈:
记录每一次的执行结果,以实现返回上一步功能。

public Stack<BufferedImage> buffstack =new Stack<BufferedImage>();

具体代码如下:

public class ImageListener extends ListenerUtils {int[][] imgarr;String btn="";String path="E:\\java\\eclipse\\eclipse javaee\\workspace\\Yu java\\66.jpg";private Graphics g;ImageUtils imageff;ImageUI jp;public Stack<BufferedImage> buffstack =new Stack<BufferedImage>();public Stack<BufferedImage> freshbuff=new Stack<BufferedImage>();int index;int p_x,p_y;int r_x,r_y;int d_x,d_y;public void setgraphics(Graphics g){this.g=g;}    public void setjpanel(ImageUI jp){this.jp=jp;     }//初始化监听器ImageListener(){      imageff=new ImageUtils();imgarr=imageff.getImagePixel(path);System.out.println("初始化成功"+imgarr.length);}@Overridepublic void windowClosing(WindowEvent e) {// TODO Auto-generated method stubsuper.windowClosed(e);jp.paint(g);         }@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubSystem.out.println("当前"+btn);//System.out.println("调用actionperformed");btn=e.getActionCommand();if(btn.equals("原图")){  jp.clear(g);                BufferedImage img=    imageff.paint1(g,imgarr);buffstack.push(img);freshbuff.push(img);System.out.println("栈顶"+buffstack.peek().getWidth());System.out.println("栈内元素数"+buffstack.size());     }else if(btn.equals("方形马赛克")) {  jp.clear(g); imageff.paint2(g, freshbuff,buffstack);                        }else if(btn.equals("灰度")) {   jp.clear(g);   imageff.paint3(g, freshbuff,buffstack);                     }else if(btn.equals("二值化")) {    jp.clear(g);imageff.paint4(g, freshbuff,buffstack);                                    }else if(btn.equals("轮廓检测")) {   jp.clear(g);imageff.paint5(g, freshbuff,buffstack);                     }else if(btn.equals("油画绘制")) {  jp.clear(g);imageff.paint6(g, freshbuff,buffstack);                       }else if(btn.equals("放大")){   jp.clear(g);imageff.piant7(g, freshbuff,buffstack);       jp.paint(g);   }else if(btn.equals("缩小")){  jp.clear(g);imageff.paint8(g,freshbuff,buffstack );          jp.paint(g);}else if(btn.equals("清空图片")){jp.clear(g);imageff.withdraw(g,jp,buffstack,freshbuff);}else if (btn.equals("撤回上一步")){jp.clear(g);freshbuff.push(imageff.backward(buffstack,g));           }     else if(btn.equals("确认")){jp.clear(g);imageff.paint12(g, freshbuff, buffstack,p_x,p_y,r_x,r_y);System.out.println("截图完成");jp.nj.dispose();}else if(btn.equals("取消")){jp.nj.dispose();jp.paint(g);}     }@Overridepublic void mousePressed(MouseEvent e) {// TODO Auto-generated method stubsuper.mousePressed(e);p_x=e.getX();p_y=e.getY();d_x=e.getX();d_y=e.getY();}@Overridepublic void mouseReleased(MouseEvent e) {// TODO Auto-generated method stubsuper.mouseReleased(e);r_x=e.getX();r_y=e.getY();if(btn.equals("截图")){Graphics2D g2d=(Graphics2D)g;g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND, 3.5f, new float[] { 10, 5 }, 0f));            g2d.setColor(Color.GREEN);g2d.drawRect(Math.min(p_x, r_x), Math.min(p_y, r_y),Math.abs(r_x-p_x) ,Math.abs(r_y-p_y));jp.nj.setVisible(true);           }}@Overridepublic void mouseDragged(MouseEvent e) {// TODO Auto-generated method stubsuper.mouseDragged(e);    int x=e.getX();int y=e.getY();if(btn.equals("拖动原图马赛克")){if(Math.abs(x-d_x)>10||Math.abs(y-d_y)>10)        { imageff.paint9(g,freshbuff,buffstack,x,y);                  d_x=x;d_y=y;}        }if(btn.equals("拖动彩色马赛克")) {if(Math.abs(x-d_x)>10||Math.abs(y-d_y)>10)        { imageff.paint10(g,freshbuff,buffstack,x,y);                     d_x=x;d_y=y;}         }        }@Overridepublic void keyPressed(KeyEvent e) {// TODO Auto-generated method stubsuper.keyPressed(e);}
}

ImageUtils

图片的渲染代码:
#说明
这里定义一个当前类的布尔全局变量flag,用来判断在返回上一步这个操作中,应该是对操作栈buffstack执行pop()操作还是peek()。例如:因为操作栈中栈顶还存着当前画图结果,如果栈中元素>1的话,得执行两次pop()方法才能返回上一步,这样就得按两次按钮才能实现理想效果。flag等于true表示当前渲染过后的图片还在操作栈中。就得执行两次pop。

public class ImageUtils { boolean flag=true;String name=""; //读取文件,获得图片像素public int[][] getImagePixel(String path) {//读取文件的数据File file =new File(path);//imageIO操作将图片文件的输入输出,//读取文件数据BufferedImage buffimage=null;try {buffimage=ImageIO.read(file);}catch (IOException e) {e.printStackTrace();System.err.println("图像读取失败");}//获取缓冲图片的大小,初始化保存像素值得二维数组int w=buffimage.getWidth();int h=buffimage.getHeight();int [][]arrPixel=new int[w][h];for(int i=0;i<w;i++){for(int j=0;j<h;j++){int pixel=buffimage.getRGB(i, j);arrPixel[i][j]=pixel;}}return arrPixel;}//清空图片public void withdraw(Graphics g,ImageUI jp,Stack<BufferedImage> buff,Stack<BufferedImage> freshbuff){jp.clear(g);             buff.clear();freshbuff.clear();flag=true;}    //原图方法public BufferedImage paint1(Graphics g,int[][] arrpixel){        BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);Graphics ng=buffimage.getGraphics();for(int i=0;i<arrpixel.length;i++){for(int j=0;j<arrpixel[0].length;j++){int value=arrpixel[i][j];if(i==0&&j==0){ System.out.println("arrpixel:"+value);}ng.setColor(new Color(value));ng.fillRect(i, j, 1, 1);//buffimage.setRGB(i, j, value);//一次性将所有像素存储完成}}             g.drawImage(buffimage, 0, 0, null);flag=true;     return buffimage;       }//方形马赛克改进算法public void paint2(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff){    if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=buff.getWidth();int newheight=buff.getHeight();BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);      Graphics ng=buffimage.getGraphics();for(int i=0;i<newwidth;i+=10){for(int j=0;j<newheight;j+=10){   int rgb=buff.getRGB(i, j);                             ng.setColor(new Color(rgb));ng.fillRect(i, j, 10, 10);               }}                g.drawImage(buffimage, 0, 0, null);flag=true; freshbuff.push(buffimage);stackbuff.push(buffimage);}    }    //灰度方法public void paint3(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff){           if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=buff.getWidth();int newheight=buff.getHeight();BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);  for(int i=0;i<buff.getWidth();i++){for(int j=0;j<buff.getHeight();j++){int value =buff.getRGB(i, j);int red=(value>>16)&0xFF;int green=(value>>8)&0xFF;int blue=(value>>0)&0xFF;                                   int gray =(red+green+blue)/3;int newvalue=(gray<<16)+(gray<<8)+(gray<<0);buffimage.setRGB(i, j, newvalue);//一次性将所有像素存储完成}}              g.drawImage(buffimage, 0, 0, null);           flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage);            }}
//二值化方法
public void paint4(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=buff.getWidth();int newheight=buff.getHeight();BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);  for(int i=0;i<newwidth;i++){for(int j=0;j<newheight;j++){int value =buff.getRGB(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.5+blue*0.6);// int newvalue=(gray<<16)+(gray<<8)+(gray<<0);if(gray<150){buffimage.setRGB(i, j, Color.black.getRGB());}else{buffimage.setRGB(i, j, Color.white.getRGB());}                 }}g.drawImage(buffimage, 0, 0, null); flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage);        }}
//轮廓检测
//相邻之间的像素点进行比较
public void paint5(Graphics g ,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{    if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=buff.getWidth();int newheight=buff.getHeight();BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);  for(int i=0;i<newwidth-2;i++){for(int j=0;j<newheight-2;j++){int value =buff.getRGB(i, j);int red=(value>>16)&0xFF;int green=(value>>8)&0xFF;int blue=(value>>0)&0xFF;int valuen=buff.getRGB(i+2, j+2);int redn=(valuen>>16)&0xFF;int greenn=(valuen>>8)&0xFF;int bluen=(valuen>>0)&0xFF;//int gray =(red+green+blue)/3;int gray =(int)(red*0.41+green*0.28+blue*0.31);int grayn =(int)(redn*0.41+greenn*0.28+bluen*0.31);if(Math.abs(gray-grayn)>15){buffimage.setRGB(i, j, Color.pink.getRGB());}else{buffimage.setRGB(i, j, Color.white.getRGB());}             }}    g.drawImage(buffimage, 0, 0, null);flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage);     }
}
//油画算法
public void paint6(Graphics g ,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{    if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=buff.getWidth();int newheight=buff.getHeight();BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);  Random random = new Random();int size=random.nextInt(5); for(int i=0;i<newwidth;i+=3){for(int j=0;j<newheight;j+=3){   int pixel=buff.getRGB(i, j);int h=i,m=j;for(int k=0;k<3;k++){                for(int p=0;p<3;p++){                  if(h<newwidth&&m<newheight)buffimage.setRGB(h,m++,pixel);                   }h++;m=j+size;}        }} g.drawImage(buffimage, 0, 0, null);flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage);     }
}
//截图
public void paint12(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int px,int py,int rx,int ry)
{if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=Math.abs(px-rx);int newheight=Math.abs(py-ry);       BufferedImage  buffimage=new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_RGB);int minx=Math.min(rx, px);int maxx=Math.max(rx, px);int miny=Math.min(ry, py);int maxy=Math.max(ry, py);System.out.println("minx"+minx+"maxx"+maxx+"miny"+miny+"maxy"+maxy);int h=0,m=0;for(int i=minx;i<=maxx;i++){for(int j=miny;j<=maxy;j++){int rgb=buff.getRGB(i, j);                   if(h<newwidth&&m<newheight){buffimage.setRGB(h, m++, rgb);}                                  }h++;m=0;}                g.drawImage(buffimage, 0, 0, null);     flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage);        }
}
//放大
public void piant7(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();int newwidth=buff.getWidth()+(int)((buff.getWidth()*20)/100);int newheight=buff.getHeight()+(int)((buff.getHeight()*20)/100);BufferedImage buffimage=new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_RGB);   Graphics ng=buffimage.getGraphics();ng.drawImage(buff,0,0, newwidth, newheight, null);g.drawImage(buffimage,0,0, null);flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage); }
}
//缩小
public void paint8(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{if(!freshbuff.isEmpty()){BufferedImage buff=freshbuff.peek();    int newwidth=(int)((buff.getWidth()*80)/100);int newheight=(int)((buff.getHeight()*80)/100);BufferedImage buffimage=new BufferedImage(newwidth, newheight,BufferedImage.TYPE_INT_RGB );Graphics ng=buffimage.getGraphics();ng.drawImage(buff, 0,0,newwidth, newheight, null);//一定要注明起点0,0g.drawImage(buffimage,0,0, null);flag=true;freshbuff.push(buffimage);stackbuff.push(buffimage);}
}//拖动马赛克
public void paint9(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int x,int y)
{    if(!stackbuff.isEmpty()) {BufferedImage buff= stackbuff.peek();BufferedImage buffimage=new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_RGB);    if(buff.getWidth()<x||buff.getHeight()<y)return;int rgb=buff.getRGB(x, y);     for(int i=0;i<buff.getWidth();i++){for(int j=0;j<buff.getHeight();j++){   int RGB=buff.getRGB(i, j);                    buffimage.setRGB(i,j , RGB);                                                             }}for(int i=x;i<x+20;i++){for(int j=y;j<y+20;j++){if(i<buffimage.getWidth()&&j<buffimage.getHeight())buffimage.setRGB(i, j, rgb);}}g.drawImage(buffimage, 0, 0,buffimage.getWidth(),buffimage.getHeight(), null);freshbuff.push(buffimage);stackbuff.push(buffimage);System.out.println("stack"+stackbuff.size());flag=true;    }}
//拖动彩色马赛克
public void paint10(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int x,int y)
{    if(!stackbuff.isEmpty()) {BufferedImage buff= stackbuff.peek();if(buff.getWidth()<x||buff.getHeight()<y)return;BufferedImage buffimage=new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_RGB);for(int i=0;i<buff.getWidth();i++){for(int j=0;j<buff.getHeight();j++){   int RGB=buff.getRGB(i, j);                 buffimage.setRGB(i,j , RGB);                                                             }}Random ram=new Random();
int rgb=ram.nextInt(0xffffff);Graphics ng=buffimage.getGraphics();ng.setColor(new Color(rgb));ng.fillOval(x, y, 20, 20);g.drawImage(buffimage, 0, 0,buffimage.getWidth(),buffimage.getHeight(), null);freshbuff.push(buffimage);stackbuff.push(buffimage);System.out.println("stack"+stackbuff.size());flag=true;  }
}//返回上一步
public BufferedImage backward(Stack<BufferedImage> buff,Graphics g){  BufferedImage top=null;if(!buff.isEmpty())System.out.println("stack"+buff.size());{     if(buff.size()==1){top=buff.peek();g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);                }else{if(flag==true&&buff.size()>1){top=buff.pop();if(buff.size()==1){                  top=buff.peek();g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);                                                        }  else {top=buff.pop();g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);       }}if(flag==false&&buff.size()>1){top=buff.pop();g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);                     }}}  flag=false;           System.out.println("stack"+buff.size());         return top;        }
}

演示动画

图片处理 2021-07-21 23-18-15

由于录屏问题,弹出界面没显示,截屏如下

Java实现图片渲染((拖动)马赛克、黑白照、油画风格等)相关推荐

  1. 图片渲染(图像编码原理)

    根据图像编码原理初步给图片渲染(马赛克.油画风格等 图像的编码原理 绘制图像 图像的编码原理 图像是由一个个带有颜色的小格组成的,每个小格的颜色都是唯一的.一张图片的像素个数=长*宽.所以不难理解,为 ...

  2. Java基础学习6(图像处理、视频处理、灰度、二值、马赛克、油画)

    图像处理.视频处理 前言 图像处理 原图 灰度 二值化 油画 马赛克 视频处理 摄像头调用 线程 小细节 前言 图像处理和视频处理有十分丰富的内容,并且他们是一个递进的关系,在图像处理的基础上加上摄像 ...

  3. Java如何去除图片上的马赛克

    Java中可以使用图像处理的库,如Java OpenCV或Java ImageJ来去除图片上的马赛克. 具体步骤如下: 使用OpenCV或ImageJ库加载图像. 使用图像处理算法进行降噪处理,以去除 ...

  4. java实现马赛克,java如何用Processing生成马赛克风格的图像

    java如何用Processing生成马赛克风格的图像 首先使用PImage来实例化对象,再通过loadImage赋值,两层for循环遍历图片上的像素点,每隔5个像素点,画一个直径为3的圆.颜色通过p ...

  5. js+java 实现图片在线预览功能

    本博客主要描述如何用JavaScript+java实现图片的预览功能,其实要点还是需要服务端的流. (一)功能描述 点击页面的 [预览] 查看已经上传的或者在服务器中存在的图片. (二)实现原理 使用 ...

  6. java读取图片、PDF中图片上的文字

    读取图片上的文字 提示:本文是基于tess4j 文章目录 读取图片上的文字 前言 一.tess4j是什么? 二.使用步骤 1.POM引入库 2.实例代码 总结 前言 总是有一些与众不同的需求在等着研发 ...

  7. HDR projects 7—HDR图片渲染工具

    HDR projects 7 professional for mac(HDR图片渲染软件)推荐给大家!HDR项目可让您从照片中获得最佳技术,并实际完成所有工作,通过先进的图片处理算法,为你生成阴影和 ...

  8. Java BufferImage图片处理(获取宽高、图片截取、转换灰度图)

    Java BufferImage图片处理(获取宽高.截取.转换灰度图) 1. 效果图 2. 源码 参考 这篇博客将介绍如何使用Java读取图片为byte[]数组,或者BufferedImage及互相转 ...

  9. java中图片和字节数组相互转化

    java中图片和字节数组相互转化 方案一:使用ImageIO来实现 将图片转化为字节数组 /*** 通过图片路径将图片文件转化为字符数组* * @param url 图片路径* @return byt ...

最新文章

  1. 欧洲、加拿大、澳大利亚新增2.1万个点可购买比特币现金
  2. 如果给你500万,让你朝对象腿上开一枪,你愿意吗?
  3. Python print函数用法,print 格式化输出
  4. CTFshow 反序列化 web266
  5. python 常用包_Python常用指引
  6. 风靡全球的儿童编程语言:Scratch
  7. 基于JAVA+Servlet+JSP+MYSQL的教室预订管理系统
  8. 2017年最新(4月20日)手机号码归属地数据库分享
  9. DMG计算机,传授dmg文件怎么打开
  10. 宏定义的大括号以及斜杠
  11. NDK 入门与进阶—第一个NDK程序(一)
  12. 波士顿学院计算机科学专业,波士顿学院计算机专业
  13. (转)常用PC服务器LSI阵列卡配置
  14. Java面试题——基础篇二
  15. C语言_SDUST_OJ(3)
  16. OSAL系统框架专题
  17. XGBOOST + LR 模型融合 python 代码
  18. Chrome中实现使用迅雷一次性选中并下载网页内全部链接的方法
  19. Labview加载3D模型(.wrl)出现内存不足的解决方法
  20. Python 多线程下载图片

热门文章

  1. 台式计算机win如何联网,Win10台式机怎么连接无线网(wifi)?
  2. NB-IOT开发|nbiot开发教程《三》AT指令类模组驱动-STM32实现AT指令状态机
  3. 二进制数字的表示方法
  4. 计算机论文致谢词范文500字,论文致谢词范文500字(精选5篇)
  5. 【小程序模板】功能模块+红色招聘信息资讯小程序网页模板+行业职位招聘小程序+招聘信息网页下载
  6. 基于魔兽RPG对当前游戏发展趋势的分析,以及尝试一个高游戏性玩法的设计
  7. 机床测头应用二:自动补偿功能,提升生产良率
  8. BAT脚本: ping检测网络稳定性 与 取命令结果的指定行方法 与 将变量内容追加写入txt文件方法
  9. C语言编码黄金螺旋线,阿基米德螺旋线
  10. 资深程序员被逼无奈出来摆摊了,快来捧个人场!