天天看點

java 像素值_(java)圖檔像素的操作

因為做個遊戲,需要一些圖檔資源,而擷取到的圖檔資源都是jpg格式的,不是透明的,例如下面樣式的:

java 像素值_(java)圖檔像素的操作

為了取出其中的藍光部分,透明化黑色背景,我開始了圖檔處理探索之路。

這篇文章的内容包含以下部分:

1.RGB是什麼?

2.擷取圖檔指定位置的RGB值

3.圖檔的灰化處理

4.修改圖檔的透明通道alpha

————————————————————————————————————————————————————————————————————

RGB是什麼?

這裡簡單說一下,RGB即是red,green,blue的縮寫,即紅綠藍三種顔色。可以通過這三種顔色按一定比例混合,可以形成任何顔色。

圖檔是由許許多多個像素組成,每一像素是一種顔色,有rgb按一定比例混合而成,平常rbg的取值範圍為0~255,當red,green,blue的值都為0時,這個像素的顔色就為黑色,都為255時就是白色,當他們的值相同時,混合色變相為灰色。是以,一個像素點可以表示的顔色的個數為 255 * 255 * 255個,是非常多的。

這裡不多做介紹,百科還是很詳細的。

擷取圖檔指定位置的RGB值

使用java擷取一個像素的RGB,需要使用BufferedImage這個類,這個類提供修改圖檔資料的方法。

1

4 public voidgetImagePixel(String image) {5

6 int[] rgb = new int[3];7 File file = newFile(image);8 BufferedImage bi = null;9 try{10 bi =ImageIO.read(file);11 } catch(IOException e) {12

13 e.printStackTrace();14 }15 int width =bi.getWidth();16 int height =bi.getHeight();17 int minX =bi.getMinX();18 int minY =bi.getMinY();19 for(int y = minY; y < height; y++) {20 for(int x = minX; x < width; x++) {21 //擷取包含這個像素的顔色資訊的值, int型

22 int pixel =bi.getRGB(x, y);23 //從pixel中擷取rgb的值

24 rgb[0] = (pixel & 0xff0000) >> 16; //r

25 rgb[1] = (pixel & 0xff00) >> 8; //g

26 rgb[2] = (pixel & 0xff); //b

27 System.out.print("("+rgb[0] + "," + rgb[1] + "," + rgb[2] + ")");28 }29 System.out.println();30 }31

32 }

表示一個像素的顔色資料的格式有很多,不過常見格式就是4byte形式,即32位資料。看下圖

java 像素值_(java)圖檔像素的操作

如果支援alpha通道,則最高的8位表示alpha的值,剩下的分别表示r,g,b的值,分别8位。還有其他的資料格式,這裡不做介紹啦。

現在應該可以看懂上邊的代碼了吧。

rgb[0]即是r的值,在24~16之間,是以pixel取此區間的值,再右移16位就取得了其值。g,b的值同理。

圖檔的灰化處理

圖檔的灰化處理,很常用,在圖檔識别之前,最常用。圖像灰化,直覺上看就是把多彩的圖像黑白化,本來用r,g,b三個值來表示一個pixel的顔色,現在用一個值來表示pixel的顔色,這樣,檢測圖檔中圖形的邊界就友善許多啦。現在,介紹幾種灰化方法。

1,以r,g,b中的其中一個值,作為灰階值

2. 以r,g,b中的最大值或最小值,作為灰階值

3.以r,g,b的平均值作為灰階值

4.以rgb的權重值作為灰階值

5.用java本身的灰化類型

下面寫個以r值為灰階值的代碼:

