Android高品質高圧縮比画像圧縮
一般的にAndroidプロジェクトでは、アルバムから写真を選択してサーバーにアップロードする必要がありますが、fileファイルを直接アップロードすることはできません.画素の高い携帯電話では、1300万台のカメラが最大9-10 mに達するなど、撮影された写真の体積も大きくなります.このようにアップロードする前に圧縮する必要がありますが、雰囲気の画像サイズの圧縮と品質の圧縮を圧縮する必要があります.圧縮中にOOMが発生する可能性が高いので、以下は画像圧縮ツール類で、まず画像幅の高い圧縮を行い、比較的大きな画像を1280*1280の大きさ範囲に圧縮してoomを減らし、その後品質の圧縮を行い、一般的に品質は70-100の間に維持され、肉眼ではほとんど差が見えないが、大きさは明らかに改善することができ、圧縮後の大きさ範囲は100 k-200 kの間で、サーバへのアップロードが容易です.幅の高い圧縮と品質の圧縮はそれぞれ1回実行して、循環圧縮がないので、私はいくつかの循環圧縮の方案が往々にして画像の品質を著しく低下させることを発見して、俗に写真のペーストと呼ばれています.
呼び出し方法:ここでは、出力ストリームからバイト配列を取得してアップロードの準備をします.
package com.example.administrator.jnidemo;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Build;
import android.util.Log;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* Created by Administrator on 2016/4/6.
*/
public class AlxBitMapUtils {
/**
* bitmap,
* @param bitmap
* @param widthRatio , 1 , 1
* @param heightRatio
* @return
*/
public static Bitmap scaleBitmap(Bitmap bitmap, float widthRatio, float heightRatio) {
Matrix matrix = new Matrix();
matrix.postScale(widthRatio,heightRatio);
return Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
}
/**
* , , ,
* @param oriFile
* @param targetFile stream
* @param ifDel
*/
public static void compressImage(File oriFile, File targetFile, OutputStream stream,boolean ifDel) {
if(oriFile ==null)return;
Log.i("Alex"," "+oriFile);
Log.i("Alex"," "+targetFile);
try {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true; // , ,
BitmapFactory.decodeFile(oriFile.getAbsolutePath(), opts);// , Options
// Options
int imageHeight = opts.outHeight;
int imageWidth = opts.outWidth;
int longEdge = Math.max(imageHeight,imageWidth);//
int pixelCount = (imageWidth*imageHeight)>>20;//
Log.i("Alex"," "+imageWidth+" "+imageHeight+" "+pixelCount+" ");
long size = oriFile.length();
Log.i("Alex","f.length "+(size)+" B");
// , bitmap
Bitmap bitmap = null;
if(pixelCount > 4){// 4 ,
float compressRatio = longEdge /1280f;
int compressRatioInt = Math.round(compressRatio);
if(compressRatioInt%2!=0 && compressRatioInt!=1)compressRatioInt++;// ,
Log.i("Alex"," "+compressRatio+" "+compressRatioInt);
//
BitmapFactory.Options options = new BitmapFactory.Options();
// 1024*1024 1 ,100k
options.inSampleSize = Math.round(compressRatioInt);// , , , 1280*1.5, ,
options.inJustDecodeBounds = false;// decode file , ,
options.inPreferredConfig = Bitmap.Config.RGB_565;// , R=5,G=6,B=5, , 5+6+5=16
// bitmap
bitmap = BitmapFactory.decodeFile(oriFile.getAbsolutePath(), options);// bitmap
// bitmap
}else {// 1920 ,
// bitmap
bitmap = BitmapFactory.decodeFile(oriFile.getAbsolutePath());
// bitmap
}
if(targetFile!=null)compressMethodAndSave(bitmap, targetFile);
if(stream!=null)compressBitmapToStream(bitmap,stream);
if(ifDel) oriFile.delete();//
System.gc();
}catch (Exception e){
Log.d("Alex",""+e.getMessage().toString());
}
}
/**
* bitmap
* @param image
* @return
*/
private static int getSize(Bitmap image){
int size=0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //API 19
size = image.getAllocationByteCount();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {//API 12
size = image.getByteCount();
} else {
size = image.getRowBytes() * image.getHeight();
}
return size;
}
/**
* bitmap , , ,
* @param image
* @param targetFile
*/
public static void compressMethodAndSave(Bitmap image,File targetFile){
try {
OutputStream stream = new FileOutputStream(targetFile);
int size = compressBitmapToStream(image,stream);
if(size==0)return;
long afterSize = targetFile.length();
Log.i("Alex"," "+(afterSize>>10)+"KB :::"+afterSize*100/size+"%");
}catch (Exception e){
Log.i("Alex"," ",e);
}
}
public static int compressBitmapToStream(Bitmap image,OutputStream stream){
if(image==null || stream==null)return 0;
try {
Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
int size = getSize(image);
Log.i("Alex"," bitmap "+(size>>10)+" KB "+image.getWidth()+" "+image.getHeight());
int quality = getQuality(size);//
Log.i("Alex"," "+quality);
long startTime = System.currentTimeMillis();
image.compress(format, quality, stream);//
if (image != null) {
image.recycle();// bitmap
image = null;
}
Log.i("Alex"," "+(System.currentTimeMillis()-startTime));
return size;
}catch (Exception e){
Log.i("Alex"," ",e);
}
return 0;
}
/**
* , bitmap , 1000*1000,
* @param size
* @return
*/
private static int getQuality(int size){
int mb=size>>20;// 100 , m
int kb = size>>10;
Log.i("Alex"," , "+kb+"KB, "+mb);
if(mb>70){
return 17;
}else if(mb>50){
return 20;
}else if(mb>40){
return 25;
}else if(mb>20){
return 40;
}else if(mb>10){
return 60;
}else if(mb>3){// 100k,
return 60;
}else if(mb>=2){
return 60;
}else if(kb > 1500){
return 70;
}else if(kb > 1000){
return 80;
}else if(kb>500){
return 85;
}else if(kb>100){
return 90;
}
else{
return 100;
}
}
/**
* assets Bitmap
* @param fileName
* @return
*/
public static Bitmap getDataFromAssets(Context context,String fileName){
Log.i("Alex"," assets "+fileName);
try {
// context.getResources().getAssets().open(fileName); InputStream BufferedInputStream
AssetFileDescriptor descriptor = context.getResources().getAssets().openFd(fileName);// FileInputStream, NIO Channel
long fileSize = descriptor.getLength();
Log.i("Alex"," "+fileSize);// , decodeStream
Bitmap bitmap = BitmapFactory.decodeStream(context.getResources().getAssets().open(fileName));
// Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);// ,AssetFileDescriptor , inputStream, FileDescriptor BitmapFactory.decodeStream
if(bitmap==null)Log.i("Alex","decode bitmap ");
return bitmap;
} catch (Exception e) {
Log.i("Alex"," ",e);
e.printStackTrace();
}
return null;
}
public static boolean copyFile(File sourceFile,File targetFile){
//NIO :1) FileInputStream Channel ;2) buffer ;3) Channel Buffer ;
FileInputStream fin = null;
FileOutputStream fout = null;
FileChannel fcin = null;
FileChannel fcout = null;
try {
fin = new FileInputStream( sourceFile );
fout = new FileOutputStream( targetFile );
fcin = fin.getChannel();
fcout =fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int r = 0;
while ((r = fcin.read(buffer))!=-1) {
buffer.clear();
buffer.flip();// ,
fcout.write(buffer);
}
return true;
} catch (Exception e){
Log.i("Alex"," ",e);
}finally {
if(fin!=null) try {
fin.close();
if(fout!=null)fout.close();
if(fcin!=null)fcin.close();
if(fcout!=null)fcout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
呼び出し方法:ここでは、出力ストリームからバイト配列を取得してアップロードの準備をします.
private byte[] getCompressedUploadPhotoBitmapByteArray(String filePath, int inSampleSize, int quality) {
byte[] bitmapDataByteArray = {};
if (!JDataUtils.isEmpty(filePath)) {
File file = new File(filePath);
if (file.exists()) {
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();// , ,
AlxBitmapUtils.compressImage(file,null,baos,false);// ,
bitmapDataByteArray = baos.toByteArray();
Log.i("Alex"," "+(bitmapDataByteArray.length>>10)+" KB");
} catch (Throwable throwable) {
} finally {
try {
if (baos != null) {
baos.close();
}
} catch (Throwable throwable) {
}
}
} else {
bitmapDataByteArray = null;
}
} else {
bitmapDataByteArray = null;
}
return bitmapDataByteArray;
}