非原創(chuàng)准谚,只是整理挫剑,如果里面發(fā)現引用的內容沒有標識出來,歡迎指出柱衔。
一樊破、基本知識
(1)兩種圖片:
1)矢量圖:
矢量圖又叫向量圖,是用一系列計算機指令來描述和記錄一幅圖秀存,一幅圖可以解為一系列由點捶码、線、面等到組成的子圖或链,它所記錄的是對象的幾何形狀惫恼、線條粗細和色彩等。生成的矢量圖文件存儲量很小澳盐,無論放大和縮小多少倍祈纯,圖形都有一樣的平滑邊緣和清晰的視覺效果。
例如叼耙,輸入法的文字就是矢量圖腕窥。
2)點陣圖(位圖):
就是圖象由無數個點(像素)組成。每個像素里都由一個顏色表現筛婉,所以點陣圖是有一個個有顏色的點(像素)排列而成簇爆。我們平時看到的文件格式有PSD癞松、TIF、JPG入蛆、GIF等都是點陣圖响蓉,數碼相機拍攝的照片就是點陣圖。
(2)像素(pixel簡稱px):
在位圖中哨毁,圖片是由很多點組成枫甲,那每個點就是1個像素。像素是屏幕中可以顯示的最小元素單元扼褪,我們應用里任何可見的東西都是由一個個像素點組成的想幻。單獨一個像素點非常的微小,肉眼是無法看見的话浇,可是當許許多多的像素點聚集到一起時脏毯,就可以拼接成五彩繽紛的圖案。
(3)屏幕尺寸
屏幕尺寸指屏幕的對角線的長度凳枝,單位是英寸抄沮,1英寸=2.54厘米
比如常見的屏幕尺寸有2.4跋核、2.8岖瑰、3.5、3.7砂代、4.2蹋订、5.0、5.5刻伊、6.0等
(4)分辨率:
圖像分辨率:圖像分辨率是指每英寸圖像內的像素點數露戒。這里的分辨率其實是密度,是指1英寸里有多少像素捶箱。它以 ?像素/英尺(ppi)為單位智什,如一個圖像的分辨率為72ppi,就表示該圖像中每英尺包含72個像素丁屎。(但是現在通常將分辨率表示成每一個方向上的像素數量荠锭,比如 640X480 等。)
屏幕分辨率:屏幕分辨率是指在橫縱向上的像素點數晨川,單位是px证九,1px=1個像素點,每個屏幕有自己的分辨率共虑。一般以縱向像素*橫向像素愧怜,如1960*1080。屏幕分辨率越高妈拌,所呈現的色彩越多拥坛,清晰度越高。
(5)色彩模式
圖像的大小和質量不僅僅由像素總數決定,還跟色彩模型有關猜惋。色彩模型有RGB模式疾党,CMYK模式,位圖模式惨奕,灰度模式等等雪位。
(6)圖片大小
通過一個例子來理解:
選擇一個24位深度的分辨率為225×225的位圖,
由于24位位圖是真彩色梨撞,沒有顏色表雹洗,所以
其文件大小為:152154=14+40+(225×3+1)×225
注:因為1個像素用三個字節(jié)來表示,所以乘以3卧波;因為位圖存儲時时肿,Windows規(guī)定一個掃描行所占的字節(jié)數必須是4的倍數(即以long為單位),不足的以0填充,225×3+1剛好是4的倍數港粱;14和40是位圖文件頭和位圖信息頭的字節(jié)大畜Τ伞;
當利用繪圖程序將文件保存為256色查坪,即8位深度的位圖后寸宏,文件大小變?yōu)?2378字節(jié):
52378 = 14 + 50 + 256 × 4 + (225 + 3)× 225
注:256色位圖有顏色表,每個顏色表結構體是4字節(jié)偿曙,所以顏色表這一項占256*4 個字節(jié)氮凝;225+3 剛好湊成4的倍數
可見分辨率沒變,因為位深從24變成了8望忆。所以圖像質量下降了罩阵,圖像大小也變小了。
二启摄、圖片的存在形式:
1.文件形式(即以二進制形式存在于硬盤上)
獲取大小(Byte):File.length()
2.流的形式(即以二進制形式存在于內存中)
獲取大小(Byte):new FileInputStream(File).available()
3.Bitmap形式
獲取大小(Byte):Bitmap.getByteCount()
這三種形式的區(qū)別:
文件形式和流的形式對圖片體積大小并沒有影響,也就是說,如果你手機SD卡上的如果是100K,那么通過流的形式讀到內存中,也一定是占100K的內存,注意是流的形式,不是Bitmap的形式稿壁。當圖片以Bitmap的形式存在時,其占用的內存會變大。
三歉备、bitmap介紹:
(1) Bitmap.Config
一張圖片Bitmap所占用的內存 =圖片長度 x 圖片寬度 x 一個像素點占用的字節(jié)數
而Bitmap.Config傅是,正是指定單位像素占用的字節(jié)數的重要參數。
其中威创,A代表透明度落午;R代表紅色;G代表綠色肚豺;B代表藍色溃斋。
ALPHA_8
表示8位Alpha位圖,即A=8,一個像素點占用1個字節(jié),它沒有顏色,只有透明度
ARGB_4444
表示16位ARGB位圖,即A=4,R=4,G=4,B=4,一個像素點占4+4+4+4=16位吸申,2個字節(jié)
ARGB_8888
表示32位ARGB位圖梗劫,即A=8,R=8,G=8,B=8,一個像素點占8+8+8+8=32位享甸,4個字節(jié)
RGB_565
表示16位RGB位圖,即R=5,G=6,B=5,它沒有透明度,一個像素點占5+6+5=16位,2個字節(jié)
Bitmap.Config主要作用是:
以何種方式像素存儲梳侨。不同的配置將會影響圖像的畫質(色彩深度)蛉威,位數越高畫質越高,顯然在這里ARGB_8888是最占內存的走哺。當然蚯嫌,畫質越高也就越占內存了。
Tips:由于ARGB_4444的畫質慘不忍睹丙躏,一般假如對圖片沒有透明度要求的話择示,可以改成RGB_565,相比ARGB_8888將節(jié)省一半的內存開銷晒旅。
配置不同Bitmap.Config在相同分辨率下的占用內存情況:
一張圖片Bitmap所占用的內存 = 圖片長度 x 圖片寬度 x 一個像素點占用的字節(jié)數
在Android里面可以通過下面的代碼來設置解碼率:
(2) Bitmap.CompressFormat
從字面上理解栅盲,它的含義是:Bitmap壓縮格式
其實這個參數很簡單,就是指定Bitmap是以JPEG废恋、PNG還是WEBP格式來壓縮
(3) Bitmap.compress()方法
重磅方法來了谈秫,通過這個方法,可以實現圖片的壓縮鱼鼓。使用該方法需要傳三個參數進去:
CompressFormat
指定Bitmap的壓縮格式拟烫,可選擇JPEG、PNG蚓哩、WEBP
int類型的quality
指定Bitmap的壓縮品質构灸,范圍是0 ~ 100;該值越高岸梨,畫質越高。0表示畫質最差稠氮,100畫質最高曹阔。
OutputStream
指定Bitmap的字節(jié)輸出流。一般使用:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
這個方法不改變圖片分辨率隔披,只通過改變編碼格式來改變每個像素大小赃份,從而改變圖片大小和質量。
四奢米、BitmapFactory
BitmapFactory是獲取Bitmap和壓縮Bitmap的重要類抓韩,下面開始介紹BitmapFactory幾個重要的成員變量和方法:
(1)通過BitmapFactory解碼(獲取)Bitmap的幾種方式
1)decodeFile()//從SD卡文件讀取
Bitmap ?bm=BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/photo.jpg");
2)decodeResource()//從資源文件res讀取
Bitmap bm=BitmapFactory.decodeResource(this.getResources(), R.mipmap.test_pic);
3)decodeStream()//從輸入流讀取
Bitmap bm=BitmapFactory.decodeStream(inputStream);
4)decodeByteArray()//從字節(jié)數組讀取
Bitmap bm=BitmapFactory.decodeByteArray(bytes,0,bytes.length);
(2)BitmapFactory.Options
BitmapFactory在使用方法decodeFile()、decodeResource()解碼圖片時鬓长,可以指定它的BitmapFactory.Options谒拴。
這個參數作用非常大,它可以設置Bitmap的采樣率涉波,通過改變圖片的寬度英上、高度炭序、縮放比例等,以達到降低圖片的像素的目的苍日,這樣可以做到圖片壓縮惭聂,減少Bitmap的內存。
下面列出BitmapFactory.Options的部分成員變量:
in開頭的代表的就是設置某參數;out開頭的代表的就是獲取某參數相恃。比如辜纲,inSampleSize就是設置Bitmap的縮放比例、outWidth就是獲取Bitmap的高度拦耐。
1)?inJustDecodeBounds 設置只去讀圖片的附加信息(寬高),不去解析真實的Bitmap
從字面上理解侨歉,它的含義是:”設置僅解碼Bitmap的邊界”。那它真正的作用是啥呢揩魂?
當inJustDecodeBounds設置為true的時候幽邓,BitmapFactory通過decodeResource或者decodeFile解碼圖片時,將會返回空(null)的Bitmap對象火脉,這樣可以避免Bitmap的內存分配牵舵,但是它可以返回Bitmap的寬度、高度以及MimeType倦挂。
這樣做的意義就在于畸颅,可以先不用產生Bitmap內存,從而獲得圖片的寬高信息方援,盡可能的做到節(jié)約內存耸棒。
2)inSampleSize 設置圖片的縮放比例(寬和高)
這里注意醋闭,google推薦用2的倍數:
在這里著重講一下這個inSampleSize。從字面上理解,它的含義是:”設置取樣大小“悴晰。
它的作用是:設置inSampleSize的值(int類型)后,假如設為4捎拯,則寬和高都為原來的1/4你弦,寬高都減少了,自然內存也降低了呀非。
如圖所示:
在這里參考Google官方文檔來解釋:
http://developer.android.com/intl/zh-cn/training/displaying-bitmaps/load-bitmap.html#load-bitmap
如何理解”設置取樣大小“呢坚俗?如果你認真看了上面的內容話,聰明的你一定知道岸裙,肯定需要配合inJustDecodeBounds猖败,先獲取圖片的寬、高【這個過程就是取樣】降允,然后通過獲取的寬高恩闻,動態(tài)的設置inSampleSize的值。
【當然拟糕,你也可以不動態(tài)判呕,可以寫死inSampleSize的值倦踢。比如設置inSampleSize = 4的話,一張分辨率為2048x1536px的圖像將使用inSampleSize值為4的設置來解碼侠草,產生的Bitmap大小約為512*384px辱挥。相較于完整圖片占用12M的內存,這種方式只需0.75M內存(假設Bitmap配置為ARGB_8888)边涕∥畹猓】
四、兩種壓縮方式:
(1)質量壓縮:
將圖片保存到本地時進行壓縮, 即將圖片從Bitmap形式變?yōu)镕ile形式時進行壓縮
該方法是利用compress方法功蜓。壓縮圖片的質量, 它不會減少圖片的像素园爷。
比方說, 你的圖片是300K的, 1280*700像素的, 經過該方法壓縮后, File形式的圖片是在100k以下, 但是你BitmapFactory.decodeFile到內存中,變成Bitmap時,它的像素仍然是1280*700。計算圖片像素的方法是?bitmap.getWidth()和bitmap.getHeight()式撼。
(2)取樣壓縮
通過調整inSampleSize的值童社,在圖片從本地讀到內存時,進行壓縮 ,即圖片從File形式變?yōu)锽itmap形式。這種方式通過改變圖像的尺寸(像素總數)來壓縮著隆,每個像素所占用的大小不變扰楼。
(3)常用的圖片壓縮方法是將兩者結合。
參考資料:
http://blog.sina.com.cn/s/blog_9e1e8c1301015xat.html
http://www.tuicool.com/articles/eue6z2
http://anany.me/2015/10/15/bitmap1/
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html