4

我需要将位图转换为字节数组才能上传到服务器我能够通过将位图转换为字节数组并按照此处的说明再次将其转换为 Base 64 字符串来实现相同的效果,但在我的银河 s2 中最坏的情况下移动设备,如果图像大小为 6MB,分辨率为 72 像素/英寸,它占用大约 600MB 的 RAM,并且应用程序因 OutOfMemoryException 而崩溃,我尝试通过压缩位图上传它工作正常,但在我的项目要求中,我需要上传图像原样,即未经任何压缩的原始图像

无论是否可能,请帮助我如何实现这一目标

提前致谢

4

2 回答 2

0

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

您正在犯两个不同的常见错误:

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

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

仅此一项 - 您可以大大减少内存分配堆的压力,因为如果这是您的 imageView 屏幕尺寸,您可以只分配 100x200 而不是分配(例如)1080x1920 整数。

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

使用这种方法,完全不限制你,即使你想上传 100M-1000M 的文件 - 也没关系,并且不会对内存分配堆产生影响。

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

于 2014-03-20T06:14:21.987 回答
0

用于上传转换为 jpeg 流

BufferedStream bs = //...

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

将bs转换为数组广告上传到服务器

于 2014-03-20T05:03:06.067 回答