- Preface
Picture Compression and Secondary Sampling
Why compress pictures?
Imagine: When an App calls the camera of the system to take photos, if we set the data data data from Intent to the picture, it just shows a thumbnail (120x160 width and height), which can't meet our needs. So when we start Activity (), putExtra() specifies a storage path to get Uri. In the case of ARGB_8888, each pixel takes four bytes. A picture usually reaches a level of 3x x x x 4xxx. After calculation, it will reach a level of 60M of tens of Ms, because by default, each App in the system only has 16m of independent memory, which is easy. The memory is blown up, so compressed pictures are very important!
Picture Compression Process
core
When we load, we use the method with options parameter to load.
- In options, we specify inJustDecodeBounds as true, only decoding edges, so that pictures will not really be loaded into memory. The basic information of pictures, such as width and height, will be loaded into memory.
- Compression ratio, sampling ratio value is n power of 2, downward integer
- Calculate a compression ratio based on the width we want and the width of the image, and set it to options.
- Close the decode-only edge and decode again
Gets the original graph of the specified path
Transfer value when starting camera
private void takePicSave() {
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
//Save EXTRA_OUTPUT: Save the captured image to the specified uri path
mUri = getUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
this.startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE_SAVE);
Gets the file for the specified path
private Uri getUri() {
if(ActivityCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)==PackageManager.PERMISSION_GRANTED){
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//DCIM
File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
long time = System.currentTimeMillis();
File picFile = new File(root,time+".jpg");
return Uri.fromFile(picFile);
}else {
File root = this.getCacheDir();
long time = System.currentTimeMillis();
return Uri.parse("file://"+root.getAbsolutePath()+File.separator+time+".jpg");
}
}else {
//Application for Read-Write Memory Card Permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE},
REQUEST_CODE_EXTERNAL);
}
return null;
}
Image Compression and Secondary Sampling
public Bitmap sampleImage(String filePath){
BitmapFactory.Options options = new BitmapFactory.Options();
// Setting the decoding edge only, the picture will not really be loaded into memory. The decoder loads and returns null.
// But the output field of the picture is assigned.
// For example, the width and height of the picture
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
int outHeight = options.outHeight;
int outWidth = options.outWidth;
int scale = Math.max(outHeight / 300, outWidth / 300);
//scale integrates downward and takes the n power of the true value 2
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath,options);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_TAKE_PICTURE_SAVE:
//If the Intent data passed by the Photo App is empty, there is no data.
//Picture display
//Secondary sampling
Bitmap bitmap = sampleImage(mUri.getPath());
showImage.setImageURI(mUri);
break;
}
In this way, the second sampling and compression of pictures can be realized. You can take the memory tool to measure it by yourself. Before compression, it is about 60M, and after compression, it is about 4M, which greatly reduces the memory occupancy. It is also an important optimization of App.
Reprinted please indicate the source