<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                文檔處理控制欄: * [x] 選題收集: * [ ] 初稿整理: * [ ] 補充校對: * [ ] 入庫存檔: --- 原文鏈接:[Android圖片壓縮的幾種方案](https://juejin.im/entry/5a41c473f265da430f3258a7) --- 原文:http://blog.csdn.net/qq_30379689/article/details/78884167 ## 效果演示 直接先給大家對比幾種圖片壓縮的效果 ![](https://user-gold-cdn.xitu.io/2017/12/26/16090e779a536711?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) ## 質量壓縮 質量壓縮:根據傳遞進去的質量大小,采用系統自帶的壓縮算法,將圖片壓縮成JPEG格式 ~~~ /** * 質量壓縮 * * @param bitmap * @param quality * @param file */ public static void compressQuality(Bitmap bitmap, int quality, File file) { ? ?ByteArrayOutputStream baos = new ByteArrayOutputStream(); ? ?bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos); ? ?try { ? ? ? ?FileOutputStream fos = new FileOutputStream(file); ? ? ? ?fos.write(baos.toByteArray()); ? ? ? ?fos.flush(); ? ? ? ?fos.close(); ? ?} catch (Exception e) { ? ? ? ?e.printStackTrace(); ? ?} } ~~~ ## 尺寸壓縮 尺寸壓縮:根據圖片的縮放比例進行等比大小的縮小尺寸,從而達到壓縮的效果 ~~~ /** * 尺寸壓縮 * * @param bitmap * @param file */ public static void compressSize(Bitmap bitmap, File file) { ? ?int ratio = 8;//尺寸壓縮比例 ? ?Bitmap result = Bitmap.createBitmap(bitmap.getWidth() / ratio, bitmap.getHeight() / ratio, Bitmap.Config.ARGB_8888); ? ?Canvas canvas = new Canvas(result); ? ?Rect rect = new Rect(0, 0, bitmap.getWidth() / ratio, bitmap.getHeight() / ratio); ? ?canvas.drawBitmap(bitmap, null, rect, null); ? ?compressQuality(result, 100, file); } ~~~ ## 采樣率壓縮 采樣率壓縮:根據圖片的采樣率大小進行壓縮 ~~~ /** * 采樣率壓縮 * * @param filePath * @param file */ public static void compressSample(String filePath, File file) { ? ?int inSampleSize = 8;//采樣率設置 ? ?BitmapFactory.Options options = new BitmapFactory.Options(); ? ?options.inJustDecodeBounds = false; ? ?options.inSampleSize = inSampleSize; ? ?Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); ? ?compressQuality(bitmap, 100, file); } ~~~ ## LibJpeg壓縮 LibJpeg壓縮:通過Ndk調用LibJpeg庫進行壓縮,保留原有的像素,清晰度高 ### 編譯LibJpeg 1、從Github上可以下載已經寫好編譯腳本的項目:https://github.com/Zelex/libjpeg-turbo-android ,并將其上傳到Linux服務器的某個目錄 ![](data:image/svg+xml;utf8,) 2、授予整個目錄權限 ~~~ chmod 777 -R libjpeg-turbo-android-master ~~~ 3、進入libjpeg目錄,使用下面指令進行編譯,前提是你的服務器已經搭建了ndk-build和配置了環境變量 ~~~ ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_ABI=armeabi-v7a obj/local/armeabi-v7a/libjpeg.a LOCAL_ARM_MODE=arm LOCAL_ARM_NEON=true ARCH_ARM_HAVE_NEON=true ~~~ 4、接著編譯成功后,會在 obj/local 目錄下生成我們需要的 libjpeg.a ![](https://user-gold-cdn.xitu.io/2017/12/26/16090e7799d328cb?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) ### 創建工程 1、創建一個新的項目,勾選包含C++,勾選C++11和C++的依賴庫 ![](https://user-gold-cdn.xitu.io/2017/12/26/16090e779a301188?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) 2、將生成的 libjpeg.a和頭文件導入到我們的項目中 ![](https://user-gold-cdn.xitu.io/2017/12/26/16090e77bf59d0ca?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) 3、配置gradle ~~~ android { ? ?compileSdkVersion 25 ? ?buildToolsVersion "25.0.3" ? ?defaultConfig { ? ? ? ?applicationId "com.handsome.bitmapcompress" ? ? ? ?minSdkVersion 16 ? ? ? ?targetSdkVersion 25 ? ? ? ?versionCode 1 ? ? ? ?versionName "1.0" ? ? ? ?testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ? ? ? ?externalNativeBuild { ? ? ? ? ? ?cmake { ? ? ? ? ? ? ? ?cppFlags "-std=c++11 -frtti -fexceptions" ? ? ? ? ? ? ? ?//支持的CPU類型 ? ? ? ? ? ? ? ?abiFilters "armeabi", "armeabi-v7a" ? ? ? ? ? ?} ? ? ? ?} ? ?} ? ?buildTypes { ? ? ? ?release { ? ? ? ? ? ?minifyEnabled false ? ? ? ? ? ?proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' ? ? ? ?} ? ?} ? ?//修改Libs庫的路徑 ? ?sourceSets.main { ? ? ? ?jniLibs.srcDirs = ['libs'] ? ? ? ?jni.srcDirs = [] ? ?} ? ?externalNativeBuild { ? ? ? ?cmake { ? ? ? ? ? ?path "CMakeLists.txt" ? ? ? ?} ? ?} } ~~~ 4、配置CMake ~~~ cmake_minimum_required(VERSION 3.4.1) include_directories(./libs/jpeg) link_directories(./libs/${ANDROID_ABI}) find_library(log-lib ? ? ? ? ? ? log) find_library(android-lib ? ? ? ? ? ? android) find_library(bitmap-lib ? ? ? ? ? ? jnigraphics) add_library( # Sets the name of the library. ? ? ? ? ? ? native-lib ? ? ? ? ? ? # Sets the library as a shared library. ? ? ? ? ? ? SHARED ? ? ? ? ? ? # Provides a relative path to your source file(s). ? ? ? ? ? ? src/main/cpp/native-lib.cpp ) target_link_libraries( native-lib ? ? ? ? ? ? ? ? ? ? ? ${log-lib} ? ? ? ? ? ? ? ? ? ? ? ${android-lib} ? ? ? ? ? ? ? ? ? ? ? ${bitmap-lib} ? ? ? ? ? ? ? ? ? ? ? jpeg ) ~~~ 5、聲明權限 ~~~ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ~~~ ### 使用LibJpeg 1、啟動選擇文件的Intent ~~~ /** * 選擇文件 */public void selectFile() { ? ? ? ?if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { ? ? ? ?startActivityForResult(new Intent(Intent.ACTION_GET_CONTENT).setType("image/*"), REQUEST_PICK_IMAGE); ? ?} else { ? ? ? ?Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); ? ? ? ?intent.addCategory(Intent.CATEGORY_OPENABLE); ? ? ? ?intent.setType("image/*"); ? ? ? ?startActivityForResult(intent, REQUEST_KITKAT_PICK_IMAGE); ? ?} } ~~~ 2、對返回的結果進行壓縮 ~~~ /** * 返回結果 * * @param requestCode * @param resultCode * @param data */@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { ? ? ? ?super.onActivityResult(requestCode, resultCode, data); ? ? ? ?if (resultCode == RESULT_OK) { ? ? ? ? ? ? ? ?switch (requestCode) { ? ? ? ? ? ? ? ? ? ? ? ?case REQUEST_PICK_IMAGE: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (data != null) { ? ? ? ? ? ? ? ? ? ?Uri uri = data.getData(); ? ? ? ? ? ? ? ? ? ?compressImage(uri); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; ? ? ? ? ? ? ? ? ? ? ? ?case REQUEST_KITKAT_PICK_IMAGE: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (data != null) { ? ? ? ? ? ? ? ? ? ?Uri uri = ensureUriPermission(this, data); ? ? ? ? ? ? ? ? ? ?compressImage(uri); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; ? ? ? ?} ? ?} }/** * 壓縮圖片 * 注意:記得手動開啟權限 * * @param uri */public void compressImage(Uri uri) { ? ? ? ?try { ? ? ? ?File saveFile = new File(getExternalCacheDir(), "NDK壓縮.jpg"); ? ? ? ?Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri); ? ? ? ? ? ? ? ?int code = CompressUtils.compressBitmap(bitmap, 20, saveFile.getAbsolutePath().getBytes(), true); ? ? ? ?File saveFile1 = new File(getExternalCacheDir(), "質量壓縮.jpg"); ? ? ? ?CompressUtils.compressQuality(bitmap, 20, saveFile1); ? ? ? ?File saveFile2 = new File(getExternalCacheDir(), "尺寸壓縮.jpg"); ? ? ? ?CompressUtils.compressSize(bitmap, saveFile2); ? ? ? ?//采樣率比較特殊,需要傳遞文件的目錄,這里采用直接指定目錄的文件 ? ? ? ?File saveFile3 = new File(getExternalCacheDir(), "采樣率壓縮.jpg"); ? ? ? ?File LocalFile = new File("/storage/emulated/0/DCIM/Camera/IMG_20171216_171956.jpg"); ? ? ? ? ? ? ? ?if (LocalFile.exists()) { ? ? ? ? ? ?CompressUtils.compressSample(LocalFile.getAbsolutePath(), saveFile3); ? ? ? ?} ? ?} catch (IOException e) { ? ? ? ?e.printStackTrace(); ? ?} } ~~~ 3、加載本地庫和聲明LibJpeg壓縮方法 ~~~ public class CompressUtils { ? ? ? ?static { ? ? ? ?System.loadLibrary("native-lib"); ? ?} ? ?public static native int compressBitmap(Bitmap bitmap, int quality, byte[] fileNameBytes, boolean optimize); } ~~~ 4、編寫LibJpeg的本地文件 * 提取圖片的ARGB通量的RGB通量 * 采用LibJpeg的API進行壓縮 * 將數據寫入到文件中 ~~~ #include <jni.h>#include <string>#include <android/bitmap.h>#include <android/log.h>#include <setjmp.h>extern "C" { ? ?#include "jpeglib.h" ? ?#include "cdjpeg.h"}#define LOG_TAG "jni"#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)typedef uint8_t BYTE;typedef struct my_error_mgr *my_error_ptr;struct my_error_mgr { ? ? ? ?struct jpeg_error_mgr pub; ? ?jmp_buf setjmp_buffer; }; METHODDEF(void) my_error_exit(j_common_ptr cinfo) { ? ?my_error_ptr myerr = (my_error_ptr) cinfo->err; ? ?(*cinfo->err->output_message)(cinfo); ? ?LOGE("jpeg_message_table[%d]:%s", myerr->pub.msg_code, ? ? ? ? myerr->pub.jpeg_message_table[myerr->pub.msg_code]); ? ?longjmp(myerr->setjmp_buffer, 1); } ? ?/** * 采用Libjpeg壓縮 * @param data * @param w * @param h * @param quality * @param outfilename * @param optimize * @return */int generateJPEG(BYTE *data, int w, int h, int quality, const char *outfilename, jboolean optimize) { ? ?//jpeg的結構體,保存的比如寬、高、位深、圖片格式等信息 ? ?struct jpeg_compress_struct jcs; ? ?//當讀完整個文件的時候就會回調my_error_exit ? ?struct my_error_mgr jem; ? ?jcs.err = jpeg_std_error(&jem.pub); ? ?jem.pub.error_exit = my_error_exit; ? ? ? ?if (setjmp(jem.setjmp_buffer)) { ? ? ? ? ? ? ? ?return 0; ? ?} ? ?//初始化jsc結構體 ? ?jpeg_create_compress(&jcs); ? ?//打開輸出文件 ? ?FILE* f = fopen(outfilename, "wb"); ? ? ? ?if (f == NULL) { ? ? ? ? ? ? ? ?return 0; ? ?} ? ?//設置結構體的文件路徑 ? ?jpeg_stdio_dest(&jcs, f); ? ?jcs.image_width = w;//設置寬高 ? ?jcs.image_height = h; ? ?//設置哈夫曼編碼,TRUE=arithmetic coding, FALSE=Huffman ? ?if (optimize) { ? ? ? ?jcs.arith_code = false; ? ?} else { ? ? ? ?jcs.arith_code = true; ? ?} ? ?//顏色通道數量 ? ?int nComponent = 3; ? ?jcs.input_components = nComponent; ? ?//設置結構體的顏色空間為RGB ? ?jcs.in_color_space = JCS_RGB; ? ?//全部設置默認參數 ? ?jpeg_set_defaults(&jcs); ? ?//是否采用哈弗曼表數據計算 品質相差5-10倍 ? ?jcs.optimize_coding = optimize; ? ?//設置質量 ? ?jpeg_set_quality(&jcs, quality, true); ? ?//開始壓縮,(是否寫入全部像素) ? ?jpeg_start_compress(&jcs, TRUE); ? ?JSAMPROW row_pointer[1]; ? ? ?int row_stride; ? ?//一行的RGB數量 ? ?row_stride = jcs.image_width * nComponent; ? ?//一行一行遍歷 ? ?while (jcs.next_scanline < jcs.image_height) { ? ? ? ?//得到一行的首地址 ? ? ? ?row_pointer[0] = &data[jcs.next_scanline * row_stride]; ? ? ? ?//此方法會將jcs.next_scanline加1 ? ? ? ?jpeg_write_scanlines(&jcs, row_pointer, 1);//row_pointer就是一行的首地址,1:寫入的行數 ? ?} ? ?jpeg_finish_compress(&jcs); ? ?jpeg_destroy_compress(&jcs); ? ?fclose(f); ? ?return 1; }/** * byte數組轉C的字符串 */char *jstrinTostring(JNIEnv *env, jbyteArray barr) { ? ? ? ?char *rtn = NULL; ? ?jsize alen = env->GetArrayLength(barr); ? ?jbyte *ba = env->GetByteArrayElements(barr, 0); ? ? ? ?if (alen > 0) { ? ? ? ?rtn = (char *) malloc(alen + 1); ? ? ? ? ? ? ? ?memcpy(rtn, ba, alen); ? ? ? ?rtn[alen] = 0; ? ?} ? ?env->ReleaseByteArrayElements(barr, ba, 0); ? ? ? ?return rtn; } ? ?extern "C"JNIEXPORT jint JNICALL Java_com_handsome_bitmapcompress_CompressUtils_compressBitmap(JNIEnv *env, jclass type, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jobject bitmap, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jint quality, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jbyteArray fileNameBytes_, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?jboolean optimize) { ? ?//獲取Bitmap信息 ? ?AndroidBitmapInfo android_bitmap_info; ? ?AndroidBitmap_getInfo(env, bitmap, &android_bitmap_info); ? ?//獲取bitmap的 寬,高,format ? ?int w = android_bitmap_info.width; ? ? ? ?int h = android_bitmap_info.height; ? ? ? ?int format = android_bitmap_info.format; ? ? ? ?if (format != ANDROID_BITMAP_FORMAT_RGBA_8888) { ? ? ? ? ? ? ? ?return -1; ? ?} ? ?//存儲ARGB所有像素點 ? ?BYTE *pixelsColor; ? ?//1、讀取Bitmap所有像素信息 ? ?AndroidBitmap_lockPixels(env, bitmap, (void **) &pixelsColor); ? ?//2、解析每個像素,去除A通量,取出RGB通量 ? ?int i = 0, j = 0; ? ?BYTE a, r, g, b; ? ?//存儲RGB所有像素點 ? ?BYTE *data; ? ?data = (BYTE *) malloc(w * h * 3); ? ?//存儲RGB首地址 ? ?BYTE *tempData = data; ? ? ? ?int color; ? ? ? ?for (i = 0; i < h; ++i) { ? ? ? ? ? ? ? ?for (j = 0; j < w; ++j) { ? ? ? ? ? ?//將8位通道轉成32位通道 ? ? ? ? ? ?color = *((int *) pixelsColor); ? ? ? ? ? ?//取值 ? ? ? ? ? ?a = ((color & 0xFF000000) >> 24); ? ? ? ? ? ?r = ((color & 0x00FF0000) >> 16); ? ? ? ? ? ?g = ((color & 0x0000FF00) >> 8); ? ? ? ? ? ?b = ((color & 0x000000FF)); ? ? ? ? ? ?//賦值 ? ? ? ? ? ?*data = b; ? ? ? ? ? ?*(data + 1) = g; ? ? ? ? ? ?*(data + 2) = r; ? ? ? ? ? ?//指針往后移 ? ? ? ? ? ?data += 3; ? ? ? ? ? ?pixelsColor += 4; ? ? ? ?} ? ?} ? ?//3、讀取像素點完畢 ? ?AndroidBitmap_unlockPixels(env, bitmap); ? ? ? ?char *fileName = jstrinTostring(env, fileNameBytes_); ? ?//4、采用Libjpeg進行壓縮 ? ?int resultCode = generateJPEG(tempData, w, h, quality, fileName, optimize); ? ? ? ?if (resultCode == 0) { ? ? ? ? ? ? ? ?return 0; ? ?} ? ? ? ?return 1; } ~~~ 需要跑一下以上幾種方案源碼的同學,可以訪問:https://github.com/AndroidHensen/BitmapCompress?獲取。 --- 參考文章 * [Android圖片壓縮的幾種方案](https://juejin.im/entry/5a41c473f265da430f3258a7)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看