Android开发之图片压缩处理

本文介绍了Android中图片压缩的处理方法,详细讲解了如何使用迭代器遍历并压缩图片,重点在于`launch()`方法的执行流程,包括压缩判断、Engine类的使用以及压缩算法的实现。文章还提醒开发者不应停止自我提升,以应对行业竞争。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个就是我们平时写自定义view的时候,要写回调方法,是一样的道理,他这里就是压缩方法的回调

[](()第五步:*launch()*

点击去看到源码为

/**

  • begin compress image with asynchronous

*/

public void launch() {

build().launch(context);

}

这里,我们看到他先调用了build(),我们前面讲了,他这个方法就是赋值,然后调用了launch(context)方法,我们点进去看:

/**

  • start asynchronous compress thread

*/

@UiThread private void launch(final Context context) {

if (mPaths == null || mPaths.size() == 0 && mCompressListener != null) {

mCompressListener.onError(new NullPointerException(“image file cannot be null”));

}

Iterator iterator = mPaths.iterator();

while (iterator.hasNext()) {

final String path = iterator.next();

if (Checker.isImage(path)) {

AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {

@Override public void run() {

try {

mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_START));

File result = Checker.isNeedCompress(mLeastCompressSize, path) ?

new Engine(path, getImageCacheFile(context, Checker.checkSuffix(path))).compress() :

new File(path);

mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_SUCCESS, result));

} catch (IOException e) {

mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_ERROR, e));

}

}

});

} else {

Log.e(TAG, "can not read the path : " + path);

}

iterator.remove();

}

}

这个方法就是最后,执行压缩的方法,前面都是初始化,我们可以看到,他这个方法是在主线程调用的,所以,我们不用考虑切换线程的问题,直接可以操作UI变化。我一步一步的讲:

  1. 首先,他这个是用的迭代器,循环遍历,遍历一个就移除一个

  2. 然后就是通过handler发消息调用

  3. 具体压缩代码。最重要的就是第三点,我把第三点,提到下面讲

接着上面的第三点,具体压缩

File result = Checker.isNeedCompress(mLeastCompressSize, path) ?

new Engine(path, getImageCacheFile(context, Checker.checkSuffix(path))).compress() :

new File(path);

首先,他整体是一个三目运算符,我们点isNeedCompress()方法看一下

static boolean isNeedCompress(int leastCompressSize, String path) {

if (leastCompressSize > 0) {

File source = new File(path);

if (!source.exists()) {

return false;

}

if (source.length() <= (leastCompressSize << 10)) {

return false;

}

}

return true;

}

这个方法就是用来判断,你给定路径的图片大小和你规定的忽略文件大小比较,他这里先做了你给定的最小值判断,要大于0,不大于0就返回ture。然后做了文件是否存在的判断,如果文件不存在,就返回fals。最后,给定文件大小是不是小于等于最小值左移10位的值,小于就返回false。

然后,如果返回的是true,就去压缩,如果,返回的是false,就直接返回file文件。压缩的方法点进去:

Engine(String srcImg, File tagImg) throws IOException {

if (Checker.isJPG(srcImg)) {

this.srcExif = new ExifInterface(srcImg);

}

this.tagImg = tagImg;

this.srcImg = srcImg;

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

options.inJustDecodeBounds = true;

options.inSampleSize = 1;

BitmapFactory.decodeFile(srcImg, options);

this.srcWidth = options.outWidth;

this.srcHeight = options.outHeight;

}

这就又要说道另一个类了Engine类,它的类注释就是:用于操作,开始压缩,管理活动,缓存资源的类。他这里传原文件,也就是你需要压缩的图片,还有一个就是目标文件,也就是你压缩之后,要保存的文件。

我们先看第二个参数是什么怎么传的,有的人看不懂

/**

  • Returns a mFile with a cache audio name in the private cache directory.

  • @param context

  • A context.
    

*/

private File getImageCacheFile(Context context, String suffix) {

if (TextUtils.isEmpty(mTargetDir)) {

mTargetDir = getImageCacheDir(context).getAbsolutePath();

}

String cacheBuilder = mTargetDir + “/” +

System.currentTimeMillis() +

(int) (Math.random() * 1000) +

(TextUtils.isEmpty(suffix) ? “.jpg” : suffix);

return new File(cacheBuilder);

}

他这里就是新建一个文件,设置路径,设置名称,然后返回文件

再掉回去看Engine的构造方法,我们这里获取到了源文件和目标文件,我们只用把压缩后的流存到目标文件就行了。我之前写过一篇关于图片压缩的博客。它这里的option就是设置压缩的参数,不懂的可以看一下我之前的博客,或者用googl 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》开源 e百度一下就知道了。具体压缩就是用的bitmap的工厂类,调用的decodeFile方法。没错就是这一句 *BitmapFactory.decodeFile(srcImg, options);*

最后,辣么一切都准备就绪了,怎么样开始压缩呢?*compress()*

File compress() throws IOException {

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

options.inSampleSize = computeSize();

Bitmap tagBitmap = BitmapFactory.decodeFile(srcImg, options);

ByteArrayOutputStream stream = new ByteArrayOutputStream();

tagBitmap = rotatingImage(tagBitmap);

tagBitmap.compress(Bitmap.CompressFormat.JPEG, 60, stream);

tagBitmap.recycle();

FileOutputStream fos = new FileOutputStream(tagImg);

fos.write(stream.toByteArray());

fos.flush();

fos.close();

stream.close();

return tagImg;

}

这里面就是常规的压缩,存储的逻辑了,最最重要的压缩算法呢?就是这里的***computeSize()***方法

private int computeSize() {

srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;

srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;

int longSide = Math.max(srcWidth, srcHeight);

int shortSide = Math.min(srcWidth, srcHeight);

float scale = ((float) shortSide / longSide);

if (scale <= 1 && scale > 0.5625) {

if (longSide < 1664) {

return 1;

} else if (longSide >= 1664 && longSide < 4990) {

return 2;

} else if (longSide > 4990 && longSide < 10240) {

return 4;

} else {

return longSide / 1280 == 0 ? 1 : longSide / 1280;

}

} else if (scale <= 0.5625 && scale > 0.5) {

return longSide / 1280 == 0 ? 1 : longSide / 1280;

} else {

return (int) Math.ceil(longSide / (1280.0 / scale));

}

}123456789101112131415161718192021222324

private Bitmap rotatingImage(Bitmap bitmap) {

if (srcExif == null) return bitmap;

Matrix matrix = new Matrix();

int angle = 0;

int orientation = srcExif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);

switch (orientation) {

case ExifInterface.ORIENTATION_ROTATE_90:

angle = 90;

break;

case ExifInterface.ORIENTATION_ROTATE_180:

angle = 180;

break;

case ExifInterface.ORIENTATION Android开源项目《ali1024.coding.net/public/P7/Android/git》 _ROTATE_270:

angle = 270;

break;

}

matrix.postRotate(angle);

总结:

各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。

  • BAT大厂面试题、独家面试工具包,

  • 资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter

nterface.ORIENTATION Android开源项目《ali1024.coding.net/public/P7/Android/git》 _ROTATE_270:

angle = 270;

break;

}

matrix.postRotate(angle);

总结:

各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。

  • BAT大厂面试题、独家面试工具包,

  • 资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter
    [外链图片转存中…(img-iR27Bz1d-1650170533288)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值