1

在 android 上,我正在绘制到 android.graphics.Picture 然后将图片保存到文件中。后来我将图片重新加载到内存中并将其绘制到画布上。我注意到位图从不绘图。经过大量调试后,我设法将问题缩小到 Picture.writeToStream 和 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)
        {
        }
    }
    
4

2 回答 2

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;
}
于 2013-06-04T12:32:08.053 回答
0

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

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

于 2013-06-19T03:13:06.410 回答