在画布上绘制单个位图与多个位图的质量(Android)
我有一组小图片。如果我在画布上单独绘制这些图像,与在屏幕大小的大位图上绘制这些图像并在画布上绘制该位图的情况相比,绘制质量要低得多。特别是线条会变形。见下面(右侧) 根据下面的代码,画布还支持缩放(缩放)。这个问题发生在小规模因素上 问题是如何将多幅小图像的绘制量提高到大图像的标准 这是在画布上绘制的多个位图的代码在画布上绘制单个位图与多个位图的质量(Android),android,canvas,bitmap,zooming,Android,Canvas,Bitmap,Zooming,我有一组小图片。如果我在画布上单独绘制这些图像,与在屏幕大小的大位图上绘制这些图像并在画布上绘制该位图的情况相比,绘制质量要低得多。特别是线条会变形。见下面(右侧) 根据下面的代码,画布还支持缩放(缩放)。这个问题发生在小规模因素上 问题是如何将多幅小图像的绘制量提高到大图像的标准 这是在画布上绘制的多个位图的代码 canvas.scale(game.mScaleFactor, game.mScaleFactor); canvas.translate(game.mPosX, game.mP
canvas.scale(game.mScaleFactor, game.mScaleFactor);
canvas.translate(game.mPosX, game.mPosY);
for (int i = 0; i < game.clusters.size(); i++) {
Cluster cluster = game.clusters.get(i);
canvas.drawBitmap(cluster.Picture, cluster.left,
cluster.top, canvasPaint);
}
画笔设置了以下属性。`所有位图都是Bitmap.Config.ARGB_8888
canvasPaint.setAntiAlias(true);
canvasPaint.setFilterBitmap(true);
canvasPaint.setDither(true);`
我能想到一对,取决于你,你正在画拼图块的边界 您遇到的问题是,当缩放单个图像时,线条将与图像的其余部分一起过滤,并且看起来平滑(混合是正确的)。当拼图是逐块绘制时,过滤读取拼图块上的相邻像素,并将其与拼图块混合 方法1 第一种方法(一种很容易做到的方法)是以游戏的逻辑大小渲染到FBO(RTT),然后使用全屏四边形将整个纹理缩放到画布上。这将得到与
single
相同的结果,因为像素混合涉及相邻块
方法B
用出血来解决问题。切割拼图时,请将相邻拼图的重叠部分包括在内。不要将丢弃的像素设置为零,只将alpha设置为零。这将导致混合函数拾取与放置在单个图像上相同的值。此外,将边界线加倍,但将外部边界alpha设置为零
接近决赛
最后一个是最复杂的,但对于任何缩放都是平滑的(AF)
将拼图块的alpha通道转换为有符号距离场,并使用专门的着色器进行渲染,该着色器将在任意距离平滑输出。此外,SDF允许您在渲染期间使用着色器绘制轮廓,并且轮廓将平滑
事实上,SDF可以是单独的纹理,您可以将其加载到第二个纹理阶段。将源图像绑定为tex单元0,tex单元1上的sdf拼图块剪切,并使用sdf着色器确定来自sdf的alpha和来自tex0的颜色,然后根据sdf计算混合轮廓
SDF是从布尔映射生成的。您的拼图块剪纸需要以单色剪纸开始,然后使用上面列出的工具或类似工具转换为SDF(脱机)。Valve和LibGDX具有示例SDF着色器以及上面列出的工具。在固定大小的画布上渲染高分辨率图像意味着每个目标像素的源像素比较小大小的源图像多,结果是较大图像的下采样质量更好。若要为较小的图像获得相同的结果,请从相同的高分辨率源以需要渲染的分辨率(即比例应为1)创建它们,谢谢您的评论。大位图是画布大小的2倍(绘制到最大缩放级别)。小图像是大位图的片段,大小较小,但其比例为2。因此,比例因子范围为0.5到1(表示缩放级别为2)。当比例大小为0.5(即正常画布大小,但图像的一半)时,会出现此问题。从右侧看,图像线在0.5级受到显著影响。你认为我必须根据缩放级别创建多个图像吗?或者所有的小图像都应该是大图像的大小?这两种方法都有问题,因为在某些情况下,我有400张小图像。我仔细查看了图像,较低的质量与双线性向下采样产生的质量损失相匹配。在
canvasPaint.setFilterBitmap(true)上进行双线性过滤因此,您无法通过编程来提高质量。由于混叠的损失仅在高对比度的线条上明显,因此最好的选择是动态地将拼图轮廓渲染为位图上的路径,从原始图像中删除线条,这将为您提供一致的线条质量。好主意。我试过了,但无法使用,因为性能影响很大。仅绘制400幅图像需要30毫秒(帧时间),但图像+轮廓需要150毫秒。必须一次性缩放图像。但是如果你分别缩放每个部分,然后再将它们放在一起,它们之间的边界看起来就不好了。部分分离应该在整体缩放后进行。你是对的。边界是主要问题。你能解释一下方法1吗。这和我在问题中解释的单图像方法相同吗。在大图上画小图,在最后的画布上画大图?我尝试了第二种方法。这大大减少了这个问题。您知道如何有选择地将像素上的alpha设置为零吗。我目前正在使用porterDuffPaint.setXfermode(新的PorterDuffXfermode(PorterDuff.Mode.SRC));要剪切片段的图像。我可以使用什么技术来实现第二种方法。方法#1很慢,但很容易执行。而不是直接绘制到屏幕,而是绘制到FBO(渲染到纹理)。然后将渲染纹理绘制到屏幕上。关于这一点,有几个Nehe教程。至于PorterDuff,我花了一点时间研究PorterDuff提供的方程式,以及ComposeShader,我不得不说手动复制像素会更容易。你想要的是源图像的颜色和拼图的alpha。PorterDuff模式都没有这个等式,我不知道如何编写一个自定义ComposeShader来满足这个问题。在OpenGLES中,可以将
canvasPaint.setAntiAlias(true);
canvasPaint.setFilterBitmap(true);
canvasPaint.setDither(true);`