日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

android使用的图片压缩格式,Android 之使用libjpeg压缩图片

發(fā)布時(shí)間:2024/9/19 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android使用的图片压缩格式,Android 之使用libjpeg压缩图片 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、環(huán)境

Android Studio 4.0.1

NDK R15c

so包是2.0.6生成的 libturbojpeg.so

二、準(zhǔn)備

1、編寫native方法并用javah命令生成頭文件

object ImageUtil {

private external fun compressBitmap(bitmap: Bitmap, quality: Int, fileName: String): Int

fun compressImage(bitmap: Bitmap, quality: Int, fileName: String) {

compressBitmap(bitmap, quality, fileName)

}

init {

System.loadLibrary("turbojpeg");

System.loadLibrary("compress");

}

fun decodeFile(filePath: String): Bitmap {

var finalWidth = 800

var opstions = BitmapFactory.Options()

//不加在圖片到內(nèi)存,只拿寬高

opstions.inJustDecodeBounds = true

BitmapFactory.decodeFile(filePath, opstions)

var bitmapWidth = opstions.outWidth

var inSampleSize = 1

if (bitmapWidth > finalWidth) {

inSampleSize = bitmapWidth / finalWidth

}

opstions.inSampleSize = inSampleSize

opstions.inJustDecodeBounds = false

return BitmapFactory.decodeFile(filePath, opstions)

}

}

注意:如果javah提示 無法確定Bitmap的簽名,則指定對應(yīng)的android.jar即可

F:\Android\workspace\ImageSelector\app\src\main\java>javah -classpath

F:\Android\android-sdk\platforms\android-28\android.jar; com.xf.imageselector.utils.Test

2、引入頭文件,并解決頭文件中的報(bào)錯(cuò),一般都是因?yàn)殛P(guān)聯(lián)文件目錄不對,頭文件則從編譯的源碼中提取需要什么頭文件

則引入對應(yīng)的頭文件

3、引入so文件,編寫CMakeList.txt

注意:so一定要是對應(yīng)架構(gòu)下的,不然可能報(bào)錯(cuò)找不到j(luò)peg_**的方法錯(cuò)誤,

例如undefined reference to 'jpeg_destroy_decompress'

4、編寫CMakeList文件,我的文件和app目錄平級(jí),所以導(dǎo)入文件目錄可能有不一致

cmake_minimum_required(VERSION 3.4.1)

add_library(compress

SHARED

src/main/cpp/compress_image.cpp)

find_library(log-lib log)

add_library(libjpeg

SHARED

IMPORTED)

set_target_properties(libjpeg

PROPERTIES

IMPORTED_LOCATION

${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/armeabi/libjpeg.so)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/main/cpp/jpeg)

target_link_libraries(compress

libjpeg

jnigraphics

${log-lib})

注意:如果你的目錄寫正確了,你按著ctrl鼠標(biāo)可以點(diǎn)過去。一定要導(dǎo)入頭文件,不然可能報(bào)找不到j(luò)peg方法

5、gradle文件配置

defaultConfig {

applicationId "com.xf.imageselector"

minSdkVersion 21

targetSdkVersion 29

versionCode 1

versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

externalNativeBuild {

cmake {

cppFlags "-fexceptions", "-frtti"//-std=c++11

abiFilters "armeabi"

}

}

ndk {

abiFilters 'armeabi'

}

}

三、編寫文件

#include

#include

#include "com_xf_imageselector_utils_ImageUtil.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include

//log打印

#define LOG_TAG "wxf"

#define LOGW(...) __android_log_write(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

#define true 1

#define false 0

//把頭文件用c包裹起來,允許混合編譯,不然會(huì)報(bào)錯(cuò)

extern "C" {

#include "jpeg/jpeglib.h"

#include "jpeg/jconfig.h"

#include "jpeg/jconfigint.h"

#include "jpeg/jerror.h"

#include "jpeg/jmorecfg.h"

}

typedef uint8_t BYTE;

char *error;

struct my_error_mgr {

struct jpeg_error_mgr pub;

jmp_buf setjmp_buffer;

};

typedef struct my_error_mgr *my_error_ptr;

METHODDEF(void)

my_error_exit(j_common_ptr cinfo) {

my_error_ptr myerr = (my_error_ptr) cinfo->err;

(*cinfo->err->output_message)(cinfo);

error = (char *) myerr->pub.jpeg_message_table[myerr->pub.msg_code];

LOGI("jpeg_message_table[%d]:%s", myerr->pub.msg_code,

myerr->pub.jpeg_message_table[myerr->pub.msg_code]);

longjmp(myerr->setjmp_buffer, 1);

}

int

