Skip to content Skip to footer

【Android 内存优化】Android 原生 API 图片压缩代码示例 ( PNG 格式压缩

文章目录一、 图片质量压缩二、 图片尺寸压缩三、 Android 10 文件访问四、 完整源码示例上一篇博客 【Android 内存优化】图片文件压缩 ( Android 原生 API 提供的图片压缩功能能 | 图片质量压缩 | 图片尺寸压缩 ) 简要介绍了 图片文件压缩格式 , 以及 Android 提供的图片质量 , 尺寸压缩 API , 本博客中使用该 API 进行图片压缩 ;

一、 图片质量压缩图片质量压缩步骤 :

① 创建输出流 : 创建一个文件输出流 , 也可是是网络输出流 ;

代码语言:javascript代码运行次数:0运行复制FileOutputStream fos = new FileOutputStream(path); ② 加载文件 : 从 Assets , 资源文件 , SD 卡 , 中 解码图片文件为内存中的 Bitmap 对象 ; 这里从资源文件中加载 ;

代码语言:javascript代码运行次数:0运行复制Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);③ 压缩图片 : 调用 Bitmap 对象的 compress 方法 , 压缩图片 ;

代码语言:javascript代码运行次数:0运行复制bitmap.compress(compressFormat, quality, fos);二、 图片尺寸压缩图片尺寸压缩流程 :

① 加载文件 : 从 Assets , 资源文件 , SD 卡 , 中解码图片文件为内存中的 Bitmap 对象 ; 这里从资源文件中加载 ;

代码语言:javascript代码运行次数:0运行复制Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);② 图片尺寸压缩 : 调用 Bitmap 对象的 createScaledBitmap 方法 , 将目标宽高作为参数传入 , 并使用双线性滤波器算法 , 该算法能大幅度提供压缩后的图片质量 , 并且开销较少 , 官方建议开启该算法 ;

代码语言:javascript代码运行次数:0运行复制bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);三、 Android 10 文件访问文件存储相关官方参考资料 :

Android 11 中的存储机制更新Android storage use cases and best practices应用数据和文件将图片压缩后 , 存储到 SD 卡中 , 这里 涉及到了在 Android 10 系统中动态申请权限 , 设置旧的存储访问策略 ( 该策略将在 Android 11 中无效 ) ;

这里简要介绍暂时性的解决方案 ;

1. AndroidManifest.xml 中配置 SD 卡权限 , 及旧存储策略 :

① SD 卡权限 : 配置 SD 卡读写权限 ;

代码语言:javascript代码运行次数:0运行复制

② 旧存储策略 : 配置在 application 标签中 , 特别注意该策略将在 Android 11 中废弃 ;

代码语言:javascript代码运行次数:0运行复制android:requestLegacyExternalStorage="true"③ 完整配置 :

代码语言:javascript代码运行次数:0运行复制

package="kim.hsl.pc">

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme"

android:requestLegacyExternalStorage="true">

2 . 在 Activity 中动态申请权限 : 在 Activity 中调用 initPermissions(); 方法 , 即可动态申请 SD 卡访问权限 ;

代码语言:javascript代码运行次数:0运行复制 /**

* 需要获取的权限列表

*/

private String[] permissions = new String[]{

Manifest.permission.READ_EXTERNAL_STORAGE,

Manifest.permission.WRITE_EXTERNAL_STORAGE

};

/**

* 动态申请权限的请求码

*/

private static final int PERMISSION_REQUEST_CODE = 888;

/**

* 动态申请权限

*/

@RequiresApi(api = Build.VERSION_CODES.M)

private void initPermissions() {

if (isLacksPermission()) {

//动态申请权限 , 第二参数是请求吗

requestPermissions(permissions, PERMISSION_REQUEST_CODE);

}

}

/**

* 判断是否有 permissions 中的权限

* @return

*/

@RequiresApi(api = Build.VERSION_CODES.M)

public boolean isLacksPermission() {

for (String permission : permissions) {

if(checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){

return true;

}

}

return false;

}执行完上述三个步骤的操作

配置权限设置旧存储策略动态申请权限即可在 Android 10 中访问 SD 卡 , 如果在 Android 11 访问 , 查看章节开始的文档 ;

