使用 Python 图像库调整透明 png 大小和光晕效果
SO 上有几个类似的问题,但没有一个真正有帮助。基本上我正在尝试调整简单的 png 图像的大小,如下所示:
http://media.spiralknights.com/wiki-images/3/3e/Equipment-Proto_Sword_icon.png (来自 MMO Spiral Knights,三环娱乐版权所有)
我最初实现了一个在 php 中使用这些图像的实用程序,并且那里的调整大小实用程序运行得非常好。我使用了 PHP 文档中 imagecopyresampled 页面上描述的方法。
老实说,我什至无法在 Photoshop 中更好地调整大小,但在 python 中结果几乎是灾难性的。我始终得到光晕效果,并且我相信这至少部分与透明像素的实际 RGBA 值有关。在这里,这张图片更好地说明了这一点:
(倒数第二个调整大小只是我在另一个论坛上看到的建议首先将大小调整为最终大小的两倍,它至少有一点帮助,但还不够)
图像在调整大小时已经处于 RGBA 模式。
正如您所看到的,PHP 和 Photoshop 调整大小是没有光环的。老实说,除了 PHP 调整大小之外,其他所有功能都做了太多工作,我喜欢 php 图像中的最小调色板(如果您查看较大的版本,您会发现 PHP 调整大小在颜色之间使用较少),但我可以接受 Photoshop 的方式已经调整了它的大小,甚至Python的内部也调整了大小,但光环是不可接受的。
在我看来——如果我错了,请纠正我——PHP 和 Photoshop 似乎知道在插值时不使用 alpha 通道中像素的颜色,但 python 正在使用浅色边框,否则它是透明的,在其调整大小中。
不幸的是,我需要调整很多不同的图标大小,具有不同的配置文件,因此它们并不都像这个圆形图标那么简单,但这只是我在实验时使用的第一个图标。
这本身并不是一个代码问题,但如果您需要看一些东西,那么这就是要点:
>> import Image
>> img = Image.open('swordorig.png')
>> img
<PngImagePlugin.PngImageFile image mode=RGBA size=256x256 at 0x2A3AF58>
>> img.resize((36,36), Image.ANTIALIAS).save('swordresize.png')
最终的问题是:有没有办法告诉 PIL 不要使用 alpha 为 的像素的颜色重采样时为 0?
There are a couple similar questions on SO, but none of them really helped. Basically I am trying to resize a simple png image, as seen here:
http://media.spiralknights.com/wiki-images/3/3e/Equipment-Proto_Sword_icon.png
(from the mmo Spiral Knights, copyright Three Rings Entertainment)
I had originally implemented a utility which uses these images in php, and the resizing utility there worked perfectly well. I used the method described on the imagecopyresampled page in PHP's documentation.
Honestly I can't even get it to resize better in Photoshop, but the results are almost disastrous in python. I consistently get a halo effect, and I believe this is at least in part to the actual RGBA values of the transparent pixels. Here, this picture tells it better:
(the second to last resize was just a suggestion I saw on another forum to resize first to twice the final size, and it DID help at least a little, but not enough)
The image is already in RGBA mode when it is being resized.
As you can see the PHP and Photoshop resizes are halo-free. Honestly everything but the PHP resize does TOO much work, I like the minimal palette in the php image (if you look at the larger versions you can see that the PHP resize uses less in between colours), but I could live with the way Photoshop has resized it, or even the inner part of the python resize, but the halo is unacceptable.
It seems to me -- and correct me if I'm wrong -- that PHP and Photoshop seem to know not to use the colour of the pixels in the alpha channel when interpolating, but python is using that light border, which is otherwise transparent, in its resize.
Unfortunately there are a lot of different icons that I need to resize, with varying profiles, so they're not all as simple as this circular one, but this was just the first one I was using while experimenting.
It's not much of a code question in and of itself, but if you need something to look at then this is the gist:
>> import Image
>> img = Image.open('swordorig.png')
>> img
<PngImagePlugin.PngImageFile image mode=RGBA size=256x256 at 0x2A3AF58>
>> img.resize((36,36), Image.ANTIALIAS).save('swordresize.png')
Eventual question being: is there a way to tell PIL NOT to use the colour of a pixel that has an alpha of 0 while resampling?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
谢谢大家的回答!特别是 rotoglup 告诉我我真正要找的东西的术语。通过查看 PIL 中预乘 alpha 的堆栈溢出页面,我找到了一个可行的解决方案;这是调整图形大小的更新表:
灰色条只是为了给人留下它们看起来的印象就像在较浅的背景上一样。
https://stackoverflow.com/a/6882161/1189554
感谢 madlag
所以我的代码最终看起来像这样
:您会看到工作表底部的图标。仍然比 PHP 版本有更多的颜色,并且环非常温和,但总体来说要好得多。我确信可以对算法进行调整以进一步改进它。再次感谢大家的回复!
Thanks to everyone for answering! And especially to rotoglup for telling me the term for what I was actually looking for. Going through the stack overflow pages for premultiplied alpha in PIL I found a solution that works; here is an updated sheet of resize graphics:
The gray bars are just to give an impression of what they would look like on a lighter background.
https://stackoverflow.com/a/6882161/1189554
Thanks to madlag
So my code ends up looking like this:
And you get the icon that is on the bottom of the sheet. Still more colours than the PHP version, and a very mild ring, but overall much, much nicer. I'm sure the algorithm could be tweaked to improve it even more. Thanks again to everyone for responding!