generateJPEG(BYTE *data, int w, int h, int quality, const char *outfileName, jboolean optimize) {

//結(jié)構(gòu)體相當(dāng)于java的類

struct jpeg_compress_struct jcs;

// 當(dāng)讀完整個(gè)文件的時(shí)候回回調(diào)

struct my_error_mgr jem;

jcs.err = jpeg_std_error(&jem.pub);

jem.pub.error_exit = my_error_exit;

//setjmp是一個(gè)系統(tǒng)級(jí)函數(shù),是一個(gè)回調(diào)

if (setjmp(jem.setjmp_buffer)) {

return 0;

}

//初始化jsc結(jié)構(gòu)體

jpeg_create_compress(&jcs);

//打開輸出文件 wb可寫 rb可讀

FILE *f = fopen(outfileName, "wb");

if (f == NULL) {

return 0;

}

//設(shè)置結(jié)構(gòu)體的文件路徑,以及寬高

jpeg_stdio_dest(&jcs, f);

jcs.image_width = w;

jcs.image_height = h;

// TRUE=arithmetic coding, FALSE=Huffman

jcs.arith_code = false;

int nComponent = 3;

// 顏色的組成rgb,三個(gè) of color components in input image

jcs.input_components = nComponent;

// 設(shè)置顏色空間為rgb

jcs.in_color_space = JCS_RGB;

jpeg_set_defaults(&jcs);

// 是否采用哈夫曼

jcs.optimize_coding = optimize;

//設(shè)置質(zhì)量

jpeg_set_quality(&jcs, quality, true);

// 開始?jí)嚎s

jpeg_start_compress(&jcs, TRUE);

JSAMPROW row_pointer[1];

int row_stride;

row_stride = jcs.image_width * nComponent;

while (jcs.next_scanline < jcs.image_height) {

//得到一行的首地址

row_pointer[0] = &data[jcs.next_scanline * row_stride];

jpeg_write_scanlines(&jcs, row_pointer, 1);

}

// 壓縮結(jié)束

jpeg_finish_compress(&jcs);

// 銷毀回收內(nèi)存

jpeg_destroy_compress(&jcs);

// 關(guān)閉文件

fclose(f);

return 1;

}

extern "C" jint Java_com_xf_imageselector_utils_ImageUtil_compressBitmap

(JNIEnv *env,

jobject thiz, jobject bitmap, jint quality, jstring fileNameStr) {

//解析RGB

//1.1獲取bitmap信息,w、h,format Android的Native要有了解

AndroidBitmapInfo info;

// java你調(diào)用完方法,往往返回的是對象,而c是參數(shù)

AndroidBitmap_getInfo(env, bitmap, &info);

// 從地址獲取值

int bitmap_height = info.height;

int bitmap_width = info.width;

int bitmap_format = info.format;

if (bitmap_format != ANDROID_BITMAP_FORMAT_RGBA_8888) {

//argb

return -1;

}

LOGI("bitmap_height = %d,bitmap_width = %d,", bitmap_height, bitmap_width);

//1.2 把bitmap解析到數(shù)組中,數(shù)組保存的是rgb->YCbCr

//1.2.1 鎖定畫布

BYTE *pixel_color;

AndroidBitmap_lockPixels(env, bitmap, (void **) &pixel_color);

// 1.2.2解析數(shù)據(jù),定義一些變量

BYTE *data;

BYTE r, g, b;

//申請一塊內(nèi)存=寬*高*3

data = (BYTE *) malloc(bitmap_width * bitmap_height * 3);

// 數(shù)組指針指向的是數(shù)組首地址,因?yàn)檫@塊內(nèi)存需要釋放,所以先保存一下

BYTE *tempData;

tempData = data;

//一個(gè)一個(gè)像素保存到data

int i = 0;

int j = 0;

int color;

for (int i = 0; i < bitmap_height; ++i) {

for (int j = 0; j < bitmap_width; ++j) {

//獲取二維數(shù)組的每一個(gè)像素信息的首地址

color = *((int *) pixel_color);

// 取出RGB

r = ((color & 0x00FF0000) >> 16);

g = ((color & 0x0000FF00) >> 8);

b = (color & 0x000000FF);

//保存到data中

*data = b;

*(data + 1) = g;

*(data + 2) = r;

data = data + 3;

// 一個(gè)像素點(diǎn)包括argb四個(gè)值,每+4下就是取下一個(gè)像素點(diǎn)

pixel_color += 4;

}

}

//1.2.3解鎖畫布

AndroidBitmap_unlockPixels(env, bitmap);

// 1.2.4 還差一個(gè)參數(shù),jstring-》char*

char *file_name = (char *) env->GetStringUTFChars(fileNameStr, NULL);

LOGI("file_name = %s", file_name);

// 2、調(diào)用第三方提供好的方法,賦值

int result = generateJPEG(tempData, bitmap_width, bitmap_height, quality, file_name, true);

// 3、回收內(nèi)存

free(tempData);

env->ReleaseStringUTFChars(fileNameStr, file_name);

// 釋放bitmap,調(diào)用bitmap的Recycler

//3.2獲取對象的class

jclass obj_clazz = env->GetObjectClass(bitmap);

// 3.3 通過class獲取方法的id

jmethodID method_id = env->GetMethodID(obj_clazz, "recycle", "()V");

//3.4調(diào)用方法釋放bitmap

env->CallVoidMethod(bitmap, method_id);

LOGI("result = %d", result);

// 4、返回結(jié)果

if (result == 0) {

return -1;

}

return 1;

}

