2013-05-02 47 views
1

在Android上,我正在绘制一个android.graphics.Picture,然后将图片保存到文件。稍后我将图片重新加载到内存中并将其绘制到画布上。我注意到Bitmaps从未画过。经过很多调试,我设法将问题缩小到Picture.writeToStream和Picture.createFromStream。看起来画在图片上的Bitmaps不能正确地重新加载。下面是我写的示例代码来显示问题。在这个示例中,我的画布不是硬件加速的。android Picture.createFromStream不重新加载位图

所以我的问题如下:

  1. 我做错什么了吗?
  2. 这是一个Android的错误?我提交了错误报告https://code.google.com/p/android/issues/detail?id=54896,因为我认为这是。
  3. 任何已知的解决方法?

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
        try 
        { 
         Picture picture = new Picture(); 
    
         // Create a bitmap 
         Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888); 
         Canvas bitmapCanvas = new Canvas(bitmap); 
         bitmapCanvas.drawARGB(255, 0, 255, 0); 
    
         // Draw the bitmap to the picture's canvas. 
         Canvas pictureCanvas = picture.beginRecording(canvas.getWidth(), canvas.getHeight()); 
    
         RectF dstRect = new RectF(0, 0, 200, 200); 
         pictureCanvas.drawBitmap(bitmap, null, dstRect, null); 
    
         picture.endRecording(); 
    
         // Save the Picture to a file. 
         File file = File.createTempFile("cache", ".pic"); 
         FileOutputStream os = new FileOutputStream(file); 
         picture.writeToStream(os); 
         os.close(); 
    
         // Read the picture back in 
         FileInputStream in = new FileInputStream(file); 
         Picture cachedPicture = Picture.createFromStream(in); 
    
         // Draw the cached picture to the view's canvas. This won't draw the bitmap! 
         canvas.drawPicture(cachedPicture); 
    
         // Uncomment the following line to see that Drawing the Picture without reloading 
         // it from disk works fine. 
         //canvas.drawPicture(picture); 
        } 
        catch (Exception e) 
        { 
        } 
    } 
    

回答

0

我也看着那备份的位图的原生Android代码后,找到这个问题的答案。 Android只能将特定类型的位图保存到图片中。这是因为SkBitmap类只支持某些类型的输入,这些输入会导致可以保存到图片的位图。所以我可以通过提供这些神奇的输入来解决问题。使用保存到磁盘的位图并调用BitmapFactory.decodeFileDescriptor来创建它。

private Bitmap createReusableBitmap(Bitmap inBitmap) 
{ 
    Bitmap reuseableBitmap = null; 

    if (inBitmap== null) 
     return null; 

    try 
    { 
     // The caller is responsible for deleting the file. 
     File tmpBitmapFile = File.createTempFile("bitmap", ".png"); 

     setBitmapPath(tmpBitmapFile.getAbsolutePath()); 

     FileOutputStream out = new FileOutputStream(tmpBitmapFile); 
     boolean compressed = inBitmap.compress(CompressFormat.PNG, 100, out); 
     out.close(); 

     if (compressed) 
     { 
      // Have to create a purgeable bitmap b/c that is the only kind that works right when drawing into a 
      // Picture. After digging through the android source I found decodeFileDescriptor will create the one we need.   
      // See https://github.com/android/platform_frameworks_base/blob/master/core/jni/android/graphics/BitmapFactory.cpp 
      // In short we have to give the options inPurgeable=true inInputShareable=true and call decodeFileDescriptor 

      BitmapFactory.Options options = new BitmapFactory.Options(); 
      options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
      options.inInputShareable = true; 
      options.inPurgeable = true; 
      options.inSampleSize = 1; 
      options.inScaled = false; 
      options.inMutable = false; 
      options.inTempStorage = DraftRenderer.tempStorage; 

      FileInputStream inStream = new FileInputStream(tmpBitmapFile); 
      FileDescriptor fd = inStream.getFD(); 
      reuseableBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options); 
      inStream.close(); 
     } 
    } catch (Exception e) { 
    } 
    return reuseableBitmap; 
} 
0

注意:从输入流创建的图片无法在硬件加速画布上重播。 Picture.createFromStream(InputStream stream)

您可以使用canvas.isHardwareAccelerated()来检测硬件加速与否。

+0

是的,我知道这一点。我说:“在这个例子中,我的画布不是硬件加速的。” – Nathan 2013-06-20 15:48:47