6

onPictureTaken,我想做以下事情:

Bitmap decodedPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.preScale(-1.0f, 1.0f);
Bitmap picture = Bitmap.createBitmap(decodedPicture, 0, 0, decodedPicture.getWidth(), decodedPicture.getHeight(), matrix, false);

View v1 = mainLayout.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap screenshot = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

Bitmap scaledPicture = Bitmap.createScaledBitmap(picture, screenshot.getWidth(), screenshot.getHeight(), true);

Bitmap compos = Bitmap.createBitmap(scaledPicture.getWidth(), scaledPicture.getHeight(), Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(compos);
canvas.drawBitmap(scaledPicture, new Matrix(), null);
canvas.drawBitmap(screenshot, new Matrix(), null);

MediaStore.Images.Media.insertImage(getContentResolver(), compos, "name" , "description");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

我唯一的要求是我想保存一张高质量的照片……看来我可能不得不牺牲它。

在我的 Nexus 4 和更新的设备上,此代码运行良好且符合预期。但是在内存较少的旧设备上,我的内存快用完了!:(

如何在不超出内存限制的情况下进行相同的图像处理?我不想在屏幕上显示这些图像,因此与缩小图像有关的解决方案在这里并不适用......

4

4 回答 4

3

您需要使用增加的样本大小来读取位图。诀窍是找到正确的样本大小,当您最终缩放图像时不会导致分辨率降低。我在这里写了一篇关于它的博客文章,其中包括一个很好的缩放实用程序类,

http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/

根据您的具体需求,您可能可以稍微简化该类。

jist 只是读取位图的大小。根据您所需的缩放大小计算最佳样本大小,使用该样本大小读取位图,然后将其精确缩放到您想要的大小。

于 2013-04-29T17:40:18.343 回答
0

你周围有很多位图对象。尝试回收/重复使用其中的一些。

不完全确定您的要求是什么,但我可以看到您可以通过简单地执行此操作来节省一些内存。

        Bitmap decodedPicture = BitmapFactory.decodeByteArray(data, 0, data.length);
        Matrix matrix = new Matrix();
        matrix.preScale(-1.0f, 1.0f);
        Bitmap picture = Bitmap.createBitmap(decodedPicture, 0, 0, decodedPicture.getWidth(), decodedPicture.getHeight(), matrix, false);

        decodedPicture.recycle();
        decodedPicture=null;

        View v1 = mainLayout.getRootView();
        v1.setDrawingCacheEnabled(true);
        Bitmap screenshot = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);

        Bitmap scaledPicture = Bitmap.createScaledBitmap(picture, screenshot.getWidth(), screenshot.getHeight(), true);

        picture.recycle();
        picture=null;

        Bitmap compos = Bitmap.createBitmap(scaledPicture.getWidth(), scaledPicture.getHeight(), Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(compos);
        canvas.drawBitmap(scaledPicture, new Matrix(), null);
        canvas.drawBitmap(screenshot, new Matrix(), null);

        MediaStore.Images.Media.insertImage(getContentResolver(), compos, "name" , "description");
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));

还要查看你的内存占用,确保你使用的设备内存不是太大。

仅供参考,在后蜂窝设备上分配在本机层上的位图像素图像。您需要recycle()finalizer()恢复记忆

于 2013-04-29T17:47:46.867 回答
0

考虑到您不想调整位图的大小并且不想显示它,我会做这样的事情:

  1. 加载位图inJustDecodeBounds以查看其原始高度和宽度(来自此处的代码)

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);
    
    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
  2. 根据您拥有的大小和内存,您可以直接从那里处理它(即加载位图)或继续使用允许您仅加载数据块的Bitmap.createBitmap方法加载多个所述位图块。recycle()可选:在处理块之前考虑将其转换为字节数组(参见下面的代码)和 null+ 。

代码

ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream();
bitmapPicture.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, byteArrayBitmapStream);
byte[] b = byteArrayBitmapStream.toByteArray();
于 2013-04-29T17:50:26.207 回答
0

我使用 Bitmap 类 WeakReference 工作,并且在我总是在实例对象 WeakReference 上调用回收之后,旋转图像的片段代码:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inPreferredConfig = Bitmap.Config.RGB_565;
WeakReference<Bitmap> imageBitmapReference = new WeakReference<Bitmap>(BitmapFactory.decodeByteArray(params[0], 0, params[0].length, options));

Matrix mat = new Matrix();
mat.postRotate(90.0f); 
imageBitmapReference = new WeakReference<Bitmap (Bitmap.createBitmap(imageBitmapReference.get(), 0, 0, resolution[0], resolution[1], mat, true));

FileOutputStream fos = new FileOutputStream(filename);
imageBitmapReference.get().compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
imageBitmapReference.get().recycle();

第二个解决方案是如何使用 Bitmap 而不会出现 OutOfMemory 异常是使用库 Universal Image Loader

(当然是在您的 AndroidManifest 属性 android:largeHeap="true" 中设置的第三个解决方案,并且真的不要使用此属性)。

完美的材料在http://developer.android.com/training/displaying-bitmaps/index.html和视频https://www.youtube.com/watch?v=_CruQY55HOk

于 2014-06-13T15:44:34.293 回答