ImageIO.write(bufferedImage)(输出图片时,图片格式和样式调整)

ImageIO.write(bufferedImage)(输出图片时,图片格式和样式调整)

在编写图像二值化、灰度化的时候无意间发现在方法中使用ImageIO.write输出图像时仍然执行给bufferedImage赋值时候的语句,下面贴上代码:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
 
import javax.imageio.ImageIO;
 
public class test {
 
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
 
        BufferedImage bufferedImage = ImageIO.read(new File("D:/adt-bundle-windows-x86_64-20140321/workspace/test/img/test6.jpg"));         
 
	
        BufferedImage bufferedImage2=grayimage( bufferedImage);
        BufferedImage bufferedImage3=erzh( bufferedImage);//这里改变了bufferedImage2值
        
        
        ImageIO.write(bufferedImage, "jpg", new File("D:/adt-bundle-windows-x86_64-20140321/workspace/test/img/yuantu.jpg"));
        ImageIO.write(bufferedImage2, "jpg", new File("D:/adt-bundle-windows-x86_64-20140321/workspace/test/img/huidutu.jpg"));
        ImageIO.write(bufferedImage3, "jpg", new File("D:/adt-bundle-windows-x86_64-20140321/workspace/test/img/ezh.jpg"));
	
	}
	
	public static BufferedImage grayimage(BufferedImage bufferedImage){
		
		int h = bufferedImage.getHeight();
	    int w = bufferedImage.getWidth();
	   //BufferedImage bufferedImage2 = new BufferedImage(w, h, BufferedImage. TYPE_3BYTE_BGR );
	    for (int x = 0; x < w; x++) 
	      {
	          for (int y = 0; y < h; y++) 
	          {
	            int argb = bufferedImage.getRGB(x, y);
	        	  int r = (argb >> 16) & 0xFF;
                  int g = (argb >> 8) & 0xFF;
                  int b = (argb >> 0) & 0xFF;
                  int grayPixel=(int)(r+g+b)/3;
	         	//将各个颜色组合为rgb颜色值
                int rgb = (grayPixel*256 + grayPixel)*256+grayPixel;  
                  if(rgb>8388608)  //rgb的最大值为8388608,因此当大于时候需要减去256*256*256
                  {  
                      rgb = rgb - 16777216;  
                  }                                 
	         	bufferedImage.setRGB(x, y, rgb);
	         	//bufferedImage2.setRGB(x, y, rgb);
	         	   
	         	          	   
	          }
	       }
		//return  bufferedImage2;
		return  bufferedImage;
		
 
	}
	public static int[][] huidutujuzhen(BufferedImage bufferedImage)
	{
		//灰度化
		bufferedImage=grayimage(bufferedImage);
		int h = bufferedImage.getHeight();
	    int w = bufferedImage.getWidth();
	    //获取灰度矩阵
	    int[][]gray=new int[h][w];       
	    for (int x = 0; x < w; x++) 
	    {
	        for (int y = 0; y < h; y++) 
	        {
	           int a = bufferedImage.getRGB(x, y);
	           gray[y][x]=a;
	                      
	        }         
	     }
		
		return gray;
		
	}
	public static BufferedImage erzh(BufferedImage bufferedImage){
        
       int h = bufferedImage.getHeight();
       int w = bufferedImage.getWidth();     		
       int[][] gray =  huidutujuzhen( bufferedImage);
      // BufferedImage bufferedImage2 = new BufferedImage(w, h, BufferedImage. TYPE_3BYTE_BGR );
              // 效果较好的二值化算法
                 int threshold = ostu(gray, w, h);
                 System.out.print(threshold);
  	         // BufferedImage binaryBufferedImage = ImageIO.read(new File("D:/adt-bundle-windows-x86-20130219/workspace/wenzi/src/huiduhua.jpg")); 
 
                //  BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);//最后一个参数就是二值化TYPE_BYTE_GRAY、、TYPE_3BYTE_BGR
                           for (int x = 0; x < w; x++) 
                           {
                              for (int y = 0; y < h; y++)
                              {
                            	  int gry=gray[y][x]&0xff;
                                   if (gry > threshold) 
                                   {
                                       gray[y][x]=0xFFFFFF;
                                   } 
                                   else
                                   {
                                      gray[y][x]=0x000000;
                                   }                                                    	 
                                   bufferedImage.setRGB(x, y, gray[y][x] );
                               }
                          }
                               
                           return bufferedImage;
              	                                    
}
	
	 //OTSU的中心思想是阈值T应使目标与背景两类的类间方差最大。取得合适二值化阀值的函数
    public static int ostu(int[][] gray, int w, int h) {
        int[] histData =new int[256];// new int[w * h];
        // Calculate histogram
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                int red = 0xFF & gray[y][x];
                histData[red]++;
            }
        }
 
        // Total number of pixels
        int total = w * h;
 
        float sum = 0;   //总的灰度和,,,,,,可能有的灰度不存在histdata就越界了。
        for (int t = 0; t < 256; t++)
            sum += t * histData[t];
 
        float sumB = 0;
        int wB = 0;
        int wF = 0;
 
        float varMax = 0;
        int threshold = 0;
 
        for (int t = 0; t < 256; t++) {
            wB += histData[t]; // Weight Background//histData[t]为灰度为t的像素点的 个数,wB为已循环到的像素点和
            if (wB == 0)
                continue;
 
            wF = total - wB; // Weight Foreground  wF剩余像素点
            if (wF == 0)
                break;
 
            sumB += (float) (t * histData[t]);//灰度为t的的像素和
 
            float mB = sumB / wB; // Mean Background  所循环到的灰度为t的和除以已经循环到的点的和
            float mF = (sum - sumB) / wF; // Mean Foreground  sum为所有灰度值的和
 
            // Calculate Between Class Variance
            float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
 
            // Check if new maximum found
            if (varBetween > varMax) {
                varMax = varBetween;
                threshold = t;
            }
        }
 
        return threshold;
    }
 
}

会发现在输出图像的时候如果在灰度化后二值化改变bufferedImage的值,最后输出灰度图时候发现灰度图像也被二值化了,由此推断(不知是否正确,望大牛指点)在ImageIO.write输出图像时候仍然执行了一遍BufferedImage bufferedImage2=grayimage( bufferedImage);而此时的bufferedImage已经被二值化方法改变了,因此灰度图2会变成二值化图!

你可能感兴趣的:(java)