在php中写入exif数据

发布于 2024-10-25 05:02:33 字数 1099 浏览 2 评论 0原文

我正在尝试创建一个网站,可以在其中添加和修改 JPEG 文件中的元数据。

有没有一种方法可以让我以相当简单的方式写入 exif 数据。

我见过一两个例子,但它们太复杂,在我给出的时间范围内无法掌握。

我了解 IPTC 并且我知道可以将元数据添加到 JPEG 文件中。但这样做的正确方法是什么?

如果有人可以提供一些关于如何使用 EXIF 或 IPTC 或 PHP 的任何其他库或功能将元数据添加到 JPEG 的帮助,那么我将非常感激。

更新:

首先感谢dbers的回复

我已经查看了代码。我已经设法让它将默认标签添加到 JPG 中。

我仍然对一小部分代码的含义感到有点困惑。

例如在php函数中写入exif数据:

function iptc_make_tag($rec, $data, $value) 
{ 
    $length = strlen($value); 
    $retval = chr(0x1C) . chr($rec) . chr($data);
    ...
}

我还没有遇到过函数变量,$rec$data$value 如果尚未定义则被引用。或者它们是从 iptc_make_tag 中获取的?

我回显了 $rec$value 但我没有在屏幕上返回值。

if(isset($info['APP13']))

我不确定 APP13 是什么意思,当我尝试回显 $info 时,当我在表中回显 $info 时,我只是得到以下内容。

'2#120' => 'Test image',
'2#116' => 'Copyright 2008-2009, The PHP Group'

I'm trying to create a website where I can add and modify metadata within a JPEG file.

Is there a way in which I can write the exif data in a fairly easy way.

I have seen one or two examples, but they are they too complex to grasp in the timeframe I have been given.

I am aware of IPTC and I know metadata can be added to the JPEG file. But what would be the correct way of doing this?

If someone could provide some help on how to add metadata to JPEG using EXIF or IPTC or any other library or feature of PHP then I'd be highly appreciative.

Update:

First of all thanks for the reply by dbers.

I've looked through the code. I've managed to get it to add the default tags into the JPG.

I am still a bit confused as to what small portions of the code mean.

For example writing exif data in the php function:

function iptc_make_tag($rec, $data, $value) 
{ 
    $length = strlen($value); 
    $retval = chr(0x1C) . chr($rec) . chr($data);
    ...
}

I haven't come across a function variable, and how are $rec, $data and $value being referenced if they havent been defined. Or are they taken from iptc_make_tag?

I echoed out $rec and $value but I dont get a value back on screen.

if(isset($info['APP13']))

I'm not sure what APP13 means and when I try to echo out $info, I just get the following when I echo out $info in a table.

'2#120' => 'Test image',
'2#116' => 'Copyright 2008-2009, The PHP Group'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遮了一弯 2024-11-01 05:02:33

我知道您找到了解决方案,但这可能会帮助其他正在寻找相同东西的人!

我修改了此处找到的类(感谢debers)。

所有对 IPTC 标签的引用都可以从此 PDF

现在是代码(PHP >= 5.4):

<?
define("IPTC_OBJECT_NAME", "005");
define("IPTC_EDIT_STATUS", "007");
define("IPTC_PRIORITY", "010");
define("IPTC_CATEGORY", "015");
define("IPTC_SUPPLEMENTAL_CATEGORY", "020");
define("IPTC_FIXTURE_IDENTIFIER", "022");
define("IPTC_KEYWORDS", "025");
define("IPTC_RELEASE_DATE", "030");
define("IPTC_RELEASE_TIME", "035");
define("IPTC_SPECIAL_INSTRUCTIONS", "040");
define("IPTC_REFERENCE_SERVICE", "045");
define("IPTC_REFERENCE_DATE", "047");
define("IPTC_REFERENCE_NUMBER", "050");
define("IPTC_CREATED_DATE", "055");
define("IPTC_CREATED_TIME", "060");
define("IPTC_ORIGINATING_PROGRAM", "065");
define("IPTC_PROGRAM_VERSION", "070");
define("IPTC_OBJECT_CYCLE", "075");
define("IPTC_BYLINE", "080");
define("IPTC_BYLINE_TITLE", "085");
define("IPTC_CITY", "090");
define("IPTC_PROVINCE_STATE", "095");
define("IPTC_COUNTRY_CODE", "100");
define("IPTC_COUNTRY", "101");
define("IPTC_ORIGINAL_TRANSMISSION_REFERENCE", "103");
define("IPTC_HEADLINE", "105");
define("IPTC_CREDIT", "110");
define("IPTC_SOURCE", "115");
define("IPTC_COPYRIGHT_STRING", "116");
define("IPTC_CAPTION", "120");
define("IPTC_LOCAL_CAPTION", "121");

