问题
I want to reduce the image file size below 100 KB while preserving the image quality like whatsapp and facebook did.
I tried almost all the code of android image compression available on stackoverflow but that doesn't work for me.
Right now i am following this blog to reduce the image size, and i am getting the image below 100 KB but image quality is poor.
Is there any way that i can reduce image size below 100 KB while preserving the quality??? (Original Image size can vary from 20 KB to 8 MB)
I tried JAI library in Java Project, and it work good.
Can i Use JAI library in android to reduce image size???
Thanks in Advance.
Source Code to compress an Image:
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.media.ExifInterface;
import android.os.Environment;
import android.util.Log;
public class CompressBitmap {
private String path;
public CompressBitmap(String path){
this.path= path;
}
public ByteArrayOutputStream getBitmap(){
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
getscaledImage(path).compress(Bitmap.CompressFormat.JPEG, 100, outStream);
return outStream;
}
public ByteArrayOutputStream getBitmap(int quality){
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
getscaledImage(path).compress(Bitmap.CompressFormat.JPEG, quality, outStream);
return outStream;
}
public String getComressFile(){
FileOutputStream out = null;
String filename = createImageFile();
try {
out = new FileOutputStream(filename);
getscaledImage(path).compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
File file = new File(filename);
Log.e("SIze of Image","Length"+file.length());
return filename;
}
private Bitmap getscaledImage(String filePath){
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath,options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float maxHeight = 800.0f;
float maxWidth = 600.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
Log.v("Pictures", "Before scaling Width and height are " + actualWidth + "--" + actualHeight);
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16*1024];
try{
bmp = BitmapFactory.decodeFile(filePath,options);
}
catch(OutOfMemoryError exception){
exception.printStackTrace();
}
try{
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
}
catch(OutOfMemoryError exception){
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float)options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth()/2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
Log.v("Pictures", "After scaling Width and height are " + scaledBitmap.getWidth() + "--" + scaledBitmap.getHeight());
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
return scaledBitmap;
}
private String createImageFile(){
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",Locale.getDefault()).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image;
try {
image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return image.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
return inSampleSize;
}
}
public void getBase64() {
CompressBitmap compressBitmap = new CompressBitmap(picturePath);
//display compressBitmap in ImageView.
byte[] bytes=null;
File file= new File(picturePath);
ByteArrayOutputStream bos = compressBitmap.getBitmap();
bytes = bos.toByteArray();
base64 = Base64.encodeToString(bytes, Base64.DEFAULT);
return base64; // send base64 String on server
}
回答1:
Missing seems:
options.inPreferQualityOverSpeed = true;
来源:https://stackoverflow.com/questions/25244799/resizing-pictures-while-still-preserving-quality-in-android