【问题标题】:Android: Resizing Bitmaps without losing qualityAndroid:在不损失质量的情况下调整位图大小
【发布时间】:2013-05-04 03:50:06
【问题描述】:

在发布之前,我已经在整个网络上进行了真正的搜索。我的问题是我无法在不丢失图像质量的情况下调整位图大小(质量非常差且像素化)。

我从相机中获取位图,然后我必须缩小它,这样我可以更快地将它上传到服务器。

这是进行采样的函数

public Bitmap resizeBitmap(Bitmap bitmap){
         Canvas canvas = new Canvas();
         Bitmap resizedBitmap = null;
         if (bitmap !=null) {
                int h = bitmap.getHeight();
                int w = bitmap.getWidth();
                int newWidth=0;
                int newHeight=0;

                if(h>w){
                    newWidth = 600;
                    newHeight = 800;
                }

                if(w>h){
                    newWidth = 800;
                    newHeight = 600;
                    }

                float scaleWidth = ((float) newWidth) / w;
                float scaleHeight = ((float) newHeight) / h;



                Matrix matrix = new Matrix();
                // resize the bit map
                matrix.preScale(scaleWidth, scaleHeight);

                resizedBitmap  = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);



                Paint paint = new Paint();
                paint.setAntiAlias(true);
                paint.setFilterBitmap(true);
                paint.setDither(true);

                canvas.drawBitmap(resizedBitmap, matrix, paint);



            }


        return resizedBitmap;   

这就是我从活动结果中获取图像的方式

 protected void onActivityResult(int requestCode, int resultCode,
             Intent data) {
         if(resultCode != RESULT_CANCELED){

         if (requestCode == 0) {
             if (resultCode == RESULT_OK) {


                    getContentResolver().notifyChange(mImageUri, null);
                    ContentResolver cr = this.getContentResolver();

                    try
                    {
                        b = android.provider.MediaStore.Images.Media.getBitmap(cr, mImageUri);
                        Log.d("foto", Integer.toString(b.getWidth()));
                        Log.d("foto", Integer.toString(b.getHeight()));
                        addPhoto.setImageBitmap(b);

                    }
                    catch (Exception e)
                    {
                        Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT).show();
                        Log.d("TAG", "Failed to load", e);
                    }



             }
         }

我开始认为获得小图片的最佳方法是设置相机分辨率。其他人可以帮忙吗?

【问题讨论】:

    标签: java android bitmap resize


    【解决方案1】:

    良好的缩小算法(不是最近邻)仅包含 2 个步骤(加上计算输入/输出图像裁剪的精确矩形):

    1. 使用 BitmapFactory.Options::inSampleSize->BitmapFactory.decodeResource() 尽可能接近您需要的分辨率,但不能低于它
    2. 使用 Canvas::drawBitmap() 稍微缩小一点以达到精确的分辨率

    这里是索尼移动如何解决这个任务的详细解释:http://developer.sonymobile.com/2011/06/27/how-to-scale-images-for-your-android-application/

    这里是SonyMobile scale utils的源代码:http://developer.sonymobile.com/downloads/code-example-module/image-scaling-code-example-for-android/

    【讨论】:

    • 这应该是公认的答案。刚刚实现了链接文章中描述的内容,结果比简单地使用 createScaledBitmap 好得多,并且在缩小时使用的也少得多。结果仍然不如缩小比例时那么好,例如不过在 Photoshop 中。
    • 我已经尝试过这种 FIT 方法,它与使用默认 Bitmap.createScaledBitmap 的质量完全相同。可能会更快/更少的内存消耗,但质量是一样的。
    • upd - 刚刚检查了时间,两种方法使用相同的时间,在我的情况下是 2-3 毫秒。而且我没有使用他们的解码方法,因为我有一个现成的位图作为输入,所以内存使用也没有变化。
    • 不幸的是,就我而言,这两个链接都不再起作用了。每个只是重定向到developer.sony.com
    【解决方案2】:

    尝试下面提到的代码来调整位图大小。

     public Bitmap get_Resized_Bitmap(Bitmap bmp, int newHeight, int newWidth) {
            int width = bmp.getWidth();
            int height = bmp.getHeight();
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // CREATE A MATRIX FOR THE MANIPULATION
            Matrix matrix = new Matrix();
            // RESIZE THE BIT MAP
            matrix.postScale(scaleWidth, scaleHeight);
    
            // "RECREATE" THE NEW BITMAP
            Bitmap newBitmap = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix, false);
            return newBitmap ;
        }
    

    我用这段代码缩小了我的位图,它的质量,嗯..,是可以接受的。

    希望这会有所帮助。

    【讨论】:

    • 位图质量没有提升,得到的结果和以前一样
    【解决方案3】:

    试试Bitmap.createScaledBitmap。 它还具有过滤源的选项。

    【讨论】:

    • 谢谢...但我试过了:resizedBitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);但它是一样的......仍然是块状和像素化
    • 我明白了。我想到的最后一个提示是您检查 BitmapFactory.Options 类,在解码您的位图时初始化并使用与质量相关的选项。这是 API 链接:developer.android.com/reference/android/graphics/…
    • 通过使用 bitmap.factory 选项从 uri 解码位图,我已经达到了至少可以接受的程度。但这仍然不是我想象的质量。 facebook 和 g+ 如何处理照片上传?我看到他们调整了您上传的所有图像的大小。他们如何做到这一点而不损失一个像素的质量?
    • 我会探索更多的 BitmapFactory.Options - 以防万一你错过了什么。我知道这不是一个非常有用的答案,但我不知道如何进一步帮助您:(
    • @Vahn84 你能更新一下你最终的结果吗?
    【解决方案4】:

    我遇到的最好的重新缩放方法 该方法使用createScaledBitmap,其中高度和宽度是根据位图高度和宽度和比例计算的,因此不会丢失质量

     public Bitmap resize(Bitmap imaged, int maxWidth, int maxHeight) {
            Bitmap image = imaged;
    
            if (maxHeight > 0 && maxWidth > 0) {
                int width = image.getWidth();
                int height = image.getHeight();
                float ratioBitmap = (float) width / (float) height;
                float ratioMax = (float) maxWidth / (float) maxHeight;
                int finalWidth = maxWidth;
                int finalHeight = maxHeight;
                if (ratioMax > 1) {
                    finalWidth = Math.round(((float) maxHeight * ratioBitmap));
                } else {
                    finalHeight = Math.round(((float) maxWidth / ratioBitmap));
                }
                return image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, false);
            }
            return image;
        }
    

    使用方法:

    Bitmap resizedBitmap = resize(scrBitMap,640,640);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 1970-01-01
      相关资源
      最近更新 更多