BitmapFactory类

在Android中,提供了一个BitmapFactory类,该类为一个工其类,用于从不同的数据源来解析、创建Bitmap对象,

BitmapFactory类提供的创建Bitmap对象,它提供了如下的方法:

<span style="font-size:18px;">static Bitmap	 decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts)
Decode an immutable bitmap from the specified byte array.
static Bitmap	 decodeByteArray(byte[] data, int offset, int length)
Decode an immutable bitmap from the specified byte array.
static Bitmap	 decodeFile(String pathName)
Decode a file path into a bitmap.
static Bitmap	 decodeFile(String pathName, BitmapFactory.Options opts)
Decode a file path into a bitmap.
static Bitmap	 decodeFileDescriptor(FileDescriptor fd)
Decode a bitmap from the file descriptor.
static Bitmap	 decodeFileDescriptor(FileDescriptor fd, Rect outPadding, BitmapFactory.Options opts)
Decode a bitmap from the file descriptor.
static Bitmap	 decodeResource(Resources res, int id, BitmapFactory.Options opts)
Synonym for opening the given resource and calling decodeResourceStream(Resources, TypedValue, InputStream, Rect, BitmapFactory.Options).
static Bitmap	 decodeResource(Resources res, int id)
Synonym for decodeResource(Resources, int, android.graphics.BitmapFactory.Options) with null Options.
static Bitmap	 decodeResourceStream(Resources res, TypedValue value, InputStream is, Rect pad, BitmapFactory.Options opts)
Decode a new Bitmap from an InputStream.
static Bitmap	 decodeStream(InputStream is)
Decode an input stream into a bitmap.
static Bitmap	 decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts)
Decode an input stream into a bitmap.</span>

例如,要解析SD卡上的图片文件img01.jpg并创建对应的Bitmap对象,可以使用下面的代码:

String path="/sdcard/pictures/abc/img01.jpg";
Bitmap bm=BitmapFactory.decodeFile(path);


要解析Drawable资源中保存的图片文件并创建对应的Bitmep对象。可以使用下面的代码:

Bitmap bm=BitmapFactory.decodeResource(getResources(),R.drawable.xxx);

可以看到此工具类非常方便,但是加载和显示图片是很消耗内存的一件事,BitmapFactory.Options 类允许我们定义图

片以何种方式如何读到内存。

inJustDecodeBounds:如果值设为true,那么将不返回实际的bitmap,也不给其分配内存空间,这样就避免了内存

溢出。但是允许我们查询图片的信息,这其中就包括图片的大小信息(options.outHeight(图片的原始高度)和

options.outWidth(图片的原始宽度))。

inSampleSize:我们可以充分利用它,实现缩放。如果设置为>1,要求解码器解码出原始图片的一个子样本,返回

一个较小的bitmap,以节省空间。例如,inSampleSize==2,则取出的缩略图的宽和高都是原始图片的1/2,图片的大

小就是原始图片的1/4。对于任何值<=1的同样处置为1.

看下面的例子:

import android.graphics.BitmapFactory;
import android.widget.Toast;
public class Decodenewbitmap {

	public Bitmap decodebitmap(Context context, int imageid) {

		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;// 如果值设为true,那么将不返回实际的bitmap,也不给其分配内存空间<span style="white-space:pre">						</span>     这样就避免了内存溢出。
		Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),imageid, options);
		if (bitmap == null) {
			Toast.makeText(context, "bitmap为空", 2).show();//这里能出来,是因为options.inJustDecodeBou<span style="white-space:pre">											</span>nds = true;
		}
		int realwidth = options.outWidth;
		int realheight = options.outHeight;
		System.out.println("图片真实高度" + realheight + "宽度" + realwidth);
		// 计算缩放。
		int scal = (int) ((realheight > realwidth ? realwidth : realheight) / 100);
		if (scal <= 0) {
			scal = 1;
		}
		options.inSampleSize = scal;

		options.inJustDecodeBounds = false;
		bitmap = BitmapFactory.decodeResource(context.getResources(), imageid,
				options);
		int w = bitmap.getWidth();
		int h = bitmap.getHeight();
		if (bitmap == null) {
			Toast.makeText(context, "bitmap为空222", 3).show();
		}
		System.out.println("图片缩略图高度" + h + "宽度" + w);
		return bitmap;
	}
}