class IPTC
{
    var $meta = [];
    var $file = null;

    function __construct($filename)
    {
        $info = null;

        $size = getimagesize($filename, $info);

        if(isset($info["APP13"])) $this->meta = iptcparse($info["APP13"]);

        $this->file = $filename;
    }

    function getValue($tag)
    {
        return isset($this->meta["2#$tag"]) ? $this->meta["2#$tag"][0] : "";
    }

    function setValue($tag, $data)
    {
        $this->meta["2#$tag"] = [$data];

        $this->write();
    }

    private function write()
    {
        $mode = 0;

        $content = iptcembed($this->binary(), $this->file, $mode);   

        $filename = $this->file;

        if(file_exists($this->file)) unlink($this->file);

        $fp = fopen($this->file, "w");
        fwrite($fp, $content);
        fclose($fp);
    }         

    private function binary()
    {
        $data = "";

        foreach(array_keys($this->meta) as $key)
        {
            $tag = str_replace("2#", "", $key);
            $data .= $this->iptc_maketag(2, $tag, $this->meta[$key][0]);
        }       

        return $data;
    }

    function iptc_maketag($rec, $data, $value)
    {
        $length = strlen($value);
        $retval = chr(0x1C) . chr($rec) . chr($data);

        if($length < 0x8000)
        {
            $retval .= chr($length >> 8) .  chr($length & 0xFF);
        }
        else
        {
            $retval .= chr(0x80) . 
                       chr(0x04) . 
                       chr(($length >> 24) & 0xFF) . 
                       chr(($length >> 16) & 0xFF) . 
                       chr(($length >> 8) & 0xFF) . 
                       chr($length & 0xFF);
        }

        return $retval . $value;            
    }   

    function dump()
    {
        echo "<pre>";
        print_r($this->meta);
        echo "</pre>";
    }

    #requires GD library installed
    function removeAllTags()
    {
        $this->meta = [];
        $img = imagecreatefromstring(implode(file($this->file)));
        if(file_exists($this->file)) unlink($this->file);
        imagejpeg($img, $this->file, 100);
    }
}

$file = "photo.jpg";
$objIPTC = new IPTC($file);

//set title
$objIPTC->setValue(IPTC_HEADLINE, "A title for this picture");

//set description
$objIPTC->setValue(IPTC_CAPTION, "Some words describing what can be seen in this picture.");

echo $objIPTC->getValue(IPTC_HEADLINE);
?>

I know you found the solution, but this might help anyone else that s looking for the same thing!

I modified a class that I found here (thanks debers).

And all the references to IPTC tags can be readed from this PDF

And now the code (PHP >= 5.4):

<?
define("IPTC_OBJECT_NAME", "005");
define("IPTC_EDIT_STATUS", "007");
define("IPTC_PRIORITY", "010");
define("IPTC_CATEGORY", "015");
define("IPTC_SUPPLEMENTAL_CATEGORY", "020");
define("IPTC_FIXTURE_IDENTIFIER", "022");
define("IPTC_KEYWORDS", "025");
define("IPTC_RELEASE_DATE", "030");
define("IPTC_RELEASE_TIME", "035");
define("IPTC_SPECIAL_INSTRUCTIONS", "040");
define("IPTC_REFERENCE_SERVICE", "045");
define("IPTC_REFERENCE_DATE", "047");
define("IPTC_REFERENCE_NUMBER", "050");
define("IPTC_CREATED_DATE", "055");
define("IPTC_CREATED_TIME", "060");
define("IPTC_ORIGINATING_PROGRAM", "065");
define("IPTC_PROGRAM_VERSION", "070");
define("IPTC_OBJECT_CYCLE", "075");
define("IPTC_BYLINE", "080");
define("IPTC_BYLINE_TITLE", "085");
define("IPTC_CITY", "090");
define("IPTC_PROVINCE_STATE", "095");
define("IPTC_COUNTRY_CODE", "100");
define("IPTC_COUNTRY", "101");
define("IPTC_ORIGINAL_TRANSMISSION_REFERENCE", "103");
define("IPTC_HEADLINE", "105");
define("IPTC_CREDIT", "110");
define("IPTC_SOURCE", "115");
define("IPTC_COPYRIGHT_STRING", "116");
define("IPTC_CAPTION", "120");
define("IPTC_LOCAL_CAPTION", "121");

class IPTC
{
    var $meta = [];
    var $file = null;

