Bitmap優(yōu)化1:
Bitmap在內(nèi)存中創(chuàng)建過程
Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, mutable, xyzD50, p);
// Bitmap.cpp L713
static jobject Bitmap_creator() {
SkBitmap bitmap; // 相當于new了個SkBitmap對象
// 給圖片設(shè)置值:寬高,colorType
bitmap.setInfo(SkImageInfo::Make(width,height,colorType, kPremul_SkAlphaType, colorSpace));
sk_sp<Bitmap> nativeBitmap= Bitmap::allocateHeapBitmap(&bitmap, NULL);
}
nativeBitmap=Bitmap::allocateHeapBitmap(bitma.get(), ctable);
return createBitmap(env, nativeBitmap.release(),
getPremulBitmapCreateFlags(isMutale), NULL, NULL, density);
在native區(qū),創(chuàng)建圖片對象(又寬高信息等)。此圖片對象,被skBitmap所指向。skBitmap的引用,會以參數(shù)的形式傳遞到j(luò)ava。
private final long mNativePtr;// java層找不到這個內(nèi)存,但是又能操作這個內(nèi)存。如壓縮,獲取寬高等。
所有的native函數(shù),都需要這個long類型的mNativePtr。
內(nèi)存分析
app內(nèi)存劃區(qū)-java:
- 方法區(qū) code
- 堆區(qū)
- 棧區(qū)
- Graphic: opengl,GPU內(nèi)存。
app內(nèi)存劃分-native:
- 圖片
Bitmap底層渲染。
extern "c"
Java_com_maniu_bitmapmaniu_ImageHandler_updateFrame(JNIEnv *env, jobject thiz, jobject bitmap) {
AndroidBitmapInfo info;
int *pixels = NULL; // 指向naive層的圖片內(nèi)存區(qū)。
AndroidBitmap_getInfo(env, bitmap, &info);
// CMakeList.txt中 的target_link_libraries添加:jnigraphics
AndroidBitmap_lockPixels(env, bitmap, reinterpret_cast<void **>(&pixels)); // 鎖住內(nèi)存
// pixels[0] = 0xFF0000; // 第一個點修改紅色
int width = info.width;
int height = info.height;
int *px = pixels;
int *line;
for(int y=0; y<height; y++) { // 一行行的遍歷。
line = px;
for(int x=0; x<width; x++){
line[x] = 0xFFFF0000; // 內(nèi)存區(qū)賦值。
}
// 切換到下一行, stride一行的字節(jié)數(shù)。(width = info.stride/4),一個像素有4個字節(jié)。
px = px + width;
}
// 解鎖
AndroidBitmap_unlockPixels(env, bitmap);
}
Bitmap復用的前提條件。
手寫案例實現(xiàn)bitmap,渲染gif。
Bitmap使用的是java內(nèi)存,還是native內(nèi)存?
------native內(nèi)存。
Bitmap直接在渲染引擎,native層,而不是java層,避免通信。
可以在native直接顯示渲染。繪制最快,性能最高。
Gif加載:android-gif-drawable
系統(tǒng)源碼(external/giflib)
gif的 LZW壓縮,將所有像素匯總到一張表里面。