【问题标题】:android Picture.createFromStream does not reload bitmapsandroid Picture.createFromStream 不会重新加载位图
【发布时间】:2013-05-02 18:03:46
【问题描述】:

在 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)
        {
        }
    }
    

【问题讨论】:

    标签: android bitmap android-canvas


    【解决方案1】:

    在查看支持位图的本机 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;
    }
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 是的,我知道。我说“在这个示例中,我的画布没有硬件加速。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-18
      • 2015-06-28
      • 1970-01-01
      • 1970-01-01
      • 2018-06-10
      相关资源
      最近更新 更多