Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Image ICC Profile with PHP or Imagick

I have been struggling all day with this issue and surprised that can't find any documentation!

I am uploading images to a website & would like to extract the name of each images ICC profile & use it in the image description. So far, standard PHP produces no results. I have checked the images with Photoshop, Bridge & Exiftool & each has identified the profile embedded.

<?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 produced the best results with:

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

Generating an array that actually mentions the profile but not a usable string. Any help appreciated.

I'm using these versions:

PHP Version 5.2.17 - imagick module version 3.0.1 - ImageMagick version 6.7.6-8

And print_r returns (for 'ProPhoto RGB' ICC profile):

Array ( [icc] => �KCMSmntrRGB XYZ � :acspMSFTKODAROMM���+KODAcprtHdesc\�wtpt�rTRC�gTRC�bTRC�rXYZgXYZbXYZ,dmnd@ndmdd��mmod�(textCopyright (c) Eastman Kodak Company, 1999, all rights reserved.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���;� )

in full (from 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)
like image 447
20pictures Avatar asked May 23 '13 13:05

20pictures


People also ask

Is imagick included in PHP?

Imagick is a PHP extension to create and modify images using the ImageMagick library. There is also a version of Imagick available for HHVM. Although the two extensions are mostly compatible in their API, and they both call the ImageMagick library, the two extensions are completely separate code-bases.

What is the use of imagick?

Use ImageMagick®to create, edit, compose, or convert digital images. It can read and write images in a variety of formats (over 200) including PNG, JPEG, GIF, WebP, HEIC, SVG, PDF, DPX, EXR and TIFF.

What is ImageMagick PHP?

The ImageMagick extension, called Imagick when referring to the PHP extension, is a native PHP extension to create and modify images using the ImageMagick API.


1 Answers

I'm not too sure, if this is the case for all images. At least the images i have, have this information in their "Properties". Thus to get a printable profile name it should work like this:

$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')
 */

If you would like to see all the properties, which are set for an image, you could probe the image manually with identify -verbose /some/filename. There you will have to look for "Properties:", the ICC name should be set there.

The above is the easy way to obtain the ICC profile name. If you really need the ICC name from the icc profile you might want to take a look at the ICC Profile Format Specification

In short:

  • The first 128 bytes are the header. Then follows a tag table, where the first 4 bytes are the size of the table.
  • Each tag consists of 4 byte triplets. The first 4 byts are the name of the tag. The next four bytes are the offset of the data in the icc file. The next four bytes define the size of the tags data.

We are interested in the 'desc' tag (see page 63 in the specification).

  • The description itself starts again with 'desc' then four bytes are reserved. The next four bytes define the size of the ICC profiles name.

In code it works like this:

$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";
    }
}
like image 118
Darokthar Avatar answered Nov 03 '22 08:11

Darokthar