一般我们的图片来源都是通过网络或者本地资源图片,对于图片的大小一般都有要求,因为在控件中显示和缓存图片文件都不能过大,因此记录一下对于图片文件尺寸的处理和图片文件的缓存还是很有必要的!
下面是一个简单的图片尺寸的处理,同样是学习了郭神的思想,在这里我仅仅是当做练习一下了。
public class MainActivity extends Activity {
private ImageView mImageView;
private Handler myHandler = new Handler(){
public void handleMessage(Message msg) {
if(msg.obj!=null){
mImageView.setImageBitmap((Bitmap)msg.obj);
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.imageView);
BitmapFactory.Options options = getImageSizeFromDrawable(R.drawable.image1);
System.out.println("resource image Width = "+options.outWidth+" Height = "+options.outHeight);//Width = 1002 Height = 762
new Thread(new Runnable() {
@Override
public void run() {
// getImageSizeFromUrl("http://pic.nipic.com/2007-11-09/2007119122519868_2.jpg");
Bitmap bitmap = getCompressBitmap("http://pic.nipic.com/2007-11-09/2007119122519868_2.jpg",200,200);
Message msg = Message.obtain();
msg.obj=bitmap;
myHandler.sendMessage(msg);
}
}).start();
}
/**
* 获取的是资源文件中的图片的大小,当我们的图片存放在xhdpi里面的时候才是真实的大小
* @param drawableId 为我们资源图片的id
* @return BitmapFactory.Options 通过这个属性我们就可以获取图片的长宽了
* */
private BitmapFactory.Options getImageSizeFromDrawable(int drawableId){
BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds=true;//inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存
BitmapFactory.decodeResource(getResources(), drawableId, option);
return option;
}
/**
* @param imageUrl为图片的网络地址
* 调用方式:getImageSizeFromUrl("http://pic.nipic.com/2007-11-09/2007119122519868_2.jpg");
* 打印结果:width=1002 height=762 type=image/jpeg
* */
private BitmapFactory.Options getImageSizeFromUrl(String imageUrl)
{
InputStream in =null;
BitmapFactory.Options option =null;
try {
in = getImageInputStream(imageUrl);
//------采样获取网络图片的宽度和高度,以及图片的类型
option = new BitmapFactory.Options();
option.inJustDecodeBounds=true;
BitmapFactory.decodeStream(in,null,option);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(in!=null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return option;
}
/**
* @param in 输入流 表示我们图片从网络上下载
* @param targetWidth 我们需要的图片宽度
* @param targetHeight 我们需要的图片高度
* @return 返回的是压缩的值,如果不需要压缩,返回1
* */
private int getSampleSize(String imageUrl,int targetWidth,int targetHeight)
{
BitmapFactory.Options option =getImageSizeFromUrl(imageUrl);
int width=0,height=0;
if(option!=null)
{
width = option.outWidth;
height = option.outHeight;
}
if(width>targetWidth || height>targetHeight)
{
int wRatio = Math.round(width/targetWidth);
int hRatio = Math.round(height/targetHeight);
return wRatio<hRatio?wRatio:hRatio;
}
return 1;//如果不需要压缩,直接返回1 ,如果需要,返回上面的比率
}
/**
* 压缩bitmap,并且保存压缩过的图片到手机sd卡中
* @param in 输入流 表示我们图片从网络上下载
* @param targetWidth 我们需要的图片宽度
* @param targetHeight 我们需要的图片高度
* @return bitmap 返回的是压缩过的图片
* */
private Bitmap getCompressBitmap(String imageUrl,int targetWidth,int targetHeight){
InputStream in =null;
Bitmap bitmap =null;
try {
int sampleSize = getSampleSize(imageUrl, targetWidth, targetHeight);
in = getImageInputStream(imageUrl);
BitmapFactory.Options option = new BitmapFactory.Options();
option.inJustDecodeBounds = false;
option.inSampleSize = sampleSize;
System.out.println("sampleSize = "+sampleSize);//打印出来采样值为3
bitmap = BitmapFactory.decodeStream(in, null, option);
System.out.println(bitmap.getHeight()+" --- "+bitmap.getWidth());
//这里我们把图片存储到手机内存卡中去,前提是你要有内存卡,如果没有可以直接存到getCacheDir().getPath()+"/TempImages"中去
String rootPath = Environment.getExternalStorageDirectory().getPath()+"/TempImages/";
new File(rootPath).mkdir();
String filetemp = rootPath+"1.jpg";//这里我们作为测试,把这张图片的名字取为1.jpg 对应下面的JPEG
File myfile = new File(filetemp);
myfile.createNewFile();
/**这里Bitmap虽然宽和高都改变了,但是我们的图片的大小还是没有变化,依然为原图的大小,通过控制第二个参数的值,能够改变文件的大小
*bitmap.compress
*这里面第一个参数是表示压缩成什么格式的图片,
*第二个参数是表示的压缩的质量,如果为100表示的就是高质量压缩,大小基本与原图一致实际测试如果为90的时候基本上压缩了60%的大小了(42kB),
*80的时候为(31KB),然后值越小压缩文件大小越来越小50的时候是(21kB)因此这里没有什么比例可言
*第三个参数表示的是图片文件压缩之后的输出流是什么,我们用一个文件去接收,这个File对象就是我们需要的压缩文件
*注意,API说了,如果我们的图片为PNG格式,则第二个参数无论怎么变化,对其压缩文件大小不产生影响(像PNG是无损的,会忽略质量设置)
*而我们图片如果是jpg格式,那么大小就像上面说的一样有压缩文件有较大的变化
*
*/
bitmap.compress(CompressFormat.JPEG, 50, new FileOutputStream(myfile));
return bitmap;
}catch(Exception e){
}finally{
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 获取图片的输入流
* */
public InputStream getImageInputStream(String imageUrl)
{
InputStream in =null;
HttpURLConnection conn = null;
try {
URL url = new URL(imageUrl);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10*1000);
conn.setConnectTimeout(5*1000);
conn.setDoInput(true);
in = conn.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
return in;
}
}
图片来源有两个,第一个是本地:
BitmapFactory.Options op=getImageSizeFromDrawable(R.drawable.image1);
返回的是一个图片属性,里面有我们需要的图片的相关信息
第二个是网络:
BitmapFactory.Options option =getImageSizeFromUrl(imageUrl);
如果需要把文件压缩之后保存在本地,getCompressBitmap函数做了一个简单的压缩保存功能。
xml文件就是一个ImageView控件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.imagedemo.MainActivity" >
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
最后是我们的code的工程:
百度云盘下载地址:
链接:http://pan.baidu.com/s/1c0Gv00S 密码:g9t3