Common compression technology for Android Images
The image upload function is currently being used to take images from the camera or select a photo album. I. Basic knowledge about images 1. File Format (that is, binary format exists on the hard disk)
Get size (Byte): File. length ()
2. Stream format (that is, it exists in the memory in the binary form)
Get size (Byte): new FileInputStream (File). available ()
3. Bitmap format
Get size (Byte): Bitmap. getByteCount ()
The following uses the picture I took as an example to see the differences between the three (the software used is a temporary tool developed by myself );
We can see that:
1. The size of the photo file is the same as the size of the file stream read to the memory, indicating that the file format and stream format have no effect on the size of the image.
2. When images exist in the form of Bitmap, the occupied memory is much larger. Why? First, we need to know the Bitmap size calculation method.
Bitmap size = image length (px) * image width (px) * bytes occupied by pixels
What is the number of bytes occupied by the unit pixel? To put it bluntly, it is the color pattern of the image.
Here we can find BitmapFactory. Options. inPreferredConfig. There are four types, which are: A transparency, R red, G green, and B blue.
The size of the above bitmap in the memory can be calculated (the default color mode is ARGB_8888 ),
2368*4224*4/1024/1024 = 38.15625
It is recommended that bitmap. recycle () is called after Bitmap is used up because the GC process automatically recycles the resource.
2. compression format of images
Q: Why do we operate images locally. Yes
A: Upload (for example, set an avatar and publish an image ).
Upload steps
So the question is
Q: Why do we need to compress images?
A: The objective is nothing more than two. One is to avoid occupying too much memory. 2. You may need to upload images. If the images are too large, the traffic will be wasted. (Except for uploading source images)
1. Avoid excessive memory compression:
In the final analysis, the image is to be displayed on the interface component, so bitmap is still used. It can be obtained from the above that the size of Bitmap in memory is only related to the image size and color mode, to change the size of Bitmap in memory, either change the size or color mode.
2. compression methods to avoid wasting upload traffic:
Change the image size, color mode, and quality. Under normal circumstances, first change the image size and color mode, and then change the image quality.
Compression Method for changing image quality:
/***** Compressing Image Quality Based on bitmap * @ param bitmap uncompressed bitmap * @ return compressed bitmap */public static Bitmap cQuality (Bitmap bitmap) {ByteArrayOutputStream bOut = new ByteArrayOutputStream (); int beginRate = 100; // The first parameter is image format, and the second parameter is image quality. The value 100 is the highest and the value 0 is the worst, the third parameter is to save the bitmap of the compressed data stream. compress (Bitmap. compressFormat. JPEG, 100, bOut); while (bOut. size ()/1024/1024> 100) {// If the size is greater than kb after compression, the compression rate is increased and the beginRate-= 10; bOut is recompressed. reset (); bitmap. Compress (Bitmap. compressFormat. JPEG, beginRate, bOut);} ByteArrayInputStream bInt = new ByteArrayInputStream (bOut. toByteArray (); Bitmap newBitmap = BitmapFactory. decodeStream (bInt); if (newBitmap! = Null) {return newBitmap;} else {return bitmap ;}}
Compression Algorithm for changing the image size:
Public static boolean getCacheImage (String filePath, String cachePath) {OutputStream out = null; BitmapFactory. options option = new BitmapFactory. options (); option. inJustDecodeBounds = true; // set to true, read-only size information, do not load pixel information to the memory Bitmap bitmap = BitmapFactory. decodeFile (filePath, option); // bitmap is empty option. inJustDecodeBounds = false; int bWidth = option. outWidth; int bHeight = option. outHeight; int toWidth = 400; int toHeight = 800; int be = 1; // be = 1 indicates not scaling if (bWidth/toWidth> bHeight/toHeight & bWidth> toWidth) {be = (int) bWidth/toWidth;} else if (bWidth/toWidth
ToHeight) {be = (int) bHeight/toHeight;} option. inSampleSize = be; // set the scaling ratio bitmap = BitmapFactory. decodeFile (filePath, option); try {out = new FileOutputStream (new File (cachePath);} catch (IOException e) {// TODO Auto-generated catch blocke. printStackTrace ();} return bitmap. compress (CompressFormat. JPEG, 100, out );}
Under normal circumstances, we should combine the two, so we have the following algorithm (it is used directly in the project, and the definition is no problem on the mobile phone)
public static File scal(Uri fileUri){String path = fileUri.getPath();File outputFile = new File(path);long fileSize = outputFile.length();final long fileMaxSize = 200 * 1024; if (fileSize >= fileMaxSize) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); int height = options.outHeight; int width = options.outWidth; double scale = Math.sqrt((float) fileSize / fileMaxSize); options.outHeight = (int) (height / scale); options.outWidth = (int) (width / scale); options.inSampleSize = (int) (scale + 0.5); options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(path, options); outputFile = new File(PhotoUtil.createImageFile().getPath()); FileOutputStream fos = null;try {fos = new FileOutputStream(outputFile);bitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos);fos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} Log.d(, sss ok + outputFile.length()); if (!bitmap.isRecycled()) { bitmap.recycle(); }else{ File tempFile = outputFile; outputFile = new File(PhotoUtil.createImageFile().getPath()); PhotoUtil.copyFileUsingFileChannels(tempFile, outputFile); } } return outputFile;}
Two methods used in the above algorithm:
public static Uri createImageFile(){ // Create an image file name String timeStamp = new SimpleDateFormat(yyyyMMdd_HHmmss).format(new Date()); String imageFileName = JPEG_ + timeStamp + _; File storageDir = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); File image = null;try {image = File.createTempFile( imageFileName, /* prefix */ .jpg, /* suffix */ storageDir /* directory */);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} // Save a file: path for use with ACTION_VIEW intents return Uri.fromFile(image);}public static void copyFileUsingFileChannels(File source, File dest){ FileChannel inputChannel = null; FileChannel outputChannel = null; try { try {inputChannel = new FileInputStream(source).getChannel();outputChannel = new FileOutputStream(dest).getChannel();outputChannel.transferFrom(inputChannel, 0, inputChannel.size());} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} } finally { try {inputChannel.close();outputChannel.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} } }
The best algorithm is based on the coding client's photo upload algorithm, which simplifies the operation and has been tested.
At last, a demo of selecting photos from the album and camera will be uploaded temporarily based on this algorithm. The function is complete.