public voidtransformGray_R(String imagePath, String path) {

BufferedImage image;try{

image= ImageIO.read(newFile(imagePath));for(int y = image.getMinY(); y < image.getHeight(); y++) {for(int x = image.getMinX(); x < image.getWidth(); x ++) {int pixel =image.getRGB(x, y);int r = (pixel >> 16) & 0x00ff;

pixel= (r & 0x000000ff) | (pixel & 0xffffff00); //用r的值設定b的值

pixel = ((r<<8) & 0x0000ff00) | (pixel & 0xffff00ff);//用r的值設定g的值

image.setRGB(x, y, pixel);

}

}try{

ImageIO.write(image,"jpg", newFile(path));

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}catch(IOException e1) {//TODO Auto-generated catch block

e1.printStackTrace();

}

}

看一下效果:

java 像素值_(java)圖檔像素的操作
java 像素值_(java)圖檔像素的操作

效果還可以,與ps的紅色通道圖檔一模一樣啊。

2,3方法就不示範啦。2方法還是很好使的,特别是處理像開頭那種顔色單一的圖檔時。

下面說一下4方法

//權重法

public voidtransformGrayJiaQuan (String imagePath, String path) {try{

BufferedImage image= ImageIO.read(newFile(imagePath));int width =image.getWidth();int height =image.getHeight();for(int y = image.getMinY(); y < height; y++) {for(int x = image.getMinX(); x < width ; x ++) {int pixel =image.getRGB(x, y);int r = (pixel >> 16) & 0xff;int g = (pixel >> 8) & 0xff;int b = pixel & 0xff;//權重法的核心,權重法是用圖檔的亮度作為灰階值的

int grayValue = (int) (0.30f * r + 0.59f * g + 0.11f *b );//int grayValue = (int) (0.21f * 4 + 0.71f * g + 0.08f * b);//還可以使用這個系數的權重法

pixel = (grayValue << 16) & 0x00ff0000 | (pixel & 0xff00ffff);

pixel= (grayValue << 8) & 0x0000ff00 | (pixel & 0xffff00ff);

pixel= (grayValue) & 0x000000ff | (pixel & 0xffffff00);

image.setRGB(x, y, pixel);

}

}

ImageIO.write(image,"jpg", newFile(path));

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

效果:

java 像素值_(java)圖檔像素的操作

相對于r值灰化的效果,清晰了好多,但亮度明顯小了。

第5種方法:

public voidtransformGray(String imagePath, String path) {

File file= newFile(imagePath);try{

BufferedImage image=ImageIO.read(file);int width =image.getWidth();int height =image.getHeight();

BufferedImage grayImage= new BufferedImage(width, height,BufferedImage.TYPE_BYTE_GRAY);//這裡的圖像類型換了

for(int y = image.getMinY(); y < height; y++) {for(int x = image.getMinX(); x < width; x++) {int rgb =image.getRGB(x, y);

grayImage.setRGB(x, y, rgb);

}

}

File newFile= newFile(path);

ImageIO.write(grayImage,"jpg", newFile);

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

看效果

java 像素值_(java)圖檔像素的操作

可以下載下傳下來自己比對一番

修改圖檔的透明通道alpha

上面說了那麼多,是為了我的終極目的,就是把黑色的背景透明化,保留我想要的顔色。

alpha的值也是在0~255之間,當alpha為0時,則圖檔完全透明,為255時不透明,是以其值越小越透明,由此可知,保留想要的顔色,透明掉不想要的顔色是很簡單的。

處理方法和灰化方法一樣,這次修改的是alpha值。通用的方法是權重法,也可以根據圖檔顔色的類型選擇合适的方法。

下面代碼以權重值為alpha值,權重值得到的圖檔的亮度,是以,越黑的地方,亮度越小,其alpha值最小,越透明。是以,此方法是可行的。

public voidclearBackground(String imagePath, String dstPath) {

ImageIcon icon= newImageIcon(imagePath);

Image srcImage=icon.getImage();

BufferedImage dstImage= newBufferedImage(srcImage.getWidth(icon.getImageObserver()), srcImage.getHeight(icon.getImageObserver()), BufferedImage.TYPE_4BYTE_ABGR);

Graphics gr=dstImage.getGraphics();

gr.drawImage(srcImage,0,0,icon.getImageObserver());int height =dstImage.getHeight();int width =dstImage.getWidth();for(int y = dstImage.getMinY(); y < height; y++) {for(int x = dstImage.getMinX(); x < width; x++) {int pixel =dstImage.getRGB(x, y);int r = (pixel & 0x00ff0000) >> 16;int g = (pixel >> 8) & 0xff;int b = pixel & 0xff;int liangDu = (int)(0.21f * 4 + 0.71f * g + 0.08f * b);//擷取亮度//以亮度作為alpha值

pixel = (liangDu << 24) & 0xff000000 | (pixel & 0x00ffffff); //alpha值在24~32

dstImage.setRGB(x, y, pixel);

}

}try{

ImageIO.write(dstImage,"png", newFile(dstPath));//不要忘記更改圖檔格式為png格式,jpg不支援透明

}catch(IOException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

看第一張圖處理後的效果:

java 像素值_(java)圖檔像素的操作
java 像素值_(java)圖檔像素的操作

其實這張圖以b值為基準,處理效果更好,但權重法更常用。

————————————————————————————————————————————————————————————————————————————

這幾天處理圖檔擷取到知識,在此總結一下。

java 像素值_(java)圖檔像素的操作