四、 完整源码示例图片压缩源码示例 :

压缩质量 : 下图中的图片压缩都压缩成最低质量的图片 ;

代码语言:javascript代码运行次数:0运行复制package kim.hsl.pc;

import androidx.annotation.RequiresApi;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;

import android.content.pm.PackageManager;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.Build;

import android.os.Bundle;

import android.os.Environment;

import android.util.Log;

import android.widget.TextView;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

static {

System.loadLibrary("native-lib");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

TextView tv = findViewById(R.id.sample_text);

tv.setText(stringFromJNI());

// 初始化权限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

initPermissions();

}

// 将图片压缩成 JPEG 格式, 不缩放

compressBitmap(R.drawable.blog, Bitmap.CompressFormat.JPEG, 0,

Environment.getExternalStorageDirectory() + "/blog_jpeg.jpeg",

0, 0);

// 将图片压缩成 WEBP 格式

compressBitmap(R.drawable.blog, Bitmap.CompressFormat.WEBP, 0,

Environment.getExternalStorageDirectory() + "/blog_webp.webp",

0, 0);

// 将图片压缩成 PNG 格式

compressBitmap(R.drawable.blog, Bitmap.CompressFormat.PNG, 0,

Environment.getExternalStorageDirectory() + "/blog_png.png",

0, 0);

// 将图片宽高各压缩一半

compressBitmap(R.drawable.blog, Bitmap.CompressFormat.PNG, 0,

Environment.getExternalStorageDirectory() + "/blog_png_half.png",

995, 510);

}

/**

* 压缩图片, 并将压缩结果保存到指定文件

* @param resId 图片资源

* @param compressFormat 图片压缩格式

* @param quality 压缩质量

* @param path 文件保存路径

*/

public void compressBitmap(int resId, Bitmap.CompressFormat compressFormat,

int quality, String path, int width, int height){

// 从资源文件中加载一张图片

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);

// 如果传入的尺寸参数大于 0, 那么压缩尺寸

if(width > 0 && height > 0){

bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);

}

// 用于写出压缩后的图片到文件中

FileOutputStream fos = null;

try {

// 打开文件输出流

fos = new FileOutputStream(path);

// 图片压缩操作

// 如果图片格式是 PNG 格式, 会忽略 质量 参数

bitmap.compress(compressFormat, quality, fos);

} catch (FileNotFoundException e) {

e.printStackTrace();

Log.i("TAG", "文件输出流打开失败");

}finally {

if(fos != null){

try {

fos.close();

} catch (IOException e) {

e.printStackTrace();

Log.i("TAG", "文件输出流关闭失败");

}

}

}

}

public native String stringFromJNI();

/**

* 需要获取的权限列表

*/

private String[] permissions = new String[]{

Manifest.permission.READ_EXTERNAL_STORAGE,

Manifest.permission.WRITE_EXTERNAL_STORAGE

};

/**

* 动态申请权限的请求码

*/

private static final int PERMISSION_REQUEST_CODE = 888;

/**

* 动态申请权限

*/

@RequiresApi(api = Build.VERSION_CODES.M)

private void initPermissions() {

if (isLacksPermission()) {

//动态申请权限 , 第二参数是请求吗

requestPermissions(permissions, PERMISSION_REQUEST_CODE);

}

}

/**

* 判断是否有 permissions 中的权限

* @return

*/

@RequiresApi(api = Build.VERSION_CODES.M)

public boolean isLacksPermission() {

for (String permission : permissions) {

if(checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){

return true;

}

}

return false;

}

}压缩结果分析 :

① 压缩后的 PNG 格式 : 2.63 MB ;

② 压缩后的 JPEG 格式 : 119 KB ;

③ 压缩后的 WEBP 格式图片 : 102 KB ;

④ 尺寸压缩图片 : 219 KB ;

压缩格式中 PNG > JPEG > WEBP 格式 ;

PNG 图片不能压缩 , 这里显示的大小是原图大小 , 非常大 ;

Copyright © 2088 世界杯八强_2018年世界杯亚洲区预选赛 - nprny.com All Rights Reserved.
友情链接