我仍然围绕着位图如何在Android上工作。我目前的情况是 - 我正在尝试显示图像的网格视图,但是大约8张左右的图片会出现内存错误。
我现在的方式是使用自定义相机(扩展surfaceview 并实现surfaceholder.callback)来拍照,使用onPreviewFrame方法解码字节数组将YUV420SP转换函数转换为int []数组,然后从该数组创建位图。我这样做有两个原因,1。将流保存到sqlite数据库中的blob中以便稍后传输到服务器,以及2.避免将其保存为手机中可以更改的jepg用。
如果有更好的方法可以做到这一点,我愿意听到它,但是现在我正在寻找一个答案,当我从数据库中调用它后显示它时,它会帮助我缩小图像大小,或在将其保存到数据库之前。我已经查看了关于这个主题的其他主题,但到目前为止我看到的所有内容都需要将其保存为jpeg,然后使用bitmapfactory.options将文件位置解码为位图。有没有人知道一种方法直接使用给定的字节数组参数,甚至在使用YUV420SP进行转换后?
如果需要进一步澄清,请告诉我。
答案 0 :(得分:0)
所以问题是你没有在将图像显示到GridView之前缩小图像,所以当你从那些int []创建Bitmap时,你应该在显示Bitmap之前创建一个缩小版本。
会有这样的事情:
public static byte[] intArraysToByteArrays(int[] data){
ByteBuffer byteBuffer = ByteBuffer.allocate(data.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(data);
return byteBuffer.array();
}
public static Bitmap decodeSampleBitmapFromByteStream(byte[] data , int reqWidth, int reqHeight){
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
/**
* Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
* bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
* the closest inSampleSize that will result in the final decoded bitmap having a width and
* height equal to or larger than the requested width and height. This implementation does not
* ensure a power of 2 is returned for inSampleSize which can be faster when decoding but
* results in a larger bitmap which isn't as useful for caching purposes.
*
* @param options An options object with out* params already populated (run through a decode*
* method with inJustDecodeBounds==true
* @param reqWidth The requested width of the resulting bitmap
* @param reqHeight The requested height of the resulting bitmap
* @return The value to be used for inSampleSize
*/
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;
// This offers some additional logic in case the image has a strange
// aspect ratio. For example, a panorama may have a much larger
// width than height. In these cases the total pixels might still
// end up being too large to fit comfortably in memory, so we should
// be more aggressive with sample down the image (=larger inSampleSize).
final float totalPixels = width * height;
// Anything more than 2x the requested pixels we'll sample down further
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
}
return inSampleSize;
}
注意:我没有测试过代码,但我相信它应该可以正常工作。为了获得更好的性能,所有这些都应该在后台线程中运行。