将位图转换为字节数组占用大量内存

时间:2014-03-20 04:39:36

标签: android performance android-bitmap android-webservice

我需要将位图转换为字节数组以便上传到服务器我能够通过将位图转换为字节数组并再次按照说明here将其转换为Base 64字符串来实现相同的效果在我的Galaxy s2手机中最糟糕的情况如果图像大小是6MB,72像素/英寸分辨率它占用大约600MB的内存并且应用程序因OutOfMemoryException而崩溃,我试图通过压缩位图来上传它工作得很好但是在我的项目中要求我需要按原样上传图像,即不对原始图像进行任何压缩

请帮助我如何实现这一目标

先谢谢

2 个答案:

答案 0 :(得分:0)

用于上传转换为jpeg流

BufferedStream bs = //...

然后致电bitmap.compress("JPEG", 0, length, bs)

将bs转换为阵列广告上传到服务器

答案 1 :(得分:0)

Android应用程序分配内存堆是有限的。特别是在低内存设备上。

你正在做两个不同的常见错误:

  • 首先:关于上传问题 - 您持有全尺寸图像的Bitmap对象(可能是用相机拍摄的)。这是第一个错误。如果您必须在用户界面上显示捕获的图像 - 您应该根据刚捕获和创建的捕获图像文件中所需的显示大小(ImageView宽度和高度..)加载缩放版本位图: / p>

    public static Bitmap getSampleBitmapFromFile(String bitmapFilePath, int reqWidth, int reqHeight) {
    try {
        File f = new File(bitmapFilePath);
        ExifInterface exif = new ExifInterface(f.getPath());
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
    
        int angle = 0;
    
        if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
            angle = 90;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
            angle = 180;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
            angle = 270;
        }
    
        Matrix mat = new Matrix();
        mat.postRotate(angle);
    
        // calculating image size
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f), null, options);
    
        int scale = calculateInSampleSize(options, reqWidth, reqHeight);
    
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
    
        Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        Bitmap correctBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
    
        return correctBmp;
    } catch (IOException e) {
        Log.e(TAG, "cant butmaputils.getSampleBitmapFromFile failed with IO exception: ", e);
        if (e != null)
            e.printStackTrace();
    } catch (OutOfMemoryError oom) {
        Log.e(TAG, "cant butmaputils.getSampleBitmapFromFile failed with OOM error: ");
        if (oom != null)
            oom.printStackTrace();
    } catch (Exception e) {
        Log.e(TAG, "cant butmaputils.getSampleBitmapFromFile failed with exception: ", e);
    }
    Log.e(TAG, "butmaputils.getSampleBitmapFromFilereturn null for file: " + bitmapFilePath);
    return null;
     }
    
    
    
    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) {
    
        // Calculate ratios of height and width to requested height and
        // width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
    
        // Choose the smallest ratio as inSampleSize value, this will
        // guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    
    return inSampleSize;
    }
    
仅凭这一点 - 你大大减少了内存分配堆的压力,因为如果不是分配(例如)1080x1920整数,你可以只分配100x200,如果这是你的imageView屏幕尺寸。

  • 第二:上传到服务器:您应该从大型原始文件上传到您的服务器直接流,而不是将其加载到内存中,因为Bitmap +将其解码为base 64或。最好的方法是使用Multipart Entity

使用这个approch,根本不限制你,即使你想上传100M-1000M文件 - 它也没关系,并且对内存分配堆没有影响。

如需更多阅读,建议您阅读 - http://developer.android.com/training/displaying-bitmaps/load-bitmap.html