    function __construct($filename)
    {
        $info = null;

        $size = getimagesize($filename, $info);

        if(isset($info["APP13"])) $this->meta = iptcparse($info["APP13"]);

        $this->file = $filename;
    }

    function getValue($tag)
    {
        return isset($this->meta["2#$tag"]) ? $this->meta["2#$tag"][0] : "";
    }

    function setValue($tag, $data)
    {
        $this->meta["2#$tag"] = [$data];

        $this->write();
    }

    private function write()
    {
        $mode = 0;

        $content = iptcembed($this->binary(), $this->file, $mode);   

        $filename = $this->file;

        if(file_exists($this->file)) unlink($this->file);

        $fp = fopen($this->file, "w");
        fwrite($fp, $content);
        fclose($fp);
    }         

    private function binary()
    {
        $data = "";

        foreach(array_keys($this->meta) as $key)
        {
            $tag = str_replace("2#", "", $key);
            $data .= $this->iptc_maketag(2, $tag, $this->meta[$key][0]);
        }       

        return $data;
    }

    function iptc_maketag($rec, $data, $value)
    {
        $length = strlen($value);
        $retval = chr(0x1C) . chr($rec) . chr($data);

        if($length < 0x8000)
        {
            $retval .= chr($length >> 8) .  chr($length & 0xFF);
        }
        else
        {
            $retval .= chr(0x80) . 
                       chr(0x04) . 
                       chr(($length >> 24) & 0xFF) . 
                       chr(($length >> 16) & 0xFF) . 
                       chr(($length >> 8) & 0xFF) . 
                       chr($length & 0xFF);
        }

        return $retval . $value;            
    }   

    function dump()
    {
        echo "<pre>";
        print_r($this->meta);
        echo "</pre>";
    }

    #requires GD library installed
    function removeAllTags()
    {
        $this->meta = [];
        $img = imagecreatefromstring(implode(file($this->file)));
        if(file_exists($this->file)) unlink($this->file);
        imagejpeg($img, $this->file, 100);
    }
}

$file = "photo.jpg";
$objIPTC = new IPTC($file);

//set title
$objIPTC->setValue(IPTC_HEADLINE, "A title for this picture");

//set description
$objIPTC->setValue(IPTC_CAPTION, "Some words describing what can be seen in this picture.");

echo $objIPTC->getValue(IPTC_HEADLINE);
?>
才能让你更想念 2024-11-01 05:02:33

也许你可以尝试:

  • PEL(PHP Exif Library)。一个使用 PHP 读取和写入 JPEG 和 TIFF 图像中的 Exif 标头的库。
  • PHP JPEG 元数据工具包。允许读取、写入和显示以下 JPEG 元数据格式:EXIF 2.2、XMP / RDF、IPTC-NAA IIM 4.1 等
  • Perl 的 ExifTool。 ExifTool 非常棒。它基本上拥有一切 – EXIF、IPTC 和 XMP 支持(读/写)以及对制造商扩展的支持。

Maybe u can try :

  • PEL(PHP Exif Library). A library for reading and writing Exif headers in JPEG and TIFF images using PHP.
  • The PHP JPEG Metadata Toolkit. Allows reading, writing and display of the following JPEG metadata formats: EXIF 2.2, XMP / RDF, IPTC-NAA IIM 4.1 ect
  • ExifTool by perl. The ExifTool is excellent. It’s basically got it all – EXIF, IPTC and XMP support (read/write) and support for manufacturer extensions.
睫毛溺水了 2024-11-01 05:02:33

Imagick 确实允许您设置 EXIF 数据,但仅限于内存中的对象,当将文件写入磁盘时,这些数据将被忽略。最流行的解决方案是使用 exiftools 或使用 PHP 库 PEL。 PEL 的文档很少,而且 API 也不是真正不言自明的。

我在尝试将正确的 EXIF 数据添加到将作为 360 度图像上传到 Facebook 的图像时遇到了这个问题,这需要将特定的相机品牌和型号指定为 EXIF。下面的代码将打开一个图像文件,设置其品牌和型号,然后保存回磁盘。如果您想设置其他 EXIF 数据,可以查看所有受支持的 PelTag 常量的完整列表 PEL 文档中

$data = new PelDataWindow(file_get_contents('IMAGE PATH'));
$tiff = null;
$file = null;

// If it is a JPEG-image, check if EXIF-headers exists
if (PelJpeg::isValid($data)) {
    $jpeg = $file = new PelJpeg();
    $jpeg->load($data);
    $exif = $jpeg->getExif();

    // If no EXIF in image, create it
    if($exif == null) {
        $exif = new PelExif();
        $jpeg->setExif($exif);

        $tiff = new PelTiff();
        $exif->setTiff($tiff);
    }
    else {
        $tiff = $exif->getTiff();
    }
}
// If it is a TIFF EXIF-headers will always be set
elseif (PelTiff::isValid($data)) {
    $tiff = $file = new PelTiff();
    $tiff->load($data);
}
else {
    throw new \Exception('Invalid image format');
}