注意:頭文件不需做任何改動(dòng),直接引入就好

四、測試,生成的so在build的cmake文件夾下可以找到

源圖片1.13M壓縮完只有300k左右,我的壓縮比是95,圖片也沒有失真

我的項(xiàng)目源碼我會(huì)放在資源中,名字turbolibjpeg

我嘗試用過 libturbojpeg.so,并引入了turbojpeg.h,但還是找不到j(luò)peg的方法,所以之能引入libjpeg.so

本文地址:https://blog.csdn.net/wanxiaofan/article/details/107961108

總結(jié)

以上是生活随笔為你收集整理的android使用的图片压缩格式,Android 之使用libjpeg压缩图片的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美视频在线一区 | www.-级毛片线天内射视视 | 国产亚洲欧美一区二区 | 日韩精品卡通动漫网站 | 黄频在线看 | 日韩中文欧美 | 激情毛片视频 | 中文字幕在线不卡视频 | 456亚洲影视| 亚洲a一区 | 午夜一区不卡 | 蜜臀av一区二区 | 欧美久久久一区二区三区 | 欧美精品一二三 | 天天干,天天爽 | 91久久国产综合久久 | 91精品国产综合久久精品图片 | xxxwww国产| 亚洲无码久久久久久久 | 国产精品亚洲第一 | 色天天色 | 色无极亚洲色图 | 成年女人18级毛片毛片免费 | 美女国产网站 | 天天干天天谢 | 国产jk精品白丝av在线观看 | 天堂中文字幕免费一区 | 国产操女人| 日本一道本在线 | 男女爱爱网站 | 伊人色图 | 欧美妞干网| 尤物视频在线观看视频 | 久久久久亚洲av片无码下载蜜桃 | 四虎av影视 | 欧美成人三级精品 | 成人一区av| 色人阁网站 | 欧美在线观看免费高清 | 性感美女一区二区三区 | 天堂av日韩 | 毛片一区 | 少妇太紧太爽又黄又硬又爽小说 | 天天插天天插 | 日韩天堂在线观看 | 国产精品美女久久久久图片 | 欧美日韩人妻一区二区 | 国产伦理av | 五月天婷婷爱 | 日韩亚洲国产欧美 | 久久精品一区二区三区四区 | 91视频h| 中文视频在线观看 | 影音先锋久久久久av综合网成人 | 欧美 日韩 综合 | 亚洲欧美激情精品一区二区 | av黄色免费网站 | 少妇久久久久久久 | 男人的天堂免费视频 | 台湾少妇xxxx做受 | 日本a级网站 | 亚洲区在线 | 91麻豆国产在线观看 | 国产一二三在线观看 | 91精品国产成人 | 制服丝袜天堂 | 理论片中文字幕 | 欧美日韩人妻精品一区二区三区 | 国产视频第一页 | 亚洲激情视频网站 | 天堂va蜜桃一区二区三区漫画版 | 成人v| 亚洲色图国产精品 | 欧美老女人xx | 中文字幕一区二区三区精彩视频 | 亚洲国产无线乱码在线观看 | 国产性生活一级片 | 永久免费看片在线播放 | 欧美日韩一区二区三区四区 | 日韩一区二区三区网站 | 日韩av综合在线 | 亚日韩在线 | 三级做爰在线观看视频 | 免费黄色av网址 | 青春草久久 | 艳母在线视频 | 新红楼梦2005锦江版高清在线观看 | 在线观看的黄网 | 19禁大尺度做爰无遮挡电影 | 青青草在线免费视频 | 久久成人乱码欧美精品一区二区 | 女人舌吻男人茎视频 | 91色交 | 亚洲美女www午夜 | 波多野结衣在线观看一区二区 | 性大毛片视频 | 精品一二三四区 | 中文字幕在线观看一区二区 | 乱淫的女高中暑假调教h |