新一版的需求中,加入了圖片二值化的處理,踩過坑,受過累,做一個標記,積累積累。。。
一、Android實現
/**
* 該函數實現對圖像進行二值化處理
*/
public static Bitmap gray2Binary(Bitmap graymap) {
//得到圖形的寬度和長度
int width = graymap.getWidth();
int height = graymap.getHeight();
//創建二值化圖像
Bitmap binarymap = null;
binarymap = graymap.copy(Config.ARGB_8888, true);
//依次循環,對圖像的像素進行處理
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//得到當前像素的值
int col = binarymap.getPixel(i, j);
//得到alpha通道的值
int alpha = col & 0xFF000000;
//得到圖像的像素RGB的值
int red = (col & 0x00FF0000) >> 16;
int green = (col & 0x0000FF00) >> 8;
int blue = (col & 0x000000FF);
// 用公式X = 0.3×R+0.59×G+0.11×B計算出X代替原來的RGB
int gray = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
//對圖像進行二值化處理
if (gray <= 95) {//固定閾值
gray = 0;
} else {
gray = 255;
}
// 新的ARGB
int newColor = alpha | (gray << 16) | (gray << 8) | gray;
//設置新圖像的當前像素值
binarymap.setPixel(i, j, newColor);
}
}
return binarymap;
}
以Bitmap形式傳入數據,能夠實現二值化,輸出黑白圖片。
當前處理方式,設置固定閾值,會存在數據丟失情形。且使用Android自己的內存運算,運算速度較慢。
二、C實現【編譯so庫】
1,C代碼實現二值化
在C中比較好處理,且內存運算佔用較低,使用指針的方式。還可以將圖片的歸一化,旋轉等一些基礎的處理都添加到代碼中。
2,c代碼打包so庫
嗯嗯,這是C打包so庫源碼。
以下描述以下曾遇見的坑:
(1)不能編譯出來so庫
不能編譯出來so庫問題主要在兩個方面,一是c代碼存在bug或者內存泄漏,或者使用數據類型,Android編譯平臺不支持。
(2)編譯出來的so庫不能適配全平臺
編譯不能適配全平臺,主要在與配置環境參數的設置。
CmakeList設置C11
cppFlags "-std=c++11" //, "-fuse-ld=bfd"
因爲C代碼中使用libpng版本比較老,在文章使用中,不能設置C11版本。
cFlags '-std=c99', '-DPNG_ARM_NEON_OPT=0'
三、細節實現注意點
1,adapter細節優化
Log.e("getView", "getView gridview position=" + position + "parent child count=" + parent.getChildCount());
if (parent.getChildCount() == position || mViewItem0 == null) {
if (mViewItem0 != null && position == 0) {
return mViewItem0;
}
//原始代碼實現方式實現
if (position == 0) {
mViewItem0 = convertView;
}
} else {
convertView = mViewItem0;
}
2,設置筆形方法優化
public static HashMap<String, Typeface> mTypeface = new HashMap<>();//避免多次讀取ttf加載,Typeface佔空間很小
if (ttfURL != null && !("".equalsIgnoreCase(ttfURL))) {
if (mTypeface.get(ttfURL) == null) {
File file = new File(ttfURL);
if (file.exists() && file.length() > 0) {
mTypeface.put(ttfURL, Typeface.createFromFile(ttfURL));//文件存在是否需要判斷
} else {
mTypeface.put("default", Typeface.createFromAsset(context.getAssets(), "FZKTJW.TTF"));
}
}
setTypeface(mTypeface.get(ttfURL));
} else {
if (mTypeface.get("default") == null) {
mTypeface.put("default", Typeface.createFromAsset(context.getAssets(), "FZKTJW.TTF"));
}
setTypeface(mTypeface.get("default"));
}
3,onpageSelected(),設置adapter
(1)在ViewPager的onPageSelected()中不需要setCurrentItem(),當前已經是選中了,且不用notify。會消耗性能,導致運行緩慢。
(2)adapter默認會加載前後兩頁數據,設置前後深度切換效果後,也需要將前後兩頁數據加載出來。
singlePagePreVP.setPageTransformer(true, new DepthPageTransformer());
在新設置數據後,需要已緩存的三頁數據刷新時,使用notify()是不成功的。
直接設置adapter就可以,setAdapter(adapter);
這是二值化的效果。