您的位置:首页 > 移动开发 > Android开发

Androidr的图片的缩放、读取、压缩保存

2014-01-02 22:36 761 查看
最近这几天一直在做一个画报的app, 需要有大量的图片来展示, 而且这些图片都是很大一张的1200×1200, 本来想用sampleSize来缩放图片, 但是因为sample size最少也要压缩2倍, 担心图片的质量会大差,后来终于找到网上的一段代码来计算这个sampleSize, 听说是google自己的代码。这里的minSideLength
为-1, 而maxNumOfPixels参数的值 如果是宽高都是400的话 就应该填400*400*4后面为什么乘四? 因为一个像素占四个字节。 我也是看到这篇文章上说的。 这样会动态计算出一个最合适sample。

/article/3744691.html

Java代码


public static int computeSampleSize(BitmapFactory.Options options,

int minSideLength, int maxNumOfPixels) {

int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);

int roundedSize;

if (initialSize <= 8 ) {

roundedSize = 1;

while (roundedSize < initialSize) {

roundedSize <<= 1;

}

} else {

roundedSize = (initialSize + 7) / 8 * 8;

}

return roundedSize;

}

private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {

double w = options.outWidth;

double h = options.outHeight;

int lowerBound = (maxNumOfPixels == -1) ? 1 :

(int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));

int upperBound = (minSideLength == -1) ? 128 :

(int) Math.min(Math.floor(w / minSideLength),

Math.floor(h / minSideLength));

if (upperBound < lowerBound) {

// return the larger one when there is no overlapping zone.

return lowerBound;

}

if ((maxNumOfPixels == -1) &&

(minSideLength == -1)) {

return 1;

} else if (minSideLength == -1) {

return lowerBound;

} else {

return upperBound;

}

}

引用

在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用 BitmapFactory的decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几 分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。

  然而,如果我们想取固定大小的缩略 图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么办?我们总不能将原始图片加载到内存中再 进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止 100K?

  经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的

   If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.

  意思就是说如果该值设为 true那么将不返回实际的bitmap不给其分配内存空间而里面只包括一些解码边界信息即图片大小信息,那么相应的方法也就出来了,通过设置 inJustDecodeBounds为true,获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize 可能小于0,必须做判断。

具体代码如下:

FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01);

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

options.inJustDecodeBounds = true;

Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test.jpg", options); //此时返回bm为空

options.inJustDecodeBounds = false;

//缩放比

int be = (int)(options.outHeight / (float)200);

if (be <= 0)

be = 1;

options.inSampleSize = be;

//重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦

bitmap=BitmapFactory.decodeFile("/sdcard/test.jpg",options);

int w = bitmap.getWidth();

int h = bitmap.getHeight();

System.out.println(w+" "+h);

ImageView iv=new ImageView(this);

iv.setImageBitmap(bitmap);

这样我们就可以读取较大的图片而不会内存溢出了。如果你想把压缩后的图片保存在Sdcard上的话就很简单了:

File file=new File("/sdcard/feng.png");

try {

FileOutputStream out=new FileOutputStream(file);

if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){

out.flush();

out.close();

}

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

ok,这样就把图片保存在/sdcard/feng.png这个文件里面了,呵呵。

但是这里的缩放保存是按长宽比例的,下边也可以按固定大小缩放哦:

int bmpWidth = bitmap.getWidth();

int bmpHeight = bitmap.getHeight();

//缩放图片的尺寸

float scaleWidth = (float) sWidth / bmpWidth; //按固定大小缩放 sWidth 写多大就多大

float scaleHeight = (float) sHeight / bmpHeight; //

Matrix matrix = new Matrix();

matrix.postScale(scaleWidth, scaleHeight);

//产生缩放后的Bitmap对象

Bitmap resizeBitmap = Bitmap.createBitmap(

bitmap, 0, 0, bmpWidth, bmpHeight, matrix, false);

bitmap.recycle();

Bitmap resizeBitmap = bitmap;

//Bitmap to byte[]

byte[] photoData = bitmap2Bytes(resizeBitmap);

//save file

String fileName = "/sdcard/test.jpg";

FileUtil.writeToFile(fileName, photoData);

引用

压缩图片质量:

bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fos);

其中的quality为0~100, 可以压缩图片质量, 不过对于大图必须对图片resize

这个是等比例缩放:

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

这个是截取图片某部分:

bitmap = Bitmap.createBitmap(bitmap, x, y, width, height);

这几个方法都是针对Bitmap的, 不过鉴于Bitmap可以从file中读取, 也可以写入file.

这是我知道Android自带库里中唯一可以缩放和压缩的图片方法.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