本文主要介绍使用 CMAKE 编译 libjpeg-turbo 类库,本文相关代码请在GitHub-TurboJpegSample 查看。

libjpeg-turbo 附GitHub 地址,libjpeg-turbo 是个运用极其广泛的库,可以说,基本上电脑上手机上能见到的 JPEG 压缩的地方用的一般都是 libjpeg-turbo,本文只介绍使用了图片压缩的功能。

使用 Android 保存图片时,我们通常使用的是 Bitmap.compress() 方法,但是使用该方法时,就算 quality 设置为 100,图片质量还是会越来越模糊,颜色也会越来越绿~,至于为什么会这样,请看 知乎回答。 这个问题在贴吧上体现尤为明显,贴吧里面经常很多绿绿的图片就是因为大家保存下来上传上去,保存下来上传上去 … 导致质量越拉越低,我解压了 美图秀秀 和 in 的 apk 发现里面都引用了 libjpeg.so,所以这个应该是一个比较通用的解决方案。

我们对图片使用质量压缩时它的底层就是用 skia 引擎进行处理,如我们调用bitmap.compress(Bitmap.CompressFormat.JPEG...) 他实际会 使用一个libjpeg.so 的动态库进行编码压缩。android 在进行 jpeg 压缩编码的时候,考虑到了效率问题使用了定长编码方式进行编码(因为当时的手机性能都比较低),而 ios 使用了变长编码的算法——哈夫曼算法。而且 IOS 对 skia 引擎也做了优化,所以我们看到同样的图片在 ios 上压缩会好一点。

文档就整理到这里吧,其实上面说的都是看了一些博客的介绍然后进行了整理和记录,来清楚为什么我们需要自己来编译 so 实现图片压缩。

资源准备

我们需要下载源码编译出 libjpeg.so 来使用,clone 源代码。1git clone git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git -b linaro-android

重命名根目录 libjpeg-turbo 为 jni,进入 jni 目录,首先你应该配置好 ndk, 使用 ndk-build 命令进行编译。1

2

3

4mv libjpeg-turbo jni

ndk-build APP_ABI=armeabi-v7a,armeabi

编译完成之后我们就可以获取到 libjpeg.so,目录如下:1

2

3

4

5

6

7

8

9

10jni

libs

- armeabi

- libjpeg.so

- armeabi-v7a

- libjpeg.so

obj

- local

- armeabi

- armeabi-v7a

此时如果出现了以下异常:1

2Users/march/AndroidRes/sdk/ndk-bundle/build/core/build-binary.mk:702:

*** Android NDK: Aborting (set APP_ALLOW_MISSING_DEPS=true to allow missing dependencies) . Stop.

打开 build-binary.mk 添加 APP_ALLOW_MISSING_DEPS=true1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18ifdef undefined_libs

$(call __ndk_warning,Module $(LOCAL_MODULE) depends on undefined modules: $(undefined_libs))

# ndk-build didn't used to fail the build for a missing dependency. This

# seems to have always been the behavior, so there's a good chance that

# there are builds out there that depend on this behavior (as of right now,

# anything using libc++ on ARM has this problem because of libunwind).

#

# By default we will abort in this situation because this is so completely

# broken. A user may define APP_ALLOW_MISSING_DEPS to "true" in their

# Application.mk or on the command line to revert to the old, broken

# behavior.

APP_ALLOW_MISSING_DEPS=true # here

ifneq ($(APP_ALLOW_MISSING_DEPS),true)

$(call __ndk_error,Aborting (set APP_ALLOW_MISSING_DEPS=true to allow missing dependencies))

endif

endif

创建工程

使用 AndroidStudio 新建工程,勾选 support c++,生成的工程中会包含 CMakeLists.txt 文件,在下面的介绍中没有截图,对目录的说明如果不够清晰,请至 GitHub-TurboJpegSample 查看工程代码。

在 app 目录下新建文件夹 libjpeg,用来存放 so 文件和头文件,目录如下:1

2

3

4

5

6

7

8

9

10

11

12app

- libjpeg

