使用PHP或Imagick获取图像ICC配置文件

9

我整天都在为这个问题苦苦挣扎,惊讶的是找不到任何文档!

我正在将图片上传到网站,并希望提取每个图像的ICC配置文件名称并在图像描述中使用它。目前,标准PHP没有产生任何结果。我已经使用Photoshop、Bridge和Exiftool检查了这些图像,每个工具都能够识别嵌入的配置文件。

<?php 
$info = exif_read_data($image);
echo 'ICC Profile: '.$info['ICC_Profile'].'<br>';
echo 'ICC Profile: '.$info['CurrentICCProfile'].'<br>';
echo 'ICC Profile: '.$info['ColorSpace'].'<br>';
?>

使用Imagick获得最佳效果的方法为:

$imagick = new Imagick();
$imagick->readImage($image);
print_r ($imagick->getImageProfiles("icc",true));

生成一个数组,其中提到了配置文件但不是可用的字符串。任何帮助都将不胜感激。
我正在使用以下版本: PHP 版本 5.2.17 - imagick 模块版本 3.0.1 - ImageMagick 版本 6.7.6-8
对于“ProPhoto RGB”ICC 配置文件,print_r 返回以下结果:
Array ( [icc] => �KCMSmntrRGB XYZ � :acspMSFTKODAROMM���+KODAcprtHdesc\�wtpt�rTRC�gTRC�bTRC�rXYZgXYZbXYZ,dmnd@ndmdd��mmod�(text 版权所有(c)Eastman Kodak Company,1999,保留所有权利。 desc ProPhoto RGB��ProPhoto RGB ProPhoto RGBXYZ ���,curv�XYZ �4I�XYZ "��>XYZ �-descKODAK��KODAKKODAKdesc'Reference Output Medium Metric(ROMM) (��Reference Output Medium Metric(ROMM) 'Reference Output Medium Metric(ROMM) mmod���;� )
完整信息(来自 Exiftool):
Profile CMM Type                : KCMS
Profile Version                 : 2.1.0
Profile Class                   : Display Device Profile
Color Space Data                : RGB
Profile Connection Space        : XYZ
Profile Date Time               : 1998:12:01 18:58:21
Profile File Signature          : acsp
Primary Platform                : Microsoft Corporation
CMM Flags                       : Not Embedded, Independent
Device Manufacturer             : KODA
Device Model                    : ROMM
Device Attributes               : Reflective, Glossy, Positive, Color
Rendering Intent                : Perceptual
Connection Space Illuminant     : 0.9642 1 0.82487
Profile Creator                 : KODA
Profile ID                      : 0
Profile Copyright               : Copyright (c) Eastman Kodak Company, 1999, all rights reserved.
Profile Description             : ProPhoto RGB
Media White Point               : 0.9642 1 0.82489
Red Tone Reproduction Curve     : (Binary data 14 bytes, use -b option to extract)
Green Tone Reproduction Curve   : (Binary data 14 bytes, use -b option to extract)
Blue Tone Reproduction Curve    : (Binary data 14 bytes, use -b option to extract)
Red Matrix Column               : 0.79767 0.28804 0
Green Matrix Column             : 0.13519 0.71188 0
Blue Matrix Column              : 0.03134 9e-005 0.82491
Device Mfg Desc                 : KODAK
Device Model Desc               : Reference Output Medium Metric(ROMM)
Make And Model                  : (Binary data 40 bytes, use -b option to extract)

你期望得到的字符串是什么? - ejrowley
我正在寻找一种方法来返回配置文件名称,因此在这个例子中:ProPhoto RGB。 - 20pictures
也许可以看看那些无法打印的字符到底是什么,看看能否发现规律?它们可能是空字符(零),例如。 - halfer
1个回答

7

我不确定是否所有的图片都是这样的。至少我所拥有的图片,在它们的“属性”中都有这些信息。因此,要获取可打印的配置文件名称,应该按照以下步骤进行:

$imagick = new imagick('/some/filename');
$profile = $imagick->getImageProperties('icc:model', true);
/**
 * If the property 'icc:model' is set $profile now should be:
 * array( 'icc:model' => 'ICC model name')
 */

如果您想查看已设置的图像属性,可以使用identify -verbose /some/filename手动探测图像。在那里,您需要寻找“Properties:”,ICC名称应在那里设置。
以上是获取ICC配置文件名称的简单方法。如果您真的需要来自icc配置文件的ICC名称,您可能需要查看ICC配置文件规范 简而言之:
  • 前128个字节是头部。然后是一个标记表,其中前4个字节是表格大小。
  • 每个标签由4个字节三元组组成。前4个字节是标签的名称。接下来的四个字节是icc文件中数据的偏移量。下一个四个字节定义了标记数据的大小。
我们对'desc'标签感兴趣(请参见规范第63页)。
  • 描述本身再次以'desc'开头,然后保留四个字节。接下来的四个字节定义ICC配置文件名称的大小。
在代码中,它是这样工作的:
$image = new imagick('/path/to/img');
try {
    $existingICC = $image->getImageProfile('icc');
} catch (ImagickException $e) {
    // Handle it
    $existingICC = null;
}

if($existingICC) {
    // Search the start of the description tag in the tag table.:
    // We are not looking in the 128 bytes for the header + 4 bytes for the size of the table
    $descTagPos = stripos( $existingICC, 'desc', 131 );
    if( $descTagPos === false) {
       // There is no description, handle it.
    } else {
        // This is the description Tag ( 'desc'|offset|size each with a size of 4 bytes
        $descTag = substr( $existingICC, $descTagPos, 12 );

        // Get the offset out of the description tag, unpack it from binary to hex and then from hex to decimal
        $descTagOffset = substr ( $descTag, 4, 4 );
        $descTagOffset = unpack( 'H*', $descTagOffset );
        $descTagOffset = hexdec( $descTagOffset[1] );

        // Same for the description size
        $descTagSize = substr ( $existingICC, $descTagPos + 8, 4 );
        $descTagSize = unpack('H*', $descTagSize);
        $descTagSize = hexdec( $descTagSize[1] );

        // Here finally is the descripton
        $iccDesc = substr( $existingICC, $descTagOffset, $descTagSize );

        // See page 63 in the standard, here we extract the size of the ICC profile name string
        $iccNameSize = substr( $iccDesc, 8, 4 );
        $iccNameSize = unpack( 'H*', $iccNameSize);
        $iccNameSize = hexdec( $iccNameSize[1]);

        // Finally got the name.
        $iccName = substr( $iccDesc, 12, $iccNameSize );
        echo "ICC name: $iccName\n";
    }
}

1
感谢您。用于分析ICC配置文件描述的代码非常可靠。getImageProperties('icc:model',true)选项却无法在我的图像集上正常工作。 - serverSentinel
许多图片无法正常工作,其中包括带有“sRGB内置”描述的图片。 - undefined
哪个描述?您是阅读图像的描述还是使用提取的ICC配置文件的描述?我的回答是针对ICC配置文件的。根据图像的创建/处理方式,图像的ICC配置文件描述可以设置为任何内容。然而,如果ICC配置文件被嵌入,您可以提取它并从中获取配置文件名称。上述答案描述了如何从ICC配置文件本身中提取ICC配置文件名称。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接