// Get the first Ifd, where most common EXIF-tags reside
$ifd0 = $tiff->getIfd();

// If no Ifd info found, create it
if($ifd0 == null) {
    $ifd0 = new PelIfd(PelIfd::IFD0);
    $tiff->setIfd($ifd0);
}

// See if the MAKE-tag already exists in Ifd
$make = $ifd0->getEntry(PelTag::MAKE);

// Create MAKE-tag if not found, otherwise just change the value
if($make == null) {
    $make = new PelEntryAscii(PelTag::MAKE, 'RICOH');
    $ifd0->addEntry($make);
}
else {
    $make->setValue('RICOH');
}

// See if the MODEL-tag already exists in Ifd
$model = $ifd0->getEntry(PelTag::MODEL);

// Create MODEL-tag if not found, otherwise just change the value
if($model == null) {
    $model = new PelEntryAscii(PelTag::MODEL, 'RICOH THETA S');
    $ifd0->addEntry($model);
}
else {
    $model->setValue('RICOH THETA S');
}

// Save to disk
$file->saveFile('IMAGE.jpg');

Imagick does let you set EXIF-data but only to objects in memory, when writing the file to disk these data is simply ignored. The most popular solution is to either shell out to exiftools or use the PHP-library PEL. The documentation of PEL is sparse, and the API is not really self-explanatory either.

I came across this problem when trying to add the correct EXIF-data to images that would be uploaded as 360 images to Facebook, which requires specific camera make and model to be specified as EXIF. The code below will open an image file, set its make and model, and save back to disk. If you are looking to set other EXIF-data there is a complete list of all supported PelTag-constants here in the PEL docs.

$data = new PelDataWindow(file_get_contents('IMAGE PATH'));
$tiff = null;
$file = null;

// If it is a JPEG-image, check if EXIF-headers exists
if (PelJpeg::isValid($data)) {
    $jpeg = $file = new PelJpeg();
    $jpeg->load($data);
    $exif = $jpeg->getExif();

    // If no EXIF in image, create it
    if($exif == null) {
        $exif = new PelExif();
        $jpeg->setExif($exif);

        $tiff = new PelTiff();
        $exif->setTiff($tiff);
    }
    else {
        $tiff = $exif->getTiff();
    }
}
// If it is a TIFF EXIF-headers will always be set
elseif (PelTiff::isValid($data)) {
    $tiff = $file = new PelTiff();
    $tiff->load($data);
}
else {
    throw new \Exception('Invalid image format');
}

// Get the first Ifd, where most common EXIF-tags reside
$ifd0 = $tiff->getIfd();

// If no Ifd info found, create it
if($ifd0 == null) {
    $ifd0 = new PelIfd(PelIfd::IFD0);
    $tiff->setIfd($ifd0);
}

// See if the MAKE-tag already exists in Ifd
$make = $ifd0->getEntry(PelTag::MAKE);

// Create MAKE-tag if not found, otherwise just change the value
if($make == null) {
    $make = new PelEntryAscii(PelTag::MAKE, 'RICOH');
    $ifd0->addEntry($make);
}
else {
    $make->setValue('RICOH');
}

// See if the MODEL-tag already exists in Ifd
$model = $ifd0->getEntry(PelTag::MODEL);

// Create MODEL-tag if not found, otherwise just change the value
if($model == null) {
    $model = new PelEntryAscii(PelTag::MODEL, 'RICOH THETA S');
    $ifd0->addEntry($model);
}
else {
    $model->setValue('RICOH THETA S');
}

// Save to disk
$file->saveFile('IMAGE.jpg');
墨小沫ゞ 2024-11-01 05:02:33

我自己没有这方面的经验,但是 php 的网站有一些看起来像你正在寻找的东西:

http://php.net/manual/en/function.iptcembed.php

如果这就是你所说的意思
“我见过一两个例子,但它们太复杂了,在我给出的时间范围内无法掌握。”

那么你可能会不知所措。

但该页面上的示例看起来并不难掌握。

I have no experience with this myself, but php's website has something that looks like what you're looking for:

http://php.net/manual/en/function.iptcembed.php

If thats what you meant when you said
"I have seen one or two examples, but they are they too complex to grasp in the timeframe I have been given."

Then you may be in over your head.

But the examples on that page do not look hard to grasp at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文