Tôi đang làm việc trên một ứng dụng Android, có tính năng chụp ảnh và chụp ảnh. Nếu thiết bị có máy ảnh có độ phân giải cao, kích thước hình ảnh được chụp sẽ thực sự lớn (1 ~ 3MB trở lên).
Vì ứng dụng sẽ cần phải tải hình ảnh này lên máy chủ, tôi sẽ cần nén hình ảnh trước khi tải lên. Ví dụ: nếu máy ảnh đã chụp ảnh có độ phân giải 1920x1080, đầu ra lý tưởng là giữ tỷ lệ 16: 9 của hình ảnh, nén nó thành hình ảnh 640x360 để giảm một số chất lượng hình ảnh và làm cho kích thước nhỏ hơn theo byte.Android - Chia tỷ lệ và nén một bitmap
Đây là mã của tôi (tham chiếu từ google):
/**
* this class provide methods that can help compress the image size.
*
*/
public class ImageCompressHelper {
/**
* Calcuate how much to compress the image
* @param options
* @param reqWidth
* @param reqHeight
* @return
*/
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height/2;
final int halfWidth = width/2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight/inSampleSize) > reqHeight
&& (halfWidth/inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
/**
* resize image to 480x800
* @param filePath
* @return
*/
public static Bitmap getSmallBitmap(String filePath) {
File file = new File(filePath);
long originalSize = file.length();
MyLogger.Verbose("Original image size is: " + originalSize + " bytes.");
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
// Calculate inSampleSize based on a preset ratio
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap compressedImage = BitmapFactory.decodeFile(filePath, options);
MyLogger.Verbose("Compressed image size is " + sizeOf(compressedImage) + " bytes");
return compressedImage;
}
Vấn đề với mã trên là:
- Nó không thể giữ tỷ lệ, các mã được buộc hình ảnh để thay đổi kích cỡ để 480x800. nếu người dùng chụp ảnh ở tỷ lệ khác, hình ảnh sẽ không đẹp sau khi nén.
Nó không hoạt động tốt. Mã sẽ luôn thay đổi kích thước hình ảnh thành 7990272byte bất kể kích thước tệp gốc là gì. Nếu kích thước ảnh gốc là khá nhỏ đã có, nó sẽ làm cho nó lớn (kết quả thử nghiệm của tôi để có một hình ảnh của bức tường của tôi, mà là khá nhiều mono màu):
Original image size is: 990092 bytes.
Compressed image size is 7990272 bytes
Tôi đang hỏi xem có cách nào tốt hơn để nén ảnh để có thể tải lên một cách trơn tru không?
Thay vì sử dụng một mã hóa cứng kích thước 480x800 - bạn nên tính toán kích thước Bitmap đầu ra động duy trì tỷ lệ khía cạnh mong muốn i.e để thay đổi cảnh quan và chân dung. Và đối với kích thước hình ảnh - hãy nhớ rằng bạn đang so sánh kích thước tệp * nén * gốc với kích thước bitmap * không nén * được mở rộng. – harism