Android压缩图片到100K以下同时保持不失真

2024-01-14 07:58

本文主要是介绍Android压缩图片到100K以下同时保持不失真,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:目前一般手机的相机都能达到800万像素,像我的Galaxy Nexus才500万像素,拍摄的照片也有1.5M左右。这么大的照片上传到服务器,不仅浪费流量,同时还浪费时间。

在开发Android企业应用时,会经常上传图片到服务器,而我们公司目前维护的一个项目便是如此。该项目是通过私有apn与服务器进行交互的,联通的还好,但移动的速度实在太慢,客户在使用软件的过程中,由于上传的信息中可能包含多张图片,会经常出现上传图片失败的问题,为了解决这个问题,我们决定把照片压缩到100k以下,并且保证图片不失真(目前图片经过压缩后,大约300k左右)。于是我就重新研究了一下Android的图片压缩技术。

Android端目录结构如下图所示:
屏幕快照 2013-01-25 下午5.44.09.png
使用的第三方库jar包,如下图所示:
屏幕快照 2013-01-25 下午5.53.02.png

其中ksoap2-android-xxx.jar是Android用来调用webservice的,gson-xx.jar是把JavaBean转成Json数据格式的。 
本篇博客主要讲解图片压缩的,核心代码如下:

 123456789
10
11
12
13
//计算图片的缩放值
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {final int height = options.outHeight;final int width = options.outWidth;int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {final int heightRatio = Math.round((float) height/ (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth);inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;}return inSampleSize;
}
 123456789
10
11
12
13
14
// 根据路径获得图片并压缩,返回bitmap用于显示
public static Bitmap getSmallBitmap(String filePath) {final BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(filePath, options);// Calculate inSampleSizeoptions.inSampleSize = calculateInSampleSize(options, 480, 800);// Decode bitmap with inSampleSize setoptions.inJustDecodeBounds = false;return BitmapFactory.decodeFile(filePath, options);}
1
2
3
4
5
6
7
8
9
//把bitmap转换成String
public static String bitmapToString(String filePath) {Bitmap bm = getSmallBitmap(filePath);ByteArrayOutputStream baos = new ByteArrayOutputStream();bm.compress(Bitmap.CompressFormat.JPEG, 40, baos);byte[] b = baos.toByteArray();return Base64.encodeToString(b, Base64.DEFAULT);}

查看全部源码,请访问:
https://github.com/feicien/StudyDemo/tree/master/FileUploadDemo

压缩原理讲解:压缩一张图片。我们需要知道这张图片的原始大小,然后根据我们设定的压缩比例进行压缩。
这样我们就需要做3件事:
1.获取原始图片的长和宽

1
2
3
4
5
               BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(filePath, options);int height = options.outHeight;int width = options.outWidth; 

以上代码是对图片进行解码,inJustDecodeBounds设置为true,可以不把图片读到内存中,但依然可以计算出图片的大小,这正好可以满足我们第一步的需要。
2.计算压缩比例

 123456789
10
     int height = options.outHeight;int width = options.outWidth; int inSampleSize = 1;int reqHeight=800;int reqWidth=480;if (height > reqHeight || width > reqWidth) {final int heightRatio = Math.round((float) height/ (float) reqHeight);final int widthRatio = Math.round((float) width / (float) reqWidth);            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;}

一般手机的分辨率为 480*800 ,所以我们压缩后图片期望的宽带定为480,高度设为800,这2个值只是期望的宽度与高度,实际上压缩后的实际宽度也高度会比期望的要大。如果图片的原始高度或者宽带大约我们期望的宽带和高度,我们需要计算出缩放比例的数值。否则就不缩放。heightRatio是图片原始高度与压缩后高度的倍数,widthRatio是图片原始宽度与压缩后宽度的倍数。inSampleSize为heightRatio与widthRatio中最小的那个,inSampleSize就是缩放值。 inSampleSize为1表示宽度和高度不缩放,为2表示压缩后的宽度与高度为原来的1/2
3.缩放并压缩图片

1
2
3
4
5
6
7
8
          //在内存中创建bitmap对象,这个对象按照缩放大小创建的options.inSampleSize = calculateInSampleSize(options, 480, 800);options.inJustDecodeBounds = false;Bitmap bitmap= BitmapFactory.decodeFile(filePath, options);ByteArrayOutputStream baos = new ByteArrayOutputStream();bm.compress(Bitmap.CompressFormat.JPEG, 60, baos);byte[] b = baos.toByteArray();

前3行的代码其实已经得到了一个缩放的bitmap对象,如果你在应用中显示图片,就可以使用这个bitmap对象了。由于考虑到网络流量的问题。我们好需要牺牲图片的质量来换取一部分空间,这里调用bm.compress()方法进行压缩,这个方法的第二个参数,如果是100,表示不压缩,我这里设置的是60,你也可以更加你的需要进行设置,在实验的过程中我设置为30,图片都不会失真。

压缩效果:本demo可以把1.5M左右的图片压缩到100K左右,并且没有失真。
效果图如下:
demo.jpg

更新:

 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
压缩图片,处理某些手机拍照角度旋转的问题
*/
public static String compressImage(Context context,String filePath,String fileName,int q) throws FileNotFoundException {Bitmap bm = getSmallBitmap(filePath);int degree = readPictureDegree(filePath);if(degree!=0){//旋转照片角度bm=rotateBitmap(bm,degree);}File imageDir = SDCardUtils.getImageDir(context);File outputFile=new File(imageDir,fileName);FileOutputStream out = new FileOutputStream(outputFile);bm.compress(Bitmap.CompressFormat.JPEG, q, out);return outputFile.getPath();}

判断照片角度

 123456789
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;}

旋转照片

 123456789
10
public static Bitmap rotateBitmap(Bitmap bitmap,int degress) {if (bitmap != null) {Matrix m = new Matrix();m.postRotate(degress); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), m, true);return bitmap;}return bitmap;}

这篇关于Android压缩图片到100K以下同时保持不失真的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/604462

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

详解C#如何提取PDF文档中的图片

《详解C#如何提取PDF文档中的图片》提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使用,下面我们就来看看如何使用C#通过代码从PDF文档中提取图片吧... 当 PDF 文件中包含有价值的图片,如艺术画作、设计素材、报告图表等,提取图片可以将这些图像资源进行单独保存,方便后续在不同的项目中使

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

Android自定义Scrollbar的两种实现方式

《Android自定义Scrollbar的两种实现方式》本文介绍两种实现自定义滚动条的方法,分别通过ItemDecoration方案和独立View方案实现滚动条定制化,文章通过代码示例讲解的非常详细,... 目录方案一:ItemDecoration实现(推荐用于RecyclerView)实现原理完整代码实现