PHP には EXIF および IPTC メタデータの読み取りサポートが組み込まれていますが、XMP を読み取る方法が見つかりません。
9 に答える
XMP データは文字どおり画像ファイルに埋め込まれているため、画像ファイル自体から PHP の文字列関数を使用して抽出できます。
以下は、この手順を示しています (私はSimpleXMLを使用していますが、他のすべての XML API または単純で巧妙な文字列解析でさえ、同等の結果が得られる場合があります)。
$content = file_get_contents($image);
$xmp_data_start = strpos($content, '<x:xmpmeta');
$xmp_data_end = strpos($content, '</x:xmpmeta>');
$xmp_length = $xmp_data_end - $xmp_data_start;
$xmp_data = substr($content, $xmp_data_start, $xmp_length + 12);
$xmp = simplexml_load_string($xmp_data);
2 つのコメント:
- XMP は XML 名前空間を多用するため、一部の XML ツールで XMP データを解析するときは、この点に注意する必要があります。
file_get_contents()画像ファイルの可能なサイズを考慮すると、この関数は画像全体をメモリにロードするため、使用できない可能性があります。を使用fopen()してファイル ストリーム リソースを開き、キー シーケンスのデータのチャンクをチェックすると<x:xmpmeta、</x:xmpmeta>メモリ フットプリントが大幅に削減されます。
XMP データの解析方法を Google で検索すると、これが最良の結果と思われるため、かなり時間が経ってから返信します。このほぼ同一のスニペットがコードで使用されているのを数回見たことがありますが、これはひどいメモリの浪費です。Stefan が例の後に言及している fopen() メソッドの例を次に示します。
<?php
function getXmpData($filename, $chunkSize)
{
if (!is_int($chunkSize)) {
throw new RuntimeException('Expected integer value for argument #2 (chunkSize)');
}
if ($chunkSize < 12) {
throw new RuntimeException('Chunk size cannot be less than 12 argument #2 (chunkSize)');
}
if (($file_pointer = fopen($filename, 'r')) === FALSE) {
throw new RuntimeException('Could not open file for reading');
}
$startTag = '<x:xmpmeta';
$endTag = '</x:xmpmeta>';
$buffer = NULL;
$hasXmp = FALSE;
while (($chunk = fread($file_pointer, $chunkSize)) !== FALSE) {
if ($chunk === "") {
break;
}
$buffer .= $chunk;
$startPosition = strpos($buffer, $startTag);
$endPosition = strpos($buffer, $endTag);
if ($startPosition !== FALSE && $endPosition !== FALSE) {
$buffer = substr($buffer, $startPosition, $endPosition - $startPosition + 12);
$hasXmp = TRUE;
break;
} elseif ($startPosition !== FALSE) {
$buffer = substr($buffer, $startPosition);
$hasXmp = TRUE;
} elseif (strlen($buffer) > (strlen($startTag) * 2)) {
$buffer = substr($buffer, strlen($startTag));
}
}
fclose($file_pointer);
return ($hasXmp) ? $buffer : NULL;
}
Linux での簡単な方法は、debian の同名のパッケージで利用可能な exiv2 プログラムを呼び出すことです。
$ exiv2 -e X extract image.jpg
は、XMP が埋め込まれた image.xmp を生成し、これを解析することができます。
その短縮版をありがとう、Sebastien B.:)。問題を回避したい場合、chunk_size が一部のファイルに対して小さすぎる場合は、再帰を追加するだけです。
function getXmpData($filename, $chunk_size = 50000){
$buffer = NULL;
if (($file_pointer = fopen($filename, 'r')) === FALSE) {
throw new RuntimeException('Could not open file for reading');
}
$chunk = fread($file_pointer, $chunk_size);
if (($posStart = strpos($chunk, '<x:xmpmeta')) !== FALSE) {
$buffer = substr($chunk, $posStart);
$posEnd = strpos($buffer, '</x:xmpmeta>');
$buffer = substr($buffer, 0, $posEnd + 12);
}
fclose($file_pointer);
// recursion here
if(!strpos($buffer, '</x:xmpmeta>')){
$buffer = getXmpData($filename, $chunk_size*2);
}
return $buffer;
}
Bryan のソリューションはこれまでで最高のものでしたが、いくつかの問題があったため、単純化するために変更し、いくつかの機能を削除しました。
彼のソリューションには 3 つの問題がありました。
A) 抽出されたチャンクが、検索している文字列の 1 つの間にある場合、それは見つかりません。チャンク サイズが小さいと、この問題が発生する可能性が高くなります。
B) チャンクに開始と終了の両方が含まれている場合、チャンクは見つかりません。これは、開始が見つかったチャンクを再チェックして終了も見つかったかどうかを確認する追加の if ステートメントを使用して簡単に修正できます。
C) xmp データが見つからない場合に while ループを中断するために最後に追加された else ステートメントには、最初のパスで開始要素が見つからない場合、それ以上チャンクをチェックしないという副作用があります。これもおそらく簡単に修正できますが、最初の問題ではそれだけの価値はありません。
以下の私のソリューションはそれほど強力ではありませんが、より堅牢です。1 つのチャンクのみをチェックし、そこからデータを抽出します。開始と終了がそのチャンクにある場合にのみ機能するため、チャンク サイズは、常にそのデータをキャプチャするのに十分な大きさである必要があります。Adobe Photoshop/Lightroom でエクスポートされたファイルに関する私の経験から、xmp データは通常、約 20kB で始まり、約 45kB で終わります。私のイメージでは 50k のチャンク サイズが適切に機能しているようですが、多くの現像設定を持つ CRS ブロックなど、エクスポート時にそのデータの一部を削除すると、はるかに少なくなります。
function getXmpData($filename)
{
$chunk_size = 50000;
$buffer = NULL;
if (($file_pointer = fopen($filename, 'r')) === FALSE) {
throw new RuntimeException('Could not open file for reading');
}
$chunk = fread($file_pointer, $chunk_size);
if (($posStart = strpos($chunk, '<x:xmpmeta')) !== FALSE) {
$buffer = substr($chunk, $posStart);
$posEnd = strpos($buffer, '</x:xmpmeta>');
$buffer = substr($buffer, 0, $posEnd + 12);
}
fclose($file_pointer);
return $buffer;
}
Xmp Php Tookit 拡張機能を開発しました。これは、adobe xmp ツールキットに基づく php5 拡張機能であり、jpeg、psd、pdf、ビデオ、オーディオから xmp メタデータを読み取り/書き込み/解析するためのメイン クラスとメソッドを提供します。拡張子は gpl ライセンスの下にあります。php 5.3 (現在は php 5.2.x とのみ互換性があります) 用の新しいリリースが間もなく利用可能になり、windows と macosx (現在は freebsd と linux システムのみ) で利用できるはずです。 http://xmpphptoolkit.sourceforge.net/