- prebuilt

- armeabi

- libjpeg.so

- include

- 头文件

- src

- main

- cpp

- java

- res

编写 compress.h 和 compress.c,这个就是压缩的核心代码了,篇幅较长,但是这里就不贴了,详情请查看 项目的 cpp 目录,使用的算法是网上查找的,看起来资料介绍的都是这一种。

CMakeLists.txt1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31# 最低版本

cmake_minimum_required(VERSION 3.4.1)

#设置生成的 so 动态库最后输出的路径

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

# 初始化目录变量

set(libjpeg_dir ${CMAKE_SOURCE_DIR}/libjpeg)

set(INC_DIR ${libjpeg_dir}/include)

set(libjpeg_lib_dir ${libjpeg_dir}/prebuilt)

# 添加头文件目录

include_directories(${INC_DIR})

# 设置资源路径

set(SOURCE_FILES src/main/cpp/compress.c)

#

add_library(compress SHARED

${SOURCE_FILES})

find_library(log-lib log)

find_library(graphics jnigraphics)

add_library(libjpeg SHARED IMPORTED)

set_target_properties(libjpeg PROPERTIES IMPORTED_LOCATION ${libjpeg_lib_dir}/${ANDROID_ABI}/libjpeg.so)

target_link_libraries(compress libjpeg ${log-lib} ${graphics})

build.gradle

相比普通的 Android 工程,app/build.gradle 文件也有些许不同,我只编译了 armeabi 。1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39android {

compileSdkVersion 25

buildToolsVersion "25.0.3"

defaultConfig {

...

externalNativeBuild {

cmake {

abiFilters 'armeabi'

}

}

ndk {

//打包进APK的ABI类型

abiFilters 'armeabi'

}

}

externalNativeBuild {

cmake {

path "CMakeLists.txt"

}

}

sourceSets {

main {

java.srcDirs 'src/java'

jniLibs.srcDirs 'libs'

// jniLibs.srcDirs '../libjpeg/prebuilt', 'libs'

// 这里没有添加libjpeg.so这个动态库,也是可以执行的。

// 原因在于android本身使用了 libjpeg.so这个动态库,

// 这个库存放在/system/lib下,如果我们没有加入

// libjpeg.so的话,他会去/system/lib下加载这个动态库

// 如果android手机上没有 libjpeg.so这个动态库的话,

// 也可以使用: jniLibs.srcDirs '../libjpeg/prebuilt' 'libcd

// 将libjpeg.so加入到apk中

}

}

}

编写 java 调用1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18public class{

static {

System.loadLibrary("compress");

}

/**

* 使用native方法进行图片压缩。

* Bitmap的格式必须是ARGB_8888 {@link android.graphics.Bitmap.Config}。

*

* @param bitmap 图片数据

* @param quality 压缩质量

* @param dstFile 压缩后存放的路径

* @param optimize 是否使用哈夫曼算法

* @return 结果

*/

public static native int compress(Bitmap bitmap, int quality, String dstFile, boolean optimize);

}

运行之后就可以测试结果,同时在 配置的 jniLibs 目录中也会生成 so 文件,在别的地方使用同包名下的 TurboJpegUtils 类也可以调用了。

总结

测试对比结果,确实比 Andorid 原生的算法压缩图片的效果好很多,但是压缩次数多了以后也会有明显的模糊现象。