注意:在Android 2.3.3以及之前,建议使用Bitmap.recycle()方法,及时释放资源。

      在Android 3.0开始,可设置BitmapFactory.options.inBitmap值,(从缓存中获取)达到重用Bitmap的目的。如果设

置,则inPreferredConfig属性值会被重用的Bitmap该属性值覆盖。

Options.inPurgeable和inInputShareable:inPurgeable:设置为True,则使用BitmapFactory创建的Bitmap用于存

储Pixel的内存空间,在系统内存不足时可以被回收,当应用需要再次访问该Bitmap的Pixel时,系统会再次调用

BitmapFactory 的decode方法重新生成Bitmap的Pixel数组。设置为False时,表示不能被回收。inInputShareable:

设置是否深拷贝,与inPurgeable结合使用,inPurgeable为false时,该参数无意义。

inTempStorage当在android设备中载入较大图片资源时,可以创建一些临时空间,将载入的资源载入到临时空间

中。opts.inTempStorage = new byte[16 * 1024];

注意decodeFileDescriptor()来生成bimap比decodeFile()省内存

原因:查看BitmapFactory的源码,对比一下两者的实现,可以发现decodeFile()最终是以流的方式生成bitmap

public static Bitmap decodeFile(String pathName, Options opts) {
    Bitmap bm = null;
    InputStream stream = null;
    try {
        stream = new FileInputStream(pathName);
        bm = decodeStream(stream, null, opts);
    } catch (Exception e) {
        /*  do nothing.
            If the exception happened on open, bm will be null.
        */
    } finally {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                // do nothing here
            }
        }
    }
    return bm;
}

decodeFileDescriptor的源码,可以找到native本地方法decodeFileDescriptor,通过底层生成bitmap

ublic static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
       if (nativeIsSeekable(fd)) {
           Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
           if (bm == null && opts != null && opts.inBitmap != null) {
               throw new IllegalArgumentException("Problem decoding into existing bitmap");
           }
           return finishDecode(bm, outPadding, opts);
       } else {
           FileInputStream fis = new FileInputStream(fd);
           try {
               return decodeStream(fis, outPadding, opts);
           } finally {
               try {
                   fis.close();
               } catch (Throwable t) {/* ignore */}
           }
       }
   }
 
private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,Rect padding, Options opts);

完整代码:

public static OutputStream decodeBitmap(String path) {
 
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;// 设置成了true,不占用内存,只获取bitmap宽高
        BitmapFactory.decodeFile(path, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, 1024 * 800);
 
        opts.inJustDecodeBounds = false;// 这里一定要将其设置回false,因为之前我们将其设置成了true
        opts.inPurgeable = true;
        opts.inInputShareable = true;
        opts.inDither = false;
        opts.inPurgeable = true;
        opts.inTempStorage = new byte[16 * 1024];
        FileInputStream is = null;
        Bitmap bmp = null;
        InputStream ins = null;
        ByteArrayOutputStream baos = null;
        try {
            is = new FileInputStream(path);
            bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);           double scale = getScaling(opts.outWidth * opts.outHeight, 1024 * 600);
            Bitmap bmp2 = Bitmap.createScaledBitmap(bmp,
                    (int) (opts.outWidth * scale),
                    (int) (opts.outHeight * scale), true);
            bmp.recycle();
            baos = new ByteArrayOutputStream();
            bmp2.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            bmp2.recycle();
            return baos;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
                ins.close();
                baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.gc();
        }
        return baos;
    }
 
private static double getScaling(int src, int des) {
/**
 * 目标尺寸÷原尺寸 sqrt开方,得出宽高百分比
 */
    double scale = Math.sqrt((double) des / (double) src);
    return scale;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值