使用 CATiledLayer,渲染时 Tiles 之间的细线,使用 ImageMagick 生成的瓷砖
Posted
技术标签:
【中文标题】使用 CATiledLayer,渲染时 Tiles 之间的细线,使用 ImageMagick 生成的瓷砖【英文标题】:Using CATiledLayer, thin line between Tiles on rendering, tiles generated with ImageMagick 【发布时间】:2011-05-12 18:38:40 【问题描述】:使用 Apple 和 ImageMagick 的 PhotoScroller 示例,我设法构建了我的目录应用程序。
但我遇到了渲染错误。平铺的图像以它们之间的细线呈现。
我使用 ImageMagick 的简单脚本是这样的:
#!/bin/sh
file_list=`ls | grep JPG`
for i in 100 50 25; do
for file in $file_list; do
convert $file -scale $i%x -crop 256x256 -set filename:tile "%[fx:page.x/256]_%[fx:page.y/256]" +repage +adjoin "$file%.*_$i_%[filename:tile].$file#*."
done
done
Apple 的代码是相同的。奇怪的是,他们提供的已经平铺的图像就像一个魅力,在相同的运行时间,与我的图像并排:(
我的第一个猜测是图块的大小与代码上的计算不匹配,但更改大小并没有解决,无论是在我的脚本还是在代码中。我的图片通常比苹果提供的图片小,实际上只有一半。
有人遇到同样的问题吗?
【问题讨论】:
感谢 shell 脚本。 :-) 【参考方案1】:我对这两种解决方案都有问题。 Damien 的方法并没有完全消除所有缩放比例下的所有线条,而 Brent 的解决方案删除了线条,但在图块边界处添加了一些伪影。
在谷歌上搜索了一段时间后,我终于找到了一个适合我的解决方案:http://openradar.appspot.com/8503490(来自 zephyr.renner 的评论)。
毕竟,Apple 对CTM.a == CTM.d
的假设似乎根本不“安全”...
【讨论】:
这个解决方案在所有规模上都像一个魅力。 Apple 代码的另一点是假设您有部分磁贴。 如果您的图像拼贴器仅创建方形拼贴,您需要从 PhotoScroller 示例中删除这行代码:drawRect 的 for 循环中的tileRect = CGRectIntersection(self.bounds, tileRect);
小心“解决方案”中的_scale = (1 / (float)((int)(1/scale))) * 1000;
行。如果比例大于 1,_scale
将变为无穷大。【参考方案2】:
我在这里有完全相同的问题,使用 PhotoScroller 代码。当scale
在- (void)drawRect:(CGRect)rect
中不正确时,就会出现问题。
您需要对scale
进行四舍五入...在CGFloat scale = CGContextGetCTM(context).a;
之后添加scale = 1.0f / roundf(1.0f / scale);
(它还可以防止瓷砖被绘制两次)。
然后绘制大 1 像素的图块...在 tileRect = CGRectIntersection(self.bounds, tileRect);
之后添加 tileRect.size.width += 1; tileRect.size.height += 1;
。
【讨论】:
酷,这行得通。我已经不得不对未调用的刻度或某种级别的瓷砖进行四舍五入。 我发现细线只出现在 25% 的缩放级别上,无法放大 tileRect 隐藏图像的某些像素点?【参考方案3】:我也遇到过同样的 PhotoScroller 问题,Damien 的解决方案非常接近,但需要稍作修正才能完全消除那些讨厌的接缝。
对我来说,在所有缩放级别上都无法绘制大一像素的图块。原因是我们以原始分辨率绘制图像,然后通过 CTM 将其缩放到屏幕分辨率。
所以,当在屏幕上以 25% 的缩放级别绘制时,我们添加的 1 个像素实际上变成了 1/4 个像素。
因此,要在屏幕上将图块放大 1 个像素,我们需要将 1.0/scale 添加到宽度/高度。 (这应该在调用 CGRectIntersection 之前完成)
tileRect.size.width += 1.0/scale; tileRect.size.height += 1.0/scale;
tileRect = CGRectIntersection(self.bounds, tileRect);
【讨论】:
知道了!按照 Damien 的建议添加 1 个像素对我来说没问题,但您的解决方案显然更精致 :) 谢谢!以上是关于使用 CATiledLayer,渲染时 Tiles 之间的细线,使用 ImageMagick 生成的瓷砖的主要内容,如果未能解决你的问题,请参考以下文章
第6章—渲染web视图—使用Apache Tiles视图定义布局
在没有 CATiledLayer 的情况下渲染 Scrollview 容器中的巨大网格?