android cmake 打印_Android使用CMAKE编译libjpeg相关推荐

  1. android cmake 打印_Android NDK 开发:CMake 使用

    1. 前言 当在做 Android NDK 开发时,如果不熟悉用 CMake 来构建,读不懂 CMakeLists.txt 的配置脚本,很容易就会踩坑,遇到编译失败,一个很小的配置问题都会浪费很多时间 ...

  2. android代码导入有错误,android新项目导入后进行编译出现cmake错误

    问题描述 使用as加载并且gradle sync 提示:SIMPLE:error configure 同时使用make project 提示 问题出现的环境背景及自己尝试过哪些方法 已经尝试更换过nd ...

  3. 【Android NDK 开发】Android Studio 使用 CMake 导入静态库 ( CMake 简介 | 构建脚本路径配置 | 引入静态库 | 指定静态库路径 | 链接动态库 )

    文章目录 I . CMake 简介 II . Android Studio 中 CMake 引入静态库流程 III . 指定 CMake 最小版本号 IV . 导入函数库 ( 静态库 / 动态库 ) ...

  4. 【错误记录】Android NDK 错误排查记录 ( Could not get version from cmake.dir path ‘xxx\cmake\3.6.4111459‘. )

    文章目录 一. 报错信息 二. 问题分析 三. 解决方案 一. 报错信息 报错信息 : Executing tasks: [:app:assembleDebug] in project D:\002_ ...

  5. CMake基础 第7节 编译标志

    引言# CMake支持以多种不同方式设置编译标志: 使用target_compile_definitions()函数 使用CMAKE_C_FLAGS和CMAKE_CXX_FLAGS变量. 本教程中的文 ...

  6. 在Windows下使用CMake+MinGW搭建C/C++编译环境

    转载自:https://blog.csdn.net/isscollege/article/details/78038921?locationNum=8&fps=1 1 工具介绍 作为一款执行效 ...

  7. cmake:解决MSVC下/MT 编译paho.mqtt.c的问题

    paho.mqtt.c是eclipse开发的C语言跨平台mqtt client 开源库,之前写过一篇博客<cmake:VS2015和GCC编译paho.mqtt C/C++ client> ...

  8. OGRE3D 使用CMake + MinGW Make源码编译安装

    OGRE3D 使用CMake + MinGW Make源码编译安装 官网下载源码 根据官方文档进行CMakeGUI编译,以及遇到的坑 没有imgui.cpp? D3D相关的undefined refe ...

  9. 性能优化 (四) ubuntu 完美编译 libjpeg 图像压缩库,媲美微信图片压缩算法

    使用方式 在 project/build.gradle 上添加以下代码 allprojects {repositories {...maven { url 'https://jitpack.io' } ...

最新文章

  1. 走进科学-盐碱地种出甜高粱
  2. [csu/coj 1078]多个序列的最长公共子序列
  3. python中的Lock与RLock
  4. JS Promise的实现原理
  5. python函数定义关键字_Python(2)深入Python函数定义
  6. 直播回顾:准确性提升到 5 秒级,ssar 独创的 load5s 指标有多硬核?| 龙蜥技术
  7. But Wang Xing, who is concerned about long-term
  8. 凭什么相信你,我的CNN模型
  9. Visual Studio.NET 无法创建或打开应用程序之解决方法
  10. 水晶报表-推拉模式实例
  11. CCDA认证的详细综合叙述
  12. 7.10 添加房间参数
  13. 一个人php建站_人人站CMS-简单安全的PHP开源CMS建站系统
  14. 英语不好,学编程太困难?或许用文言文来编程你就更加容易上手了!
  15. matlab的开方算法_常见算法的MATLAB实现
  16. 【软件工程师学硬件】之 接口
  17. Oracle 12C Sharding分片数据库
  18. 台式计算机网卡驱动不能正常使用,系统提示“您的网卡驱动程序不正常!”怎么办 是什么原因...
  19. 第43期ACM_ICPC亚洲区域赛(焦作站)感想
  20. SS2H框架搭建,基础上篇

热门文章

  1. 缓存(Cache)管理 ---- 系列文章
  2. 第二十四章——文件管理的代码保存
  3. 响应性web设计实战总结(二)
  4. BulkLoader类使用
  5. learning to rank评价指标
  6. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第27篇]什么是对称密码加密的AEAD安全定义?
  7. java构造方法和实例化,10. JavaSE-子类实例化过程 构造方法间调用
  8. aMDcpu不支持mysql_Oracle 11.2.0.1在AMD CPU 64位硬件,32位操作系统下的BUG 8670579
  9. css 可编辑,如何设置DIV可编辑
  10. mysql 预留一个自定义字段_MySQL 按指定字段自定义列表排序 | DevOps