php 在php中写入exif数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5384962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:13:58  来源:igfitidea点击:

writing exif data in php

phpmetadatajpegexif

提问by lovinxlost

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

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

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

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

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?

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

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.

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

Update:

更新:

First of all thanks for the reply by dbers.

首先感谢dbers的回复。

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

我已经查看了代码。我设法让它将默认标签添加到 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:

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

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, $dataand $valuebeing referenced if they havent been defined. Or are they taken from iptc_make_tag?

我还没有碰到过的函数变量,如何$rec$data以及$value如果它们还没有被定义被引用。或者他们是从iptc_make_tag什么地方拿来的?

I echoed out $recand $valuebut I dont get a value back on screen.

我回应了$rec$value但我没有在屏幕上获得价值。

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 $infoin a table.

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

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

回答by Matías Cánepa

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).

我修改了我在这里找到的一个类(感谢debers)。

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

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

And now the code (PHP >= 5.4):

现在代码(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);
?>

回答by Riceball LEE

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.
  • PEL(PHP Exif 库)。使用 PHP 在 JPEG 和 TIFF 图像中读取和写入 Exif 标头的库。
  • PHP JPEG 元数据工具包。允许读取、写入和显示以下 JPEG 元数据格式:EXIF 2.2、XMP / RDF、IPTC-NAA IIM 4.1 等
  • Perl 的 ExifTool。ExifTool 非常棒。它基本上已经具备了 - EXIF、IPTC 和 XMP 支持(读/写)以及对制造商扩展的支持。

回答by Andreas Bergstr?m

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.

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

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.

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

$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');

回答by dbers

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

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

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

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.

但是该页面上的示例看起来一点也不难理解。