Drawing scaled bitmaps on a SurfaceView — no antia

2019-01-25 21:14发布

问题:

I'm sorry if this topic has been brought before, but all my searches on the web and google groups did not help me.

I'm currently developing a little game with the Android SDK, and use hi-res bitmaps that I resize accordingly to match the device's resolution (letting the system do it for me is not "crisp" enough).

I use a SurfaceView, on which I paint in one pass a canvas filling the whole surface. The paint uses setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)) to allow masking. Beforehand, I retrieve various bitmaps -- which are resized at initialization with createScaledBitmap() and put in a cache -- and I apply the bitmaps with a paint on this canvas, before drawing this canvas on the SurfaceView.

My problem is, whatever I try, whatever paint settings I use (dithering, antialias, etc..), the resized bitmaps are not antialiased and the drawing present jagged edges. I tried everything. The only little success I had was using inSampleSize to approach the desired scaled size and force a first pass of antialiasing, before invoking createScaledBitmap on the retrieved hi-res bitmap, but it is not beautiful enough. I just can't allow to create multitudes of pre-sized bitmaps for every combination of resolution. What did I miss ?

Thanks a lot in advance

回答1:

First when you load your bitmap you make sure that you don't lose any image quality by settings options to argb_8888:

Options options = new Options();    
options.inScaled = false; 
options.inPreferredConfig = Bitmap.Config.ARGB_8888; 
Bitmap pic = BitmapFactory.decodeResource(getResources(), R.id.pic, options);

When you scale the bitmap turn on the filter:

pic = Bitmap.createScaledBitmap(pic, screenW, screenH, true);

However if one streaches the image too much inevitably it degrades in quality.

When you use paint you can improve quality but lose on speed with turning on ditherig and filtering:

Paint paint = new Paint(); 
paint.setFlags(Paint.DITHER_FLAG);
paint.setFilterBitmap(true);

Finally the entire activity window could be set on argb_4444 instead on argb_8888 (OS < 2.3). You can chage this if you instert this line before setContentView:

getWindow().setFormat(PixelFormat.RGBA_8888); 


回答2:

If it comes down to it, you can manually antialias without too much trouble. Just apply a simple lowpass filter (something like an NxN average) to the pixel data before asking the bitmap object to rescale itself.



回答3:

you may clear canvas buffer by youself! such as follows:

canvas.drawColor(Color.TRANSPARENT, android.graphics.PorterDuff.Mode.CLEAR);