2013-12-15 14 views
6

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à:

  1. 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.
  2. 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?

+2

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

Trả lời

12
  1. Bạn cần quyết định giới hạn chiều rộng hoặc chiều cao (không phải cả hai, rõ ràng). Sau đó, thay thế những kích thước hình ảnh cố định với những người tính toán, nói:

    int targetWidth = 640; // your arbitrary fixed limit 
    int targetHeight = (int) (originalHeight * targetWidth/(double) originalWidth); // casts to avoid truncating 
    

    (Thêm kiểm tra và thay thế tính cho hướng dọc/chân dung, khi cần thiết.)

  2. Như @harism cũng nhận xét: kích thước lớn bạn được đề cập là kích thước thô của bitmap 480x800, không phải kích thước tệp, mà phải là JPEG trong trường hợp của bạn. Làm thế nào bạn sẽ tiết kiệm được bitmap đó, BTW? Mã của bạn dường như không chứa phần lưu.

    Xem this question here để được giúp đỡ vào đó, với việc một cái gì đó quan trọng như:

    OutputStream imagefile = new FileOutputStream("/your/file/name.jpg"); 
    // Write 'bitmap' to file using JPEG and 80% quality hint for JPEG: 
    bitmap.compress(CompressFormat.JPEG, 80, imagefile); 
    
2

Trước hết tôi kiểm tra kích thước của hình ảnh sau đó tôi nén hình ảnh theo kích thước và được bitmap nén sau đó gửi bitmap đó đến máy chủ Đối với cuộc gọi bitmap nén dưới Chức năng chúng ta phải vượt qua con đường hình ảnh trong funtion dưới

public Bitmap get_Picture_bitmap(String imagePath) { 

    long size_file = getFileSize(new File(imagePath)); 

    size_file = (size_file)/1000;// in Kb now 
    int ample_size = 1; 

    if (size_file <= 250) { 

     System.out.println("SSSSS1111= " + size_file); 
     ample_size = 2; 

    } else if (size_file > 251 && size_file < 1500) { 

     System.out.println("SSSSS2222= " + size_file); 
     ample_size = 4; 

    } else if (size_file >= 1500 && size_file < 3000) { 

     System.out.println("SSSSS3333= " + size_file); 
     ample_size = 8; 

    } else if (size_file >= 3000 && size_file <= 4500) { 

     System.out.println("SSSSS4444= " + size_file); 
     ample_size = 12; 

    } else if (size_file >= 4500) { 

     System.out.println("SSSSS4444= " + size_file); 
     ample_size = 16; 
    } 

    Bitmap bitmap = null; 

    BitmapFactory.Options bitoption = new BitmapFactory.Options(); 
    bitoption.inSampleSize = ample_size; 

    Bitmap bitmapPhoto = BitmapFactory.decodeFile(imagePath, bitoption); 

    ExifInterface exif = null; 
    try { 
     exif = new ExifInterface(imagePath); 
    } catch (IOException e) { 
     // Auto-generated catch block 
     e.printStackTrace(); 
    } 
    int orientation = exif 
      .getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); 
    Matrix matrix = new Matrix(); 

    if ((orientation == 3)) { 
     matrix.postRotate(180); 
     bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, 
       bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, 
       true); 

    } else if (orientation == 6) { 
     matrix.postRotate(90); 
     bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, 
       bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, 
       true); 

    } else if (orientation == 8) { 
     matrix.postRotate(270); 
     bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, 
       bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, 
       true); 

    } else { 
     matrix.postRotate(0); 
     bitmap = Bitmap.createBitmap(bitmapPhoto, 0, 0, 
       bitmapPhoto.getWidth(), bitmapPhoto.getHeight(), matrix, 
       true); 

    } 

    return bitmap; 

} 

getFileSize Chức năng để nhận được kích thước của hình ảnh

public long getFileSize(final File file) { 
    if (file == null || !file.exists()) 
     return 0; 
    if (!file.isDirectory()) 
     return file.length(); 
    final List<File> dirs = new LinkedList<File>(); 
    dirs.add(file); 
    long result = 0; 
    while (!dirs.isEmpty()) { 
     final File dir = dirs.remove(0); 
     if (!dir.exists()) 
      continue; 
     final File[] listFiles = dir.listFiles(); 
     if (listFiles == null || listFiles.length == 0) 
      continue; 
     for (final File child : listFiles) { 
      result += child.length(); 
      if (child.isDirectory()) 
       dirs.add(child); 
     } 
    } 

    return result; 
} 
Các vấn đề liên quan