2013-12-15 93 views
6

我正在开发一款安卓应用,该应用具有相机捕获和照片上传功能。如果设备具有高分辨率照相机,拍摄的图像尺寸将非常大(1〜3MB或更多)。
由于应用程序需要将此图像上传到服务器,因此我需要在上传前压缩图像。例如,如果相机捕获1920x1080全分辨率照片,理想的输出是保持图像的16:9比例,将其压缩为640x360图像,以降低某些图像质量并使其以较小的字节数进行缩小。Android - 缩放并压缩位图

这是我的代码(来自谷歌引用):

/** 
* 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; 
} 

与上述代码的问题是:

  1. 它不能保持率,代码迫使图像大小调整为为480x800。如果用户以另一个比例捕捉图像,压缩后图像看起来不太好。
  2. 它运行不正常。无论原始文件大小如何,代码将始终将图像大小更改为7990272byte。如果原始图像尺寸是非常小的已经,它将使大(我的测试结果把我的墙,这是非常单色的图片):

    Original image size is: 990092 bytes.
    Compressed image size is 7990272 bytes

我在问是否有更好的方式来压缩照片,以便它可以顺利上传的建议?

+2

的大小代替使用硬编码的480×800大小 - 你应该计算出维持所需的纵横比i动态输出位图的大小。e改变风景和人像。对于图像大小 - 请记住,您正在比较原始*压缩*文件大小与缩放*未压缩*位图大小。 – harism

回答

12
  1. 您需要决定宽度或高度的限制(不是两个,显然)。然后替换那些固定的图像尺寸的计算的,说:

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

    (添加检查和横向/纵向姿态计算的替代品,如需要)。

  2. 由于@harism也评论:大尺寸您提到的是原始大小,即480x800位图,而不是文件大小,在你的情况下应该是JPEG。你如何保存该位图,BTW?您的代码似乎不包含保存部分。

    用于对帮助,请参见this question here,关键是这样的:

    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

首先我检查图像的大小,然后我根据大小压缩图像,并得到压缩的位图,然后发送一个位图服务器 对于低于funtion压缩位电话我们必须通过以下funtion图像路径

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 funtion用于获取图像

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; 
}