当用户上传图片时,我正在处理图片,但我的问题是高分辨率图片。您如何检测用户何时上传?我正在为 PHP 使用 GD 库。使用 imagejpeg() 方法将质量设置为 90 对它没有任何作用,而是缩放尺寸,然后将 ppi 设置为 72。我希望能够同时保留尺寸并将 ppi 降至 72。任何建议将不胜感激。
6 回答
就您需要关注的而言,没有 PPI 这样的东西。此外,DPI 不存在于数字中。只有像素和尺寸(只是在任一方向上的像素测量)。
您真正想做的是对图像进行下采样,从而减小图像的整体尺寸。您可能希望按比例执行此操作,也就是说,您希望保持相同的宽高比,以便图像在重新采样后不会显得拉伸。另外值得注意的是,调整大小和重新采样的不同之处在于调整大小并不太关注内容,导致调整后的图像在视觉上非常糟糕。您可能需要重新采样。
PHP 文档有一些关于处理上传文件以及如何使用 GDImage 库调整图像大小的优秀示例。我建议你检查一下。您可能想了解的其他相关方法:
- getimagesize()将让您在不打开图像的情况下检查图像的尺寸(用于检查是否需要在不加载图像的情况下调整其大小)。
- imagesx()和imagesy()抓取 GD Image 资源的尺寸。
PPI、DPI...
首先,让我们澄清一下术语。PPI(每英寸像素数)和DPI (每英寸点数)都是指定将像素转换为物理单位(在本例中为英寸)的比率。在数字世界中——计算机、图像…… DPI 被错误地使用在应该使用 PPI 的地方。DPI 实际上只存在于印刷界。但现在对我们来说,DPI = PPI。>> 更多信息
分辨率信息(有时称为 DPI,但它是 PPI)存储在标头(图像元信息)中。JPG 和 PNG 确实支持这一点;但GIF 不支持 DPI - 它不存在于 GIF 标头中。
在 PHP 中更改 PPI
那么,您可能会问如何在图像标题中设置 PPI(DPI)?在 PHP 中,您可以使用 Imagick 库(当然不适用于 GIF):
$image = new Imagick('img.jpg'); // default 72 dpi image
$image->setImageResolution(500, 500);
$image->writeImage("img-500dpi.jpg"); // this image will have 500 dpi
如果您下载这些图像并尝试在 IrfanView 中打印它们,它实际上会使用 dpi 信息将像素转换为目标物理单位。两个图像将以不同的尺寸打印。
图片 PPI 在网络上不起作用
坏消息是,在网页上显示图像时,这不会改变任何东西。显示的锚单元始终是 CSS 中的一个像素。因此img.jpg
,img-500dpi.jpg
在浏览器中将具有完全相同的大小。即使您直接打开图像。即使您使用物理单位,例如cm
:
img { width: 8cm; height: 6cm; }
两个图像将以相同的尺寸显示;无论图像分辨率如何,物理单位都使用固定比率转换为像素。令人惊讶的是,即使您尝试在 Firefox 中打印原始图像(而不是页面),它们也会以相同的尺寸打印。无法评论其他浏览器。很奇怪——这在 Irfanview 中按预期工作。
PPI 和视网膜图像
现在随着 Iphone 等视网膜(即高分辨率)图像变得流行。这里谈了很多关于 DPI(实际上是 PPI)的内容,但这都只与目标设备和CSS 媒体查询有关。没有什么可以真正识别您图像的 PPI;您必须以像素为单位指定高分辨率视网膜图像的实际尺寸。这是 66x66 图标的示例(来自此处):
@media (-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.box {
background:url('images/icon66x66.png') no-repeat top left;
background-size: 33px 33px;
}
}
因此,您实际上可以通过在 CSS 中为它们设置较低的尺寸来“缩小”高分辨率图像。但我只建议对视网膜图像和正确的媒体查询执行此操作。
所以,你必须在 PHP 中重新采样
所以事实上,如果你想让上传的图片在“网络上”看起来更小,最好的方法是重新采样。重采样意味着不只是改变标题,而是改变图像的实际像素矩阵。这是我在 PHP 中使用的代码,它使用了 GD 库:
$t = imagecreatefromjpeg($old_img_path);
$s = imagecreatetruecolor($new_width, $new_height);
$x = imagesx($t);
$y = imagesy($t);
imagecopyresampled($s, $t, 0, 0, 0, 0, $new_width, $new_height, $x, $y);
imagejpeg($s, $new_img_path);
chmod($new_img_path, 0644);
请注意,这需要相当多的内存,这可能会受到您的托管服务提供商的限制。
如果您经常处理高分辨率图像,我会沿着 ImageMagick 路径走,因为它更快 + 提供有关图像的更多信息 + 如果您愿意,可以让您以 300 DPI(或其他分辨率)写回图像.
这是我对 Jcrop 和 ImageMagick 所做的(但 DPI 为 72)
$picture = new Imagick($src);
$picture->cropImage( $_POST['w'], $_POST['h'], $_POST['x'], $_POST['y']);
$picture->resizeImage(690, 500, Imagick::FILTER_LANCZOS,1, true);
$picture->writeImage($cropped);
$picture->clear();
$picture->destroy();
使用 phpthumb ( http://phpthumb.gxdlabs.com ) 是一个很好、优雅且简单的解决方案。
我有一个使用它上传到 GitHub 的工作代码示例。它可以同时使用 GD 和 Imagemagick,这取决于你。
bool Imagick::setResolution ( float $x_resolution , float $y_resolution )
如果您要减少 ppi,尺寸会发生变化以反映减少情况 - 每英寸像素越少意味着图片的英寸数越少。