How to blit() in android?

2019-01-21 23:59发布

问题:

I'm used to handle graphics with old-school libraries (allegro, GD, pygame), where if I want to copy a part of a bitmap into another... I just use blit.

I'm trying to figure out how to do that in android, and I got very confused. So... we have these Canvas that are write-only, and Bitmaps that are read-only? It seems too stupid to be real, there must be something I'm missing, but I really can't figure it out.

edit: to be more precise... if bitmaps are read only, and canvas are write only, I can't blit A into B, and then B into C?

回答1:

The code to copy one bitmap into another is like this:

Rect src = new Rect(0, 0, 50, 50); 
Rect dst = new Rect(50, 50, 200, 200);  
canvas.drawBitmap(originalBitmap, src, dst, null);

That specifies that you want to copy the top left corner (50x50) of a bitmap, and then stretch that into a 150x150 Bitmap and write it 50px offset from the top left corner of your canvas.

You can trigger drawing via invalidate() but I recommend using a SurfaceView if you're doing animation. The problem with invalidate is that it only draws once the thread goes idle, so you can't use it in a loop - it would only draw the last frame. Here are some links to other questions I've answered about graphics, they might be of use to explain what I mean.

  • How to draw a rectangle (empty or filled, and a few other options)
  • How to create a custom SurfaceView for animation
  • Links to the code for an app with randomly bouncing balls on the screen, also including touch control
  • Some more info about SurfaceView versus Invalidate()
  • Some difficulties with manually rotating things

In response to the comments, here is more information: If you get the Canvas from a SurfaceHolder.lockCanvas() then I don't think you can copy the residual data that was in it into a Bitmap. But that's not what that control is for - you only use than when you've sorted everything out and you're ready to draw.

What you want to do is create a canvas that draws into a bitmap using

Canvas canvas = new Canvas(yourBitmap)

You can then do whatever transformations and drawing ops you want. yourBitmap will contain all the newest information. Then you use the surface holder like so:

Canvas someOtherCanvas = surfaceHolder.lockCanvas()
someOtherCanvas.drawBitmap(yourBitmap, ....)

That way you've always got yourBitmap which has whatever information in it you're trying to preserve.



回答2:

In android you draw to the canvas, and when you want it to update you call invalidate which will the redraw this canvas to the screen. So I'm guessing you have overridden the onDraw method of your view so just add invalidate();

@Override
public void onDraw(Canvas canvas) {
    // Draw a bitmap to the canvas at 0,0
    canvas.drawBitmap(mBitmap, 0, 0, null);
    // Add in your drawing functions here
    super.onDraw(canvas);
    // Call invalidate to draw to screen
    invalidate();
}

The above code simply redraws the bitmap constantly, of course you want to add in extra thing to draw and consider using a timing function that calls invalidate so that it is not constantly running. I'd advice having a look at the lunarlander sources.