在SurfaceView上绘制缩放的位图--无抗锯齿

4
很抱歉如果这个话题之前已经被提出过,但是我在网络和谷歌群组上的所有搜索都没有帮助我。

我目前正在使用Android SDK开发一个小游戏,并使用高分辨率位图,根据设备的分辨率调整大小(让系统为我调整大小不够“清晰”)。

我使用SurfaceView,在其上绘制一个填充整个表面的画布。 该画笔使用setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN))来允许遮罩。 事先,我检索各种位图 - 这些位图在初始化时使用createScaledBitmap()进行调整大小并放入缓存中 - 然后我使用画笔将位图应用于此画布,然后将该画布绘制到SurfaceView上。

我的问题是,无论我尝试什么,无论我使用什么画笔设置(抖动,抗锯齿等),调整大小的位图都没有抗锯齿效果,绘图呈现锯齿状边缘。我试过了一切。 我唯一取得的小成功是使用inSampleSize接近所需的缩放大小,并在检索到的高分辨率位图上强制首次通过抗锯齿,然后调用createScaledBitmap,但这还不够美观。我不能允许为每种分辨率组合创建大量预调整大小的位图。我错过了什么?

非常感谢您提前的帮助。

3个回答

1

当你加载位图时,首先要确保通过设置选项为argb_8888不会丢失任何图像质量:

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

当你缩放位图时,请打开过滤器:

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

然而,如果将图像拉伸得太多,它的质量必然会降低。

当您使用绘画工具时,可以通过打开抖动和过滤来提高质量,但会牺牲速度:

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

最后,整个活动窗口可以设置为argb_4444而不是argb_8888(OS<2.3)。如果您在setContentView之前插入此行,则可以更改此设置:

getWindow().setFormat(PixelFormat.RGBA_8888); 

抱歉,但我已经在做这件事了。我不能在这里发布图片,但结果非常模糊,我显然不明白为什么,就好像Android提供的调整大小非常基本,类似于MS-Paint。使用Gimp将我的位图缩小到相同比例会产生漂亮的抗锯齿位图(注意:我将位图缩小而不是放大,因此没有拉伸)。 - altesseFReDD
经过仔细检查我的一个应用程序,我认为你是正确的。缩小比例不会产生良好的抗锯齿图像,我也无法改进它。你可能需要在Google Android支持论坛上提出这个问题。在此之前,最好先制作一个简单而清晰的示例。在我的情况下,我正在使用小型预览图像,所以我可以暂时忍受这种情况...祝你好运! - Lumis
啊,谢谢,看到我不是唯一遇到这个问题的人,我感到很欣慰。我已经把这个问题带到了Android开发Google小组,但你说得对,我需要完善我的例子。谢谢。 - altesseFReDD

0

你可以自己清空画布缓冲区!例如:

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

0
如果必要的话,你可以手动进行抗锯齿处理而不会太麻烦。只需在请求位图对象重新缩放之前,对像素数据应用一个简单的低通滤波器(例如NxN平均值)即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接