在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和更新的设备上,此代码运行正常且符合预期。但是在内存较少的旧设备上,我的内存不足了! :(
如何在不超出内存限制的情况下进行相同的图像处理?我不是试图在屏幕上显示这些图像,因此与缩小图像有关的解决方案并不适用于此...
答案 0 :(得分:3)
您需要使用增加的样本大小来读取位图。诀窍是找到正确的样本大小,在最终缩放图像时不会导致分辨率降低。我在这里写了一篇关于它的博客文章,其中包括一个很好的缩放实用程序类,
http://zerocredibility.wordpress.com/2011/01/27/android-bitmap-scaling/
根据您的具体需求,您可能会相当简化该课程。
jist只是读取位图的大小。根据您所需的缩放尺寸计算最佳样本大小,使用该样本大小读取位图,然后将其精确缩放到您想要的大小。
答案 1 :(得分:0)
你有很多Bitmap对象。尝试回收/重复使用其中一些。
不完全确定您的要求是什么,但我可以看到您可以通过简单地执行此操作来节省一些内存。
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())));
另外,请查看您的内存占用情况,确保您使用的设备智能内存不是太大。
仅供参考,在本机层上分配的后honycomb设备位图像素图像上。您需要recycle()
或finalizer()
来恢复内存
答案 2 :(得分:0)
考虑到你不想调整你的位图大小并且不想显示它,我会做这样的事情:
使用inJustDecodeBounds
加载位图以查看其原始高度和宽度(代码来自here)
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
根据您拥有的大小和内存,您可以直接从那里处理它(即加载位图)或继续使用允许您的Bitmap.createBitmap方法加载一些所述位图的块只加载一大块数据。可选:在处理块之前,考虑将其转换为字节数组(请参阅下面的代码)和null + recycle()
。
<强>码强>
ByteArrayOutputStream byteArrayBitmapStream = new ByteArrayOutputStream();
bitmapPicture.compress(Bitmap.CompressFormat.PNG, COMPRESSION_QUALITY, byteArrayBitmapStream);
byte[] b = byteArrayBitmapStream.toByteArray();
答案 3 :(得分:0)
我用于处理Bitmap类WeakReference,之后我总是在实例对象WeakReference上调用recycle,这是旋转图像的代码片段:
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 Exception就是使用库Universal Image Loader
(当然是AndroidManifest属性中设置的第三个解决方案android:largeHeap =&#34; true&#34;真的不要使用这个属性)。
完美素材位于http://developer.android.com/training/displaying-bitmaps/index.html和视频https://www.youtube.com/watch?v=_CruQY55HOk