跳至内容
Python 俱乐部
用户工具
登录
站点工具
搜索
工具
显示页面
修订记录
反向链接
最近更改
媒体管理器
网站地图
登录
>
最近更改
媒体管理器
网站地图
您的足迹:
modules:pil:convert-png-gif
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
====== PIL Tutorial: Converting Between PNG and GIF ====== PIL supports both PNG and GIF image formats, but converting between the two while keeping transparency can be tricky. Inside is a list of tips for dealing with transparency and dithering issues when processing GIF image formats in PIL. If you are only interested in the final solution you can skip this tutorial and go directly to the code <html> <h2 id="SavingGIFwithtransparency">Saving GIF with transparency</h2> <p>Support for writing GIF transparency was added in <a href="http://effbot.org/zone/pil-changes-114.htm">PIL1.1.4</a>. Yet the latest PIL version 1.1.6 doesn't not automatically write the transparency index for you. In order to keep the transparency, you need to explicitly specify the transparent color index as an option when saving the image in GIF format.<br> </p><div class="geshifilter"><pre class="geshifilter-python">im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'icon.gif'</span><span class="br0">)</span> transparency = im.<span class="me1">info</span><span class="br0">[</span><span class="st0">'transparency'</span><span class="br0">]</span> im.<span class="me1">save</span><span class="br0">(</span><span class="st0">'icon.gif'</span>, transparency=transparency<span class="br0">)</span></pre></div><br> <span class="geshifilter"><code class="geshifilter-text">im.info</code></span> is a dictionary that contains a set of properties defined by the <span class="geshifilter"><code class="geshifilter-text">Image.open</code></span> method. <h2 id="ConvertingfromGIFintoPNG">Converting from GIF into PNG</h2> <p>Luckily PNG supports palette-based images. This will save us from a lot of work. The only thing you have to do is setting the transparency option.<br> </p><div class="geshifilter"><pre class="geshifilter-python">im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'icon.gif'</span><span class="br0">)</span> transparency = im.<span class="me1">info</span><span class="br0">[</span><span class="st0">'transparency'</span><span class="br0">]</span> im .<span class="me1">save</span><span class="br0">(</span><span class="st0">'icon.png'</span>, transparency=transparency<span class="br0">)</span></pre></div> <h2 id="ConvertingfromPNGintoGIF">Converting from PNG into GIF</h2> <p>This can be tricky for two reasons:</p> <ul> <li>PNG gives a much wider range of color depths than GIF, truecolor up to 48-bit compared to 8-bit 256-color.</li> <li>PNG gives a much wider range of transparency options than GIF, including alpha channel transparency.</li> </ul> <h3 id="PNGimageispalettebased">PNG image is palette-based </h3> <p>If the PNG image is palette-based, i.e. P mode, then the conversion is straightforward. The only thing you have to do is setting the transparency option as before:<br> </p><div class="geshifilter"><pre class="geshifilter-python">im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'icon.png'</span><span class="br0">)</span> <span class="kw1">assert</span> im.<span class="me1">mode</span> == <span class="st0">'P'</span> transparency = im.<span class="me1">info</span><span class="br0">[</span><span class="st0">'transparency'</span><span class="br0">]</span> im .<span class="me1">save</span><span class="br0">(</span><span class="st0">'icon.gif'</span>, transparency=transparency<span class="br0">)</span></pre></div> <h3 id="PNGimageisinRGBAmode">PNG image is in RGBA mode</h3> <p>When converting form RGBA into P, we need to reduce the number of distinct colors used in the image to a maximum of 256 colors through a process called <a href="http://en.wikipedia.org/wiki/Color_quantization">quantization</a>.</p> <p>PIL supports two types of palette quantizers, <span class="geshifilter"><code class="geshifilter-text">WEB</code></span> and <span class="geshifilter"><code class="geshifilter-text">ADAPTIVE</code></span>. The default quantizer in PIL1.1.6 is <span class="geshifilter"><code class="geshifilter-text">Image.WEB</code></span> which reduces the color space to <a href="http://en.wikipedia.org/wiki/Web_colors#Web-safe_colors">web safe colors</a> and <a href="http://en.wikipedia.org/wiki/Dither#Digital_photography_and_image_processing">dithers</a> the rest. While <span class="geshifilter"><code class="geshifilter-text">Image.ADAPTIVE</code></span> quantizer is intended to keep the converted image as visually similar as possible to the original image.</p> <p>The following table explains the difference in output between <span class="geshifilter"><code class="geshifilter-text">WEB</code></span> and <span class="geshifilter"><code class="geshifilter-text">ADAPTIVE</code></span> quantizers in PIL:</p> <table> <thead> <tr> <th class="center">PNG: Original Image</th> <th class="center">GIF: WEB quantizer</th> <th class="center">GIF: ADAPTIVE quantizer</th> </tr> </thead> <tbody> <tr class="center"> <td><img src="/sites/default/files/pil_tips/mouse.png" alt="mouse"></td> <td><img src="/sites/default/files/pil_tips/mouse-bad.gif" alt="mouse bad"></td> <td><img src="/sites/default/files/pil_tips/mouse.gif" alt="mouse"></td> </tr> </tbody><tbody> </tbody></table> <p>So to avoid dithering, we should use the <span class="geshifilter"><code class="geshifilter-text">ADAPTIVE</code></span> quantizer like this:<br> </p><div class="geshifilter"><pre class="geshifilter-python">im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'mouse.png'</span><span class="br0">)</span> im = im.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'RGB'</span><span class="br0">)</span>.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'P'</span>, palette=Image.<span class="me1">ADAPTIVE</span><span class="br0">)</span> im.<span class="me1">save</span><span class="br0">(</span><span class="st0">'mouse.gif'</span><span class="br0">)</span></pre></div> <p>Now that we know how to solve the first issue, we need to find a solution for the transparency issue.</p> <h4 id="Solidbackgroundworkaround">Solid background workaround</h4> <p>Sometimes you don't need to keep the transparency; all what you want is a solid background. This will do the trick for you:<br> </p><div class="geshifilter"><pre class="geshifilter-python">im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'mouse.png'</span><span class="br0">)</span> <span class="co1"># Create a new image with a solid color</span> background = Image.<span class="kw3">new</span><span class="br0">(</span><span class="st0">'RGBA'</span>, im.<span class="me1">size</span>, <span class="br0">(</span><span class="nu0">255</span>, <span class="nu0">255</span>, <span class="nu0">255</span><span class="br0">)</span><span class="br0">)</span> <span class="co1"># Paste the image on top of the background</span> background.<span class="me1">paste</span><span class="br0">(</span>im, im<span class="br0">)</span> im = background.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'RGB'</span><span class="br0">)</span>.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'P'</span>, palette=Image.<span class="me1">ADAPTIVE</span><span class="br0">)</span> im.<span class="me1">save</span><span class="br0">(</span><span class="st0">'mouse.gif'</span><span class="br0">)</span></pre></div><br> <img src="/sites/default/files/pil_tips/mouse-white.gif" alt="mouse with white background"> <h4 id="Solutionforkeepingtransparency">Solution for keeping transparency</h4> <p>GIF allows you to set one of the colors in the palette as fully transparent, whereas PNG images in RGBA mode allow you to have different levels of transparency through the alpha band. An alpha value of 255 means the pixel is fully opaque, 0 means fully transparent and Intermediate values indicate partially transparent pixels.</p> <p>Let's try to set the black background to transparent:<br> </p><div class="geshifilter"><pre class="geshifilter-python">im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'mouse.png'</span><span class="br0">)</span> im = im.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'RGB'</span><span class="br0">)</span>.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'P'</span>, palette=Image.<span class="me1">ADAPTIVE</span><span class="br0">)</span> <span class="co1"># The black index in the palette of this image is 255</span> im.<span class="me1">save</span><span class="br0">(</span><span class="st0">'mouse.gif'</span>, transparency=<span class="nu0">255</span><span class="br0">)</span></pre></div><br> <img src="/sites/default/files/pil_tips/mouse-trans-bad.gif" alt="bad transparent mouse"><br> In addition to the background, black is also used in other places in the image, such as the eyes. That's why the result is bad. A solution to this is to fill the transparent parts with a unique color that doesn't exist in other opaque parts. <h5 id="Thesolution">The solution</h5> <p>The trick is to use the <span class="geshifilter"><code class="geshifilter-text">colors</code></span> keyword argument in <span class="geshifilter"><code class="geshifilter-text">im.convert</code></span>. This argument tells <span class="geshifilter"><code class="geshifilter-text">convert</code></span> how many colors it should use in the palette. The default is 256 which is the maximum possible number of colors in the palette. To reserve a color in the palette for transparency we can tell <span class="geshifilter"><code class="geshifilter-text">convert</code></span> to only use 255 out of 256 and then use the last index 255 to fill the transparent parts.</p> <p></p><div class="geshifilter"><pre class="geshifilter-python"><span class="kw1">from</span> PIL <span class="kw1">import</span> Image im = Image.<span class="kw2">open</span><span class="br0">(</span><span class="st0">'mouse.png'</span><span class="br0">)</span> <span class="co1"># Get the alpha band</span> alpha = im.<span class="me1">split</span><span class="br0">(</span><span class="br0">)</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span> <span class="co1"># Convert the image into P mode but only use 255 colors in the palette out of 256</span> im = im.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'RGB'</span><span class="br0">)</span>.<span class="me1">convert</span><span class="br0">(</span><span class="st0">'P'</span>, palette=Image.<span class="me1">ADAPTIVE</span>, colors=<span class="nu0">255</span><span class="br0">)</span> <span class="co1"># Set all pixel values below 128 to 255,</span> <span class="co1"># and the rest to 0</span> mask = Image.<span class="kw2">eval</span><span class="br0">(</span>alpha, <span class="kw1">lambda</span> a: <span class="nu0">255</span> <span class="kw1">if</span> a <span class="sy0"><</span>=<span class="nu0">128</span> <span class="kw1">else</span> <span class="nu0">0</span><span class="br0">)</span> <span class="co1"># Paste the color of index 255 and use alpha as a mask</span> im.<span class="me1">paste</span><span class="br0">(</span><span class="nu0">255</span>, mask<span class="br0">)</span> <span class="co1"># The transparency index is 255</span> im.<span class="me1">save</span><span class="br0">(</span><span class="st0">'mouse.gif'</span>, transparency=<span class="nu0">255</span><span class="br0">)</span></pre></div><br> We used the paste function to fill the transparent parts with the last reserved index. For more examples on using the paste function please refer to <a href="/pil-tutorial-how-create-button-generator">PIL Tutorial: How to Create a Button Generator</a>. <p>And here is the final result:<br> <img src="/sites/default/files/pil_tips/mouse-trans.gif" alt="background mouse"> </p> </html> ===== Source ===== http://nadiana.com/pil-tips-converting-png-gif
modules/pil/convert-png-gif.txt
· 最后更改: 2010/06/02 01:18 (外部编辑)
页面工具
显示页面
修订记录
反向链接
回到顶部