最近在做一個相機(jī)有關(guān)的應(yīng)用,相機(jī)輸出的一般來說都是需要旋轉(zhuǎn)才能變?yōu)槲覀兛磥碚虻膱D像的,這是因為相機(jī)傳感器的坐標(biāo)體系和屏幕不一致造成的,具體的不展開說了。但是圖像輸出導(dǎo)致的一系列問題值得記錄一番。
首先是圖像預(yù)覽輸出很慢很卡,這時候就要注意一下,ImageReader的輸出格式不要使用ImageFormat.JPEG,可以使用ImageFormat.YUV_420_888,我猜測原因是JPEG格式輸出的話,相機(jī)還得為我們做一次轉(zhuǎn)碼,在低性能手機(jī)上很容易導(dǎo)致卡頓,如果改了格式還卡的話,考慮一下降低圖像輸出的分辨率吧。至于YUV轉(zhuǎn)Bitmap的話,可以網(wǎng)上找找C的庫,性能比直接輸出JPEG轉(zhuǎn)Bitmap更高。
接下來就是圖像的方向和屏幕不一致了,網(wǎng)上搜索旋轉(zhuǎn)Bitmap,基本上都是說使用
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
來創(chuàng)建一個新的Bitmap,然后將原Bitmap釋放掉,這時候坑就來了,在平時這樣使用是沒事的,但是在相機(jī)預(yù)覽輸出的時候就有問題了,因為相機(jī)預(yù)覽輸出速度很快,這種情況下Bitmap是來不及釋放掉的,會慢慢的內(nèi)存泄漏,直到最后出現(xiàn)內(nèi)存溢出。而且Bitmap的創(chuàng)建時非常消耗內(nèi)存的,這樣頻繁創(chuàng)建Bitmap,內(nèi)存的消耗是飛速的,這時候我們可以選用另外一種方式,網(wǎng)上很少有人提到的方法來旋轉(zhuǎn)Bitmap,這個方法就是使用Canvas。
我們知道,Canvas創(chuàng)建的時候可以傳入Bitmap,這時候Canvas上的所有繪制都會直接繪制在Bitmap上,而且Canvas也有drawBitmap方法,可以用其他Bitmap做畫筆,更關(guān)鍵的是,drawBitmap的重載方法里有一個是可以傳入Matrix的,這時候解決方法就出來了,我們可以創(chuàng)建一個全局復(fù)用的Bitmap,注意大小使用旋轉(zhuǎn)后的大小,然后使用它來創(chuàng)建Canvas,之后所有bitmap旋轉(zhuǎn)都不用再生成新的bitmap,只要使用canvas.drawBitmap在全局Bitmap上畫就行。不過事情還沒完。
通過Bitmap創(chuàng)建的Canvas的畫布大小就是Bitmap的大小,我們旋轉(zhuǎn)bitmap的時候要注意,Matrix旋轉(zhuǎn)時畫筆Bitmap的位置是會發(fā)生變化的,最后畫出來能輸出到Bitmap上的可能只有小部分,甚至完全沒有畫在Bitmap上。這時候我們就需要在Matrix里面添加位移操作,來保持畫筆輸出位置和畫布一致了,具體的位移距離就得自己算了,因為線代我已經(jīng)忘干凈了,所以我的做法是,拿兩張紙,自己旋轉(zhuǎn)完看位置......
到此,相機(jī)圖像輸出導(dǎo)致的所有問題都解決了,寫出來就這么幾步,但是摸索的時候也卡了我老半天,因為網(wǎng)上沒有搜到相關(guān)的問題記錄,所以記錄下來以免忘記。
——在YUV轉(zhuǎn)Bitmap可以使用libyuv庫,同時旋轉(zhuǎn)操作也可以通過該庫完成,如果可以,最好不要使用Java做旋轉(zhuǎn)