canvas.drawBitmap(image, null, rect, null);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int options = 100;

result.compress(Bitmap.CompressFormat.JPEG, options, baos);

// 循环判断如果压缩后图片是否大于100kb,大于继续压缩

while (baos.toByteArray().length / 1024 > maxSize) {

// 重置baos即清空baos

baos.reset();

// 每次都减少10

options -= 10;

// 这里压缩options%,把压缩后的数据存放到baos中

result.compress(Bitmap.CompressFormat.JPEG, options, baos);

}

// JNI调用保存图片到SD卡 这个关键

NativeUtil.saveBitmap(result, options, filePath, true);

// 释放Bitmap

if (result != null && !result.isRecycled()) {

result.recycle();

result = null;

}

}

五. NativeUtil类的源码


16.9.29更新

1、添加getBitmapFromFile()方法,解决OOM和图片旋转的问题

2、添加compressBitmap()方法,传递当前图片本地路径和解压后图片保存路径两个参数,即可,实现压缩

package net.bither.util;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import android.graphics.Bitmap;

import android.graphics.Bitmap.Config;

import android.graphics.BitmapFactory;

import android.graphics.Canvas;

import android.graphics.Matrix;

import android.graphics.Rect;

import android.media.ExifInterface;

/**

  • JNI图片压缩工具类

  • @Description TODO

  • @Package net.bither.util

  • @Class NativeUtil

  • @Copyright: Copyright © 2015

  • @version V1.0.0

*/

