文章目录

  • 概述
  • 需求分析
  • 各种压缩方式
  • libjepg-turbo+jnigraphics
    • 介绍
    • 编译
    • 使用
  • 引用文章

概述

之前在网络上搜索Android图片压缩,能看到各种各样的关于图片压缩的文章,本没有必要再写一篇,但是最近的一个需求真是折腾了我很久,本来以为很简单的事情,愣是搞了好几天。这里记录下我完成的整个过程,作为一个笔记供以后查阅。如果读友觉得有帮助,就?下

需求分析

需求(额呵,这个肯定不是客户的需求):在即时通讯发消息的场景中,需要发送的图片保持清晰度的同时压缩一定的比例,最好不要超过1M。

衍生需求(一看就是后台小哥的臆想):上传到服务器的图片要适当的压缩,不然服务器撑不住。

附加需求:(无力吐槽)最好能做个sdk供调用

分析下:就是个图片压缩嘛,简单


private Bitmap compressImage(Bitmap image) {ByteArrayOutputStream baos = new ByteArrayOutputStream();image.compress(Bitmap.CompressFormat.JPEG, 100, baos);int options = 100;//循环判断如果压缩后图片是否大于100kb,大于继续压缩while (baos.toByteArray().length / 1024 > 100) {baos.reset();image.compress(Bitmap.CompressFormat.JPEG, options, baos);//每次都减少10options -= 10;}ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());return BitmapFactory.decodeStream(isBm, null, null);}

试了试,好像不行,图片压缩了之后会失真,而且用起来不是那么顺手

上述代码中Bitmap.CompressFormat.JPEG可以更换为CompressFormat.PNG和CompressFormat.WEBP

PNG 格式是无损的,它无法再进行质量压缩,options 这个参数就没有作用了,会被忽略,图片并不会缩小
CompressFormat.WEBP ,这个格式是 google 推出的图片格式,它会比 JPEG 更加省空间,但是IOS好像兼容有些问题,还是JPEG靠谱

到网上搜搜,我的天,各种图片压缩的文章,看得的我眼花缭乱。

这里放个原图,然后继续分析

原图大小:116 KB

各种压缩方式

  1. 质量压缩

  2. 采样率压缩

  3. 按比例大小压缩

libjepg-turbo+jnigraphics

介绍

翻译一下官网的描述

libjpeg-turbo是一种jpeg图像编解码器,它使用simd指令(mmx、sse2、avx2、neon、altivec)加速x86、x86-64、ARM和PowerPC系统上的Baseline JPEG(标准型)压缩和解压缩,以及x86和x86-64系统上的渐进式progressive JPEG(渐进式)压缩。在这些系统中,libjpeg-turbo的速度通常是libjpeg的2-6倍,其他的都是相同的。在其他类型的系统上,libjpeg-turbo由于其高度优化的哈夫曼编码例程,仍然可以在很大程度上超过libjpeg 。在许多情况下,libjpeg-turbo的性能与专有的高速JPEG编解码器的性能相当。

libjpeg-turbo最初基于libjpeg/simd,这是 Miyasaka Masaru 开发的libjpeg v6b的MMX(多媒体扩展)加速衍生产品。
2009年,在TigerVnc和VirtualGL项目中对编解码器进行了大量改进,2010年初,libjpeg turbo被拆分成了一个独立的项目,其目标是为更广泛的用户和开发人员提供高速的jpeg压缩/解压缩技术。

编译

github编译教程:https://github.com/libjpeg-turbo/libjpeg-turbo/blob/master/BUILDING.md

刚开始我也是用linux编译,使用像下面的编译脚本可以编译成功

#!/bin/bash
NDK_PATH=/home/shuai/Android/android-ndk-r13
TOOLCHAIN=gcc
ANDROID_VERSION=17
cd libjpeg-turbo-2.0.2cmake -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 \-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=android/arm-v7a \-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=android/arm-v7a \make

后来发现,可以直接在android studio中直接编译通过,真是开心的像廋了10斤一样

新建带jni的Android项目,将libjpeg-turbo整个项目直接拷贝到jni目录下,然后在CmakeLists.txt中加入这个

cmake_minimum_required(VERSION 3.4.1)
add_library(native-jpegSHAREDnative-jpeg.cpp)
# 编译子项目(源码路径)
ADD_SUBDIRECTORY(libjpeg-turbo-2.0.2)find_library(log-liblog)
target_link_libraries(native-jpeg${log-lib})

build之后妥妥可以拿到动态和静态库

同样的方法,我又编译了libpng的代码

具体请参考:https://github.com/ddssingsong/NdkImage,下载项目直接运行,里面还有使用demo

使用

打造一个图片压缩框架

// 压缩bitmap
extern "C"
JNIEXPORT void JNICALL
Java_com_dds_ndkimage_NativeImageUtils_compressBitmap(JNIEnv *env, jclass type, jobject                                                        bitmap,jint q,jstring p_) {if (bitmap == NULL) {LOGE("bitmap is null");return;}const char *path = env->GetStringUTFChars(p_, 0);AndroidBitmapInfo info;// 获取bitmap中信息AndroidBitmap_getInfo(env, bitmap, &info);// 获取图片中的像素信息uint8_t *pixels;AndroidBitmap_lockPixels(env, bitmap, (void **) (&pixels));int w = info.width;int h = info.height;int color;//data中可以存放图片的所有内容uint8_t *data = (uint8_t *) malloc((size_t) (w * h * 3));uint8_t *temp = data;uint8_t r, g, b;//bytefor (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {color = *(int *) pixels;//取出rgbr = (uint8_t) ((color >> 16) & 0xFF);//    #00rrggbb  16  0000rr   8  00rrggg = (uint8_t) ((color >> 8) & 0xFF);b = (uint8_t) (color & 0xFF);*data = b;*(data + 1) = g;*(data + 2) = r;data += 3;//指针跳过4个字节pixels += 4;}}//把得到的新的图片的信息存入一个新文件 中jpegcompress::write_JPEG_file(temp, w, h, q, path);//释放内存free(temp);AndroidBitmap_unlockPixels(env, bitmap);env->ReleaseStringUTFChars(p_, path);
}
void jpegcompress::write_JPEG_file(uint8_t *data, int w, int h, jint q, const char *path) {//3.1、创建jpeg压缩对象jpeg_compress_struct jcs;//错误回调jpeg_error_mgr error;jcs.err = jpeg_std_error(&error);//创建压缩对象jpeg_create_compress(&jcs);//3.2、指定存储文件  write binaryFILE *f = fopen(path, "wb");jpeg_stdio_dest(&jcs, f);//3.3、设置压缩参数jcs.image_width = (JDIMENSION) (w);jcs.image_height = (JDIMENSION) h;//bgrjcs.input_components = 3;jcs.in_color_space = JCS_RGB;jpeg_set_defaults(&jcs);//开启哈夫曼功能jcs.optimize_coding = true;jpeg_set_quality(&jcs, q, 1);//4 开始压缩jpeg_start_compress(&jcs, 1);// 5 循环写入每一行数据int row_stride = w * 3;//一行的字节数JSAMPROW row[1];while (jcs.next_scanline < jcs.image_height) {//取一行数据uint8_t *pixels = data + jcs.next_scanline * row_stride;row[0] = pixels;jpeg_write_scanlines(&jcs, row, 1);}//6 压缩完成jpeg_finish_compress(&jcs);//7 释放jpeg对象fclose(f);jpeg_destroy_compress(&jcs);
}

详见:https://github.com/ddssingsong/NdkImage

引用文章

Android 中图片压缩分析https://www.cnblogs.com/qcloud1001/p/7827133.html)https://www.cnblogs.com/qcloud1001/p/7827133.html

Android性能优化——图片压缩的终极选择libjpeg-turbo相关推荐

  1. 性能优化——图片压缩、加载和格式选择

    本文首发于政采云前端团队博客:性能优化--图片压缩.加载和格式选择 https://www.zoo.team/article/images-compress 前言 相信大家都听说过 "258 ...

  2. android性能优化透明,Android性能优化-图片篇

    (1)drawable目录详解(mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi) 1.1.图片在各个目录中要如何存放?(必须理解) android的drawable目录有: drawab ...

  3. [Android 性能优化系列]内存之终极篇--降低你的内存消耗

    原文地址:http://developer.android.com/training/articles/memory.html 拒绝在 Bitmap 上浪费你的内存 当你加载一张 Bitmap 的时候 ...

  4. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

    文章目录 一. 哈夫曼编码开关 二. 哈夫曼编码原理 三. libjpeg-turbo 函数库 四. libjpeg-turbo 函数库下载 [Android 内存优化]图片文件压缩 ( Androi ...

  5. Android 性能优化之——高性能使用图片全面总结

    Android 性能优化之--高性能使用图片全面总结 移动设备的系统资源有限,所以应用应该尽可能的降低内存的使用.在应用运行过程中,Bitmap (图片)往往是内存占用最大的一个部分,Bitmap 图 ...

  6. Android 性能优化——之图片的优化

    Android 性能优化--之图片的优化 在Android性能优化中,我们会发现占内存最大的和对性能影响最大的往往是图片资源,其次是控件资源.相对来说,其他的资源的影响会小一点.这里我就先对图片资源的 ...

  7. 【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 )

    文章目录 一. 图片质量压缩方法 二. Skia 二维图形库 三. libjpeg.libpng 函数库引入 在博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供的 ...

  8. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )

    文章目录 一. 图片质量压缩方法 二. 查找对应的 Native 方法源码 三. 分析 Bitmap.cpp 中动态注册 Native 方法 在博客 [Android 内存优化]图片文件压缩 ( An ...

  9. Android 性能优化

    为什么80%的码农都做不了架构师?>>>    原文作者:鸿洋 原文地址:点我跳转原文 一般情况下,我们谈性能优化基本上会从以下几个方面: App启动速度优化 UI流畅度优化 内存优 ...

最新文章

  1. poj3508(高精度模拟减法)
  2. 2020 蚂蚁面试指南!
  3. Pet Shop4解密配置文件
  4. 如何抓取html请求,请求获取网页的response,获取网页的html 怎么那么慢
  5. Spring框架----Spring框架的基本概念
  6. 华为 MateBook 笔记本 Linux 版正式开售
  7. idea配置jfinal_JFinal 开箱评测,这次我是认真的
  8. Linux安装yum教程
  9. ftp工具哪个好,推荐8个超级好用而且免费的ftp工具,支持中文版windows系统的。
  10. SecureCRT免费安装教程
  11. 计算机网络-域名与IP地址详解
  12. java delete()_Java File delete()用法及代码示例
  13. 程序员找工作-----人力资源面试题
  14. java/kafka的使用,生产者 ,发布/发送消息,自定义数据/json数据,实战。
  15. Swing中如何实现二级联动下拉列表
  16. 多模态情感识别数据集和模型(下载地址+最新综述2021.8)
  17. win10图标变白纸_同是Office365,为什么你的软件图标还是旧版的?
  18. 《zw版·Halcon-delphi系列原创教程》 邮票艺术品自动分类脚本
  19. Android 11.0 根据包名授予WRITE_SETTINGS权限
  20. 窄告:超越搜索引擎关键词模式的精准营销

热门文章

  1. C++定义指针数组,数组指针,指针数据
  2. python库01—scipy.linalg(线性代数)
  3. 算法导论课后题和思考题 第3章
  4. 通过神经网络实现线性回归模型预测水泥强度
  5. diy写字机器人_自己动手做一个写字机器人
  6. Hadoop学习之MapReduce分布式计算框架
  7. 前端网格布局grid
  8. 修改Github仓库中项目语言类型
  9. 指针地址左移右移的代码实例
  10. 马云的SNS梦美好却残酷