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

根据图像编码原理初步给图片渲染(马赛克、油画风格等

图像的编码原理

图像是由一个个带有颜色的小格组成的,每个小格的颜色都是唯一的。一张图片的像素个数=长*宽。所以不难理解,为什么一张图片的像素(像素点个数)越高,图片就越清晰,因为图片的精密度更高。下图显示的是一个分辨率为 900 × \times × 600的图片。
在这里插入图片描述
而每个像素的颜色取值是通过RGB模式确定的,RGB色彩就是常说的光学三原色,R代表Red(红色),G代表Green(绿色),B代表Blue(蓝色)。自然界中肉眼所能看到的任何色彩都可以由这三种色彩混合叠加而成,因此也称为加色模式。R、G、B各自的取值都是0~255,用 8bit一个字节就可以存储。所以用int数据类型就可以把RGB所需三个字节存储起来,最后还剩一个字节可以添加额外的信息。然后通过相应的位移运算和与运算就可以获得所需的RGB分量。

// 0000 0000 1000 0000 1000 0000 1000 0000 = 8421504
             R         G         B 
int value = 8421504;
int red = (value >> 16) & 0xFF;
int green = (value >> 8) & 0xFF;
//0000 0000 1000 0000 1000 0000 1000 0000
//右移八位:  0000 0000 1000 0000 1000 0000
//                         0xFF: 1111 1111    
// 最后做与运算获得分量:green:     
int blue = (value >> 0) & 0xFF;

绘制图像

接下来就可以将图片的像素存储到二维数组里,
Image是一个抽象类,BufferedImage是其实现类,是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片)
流程如下:

1.首先根据提供的图片路径path创建一个文件对象
String path="E:\\java\\eclipse\\eclipse javaee\\workspace\\Yu java\\66.jpg"
File file =new File(path);//java.io.File
2.再次具体化file是什么类型的文件,
  以便于调用不同类型文件所具有的不同方法,这里是image文件
  那么就可以调用getRGB(i, j)来获取像素。
  //读取文件数据
  //java.awt.image.BufferedImage;
  BufferedImage buffimage=null;
 try {
	 buffimage=ImageIO.read(file);//javax.imageio.ImageIO
	 }catch (IOException e) {
	 e.printStackTrace();
	 System.err.println("图像读取失败");
	                           }
3.通过循环将buffimage.getRGB(i, j)获得像素存放在数组中  

详细实现如下:

//读取文件,获得图片像素
	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;

	}

在这里插入图片描述
以上是原图重绘效果。除此之外,根据像素的重绘间隔和色彩RGB设置我们可以获得不同的图片渲染效果。例如:马赛克(间隔取像素,不一个一个重绘),二值化(根据计算出来的灰度值定一个阈值 100 ,大于画白, 小于画黑色)。

//马赛克 间距取像素值 绘制成间距大小的方块
public void paint2(Graphics g,String path)
{
	int [][]arrpixel=getImagePixel(path);
	for(int i=0;i<arrpixel.length;i+=20)
	{
	  for(int j=0;j<arrpixel[i].length;j+=20)
	  {   
		  int pixel=arrpixel[i][j];
		  int red=(pixel>>16&0xFF);
		  int green=(pixel>>8&0xFF);
		  int blue =(pixel>>0&0xFF);
		  Color color=new Color(red,green,blue);
		  g.setColor(color);
		  g.fillRect(i, j+200, 20,20);
	       
	  }
	}
	
}


//灰度
public void paint3(Graphics g ,String path)
{
	int [][]pixel=getImagePixel(path);
	for(int i=0;i<pixel.length;i++)
	{
		for(int j=0;j<pixel[i].length;j++)
		{
			int value =pixel[i][j];
			int red=(value>>16)&0xFF;
		    int green=(value>>8)&0xFF;
		    int blue=(value>>0)&0xFF;
		    int gray =(red+green+blue)/3;
		   // int gray =(int)(red*0.4+green*0.28+blue*0.31); 		
		   //Color color=new Color(red/2,green/2,blue/2);
		    Color color=new Color(gray,gray,gray);
		    g.setColor(color);
		    g.fillRect(i,j+200,1,1);
		}
	}
}

//二值化手绘
public void paint4(Graphics g ,String path)
{
	int [][]pixel=getImagePixel(path);
	for(int i=0;i<pixel.length;i++)
	{
		for(int j=0;j<pixel[i].length;j++)
		{
			int value =pixel[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);
		    //以gray<100为分界线,大于这个数的全部是白色
		    if(gray<150)
		    {
		    	g.setColor(Color.black);
		    }
		    else
		    {
		    	g.setColor(Color.white);
		    }
		    g.fillRect(i, j+200,1, 1);
		}
	}
}

//轮廓检测
//相邻之间的像素点进行比较
public void paint5(Graphics g ,String path)
{
	int [][]pixel=getImagePixel(path);
	for(int i=0;i<pixel.length-2;i++)
	{
		for(int j=0;j<pixel[i].length-2;j++)
		{
			int value =pixel[i][j];
			int red=(value>>16)&0xFF;
		    int green=(value>>8)&0xFF;
		    int blue=(value>>0)&0xFF;
		    
		    int valuen=pixel[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){
                g.setColor(Color.PINK);
            }else{
                g.setColor(Color.white);
            }
		    g.fillRect(i, j+200, 1, 1);
		    
		}
	}
}
//绘制油画
public void paint6(Graphics g ,String path)
{
	Random random = new Random();
	int [][]pixel=getImagePixel(path);
	for(int i=0;i<pixel.length;i+=3)
	{
		for(int j=0;j<pixel[i].length;j+=3)
		{
			Color color=new Color(pixel[i][j]);
			g.setColor(color);
		    int size = random.nextInt(5)+5; 
		    g.fillOval(i,j+200,size,size);
		}
	}
}

马赛克
在这里插入图片描述
灰度
在这里插入图片描述
二值化
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GuochaoHN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值