性能優化01 - 圖片壓縮 (NDK 哈夫曼算法壓縮)

libjpeg-turbo | Main / libjpeg-turbo

libjpeg編譯文檔
libjpeg-turbo/BUILDING· GitHub
Mac環境編譯 libjpeg壓縮庫
cmake version 3.5.2
針對的arm-v7完整的編譯腳本

#!/bin/bash

# Set these variables to suit your needs
NDK_PATH=/Users/dsh/Downloads/android/NDK/android-ndk-r17c
TOOLCHAIN=gcc
ANDROID_VERSION=21

# cd {build_directory}
cmake -G"Unix Makefiles" \
  -DANDROID_ABI=armeabi-v7a \
  -DANDROID_ARM_MODE=arm \
  -DANDROID_PLATFORM=android-${ANDROID_VERSION} \
  -DANDROID_TOOLCHAIN=${TOOLCHAIN} \
  -DCMAKE_ASM_FLAGS="--target=arm-linux-androideabi${ANDROID_VERSION}" \
  -DCMAKE_TOOLCHAIN_FILE=${NDK_PATH}/build/cmake/android.toolchain.cmake \
# [additional CMake flags] {source_directory}
make

編譯完成以後 需要在libjpeg-turbo-2.0.4 文件夾下找到以下文件
1、 需要用到的頭文件
turbojpeg.h
jpeglib.h
jmorecfg.h
jerror.h
jconfig.h

2、編譯完成的靜態庫
libturbojpeg.a

編寫代碼

    const char *path = env->GetStringUTFChars(path_, 0);


    //從bitmap獲取argb數據
    AndroidBitmapInfo info;//info=new 對象();
    //獲取裏面的信息
    AndroidBitmap_getInfo(env, bitmap, &info);
    //得到圖片中的像素信息
    uint8_t *pixels;//uint8_t char    java   byte     *pixels可以當byte[]
    AndroidBitmap_lockPixels(env, bitmap, (void **) &pixels);
    //jpeg argb中去掉他的a ===>rgb
    int w = info.width;
    int h = info.height;
    int color;
    //開一塊內存用來存入rgb信息
    uint8_t *data = (uint8_t *) malloc(w * h * 3);//data中可以存放圖片的所有內容
    uint8_t *temp = data;
    uint8_t r, g, b;
    //循環取圖片的每一個像素
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            color = *(int *) pixels;//0-3字節  color4 個字節  一個點
            //取出rgb
            r = (color >> 16) & 0xFF;//    #rrggbb  16  0000rr   8  00rrgg
            g = (color >> 8) & 0xFF;
            b = color & 0xFF;
            //存放,以前的主流格式jpeg    bgr
            *data = b;
            *(data + 1) = g;
            *(data + 2) = r;
            data += 3;
            //指針跳過4個字節
            pixels += 4;
        }
    }
    //把得到的新的圖片的信息存入一個新文件 中
    write_JPEG_file(temp,w,h,q,path);

    AndroidBitmap_unlockPixels(env, bitmap);
    free(data);

    env->ReleaseStringUTFChars(path_, path);

理解哈夫曼算法
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EMNQFZTX-1580611679589)(:storage/83fcef4e-9744-4603-8b77-b6af6186e1c1/b5c83a8f.png)]

編寫libjepg 壓縮代碼

void write_JPEG_file(uint8_t *data, int width, int height, jint quality, const char *path) {
    // 1、 創建jpeg壓縮對象
    jpeg_compress_struct jpegStruct;
    jpeg_error_mgr errorMgr;
    jpegStruct.err = jpeg_std_error(&errorMgr);
    jpeg_create_compress(&jpegStruct);
    // 2、 指定存儲文件
    FILE * file = fopen(path,"wb");
    jpeg_stdio_dest(&jpegStruct,file);
    // 3、 設置壓縮參數
    jpegStruct.image_width = width;
    jpegStruct.image_height = height;
    jpegStruct.input_components = 3;
    jpegStruct.in_color_space = JCS_RGB;
    jpeg_set_defaults(&jpegStruct);
    jpegStruct.optimize_coding = true;
    jpeg_set_quality(&jpegStruct,quality,1);
    // 4、 開始壓縮
    jpeg_start_compress(&jpegStruct,1);
    // 5、循環寫入每一行數據
    int row_stride = width * 3;
    JSAMPROW row[1];
    while (jpegStruct.next_scanline < jpegStruct.image_height){
        uint8_t * pixels = data + jpegStruct.next_scanline;
        row[0] = pixels;
        jpeg_write_scanlines(&jpegStruct,row,1);
    }
    // 6、壓縮完成
    jpeg_finish_compress(&jpegStruct);

    // 7、釋放jpeg對象
    fclose(file);
    jpeg_destroy_compress(&jpegStruct);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章