1、介绍。
通道。三通道一般指彩色图片,分别为R、G、B通道,我们所见的彩色图片,则是这三个通道叠加的效果。四通道一般是指在三通道的基础上再加上一个透明度的通道。单通道一般指灰度图,但是三通道如果每个像素的三个通道值都相等的话,我们也称为灰度图。
灰度图。Gray Scale Image 或是Grey Scale Image,又称灰阶图。把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶。因为彩色图片每个像素有三个字节(24bit)的值,怎么样才能取到一字节(8bit)的灰度等级呢。我们一般有7种方法:最小值法、最大值法、平均值法、加权法、红色值法、绿色值法和蓝色值法。
下面我会介绍这7种方法,以下图所示的源图为例。
2、代码。生成两个文件夹,一个存放单通道的图像,另一个存放是三通道的图像。每个文件夹都会各生成7种不同方法灰度化处理的图像。至于使用哪种方法,要看具体的例子。
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
public class ImgTest {
private static final byte Gray_Type_Min = 1;//最大值法
private static final byte Gray_Type_Max = 2;//最小值法
private static final byte Gray_Type_Average = 3;//平均值法
private static final byte Gray_Type_Weight = 4;//加权法
private static final byte Gray_Type_Red = 5;//红色值法
private static final byte Gray_Type_Green = 6;//绿色值法
private static final byte Gray_Type_Blue = 7;//蓝色值法
private static final String File_Path = "G:\\xiaojie-java-test\\img\\%s\\%s.jpg";
private static final String Source_Path = "G:\\xiaojie-java-test\\img\\source.jpg";
public static void main(String[] args) {
//图片灰度化
toGrayImg(Gray_Type_Min, "gray_min");//最大值法
toGrayImg(Gray_Type_Max, "gray_max");//最小值法
toGrayImg(Gray_Type_Average, "gray_average");//平均值法
toGrayImg(Gray_Type_Weight, "gray_weight");//加权法
toGrayImg(Gray_Type_Red, "gray_color_red");//红色值法
toGrayImg(Gray_Type_Green, "gray_color_green");//绿色值法
toGrayImg(Gray_Type_Blue, "gray_color_blue");//蓝色值法
}
/**
* 图片灰度化的方法
*
* @param type 灰度化方法
* @param grayFileName 目标图片文件名
*/
private static void toGrayImg(int type, String grayFileName) {
try {
BufferedImage image = ImageIO.read(new File(Source_Path));
final int imgWidth = image.getWidth();
final int imgHeight = image.getHeight();
BufferedImage bufferedImage_1 = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_BYTE_GRAY);
BufferedImage bufferedImage_3 = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
//这边因为只是灰度操作,所以内外循环imgWidth和imgHeight可以随便放
for (int i = 0; i < imgHeight; i++) {
for (int j = 0; j < imgWidth; j++) {
final int pixel = image.getRGB(j, i);
final int[] grb = getRgb(pixel);
final int gray = getGray(grb, type);
bufferedImage_1.setRGB(j, i, (byte) gray);//这里一定要用byte类型的,不然图片会很暗
bufferedImage_3.setRGB(j, i, getPixel(gray, gray, gray));
//System.out.print(String.format("%4d ", gray));
}
//System.out.println();
}
ImageIO.write(bufferedImage_1, "JPEG", new File(String.format(File_Path, "单通道-灰度图", grayFileName)));
Thread.sleep(1);
ImageIO.write(bufferedImage_3, "JPEG", new File(String.format(File_Path, "三通道-灰度图", grayFileName)));
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
//将一个int值转化为3个r、g个b的byte值
private static int[] getRgb(int pixel) {
int[] rgb = new int[3];
rgb[0] = (pixel >> 16) & 0xff;
rgb[1] = (pixel >> 8) & 0xff;
rgb[2] = pixel & 0xff;
return rgb;
}
//将3个r、g个b的byte值转化为一个int值
private static int getPixel(int r, int g, int b) {
int getPixel = b;
getPixel += (r << 16);
getPixel += (g << 8);
return getPixel;
}
//根据不同的灰度化方法,返回byte灰度值
private static int getGray(int[] rgb, int type) {
if (type == Gray_Type_Average) {
return (rgb[0] + rgb[1] + rgb[2]) / 3; //rgb之和除以3
} else if (type == Gray_Type_Weight) {
return (int) (0.3 * rgb[0] + 0.59 * rgb[1] + 0.11 * rgb[2]);
} else if (type == Gray_Type_Red) {
return rgb[0];//取红色值
} else if (type == Gray_Type_Green) {
return rgb[1];//取绿色值
} else if (type == Gray_Type_Blue) {
return rgb[2];//取蓝色值
}
//比较三个数的大小
int gray = rgb[0];
for (int i = 1; i < rgb.length; i++) {
if (type == Gray_Type_Min) {
if (gray > rgb[i]) {
gray = rgb[i];//取最小值
}
} else if (type == Gray_Type_Max) {
if (gray < rgb[i]) {
gray = rgb[i];//取最大值
}
}
}
return gray;
}
}
3、结果。