2013-05-23 22 views
7

Ho lottato tutto il giorno con questo problema e sono sorpreso che non riesca a trovare alcuna documentazione!Ottieni immagine ICC Profile con PHP o Imagick

Sto caricando immagini su un sito web & vorrei estrarre il nome di ogni immagine profilo ICC & usarlo nella descrizione dell'immagine. Finora, PHP standard non ha prodotto risultati. Ho controllato le immagini con Photoshop, Bridge & Exiftool & ciascuna ha identificato il profilo incorporato.

<?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 prodotto i migliori risultati con:

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

Generazione di un array che effettivamente menziona il profilo, ma non una stringa utilizzabile. Qualsiasi aiuto apprezzato.

sto usando queste versioni:

PHP versione 5.2.17 - imagick modulo Versione 3.0.1 - Versione ImageMagick 6.7.6-8

E print_r rendimenti (per 'ProPhoto RGB' profilo ICC):

Array ([ICC] => KCMSmntrRGB XYZ: acspMSFTKODAROMM + KODAcprtHdesc \ wtptrTRCgTRCbTRCrXYZgXYZbXYZ, DMND @ ndmddmmod (textcopy a destra (c) Eastman Kodak Company, 1999, tutti i diritti riservati.desc ProPhoto RGB ProPhoto RGB ProPhoto RGBXYZ , curv XYZ 4I XYZ " > XYZ -descKODAK KODAKKODAKdesc'Riferimento Media di uscita Metrica (Romm) (riferimento di uscita media Internazionale (Romm) 'di riferimento di uscita media Internazionale (Romm) MMOD;)

per intero (da 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) 
+0

Qual è la stringa che vi aspettate di nuovo – ejrowley

+0

Sto cercando un modo per restituire il nome del profilo, quindi, in questo esempio: ProPhoto RGB – 20pictures

+0

Forse vedi quali sono effettivamente quei caratteri non stampabili, per vedere se riesci a individuare un motivo? Potrebbero essere caratteri nulli (zero), per esempio. – halfer

risposta

4

I' Non sono troppo sicuro, se questo è il caso per tutte le immagini. Almeno le immagini che ho, hanno questa informazione nelle loro "Proprietà". Così, per ottenere un nome di profilo stampabile dovrebbe funzionare in questo modo:

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

Se volete vedere tutte le proprietà, che sono impostati per un'immagine, si potrebbe sondare l'immagine manualmente con identify -verbose /some/filename. Lì dovrai cercare "Proprietà:", il nome ICC dovrebbe essere impostato lì.

Quanto sopra è il modo semplice per ottenere il nome del profilo ICC. Se si ha realmente bisogno il nome ICC dal profilo ICC che si potrebbe desiderare di dare un'occhiata al ICC Profile Format Specification

In breve:

  • I primi 128 byte sono l'intestazione. Segue quindi una tabella di tag, in cui i primi 4 byte corrispondono alla dimensione della tabella.
  • Ogni tag è composto da terzine di 4 byte. I primi 4 byte sono il nome del tag. I successivi quattro byte rappresentano l'offset dei dati nel file icc. I successivi quattro byte definiscono la dimensione dei dati dei tag.

Siamo interessati al tag 'desc' (vedere pagina 63 nelle specifiche).

  • La descrizione stessa inizia di nuovo con "desc", quindi quattro byte sono riservati. I successivi quattro byte definiscono la dimensione del nome dei profili ICC.

Nel codice funziona così:

$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"; 
    } 
}