How to subsample/resize an image like in whatsapp

2020-02-26 14:30发布

When sending an image through whatsapp, you can see the image you are sending in an imageview scaled very very well

for example, i sent two images to my friend

  • size of first image : 1296 pixels X 2304 pixels

  • size of second image : 1920 pixels X 1080 pixels

this images are too big therefore whatsapp has to scale them before showing them to me in an imageview

  • size of first image after being scaled by whatapp 333 pixels X 339 pixels

  • size of second image after being scaled by whatsapp 333 pixels X 187 pixels

As you can see the width is the same only height differs. i have tried to figure out how whatapp scales this images, but my methods gives me an image with a different dimensions far from whatsapp's ones

Method 1

private void resizeImage(){

Uri selectedImage = imageReturnedIntent.getData();
                      d("image url is " + selectedImage);
                      InputStream imageStream = getContentResolver().openInputStream(selectedImage);
                       BitmapFactory.decodeStream(imageStream,null, options);
                      imageHeight = options.outHeight;
                      imageWidth = options.outWidth;

                      options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
                      options.inJustDecodeBounds = false;
                      bitmap = BitmapFactory.decodeStream(imageStream,null, options);

}
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth , int reqHeght){

    int height = options.outHeight;
    int width = options . outWidth;
    d("width is "+ width + " height is "+ height);
    d("required width is "+ reqWidth + " required height "+ reqHeght);
    int inSampleSize = 1;

    if(height > reqHeght || width > reqWidth){

        int heightRatio = Math.round((float)height/(float)reqHeght);
        d("height ratio is "+ heightRatio);

        int widthRatio = Math.round((float)width / (float) reqWidth);
        d("width ratio is "+widthRatio);

        inSampleSize = (heightRatio > widthRatio)? heightRatio :widthRatio;
    }
    d(" insample size is "+ inSampleSize);
    return inSampleSize;
}

Output for first image using the above method : Smaller(< 333) width, very big height(>339. it's 579!!)

Second method

private Bitmap scaleToFitWidth(Bitmap b, int width){
  float factor = width/b.getWidth(); // width is 333

  return Bitmap.createScaledBitmap(b, width,(int)(b.getHeight() * factor),true)
}

Output of first image in second method: image height is very very big!

Question Does anyone knows how to scale images very well like whatapp Across all devices?(i would like to be the same as whatsapp if possible)

EDIT: whatsapp Images

My huawel phone

 image is huawel

samsung tablet

image in samsung talet

2条回答
祖国的老花朵
2楼-- · 2020-02-26 15:00

You can checkout this code it works same as you wanted WhatsApp Like Image Compression. This code has been modified according to my usage. Using this code will provide you :

  • Low Size Images around 100kb without playing with image quality.
  • High pixel images will be scaled down to maxWidth and maxHeight without loosing its original quality.

Original Article : Loading images Super-Fast like WhatsApp

Demo :

Original Image : Size - 3.84Mb Dimensions - 3120*4160

Compressed Image : Size - 157Kb Dimensions - 960*1280

Edit 1: You can also make a custom Square ImageView which extends ImageView Class. SquareImageView

查看更多
\"骚年 ilove
3楼-- · 2020-02-26 15:10

How to subsample/resize an image like in whatsapp

  • You can do it by simply using Glide as follows. Replace the value 500,500 with your required image quality.

    Glide.with(getApplicationContext())
                .load(uri)
                .asBitmap()
                .into(new SimpleTarget<Bitmap>(500, 500) {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
                        bitmap = resource;//this is the required bitmap
                        imageView.setImageBitmap(resource); 
                    }
                });
    
  • If you want to save the Bitmap as a file, use the following method

      private File savebitmap(String filename) {
      String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
      OutputStream outStream = null;
    
      File file = new File(filename + ".png");
      if (file.exists()) {
         file.delete();
         file = new File(extStorageDirectory, filename + ".png");
         Log.e("file exist", "" + file + ",Bitmap= " + filename);
      }
      try {
         // make a new bitmap from your file
         Bitmap bitmap = BitmapFactory.decodeFile(file.getName());
    
         outStream = new FileOutputStream(file);
         bitmap.compress(Bitmap.CompressFormat.JPG, 100, outStream);
         outStream.flush();
         outStream.close();
      } catch (Exception e) {
         e.printStackTrace();
      }
      Log.e("file", "" + file);
      return file;
    

    }

  • To include Glide in your project, add the following to your gradle file

     repositories {
     mavenCentral() // jcenter() works as well because it pulls from Maven    Central
     }
    
     dependencies {
     compile 'com.github.bumptech.glide:glide:3.7.0'
     compile 'com.android.support:support-v4:19.1.0'
     }
    
查看更多
登录 后发表回答