2013-05-02 3 views
1

На андроиде я рисую в android.graphics.Picture, затем сохраняю изображение в файл. Позже я перезаряжаю картинку в память и рисую ее на холст. Я заметил, что битмапы никогда не рисовались. И после большой отладки мне удалось сузить проблему до Picture.writeToStream и Picture.createFromStream. Кажется, что растровые изображения, нарисованные на картинке, не перезаряжаются должным образом. Ниже приведен пример кода, который я написал, чтобы показать проблему. В этом примере мое полотно не аппаратно ускорено.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 только может сохранять только определенные типы растровых изображений. Это связано с тем, что класс 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