Android Bitmap解析 缩放问题

本文探讨了Android中Bitmap解析时遇到的大小与资源文件位置相关的问题。当Bitmap位于不同dpi资源文件夹时,Android系统会根据屏幕密度进行自动缩放,导致文字和图片位置、大小不符。解决方案是在decodeResource时使用Options防止缩放。
摘要由CSDN通过智能技术生成

想起以前做东西的时候遇到一个Bitmap 大小与资源文件存放位置有关的问题,有时间了分享下。在这里插入图片描述
索大大霸气镇楼,哈哈哈哈哈。
做的东西大概是这样子要求:

  1. 需要分享一张索大大的海报,这张海报的底图放在app里,
  2. 这张海报上要写一些前辈赠言,这些文字由服务器下发,
  3. 可能还需要在某些位置添加一些图片,也从服务器获取,
  4. 图片和文字的绝对位置都会标注出来(就是距离左边和上边多少像素)
  5. 在用户点击分享的时候把这些信息在底图上绘制出来(不显示预览),直接把生成的新海报分享出去。

看到这里感觉还不难,不就是在Bitmap上画几张图片和几句话嘛,然后就开始码了。

    Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.zoro).copy(Bitmap.Config.ARGB_8888, true);
        Canvas canvas = new Canvas(bitmap);
        TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        paint.setTextSize(20);
        paint.setColor(Color.BLACK);
        paint.setTypeface(Typeface.DEFAULT_BOLD);
        Rect rect = new Rect();
        paint.getTextBounds("认", 0, 1, rect);//获取单个文字宽度
        canvas.save();
        canvas.translate(50, 50); //在距离左边50像素,上边50像素处开始绘制文字
        StaticLayout textLayout = new StaticLayout("认清自己", paint, rect.width(), Layout.Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);//让文字竖着显示
        textLayout.draw(canvas);
        canvas.restore();
        imageView.setImageBitmap(bitmap);

背景图zoro放在hdpi资源文件夹里面,尺寸为720×360,然后我将需要的效果图和自己绘制的图同时显示在手机上一看,运行代码得到的海报图片与效果图文字位置大小一点都不对。看图:
在这里插入图片描述
上面的图是要的效果图,而下面的图是自己用代码绘制出来,文字的位置不对,大小也不对,怎么会这样呢!位置和大小像是被缩小了两倍。看了下代码也没什么问题,然后打印日志看一下生成图片的大小,尺寸居然是1260×630,原来是图片放大了,这就想通了为什么文字位置和大小会不一样了。问题找到了,但是为什么出现这样的问题呢?第一反应想到的就是Android屏幕适配了,hdpi,xhdpi,xxhdpi等几个文件夹存放的的资源文件都是为了适配不同像素密度的手机的。然后我把底图zoro换到xxhdpi文件夹中,看下效果。文字大小和位置差就不是很多了,果然跟适配有关系。看下几个不同资源文件夹下生成的图片尺寸大小。
在这里插入图片描述
看完这些数据应该就明白了,存放的位置不同导致生成的图片尺寸的不同。以图片存放在hdpi文件里为例,hdpi对应的密度值是240,而实际屏幕的密度值是420,要达到这样的密度值,需要放大420/240=1.75倍,那么图片实际生成的宽度就是720×1.75=1260,高度就是360×1.75=630。这也应该是Android屏幕适配的基础了。资源文件存放的位置不对,加载图片也会导致OOM。
那怎么解决呢?既然我看看到了Bitmap会对图片缩放,只要解析图片的不进行缩放即可,看代码


 BitmapFactory.Options options = new BitmapFactory.Options();
 options.inDensity = 1;
 options.inTargetDensity = 1;
 
  Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.zoro,options).copy(Bitmap.Config.ARGB_8888, true);

我们decodeResource时候加一个Options即可。之所以要这样是因为BitmapFactory.decodeResource()这个方法里面做了像素密度处理。看源码:

public static Bitmap decodeResource(Resources res, int id, Options opts) {
        Bitmap bm = null;
        InputStream is = null; 
        
        try {
            final TypedValue value = new TypedValue(); //实例了TypeValue
            is = res.openRawResource(id, value);  //这里的TypeValue会根据资源存放在不同资源文件夹里面获取对应密度值,下面要用

            bm = decodeResourceStream(res, value, is, null, opts);
        } catch (Exception e) {
            /*  do nothing.
                If the exception happened on open, bm will be null.
                If it happened on close, bm is still valid.
            */
        } finally {
            try {
                if (is != null) is.close();
            } catch (IOException e) {
                // Ignore
            }
        }

        if (bm == null && opts != null && opts.inBitmap != null) {
            throw new IllegalArgumentException("Problem decoding into existing bitmap");
        }

        return bm;
    }

没什么东西接着看decodeResourceStream()

public static Bitmap decodeResourceStream(Resources res, TypedValue value,
            InputStream is, Rect pad, Options opts) {

        if (opts == null) {
            opts = new Options();
        }

        if (opts.inDensity == 0 && value != null) {
            final int density = value.density;//就是这里,这个密度就是资源文件夹对应的密度
            if (density == TypedValue.DENSITY_DEFAULT) {
                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
            } else if (density != TypedValue.DENSITY_NONE) {
                opts.inDensity = density;
            }
        }
        
        if (opts.inTargetDensity == 0 &&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值