public class NativeUtil {

private static int DEFAULT_QUALITY = 95;

/**

  • @Description: JNI基本压缩

  • @param bit

  •        bitmap对象
    
  • @param fileName

  •        指定保存目录名
    
  • @param optimize

  •        是否采用哈弗曼表数据计算 品质相差5-10倍
    
  • @version V1.0.0

*/

public static void compressBitmap(Bitmap bit, String fileName, boolean optimize) {

saveBitmap(bit, DEFAULT_QUALITY, fileName, optimize);

}

/**

  • @Description: 通过JNI图片压缩把Bitmap保存到指定目录

  • @param image

  •        bitmap对象
    
  • @param filePath

  •        要保存的指定目录
    
  • @version V1.0.0

*/

public static void compressBitmap(Bitmap image, String filePath) {

// 最大图片大小 150KB

int maxSize = 150;

// 获取尺寸压缩倍数

int ratio = NativeUtil.getRatioSize(image.getWidth(),image.getHeight());

// 压缩Bitmap到对应尺寸

Bitmap result = Bitmap.createBitmap(image.getWidth() / ratio,image.getHeight() / ratio,Config.ARGB_8888);

Canvas canvas = new Canvas(result);

Rect rect = new Rect(0, 0, image.getWidth() / ratio, image.getHeight() / ratio);

canvas.drawBitmap(image,null,rect,null);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int options = 100;

result.compress(Bitmap.CompressFormat.JPEG, options, baos);

// 循环判断如果压缩后图片是否大于100kb,大于继续压缩

while (baos.toByteArray().length / 1024 > maxSize) {

// 重置baos即清空baos

baos.reset();

// 每次都减少10

options -= 10;

// 这里压缩options%,把压缩后的数据存放到baos中

result.compress(Bitmap.CompressFormat.JPEG, options, baos);

}

// JNI保存图片到SD卡 这个关键

NativeUtil.saveBitmap(result, options, filePath, true);

// 释放Bitmap

if (!result.isRecycled()) {

result.recycle();

}

}

/**

  • @Description: 通过JNI图片压缩把Bitmap保存到指定目录

  • @param curFilePath

  •        当前图片文件地址
    
  • @param targetFilePath

  •        要保存的图片文件地址
    
  • @author XiaoSai

  • @date 2016年9月28日 下午17:43:15

  • @version V1.0.0

*/

public static void compressBitmap(String curFilePath, String targetFilePath) {

// 最大图片大小 150KB

int maxSize = 150;

//根据地址获取bitmap

Bitmap result = getBitmapFromFile(curFilePath);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int quality = 100;

result.compress(Bitmap.CompressFormat.JPEG, quality, baos);

// 循环判断如果压缩后图片是否大于100kb,大于继续压缩

while (baos.toByteArray().length / 1024 > maxSize) {

// 重置baos即清空baos

baos.reset();

// 每次都减少10

quality -= 10;

// 这里压缩quality,把压缩后的数据存放到baos中

result.compress(Bitmap.CompressFormat.JPEG, quality, baos);

}

// JNI保存图片到SD卡 这个关键

NativeUtil.saveBitmap(result, quality, targetFilePath, true);

// 释放Bitmap

if (!result.isRecycled()) {

result.recycle();

}

}

/**

  • 计算缩放比

  • @param bitWidth 当前图片宽度

  • @param bitHeight 当前图片高度

  • @return int 缩放比

  • @version V1.0.0

*/

public static int getRatioSize(int bitWidth, int bitHeight) {

// 图片最大分辨率

int imageHeight = 1280;

int imageWidth = 960;

// 缩放比

int ratio = 1;

// 缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可

if (bitWidth > bitHeight && bitWidth > imageWidth) {

// 如果图片宽度比高度大,以宽度为基准

ratio = bitWidth / imageWidth;

} else if (bitWidth < bitHeight && bitHeight > imageHeight) {

// 如果图片高度比宽度大,以高度为基准

ratio = bitHeight / imageHeight;

}

// 最小比率为1

if (ratio <= 0)

ratio = 1;

return ratio;

}

/**

  • 通过文件路径读获取Bitmap防止OOM以及解决图片旋转问题

  • @param filePath

  • @return

*/

public static Bitmap getBitmapFromFile(String filePath){

BitmapFactory.Options newOpts = new BitmapFactory.Options();

newOpts.inJustDecodeBounds = true;//只读边,不读内容

BitmapFactory.decodeFile(filePath, newOpts);

int w = newOpts.outWidth;

int h = newOpts.outHeight;

// 获取尺寸压缩倍数

newOpts.inSampleSize = NativeUtil.getRatioSize(w,h);

newOpts.inJustDecodeBounds = false;//读取所有内容

newOpts.inDither = false;

newOpts.inPurgeable=true;

newOpts.inInputShareable=true;

newOpts.inTempStorage = new byte[32 * 1024];

Bitmap bitmap = null;

File file = new File(filePath);

FileInputStream fs = null;

try {

fs = new FileInputStream(file);

} catch (FileNotFoundException e) {

e.printStackTrace();

}

try {

if(fs!=null){

bitmap = BitmapFactory.decodeFileDescriptor(fs.getFD(),null,newOpts);

//旋转图片

int photoDegree = readPictureDegree(filePath);

if(photoDegree != 0){

Matrix matrix = new Matrix();

matrix.postRotate(photoDegree);

// 创建新的图片

bitmap = Bitmap.createBitmap(bitmap, 0, 0,

bitmap.getWidth(), bitmap.getHeight(), matrix, true);

}

}

} catch (IOException e) {

e.printStackTrace();

} finally{

if(fs!=null) {

try {

fs.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

return bitmap;

}

/**

  • 读取图片属性:旋转的角度

  • @param path 图片绝对路径

  • @return degree旋转的角度

*/

public static int readPictureDegree(String path) {

int degree = 0;

try {

ExifInterface exifInterface = new ExifInterface(path);

int orientation = exifInterface.getAttributeInt(

ExifInterface.TAG_ORIENTATION,

ExifInterface.ORIENTATION_NORMAL);

switch (orientation) {

case ExifInterface.ORIENTATION_ROTATE_90:

degree = 90;

break;

case ExifInterface.ORIENTATION_ROTATE_180:

degree = 180;

break;

case ExifInterface.ORIENTATION_ROTATE_270:

degree = 270;

break;

}

} catch (IOException e) {

e.printStackTrace();

}

return degree;

}

/**

  • 调用native方法

  • @Description:函数描述

  • @param bit

  • @param quality

  • @param fileName

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

Android学习PDF+学习视频+面试文档+知识点笔记

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

【Android高级架构视频学习资源】

以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

Android学习PDF+学习视频+面试文档+知识点笔记

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

[外链图片转存中…(img-F1jkcytZ-1645094067039)]

【Android高级架构视频学习资源】

**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!

Android 图片压缩之多种压缩方式结合使用,阿里Android开发面试解答相关推荐

  1. Android图片视频拍摄选取及压缩

    Android图片视频选取及压缩上传 此博客的主要技术点 需求 开车了 图片选择库 视频压缩 上传 此博客的主要技术点 视频拍摄.视频选取获取视频地址 视频压缩 视频上传 需求 我的项目1.0版本最近 ...

  2. Android 图片压缩之多种压缩方式结合使用

    原文地址:http://www.jianshu.com/p/e9e1db845c21 如题,多种压缩方式常用的有尺寸压缩.质量压缩以及通过JNI调用libjpeg库来进行压缩,三种方式结合使用实现指定 ...

  3. android图片选择器框架支持长图,基于RxJava的Android图片选择器. – RxPicker

    RxPicker 基于 RxJava 的 Android 图片选择器. 特性 与 RxJava 结合,支持响应式得到选择图片结果 兼容 Android 7.0 自定义 ImageLoader 预览 使 ...

  4. 2022中级Android开发面试解答,当上项目经理才知道

    缘起 随着互联网企业的不断发展,产品项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑.快速迭代的目的越来越难,还有65535,应用之间的互相调用等等问题,插件化技术应用而生.如果没有插件化 ...

  5. android 图片方法,分享实现Android图片选择的两种方式

    Android选择图片的两种方式: 第一种:单张选取 通过隐式启动activity,跳转到相册选择一张返回结果 关键代码如下: 发送请求: private static final int PICTU ...

  6. 通过纯css实现图片居中的多种实现方式

    html结构: 1 <div class="demo" style="width: 800px;height: 600px; border:1px solid #d ...

  7. android期末考试选择题,轻松拿到了阿里Android高级开发工程师的offer

    前言 在这个网络发展快速的时代,我想问为什么你选择做程序员?有人说因为不善交际,也有人说最火的行业互联网,最好的职业程序员.确实在这个繁荣的行业,只要你自己不下船技术不水,就可以衣食无忧,努力努力说不 ...

  8. Android 图片压缩各种方式

    前言:由于公司项目当中需要用到压缩这块的相应技术,之前也做过的图片压缩都不是特别的理想, 所以这次花了很多心思,仔细研究和在网上找到了很多相对应的资料.为了就是 以后再做的时候直接拿来用就可以了! 第 ...

  9. android图片压缩的三种方式

    为了避免oom的出现,几乎每个应用都会对大图进行压缩,我现在手头做的产品就有很多地方用到,以前封装工具类的时候,都是在网上找东找西,然后拼拼凑凑,有效果就行了,一直用的迷迷糊糊,这几天工作比较闲,正好 ...

最新文章

  1. 史上最全的“大数据”学习资源
  2. C 关于页面刷新和combobox的使用
  3. 复制订阅服务器和 AlwaysOn 可用性组 (SQL Server)
  4. 为什么百万医疗险越来越多,到底选哪款?
  5. 兼容多种屏幕分辨率的通栏大图实现方法
  6. iptables 范例
  7. linux fedora35让GRUB 2记住上一次启动的操作系统
  8. ASP.NET Core Cookie SameSite
  9. 编程 ul 不能一行显示 跳到下行_史上最全的数控G代码编程详解
  10. Android4.0源码目录结构详解
  11. 淘宝用户行为分析(python+mysql+tableau)
  12. 解决Python爬取百度页面出现中文乱码问题
  13. 9 个将改变一切的物联网应用
  14. 论文解读:Making Pre-trained Language Models Better Few-shot Learners(LM-BFF)
  15. Typora如何把图片上传到图床smms.app
  16. 电影: 嘲笑过片名后,我哭着看完这部片
  17. 关于实现校园网防断网的可行方案
  18. 使用图像处理技术去除图片水印
  19. 微营销软件需要的计算机技术,WeTool 一款专用于个人微信营销操作及运营的电脑工具...
  20. 技术中台建设方法和关键设计

热门文章

  1. 【深度学习框架】|PyTorch|完成一个手写体识别任务
  2. java操作jacoco
  3. C++ DLL总结—静动态调用、导出类
  4. JDBC由浅入深解析(C3P0)(DBUtils)
  5. sparkSql 随机打散分配
  6. 2W字!梳理50道经典计算机网络面试题(收藏版)
  7. 【数学建模】基于matlab武汉地铁2号线路线地图动态模拟【含Matlab源码 1092期】
  8. 导线中电流分布和集肤深度
  9. go mod查看包依赖关系
  10. el-dialog改变中间内容的高度问题