聊聊Android影象格式類及影象轉換方法
本文主要介紹Android影象格式類及影象轉換方法,一款軟體的開發和影象密切相關,特別是移動應用程式,在視覺效果、使用者的體驗效果等方面是至關重要的,在Android程式開發的過程中,瞭解存在哪些影象格式類(ImageFormat、PixelFormat及BitmapConfig等)及影象格式(JPG、PNG及BMP等)的轉換方法,對以後的開發會有些幫助。
關於影象格式類,介紹以下三個:ImageFormat、PixelFormat及BitmapConfig。
1、ImageFormat(android.graphics.ImageFormat),格式引數有以下幾種:
int JPEG ,Encoded formats,常量值: 256 (0x00000100)
int NV16,YCbCr format, used for video,16 (0x00000010)
int NV21,YCrCb format used for images, which uses the NV21 encoding format,常量值: 17 (0x00000011)
int RGB_565,RGB format used for pictures encoded as RGB_565,常量值: 4 (0x00000004)
int UNKNOWN, 常量值:0 (0x00000000)
int YUY2,YCbCr format used for images,which uses YUYV (YUY2) encoding format,20 (0x00000014)
int YV12,Android YUV format,This format is exposed to software decoders and applications
YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed by (W/2) x (H/2) Cr and Cb planes
解釋總是英文的最通俗易懂,這裡就不獻醜翻譯了。
用法舉例,在構建ImageReader類的物件時,會用到ImageFormat類的影象格式物件。如
<span style="font-size:14px;"> ImageReader imageReader = ImageReader.newInstance(width, height, ImageFormat.RGB_565, 2);</span>
imageReader物件表示其快取中最多存在寬高分別為width和height、RGB_565格式的影象流兩幀。在需求中用哪一種影象格式,要視實際情況而定,後面的類似。
2、PixelFormat(android.graphics.PixelFormat),格式引數有以下幾種:
int A_8,常量值:8 (0x00000008)
int JPEG,常量值:256 (0x00000100),constant,已宣告不贊成使用,use ImageFormat.JPEG instead.
int LA_88,常量值:10 (0x0000000a)
int L_8, 常量值:9 (0x00000009)
int OPAQUE,常量值: -1 (0xffffffff),System chooses an opaque format (no alpha bits required)
int RGBA_4444,常量值:7 (0x00000007)
int RGBA_5551,常量值:6 (0x00000006)
int RGBA_8888,常量值:1 (0x00000001)
int RGBX_8888,常量值:2 (0x00000002)
int RGB_332,常量值:11 (0x0000000b)
int RGB_565,常量值:4 (0x00000004)
int RGB_888,常量值:3 (0x00000003)
int TRANSLUCENT,常量值: -3 (0xfffffffd),System chooses a format that supports translucency (many alpha bits)
int TRANSPARENT,常量值:-2 (0xfffffffe),System chooses a format that supports transparency (at least 1 alpha bit)
int UNKNOWN,常量值: 0 (0x00000000)
int YCbCr_420_SP,常量值:17 (0x00000011),constant 已宣告不贊成使用 use ImageFormat.NV21 instead
int YCbCr_422_I,常量值: 20 (0x00000014),constant 已宣告不贊成使用 use ImageFormat.YUY2 instead
int YCbCr_422_SP,常量值:16 (0x00000010),constant 已宣告不贊成使用 use ImageFormat.NV16 instead
注意,有四種影象格式已被宣告不贊成使用,可以用ImaggFormat相對應的格式進行代替。由此可知,兩種影象格式之間存在相通之處。
用法舉例,讓視窗實現漸變的效果,如:
<span style="font-size:14px;"> 1 getWindow().setFormat(PixelFormat.RGBA_8888);</span>
注意說明:RGBA_8888為android的一種32位顏色格式,R、G、B、A分別用八位表示,Android預設的影象格式是PixelFormat.OPAQUE,其是不帶Alpha值的。
3、Bitmap.Config(Android.graphics.Bitmap內部類)
Possible bitmap configurations。A bitmap configuration
describes how pixels are stored。This affects the quality (color
depth) as well as the ability to display transparent/translucent
colors。(官網介紹,大致意思是說:影響一個圖片色彩色度顯示質量主要看
點陣圖配置,顯示圖片時透明還是半透明)。
ALPHA_8:Each pixel is stored as a single translucency (alpha) channel。(原圖的每一個畫素以半透明顯示)
ARGB_4444:This field was deprecated in API level 13。 Because of the poor quality of thisconfiguration, it is advised to use ARGB_8888 instead。(在API13以後就被棄用了,建議使用8888)。
ARGB_8888 :Each pixel is stored on 4 bytes。 Each channel
(RGB and alpha for translucency) is stored with 8 bits of precision
(256 possible values) 。This configuration is very flexible and
offers the best quality。 It should be used whenever possible。
(每個畫素佔4個位元組,每個顏色8位,反正很清晰,看著很舒服)。
RGB_565:Each pixel is stored on 2 bytes and only the RGB
channels are encoded:red is stored with 5 bits of precision (32
possible values),green is stored with 6 bits of precision (64
possible values) and blue is stored with 5 bits of precision。(這個應該很容易理解了)。
用法舉例,構建Bitmap物件時,會用到BitmapConfig類影象格式物件,如:
<span style="font-size:14px;"> 1 Bitmap bitmap = Bitmap.createBitmap(width, height,Bitmap.Config.RGB_565)</span>
下面來看各種型別影象之間的轉換都有哪些方法、差異及共同點:
1、YUV轉JPG
查閱到的資料大部分是把Yuv影象資料通過數學運算得到每個畫素點的
RGB編碼,存入Bitmap物件,再呼叫Bitmap類自帶的壓縮方法生成JPG圖片。
這種方法效率極低,一張480x320解析度的圖片有20萬個位元組,因此運算需要
經過20萬次迴圈。其實android.graphics包下面有一個YuvImage類,可以將資料直接匯入:
<span style="font-size:14px;">1 YuvImage image = new YuvImage(data, ImageFormat.NV21, IMG_WIDTH, IMG_HEIGHT, null);</span>
前面兩個引數決定了資料來源與影象格式,後面單個引數就不解釋了。而YuvImage類正好有一個compressToJPEG(Rect rect, int i, OutputStream)方法,可以直接將資料儲存在JPG檔案的輸出流中。
2、PNG轉Bitmap
<pre name="code" class="java"><span style="font-size:14px;"> 1 byte[] data = null;
2 File pngImage = null;
3 BufferedOutputStream stream = null;
4 try {
5 pngImage = new File(outputFile); //outputFile為png影象名稱
6 FileOutputStream fstream = new FileOutputStream(pngImage);
7 stream = new BufferedOutputStream(fstream);
8 stream.write(data);
9 } catch (Exception e) {
10 e.printStackTrace();
11 } finally {
12 if (stream != null) {
13 try {
14 stream.close();
15 } catch (IOException e) {
16 e.printStackTrace();
17 }
18 }
19 }
20 Bitmap bitmap=BitmapFactory.decodeByteArray(data, 0,
data.length);</span>
如果通過資源(drawable)的形式,那就方便地多,只需要一句話。
<span style="font-size:14px;">1 Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);</span>
雖然沒有華麗的演算法,但效果不錯哦,就是想改變影象屬性時得另外實現。3、ARGB轉Bitmap
<span style="font-size:14px;"> 1 Bitmap bitmapOrg = BitmapFactory.decodeByteArray(rawData, 0,
rawData.length);
2 Bitmap bitmapNew = bitmapOrg.copy(Config.ARGB_8888, true);
3 if(bitmapNew == null)
4 return;
5 for(int i = 0;i<bitmapNew.getWidth();i++)
6 {
7 for(int j =0;j<bitmapNew.getHeight();j++)
8 {
9 int col = bitmapNew.getPixel(i, j);
10 int alpha = col&0xFF000000;
11 int red = (col&0x00FF0000)>>16;
12 int green = (col&0x0000FF00)>>8;
13 int blue = (col&0x000000FF);
14 int gray = (int)((float)red*0.3+(float)
green*0.59+(float)blue*0.11);
15 int newColor = alpha|(gray<<16)|(gray<<8)|gray;
16 }
17 }
18 sendMsg(bitmapNew);
19 File file = new File(Environment.getExternalStorageDirectory
()+File.separator+"gray"+number+".jpg");
20 OutputStream out;
21 try {
22 out = new FileOutputStream(file);
23 if(bitmapNew.compress(Bitmap.CompressFormat.JPEG, 100, out))
24 out.close();
25 } catch (FileNotFoundException e) {
26 e.printStackTrace();
27 } catch (IOException e) {
28 e.printStackTrace();
29 } </span>
注意,程式碼中做了灰度處理,若想得到彩色圖,分別對Bitmap影象R、G、B三通道進行賦值即可。