PHP/GD:如何处理 jpg 透明度?

Posted

技术标签:

【中文标题】PHP/GD:如何处理 jpg 透明度?【英文标题】:PHP/GD: How to handle jpg transparency? 【发布时间】:2019-01-04 19:22:49 【问题描述】:

JPG 不支持透明度。

但是,您可以从例如 GIMP 导出具有透明区域的图像。在这种情况下,透明区域将在您的浏览器、Windows 资源管理器或其他软件中显示为黑色或白色。

我经常收到需要处理并以几种较小格式提供的此类文件。我使用 GD 库通过一些 php 脚本来做到这一点。问题是无法预测这些区域在处理后的版本中会变成黑色还是白色。即使是白色背景也可以变成黑色。

所以我的问题是是否可以通过某种方式检测 GD 中的这个“透明”区域并为其分配特定颜色。

例如看这两张图片: http://www.bilbil.com/9156-thickbox_default/bus.jpg http://bilbil.com/img/p/9/1/5/6/9156.jpg

目前我使用此代码:

$srcfile = "9158.jpg";
$dir ="/test/";
list($width, $height, $imgtype, $attr) = @getimagesize( $dir.$srcfile );
$src = imagecreatefromjpeg($dir.$srcfile);
$newheight=$newwidth = 800;
$img = imagecreatetruecolor ( $newwidth , $newheight );
$white = imagecolorallocate($img, 255, 255, 255);
imagefill($img, 0, 0, $white);
imagecopyresampled($img, $src, ($newwidth-$width)/2, ($newheight-$height)/2, 0, 0, $width, $height, $width, $height);
if(!imagejpeg($img, $dir.'test.jpg', 97))
  echo("Error creating testimage");

【问题讨论】:

它们不会“显示为”黑色或白色,它们黑色或白色。您可以编写一些东西,为边缘的所有#000000 或#FFFFFF 像素设置 alpha 通道,然后以实际支持透明度的格式保存,但随后您将遇到锯齿问题和 JPEG 伪像。解决方案是让人们以正确的格式而不是 JPEG 向您发送图像。 当我在 Windows 资源管理器中看到 jpg 的图像背景为黑色而在浏览器中为白色时,除了“显示为”之外,我无法描述它。 【参考方案1】:

在几乎所有情况下,您都可以使用左上角的像素颜色作为透明颜色。

【讨论】:

【参考方案2】:

你可以给ImageMagick一个机会。以下命令会将 .jpeg 文件转换为具有透明度的 .png。

convert bus.jpg \
    -alpha set -fill none -fuzz 1% \
    -bordercolor white -border 1 -draw 'color 0,0 floodfill' -shave 1x1 \
    -bordercolor black -border 1 -draw 'color 0,0 floodfill' -shave 1x1 \
    a.png

这是它的工作原理:

    在整个图像周围添加白色边框 从左上角开始用透明填充白色(以及所有与其相似的颜色 1%) 移除图片周围的多余边框 在整个图像周围添加黑色边框 从左上角开始用透明填充黑色(以及所有与其相似的颜色 1%) 移除图片周围的多余边框 将结果图像写入文件a.png

这是 PHP 的 sn-p:

<?php

function jpg_to_png($jpg, $png)

$templ = trim("
convert jpg \
    -alpha set -fill none -fuzz 1% \
    -bordercolor white -border 1 -draw 'color 0,0 floodfill' -shave 1x1 \
    -bordercolor black -border 1 -draw 'color 0,0 floodfill' -shave 1x1 \
    png
");
    $cmd = strtr($templ, [
        'jpg' => escapeshellarg($jpg),
        'png' => escapeshellarg($png)
    ]);
    exec($cmd, $stdout, $exitcode);
    if ($exitcode) 
        throw new Error("Command failed with code $exitcode");
    


jpg_to_png('bus.jpg', 'a.png');

以下命令 (ref) 也可能对您的情况有所帮助:

convert bus.jpg -fuzz 1% -trim +repage a.jpg

它将从输入图像中删除所有“空白”。

【讨论】:

【参考方案3】:

我不确定你在问什么。您是从具有透明度的非 JPG 图像开始并转换为 JPG 吗?或者你已经有JPG。

如果您从 PNG 或 TIFF 等透明图像开始,并希望转换为 JPG 并且始终具有黑色(或任何其他颜色)背景,那么在 Imagemagick 中,您可以执行以下操作:

convert image.png -background black -alpha background -alpha off image.jpg

convert image.png -background black -flatten image.jpg

将黑色替换为透明的任何其他颜色,例如白色。

如果您已经有一个带有某种颜色的 JPG 并且想要将其更改为黑色,那么请执行以下操作:

convert image.jpg -fuzz XX% -fill black -opaque somecolor image.jpg

其中 XX% 是您想要考虑的接近“somecolor”的百分比,您想要将“somecolor”和附近的颜色更改为黑色。

对不起,我不知道 GD。但我希望它具有类似的功能。或者您可以使用基于 Imagemagick 构建的 PHP Imagick。

【讨论】:

以上是关于PHP/GD:如何处理 jpg 透明度?的主要内容,如果未能解决你的问题,请参考以下文章

函数式编程中如何处理副作用?

函数式编程中如何处理副作用?

PHP GD 库中的图像透明度

unity3d 如何将贴图的黑色背景变为透明

PHP GD从创建的PNG修剪透明像素

PHP GD 在另一个形状上绘制形状并使其透明