在我的App中用户可以预览照片,可以自由的移动照片(照片的大小是1920x1080),在用户移动到合适位置时程序会保存在屏幕内的图片部分和完整的图片。在保存部分图片时可以正常保存,在保存完整图片时就会出内存溢出的错误。
我的代码如下:
private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); mPreview.setDrawingCacheEnabled(true); mPreview.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO); Bitmap bitmap = mPreview.getDrawingCache(); bmp = BitmapFactory.decodeByteArray(data, 0, data.length); combination = overlay(bmp, bitmap); if(pictureFile == null) { return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); combination.compress(CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ mediaStorageDir))); } catch(FileNotFoundException e) { Log.d(TAG, "File not found: "+e.getMessage()); } catch(IOException e) { Log.d(TAG, "Error accessing file: "+e.getMessage()); } } }; public static Bitmap overlay(Bitmap bmp1, Bitmap bmp2) { Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(),bmp1.getConfig()); Canvas canvas = new Canvas(bmOverlay); canvas.drawBitmap(bmp1, new Matrix(), null); canvas.drawBitmap(bmp2, null, new Rect(0,0,bmp1.getWidth(), bmp1.getHeight()), null); return bmOverlay; } private static File getOutputMediaFile(int type) { File mediaFile = null; if(isSdPresent() == false) { Log.d(TAG, "There is no Sd card. Cannot use the camera"); } else { File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "World Cup Camera"); if(!mediaStorageDir.exists()) { if(!mediaStorageDir.mkdirs()) { Log.d("WorldCupApp", "failed to create directory"); return null; } } String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); if (type == MEDIA_TYPE_IMAGE) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else { return null; } } return mediaFile; }
我尝试用下面的方法来解决这个问题,但是会损失图片的质量
private Bitmap decodeFile(File f) { try { //Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f),null,o); //缩小的尺寸 final int REQUIRED_SIZE=70; //Find the correct scale value. It should be the power of 2. int scale=1; while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE) scale*=2; //Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize=scale; return BitmapFactory.decodeStream(new FileInputStream(f), null, o2); } catch (FileNotFoundException e) {} return null; }
如果不想损失图片的质量,可以通过在application标签上添加 android:largeHeap="true"属性来解决此问题