Php 检测JPEG图像质量

Php 检测JPEG图像质量,php,imagemagick,jpeg,Php,Imagemagick,Jpeg,我允许用户上传图片。但是,我想保持JPEG质量不超过90%。我计划做的是检测当前质量: -如果低于90%,则什么也不做 -如果超过90%,则使用Image Magick将图像重新压缩到90% 有可能吗?我更喜欢PHP,但任何语言都会有所帮助。您不能保证质量设置存储在JPEG的元数据中。这是编码器设置,不是图像属性 在这里阅读更多关于 简单地定义最大文件大小可能更有意义。归根结底,限制图像质量就是为了节省带宽。因此,设置图像尺寸和文件大小之间的比率更合适。paddy正确的是,此设置并不总是存储在J

我允许用户上传图片。但是,我想保持JPEG质量不超过90%。我计划做的是检测当前质量: -如果低于90%,则什么也不做 -如果超过90%,则使用Image Magick将图像重新压缩到90%


有可能吗?我更喜欢PHP,但任何语言都会有所帮助。

您不能保证质量设置存储在JPEG的元数据中。这是编码器设置,不是图像属性

在这里阅读更多关于


简单地定义最大文件大小可能更有意义。归根结底,限制图像质量就是为了节省带宽。因此,设置图像尺寸和文件大小之间的比率更合适。

paddy正确的是,此设置并不总是存储在JPEG文件中。如果是,则可以使用Imagemagick中的
标识
读取质量。例如:

$ identify -format '%Q' tornado_ok.jpg
93%

更新:基于此问题的答案 我 发现显然
identify
命令仍然可以确定 通过对量化表进行反向工程(即使所有量化表 图像EXIF/其他元数据丢失。顺便说一句,书名是 你现在的问题很可能是重复的 我链接到的问题

但对我来说,你的问题本身就有价值,因为在你的 问题的文本你解释你想做什么,哪个更重要 而不仅仅是检测jpeg质量。然而,也许你应该 如果要反映您正在尝试解决问题,请更新标题 比仅仅读取JPEG图像质量更具体的问题

除非您正在存档原始图像,否则对于web使用来说,即使是90%也是多余的。在过去,75%是默认值(只有在并排图像之间仔细检查时才能看到退化),而现在在高带宽的日子里,85%是一个非常高的质量选项。90%和85%之间5%的质量差异实际上是看不见的,但通常会为您节省超过30%的文件大小。JPEG算法的设计初衷是在第一个压缩阶段(超过80%左右)消除人类感知不到的信息

更新/注意:我谈论的压缩质量设置是 通过对libjpeg的测试,这是一个使用非常广泛的JPEG库。Photoshop的 压缩百分比和其他软件的质量设置都是 独立和不一定意味着与设置相同的事情 libjpeg

paddy使用图像高度和图像宽度来计算可接受的文件大小的想法是合理的:

您可以按如下方式获得图像的高度/宽度:

list($originalWidth, $originalHeight) = getimagesize($imageFile);
我自己在网上发布的高质量照片,比如: 通常以每百万像素约200 KB的比率保存


例如,您可以将宽度乘以高度,再除以1000000来计算图像中的百万像素。将文件大小除以1024以计算KB。然后将结果KB除以百万像素。如果结果小于200或您决定的任何值,则不需要重新压缩它。否则,您可以以85%的质量或您决定的任何质量重新压缩它。

怎么了?我在开发一款应用程序时遇到了同样的问题。。。我的问题是,我从一个随机站点提取了几个图像,每个项目都有几个图像,我想为每个项目显示一个图像,并为用户提供质量最好的图像

我提出了这个想法,它非常简单,适用于任何语言和任何类型的压缩:

//Parameters you will need to retrieve from image
$width = 0; 
$height = 0;
$filesize = 0;

//Quality answer for your image
$quality = (101-(($width*$height)*3)/$filesize);
我针对上述情况运行了此算法,结果如下:

Filename            Width   Height  Pixels  BitmapBytes FileBytes   Quality 
estq-baseline.png   400     300     120000  360000      163250      98,79
estq-90.jpg         400     300     120000  360000      34839       90,67
estq-80.jpg         400     300     120000  360000      24460       86,28
estq-70.jpg         400     300     120000  360000      19882       82,89
estq-25.jpg         400     300     120000  360000      10300       66,05
此算法背后的基本思想是将以位图方式写入的图像的大小(无任何压缩,每像素3字节,RGB为3字节)与该图像当前使用的大小进行比较。图像大小越小,压缩越高,与所使用的压缩方法无关,而不是JPG、PNG或其他任何形式,这将导致我们在未压缩图像和压缩图像之间有更大或更小的差距

还有一点很重要,这是一个用于比较的数学解决方案,该方法不会返回图像的实际质量,它将回答未压缩和压缩大小之间的距离百分比


如果您需要更多详细信息,可以向我发送电子邮件:rafaelkarst@gmail.com

由于OP表示他更喜欢php,我提供以下内容:

$img = new Imagick($filename);
$quality = $img->getImageCompressionQuality();

对于使用GraphicsMagick而不是ImageMagick的用户,可以使用以下命令获得JPEG质量:

gm identify -format '%[JPEG-Quality]' path_to/image_file.jpg
根据文件

请注意,JPEG没有“质量”的概念,软件使用和估计的质量指标基于IJG JPEG 6b建立的质量指标。其他编码器(例如Adobe Photoshop使用的编码器)使用不同的编码度量


如果您的jpeg是使用标准图像量化表的直接缩放创建的,并且基于独立jpeg组的公式使用了0-100质量,那么,假设您在一个名为
quantization
的数组中有亮度量化表(例如Python的PIL模块在
image.quantization[0]中提供的)
),则可通过以下方式获得原始值:

if quantization[58] <= 100:
    originalQuality = int(100 - quantization[58] / 2)
else:
    originalQuality = int(5000.0 / 2.5 / quantization[15])

if quantization[58]这里有一个PHP函数,它尝试所有可用的方法来获得质量(据我所知):


事实上,我目前的质量设置可能重复85%,但一些贡献者甚至说这很难看。因为我不存档原始图像,所以我需要相当高的质量(对于衍生图像,如缩略图,我使用较低的质量)。使用维度/大小比率作为阈值听起来是合理的。我选择你的答案是因为它解释得很好。谢谢,谢谢你的回答。我犹豫是否决定接受它。伊秋
/* Try to detect quality of jpeg.
   If not possible, nothing is returned (null). Otherwise quality is returned (int)
    */
function detectQualityOfJpg($filename)
{
    // Try Imagick extension
    if (extension_loaded('imagick') && class_exists('Imagick')) {
        $img = new Imagick($filename);

        // The required function is available as from PECL imagick v2.2.2
        if (method_exists($img, 'getImageCompressionQuality')) {
            return $img->getImageCompressionQuality();
        }
    }

    if (function_exists('shell_exec')) {

    // Try Imagick
        $quality = shell_exec("identify -format '%Q' " . $filename);
        if ($quality) {
            return intval($quality);
        }

        // Try GraphicsMagick
        $quality = shell_exec("gm identify -format '%Q' " . $filename);
        if ($quality) {
            return intval($quality);
        }
    }
}