downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

iptcparse> <imagexbm
Last updated: Fri, 30 Oct 2009

view this page in

iptcembed

(PHP 4, PHP 5)

iptcembedEmbeds binary IPTC data into a JPEG image

Beschreibung

mixed iptcembed ( string $iptcdata , string $jpeg_file_name [, int $spool ] )

Embeds binary IPTC data into a JPEG image.

Parameter-Liste

iptcdata

The data to be written.

jpeg_file_name

Path to the JPEG image.

spool

Spool flag. If the spool flag is over 2 then the JPEG will be returned as a string.

Rückgabewerte

If success and spool flag is lower than 2 then the JPEG will not be returned as a string, FALSE on errors.

Beispiele

Beispiel #1 Embedding IPTC data into a JPEG

<?php

// iptc_make_tag() function by Thies C. Arntzen
function iptc_make_tag($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;
}

// Path to jpeg file
$path './phplogo.jpg';

// We need to check if theres any IPTC data in the jpeg image. If there is then 
// bail out because we cannot embed any image that already has some IPTC data!
$image getimagesize($path$info);

if(isset(
$info['APP13']))
{
    die(
'Error: IPTC data found in source image, cannot continue');
}

// Set the IPTC tags
$iptc = array(
    
'2#120' => 'Test image',
    
'2#116' => 'Copyright 2008-2009, The PHP Group'
);

// Convert the IPTC tags into binary code
$data '';

foreach(
$iptc as $tag => $string)
{
    
$tag substr($tag2);
    
$data .= iptc_make_tag(2$tag$string);
}

// Embed the IPTC data
$content iptcembed($data$path);

// Write the new image data out to the file.
$fp fopen($path"wb");
fwrite($fp$content);
fclose($fp);
?>

Anmerkungen

Hinweis: This function does not require the GD image library.



iptcparse> <imagexbm
Last updated: Fri, 30 Oct 2009
 
add a note add a note User Contributed Notes
iptcembed
support at image-host-script dot com
23-Sep-2008 06:39
A class I recently wrote for manipulating IPTC data in an jpeg images. It does the job for editing exisiting data too, in easy manner. It is just a compilation of examples into single class.

<?

    /************************************************************\
   
        IPTC EASY 1.0 - IPTC data manipulator for JPEG images
           
        All reserved www.image-host-script.com
       
        Sep 15, 2008
   
    \************************************************************/

    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=Array();
        var $hasmeta=false;
        var $file=false;
       
       
        function iptc($filename) {
            $size = getimagesize($filename,$info);
            $this->hasmeta = isset($info["APP13"]);
            if($this->hasmeta)
                $this->meta = iptcparse ($info["APP13"]);
            $this->file = $filename;
        }
        function set($tag, $data) {
            $this->meta ["2#$tag"]= Array( $data );
            $this->hasmeta=true;
        }
        function get($tag) {
            return isset($this->meta["2#$tag"]) ? $this->meta["2#$tag"][0] : false;
        }
       
        function dump() {
            print_r($this->meta);
        }
        function binary() {
            $iptc_new = '';
            foreach (array_keys($this->meta) as $s) {
                $tag = str_replace("2#", "", $s);
                $iptc_new .= $this->iptc_maketag(2, $tag, $this->meta[$s][0]);
            }       
            return $iptc_new;   
        }
        function iptc_maketag($rec,$dat,$val) {
            $len = strlen($val);
            if ($len < 0x8000) {
                   return chr(0x1c).chr($rec).chr($dat).
                   chr($len >> 8).
                   chr($len & 0xff).
                   $val;
            } else {
                   return chr(0x1c).chr($rec).chr($dat).
                   chr(0x80).chr(0x04).
                   chr(($len >> 24) & 0xff).
                   chr(($len >> 16) & 0xff).
                   chr(($len >> 8 ) & 0xff).
                   chr(($len ) & 0xff).
                   $val;
                  
            }
        }   
        function write() {
            if(!function_exists('iptcembed')) return false;
            $mode = 0;
            $content = iptcembed($this->binary(), $this->file, $mode);   
            $filename = $this->file;
               
            @unlink($filename); #delete if exists
           
            $fp = fopen($filename, "w");
            fwrite($fp, $content);
            fclose($fp);
        }   
       
        #requires GD library installed
        function removeAllTags() {
            $this->hasmeta=false;
            $this->meta=Array();
            $img = imagecreatefromstring(implode(file($this->file)));
            @unlink($this->file); #delete if exists
            imagejpeg($img,$this->file,100);
        }
    };
   
   
?>

Example read copyright string:

$i = new iptc("test.jpg");
echo $i->get(IPTC_COPYRIGHT_STRING);

Update copyright statement:
$i = new iptc("test.jpg");
echo $i->set(IPTC_COPYRIGHT_STRING,"Here goes the new data");
$i->write();

NOTE1: Data may be anything, even a binary file. I have so far tested and embedded an MS-Excel file directly to jpeg and it worked just perfect.

NOTE2: The writing purpose, it uses GD Library.

Further imporvements / changes may be followed at www.image-host-script.com

I hope it helps.
Ali..
jb at ibbeck dot de
04-Oct-2007 02:40
If you have a file without any IPTC record, you can add a new, empty one by calling iptcembed with an empty string as first argument, like this:

$buffer = iptcembed("",$imagename,0);
$fp = fopen($imagename,"w");
fwrite($fp,$buffer);
fclose($fp);
Bryce Fisher
04-Jul-2007 04:55
In Thomas's wonderful code snippet below, the second parameter needs to be changed to "$filename", otherwise the script has no write the file. So the code should read:

<?php
//This function removes all header data from a JPG
function remove_XMP($image_in, $filename) {
 
$filename_in = addslashes($image_in);
  list(
$width, $height) = getimagesize($filename_in);
 
$image_dest = imagecreatetruecolor($width, $height);
 
$image = imagecreatefromjpeg($filename_in);
 
imagecopyresampled($image_dest, $image, 0, 0, 0, 0$width, $height,$width, $height);
 
imagejpeg($image_dest, $filename);
}
?>
thomas at anakrome dot net
04-Jul-2005 04:02
here is a small code to remove all header from a jpg file, including IPTC, Exif, XMP...

function remove_XMP($image_in, $image_dest) {
  $filename_in = addslashes($image_in);
  list($width, $height) = getimagesize($filename_in);
  $image_dest = imagecreatetruecolor($width, $height);
  $image = imagecreatefromjpeg($filename_in);
  imagecopyresampled($image_dest, $image, 0, 0, 0, 0,  $width, $height,
  $width, $height);
  imagejpeg($image_dest, $filename);
}

the problem comes from Photoshop CS cannot read IPTC if XMP is present.
removing XMP and other header _before_ adding IPTC with iptcembed is a good way.
muguran
13-May-2005 08:41
Pay attention not add codes with length of value equal to 0; the behavior could be strange...
(e.g. $iptc_old["2#015"][0] = "")
evan at nospam dot ozhiker dot com
09-Aug-2004 04:53
You might have noticed that several metadata fields in Photoshop are not available via IPTC.
Also, Photoshop now uses XMP for it's primary metadata, meaning IPTC is only read by Photoshop if XMP is not present.

I have written a library "PHP JPEG Metadata Toolkit" which bypasses this problem as it allows reading, writing and interpreting of virtually any type of metadata, including XMP, IPTC and EXIF.

Try it out, and download it at:
http://www.ozhiker.com/electronics/pjmt/index.html
dj dot cyberdance at gmx dot at
30-May-2004 01:47
Yep it's me again :-) After some time I spent searching around for other possibilities to write IPTC fields to JPEG files I found this one:

http://www.zonageek.com/software/php/jpeg/index.php

This one seems to work pretty fine, remember that you have to install PEAR to get this running (Debian package php4-pear).
dj dot cyberdance at gmx dot at
06-May-2004 11:29
I've spent a whole day debugging my code (that was based on the example below, posted by knut) until I found out, that iptcembed() only works if the image specified in jpeg_file_name already has IPTC fields included.

That means that you cannot write IPTC fields in a jpeg file without preexisting IPTC information in it.

Updating of IPTC fields also worked only with a few files, I don't really know what it depends on whether it works or not. (Well, it depends on the IPTC header, that's for sure :-)

I'm using PHP 4.2.1, maybe this is fixed in more recent versions, but I don't believe...

Nevertheless, here's some piece of code I tried:

I replaced the line

<?
$iptc_old = iptcparse ($info["APP13"]);
?>

from knut's example below with

<?
$iptc_old["2#000"][0] = chr(0) . chr(2);
?>

This creates just an empty "Header" according to the IPTC spec. This one also is included when getting IPTC info using iptcparse(). So my intention was to create a fully new header, but when using iptcembed() afterwards, the file size of the new file was a little smaller than the original but without any IPTC info stored in it.
pprem at pprem dot net
20-Feb-2004 06:04
I've a problem with the ltrim fucntion: sometimes it remove more characters than it must, so it's better to delete the line

<?
//   $image = rtrim ($image, $endchar);
?>

in the XMP_remove_from_jpeg function
pprem at pprem dot net
20-Feb-2004 12:10
Reading and changing IPTC make no problem with the PEAR function, but recent Adobe software add XMP datas on JPEG files and read them instead of IPTC datas. If you need to change IPTC on a JPEG file and want Adobe PS7 read them, you have two solutions:
- writing XMP and IPTC datas
- writing IPTC datas and removing XMP datas

Because I've not enough time to work on XMP datas, I've choosen the second solution. Here is the result of this work:

<?php
// removing XMP datas from a JPEG file
// (c) Patrick Premartin 19/02/2004

function XMP_remove_from_jpeg (&$image) {
 
$xmp_str = "http://ns.adobe.com/xap/1.0/";
 
$xmp_end = "<?xpacket end='w'?>";
 
$n_str = strpos ($image, $xmp_str);
 
$n_end = strpos ($image, $xmp_end);
  if ((
$n_str !== false) && ($n_end !== false) && ($n_str < $n_end)) {
   
$n_str -= 4; // FF E1 .x. .y. (xy is the length of the XMP block -> first char of this block
   
$n_end += strlen ($xmp_end)-1; // last char of this block
   
$endchar = $image [$n_str-1];
    if (
$endchar == " ") {
     
$endchar = "A";
    } else {
     
$endchar = " ";
    }
   
$xmp_len = $n_end-$n_str+1;
   
$img_len = strlen ($image);
   
$len = $img_len - $xmp_len;
    for (
$i = $n_str; $i < $img_len; $i ++) {
      if (
$i < $len) {
       
$image [$i] = $image [$i+$xmp_len];
      } else {
       
$image [$i] = $endchar;
      }
    }
   
$image = rtrim ($image, $endchar);
    return
true;
  } else {
    return
false;
  }
}

function
XMP_remove_from_jpegfile ($filename_in, $filename_out="") {
  if (
""==$filename_out) {
   
$filename_out = $filename_in;
  }
  if ((
""!=$filename_in) && (file_exists ($filename_in)) && (($len_in = filesize ($filename_in)) > 0)) {
   
// chargement du fichier en mémoire
   
$f_in = fopen ($filename_in, "rb");
   
$img = fread ($f_in, $len_in);
   
fclose ($f_in);
   
// suppression du XMP de l'image
   
if (XMP_remove_from_jpeg ($img)) {
     
// enregistrement du fichier sur disque
     
$f_out = fopen ($filename_out, "wb");
     
fwrite ($f_out, $img, strlen ($img));
     
fclose ($f_out);
    }
  }
}

XMP_remove_from_jpegfile ("ps7_hr.jpg", "ps7_hr_.jpg"); // create a new picture without XMP datas

XMP_remove_from_jpegfile ("ps8_hr.jpg"); // replace the existing file
?>

In the future, I'll work on changing XMP datas and IPTC in the same way and will publish it ther or as a in PEAR.

May the force be with us :-)
pprem
15-Feb-2004 03:00
I confirm: Photoshop 7 and other recent Adobe programs use XMP instead of IPTC. They write datas in IPTC format only for compatibility with older programs, but use only XMP.

I'm working on a program that write XMP and IPTC together and probably post it here as soon as possible.
collord
27-Jan-2004 09:20
Regarding issues with photoshop IPTC... Photoshop actually prefers a different embedded metadata format, XMP, which is RDF-based. When Photoshop manages metadata via File Info, what you're actually doing is manipulating RDF in a "photoshop" namespace as well as the standard Dublin Core (dc) namespace, and a couple others. When a file is written that supports IPTC, the equivalent fields e.g. copyright, keywords, etc. are serialized into the IPTC block.

So, if one manipulates the IPTC block of a Photoshop-generated image and leaves the XMP block alone, it's my guess that Photoshop will treat data from the XMP as authoritative.

HTH, jerritt
jofr at gmx dot com
29-Dec-2003 06:42
I found out, that iptcembed does not overwrite the full IPTC-Tags from Photoshop.
If you modify the IPTC-Tag with iptcembed, Photoshop will still show you the old IPTC-Tag.
Programs like Fotostation works fine.

JO
bob at lucid-systems dot com
22-Aug-2002 10:37
The above example doesn't handle keywords properly. The 'create string' code needs to be modified to cater for the array:

$c = count ($iptc_old[$s]);
for ($i=0; $i <$c; $i++)
    {
    $iptc_new .= iptc_maketag(2, $tag, $iptc_old[$s][$i]);
    }
rupix at rediffmail dot com
28-Jan-2002 12:24
Windows makes a distinction between 'text' and 'binary' files. So if you run the above code on a windows platform, it will produce a garbled image. To overcome this problem put the file mode in fopen() as 'wb' instead of 'w'.

Cheerio !!

Rupinder
knut dot satre dot NoSpam at No_Spam dot nord dot no
27-Jan-2002 11:45
Example to read IPTC text from an image, changing the text an write to a new file using the functions iptcparse and iptcembed.
 
Also a list of the most common IPTC fields.

<?
// original file name
$image_name_old = "test.jpg";

// New file name
$image_name_new = "test2.jpg";

// Reads the IPTC text in to the array '$iptc'
// The number after the '#' is the IPTC field
// Ex: $iptc["2#120"][0] is Caption
// $iptc["2#055"][0]; is Creation date
$size = GetImageSize ("$image_name_old",&$info);
$iptc_old = iptcparse ($info["APP13"]);

// Adding or replacing IPTC text
   // This ex. replace the original category or create it if it dos not exist
   $iptc_old["2#015"][0] = "Sport";
   // .. and adding more text to the original caption
   $iptc_old["2#120"][0] .= " More caption text";

   // Making the new IPTC string
   foreach (array_keys($iptc_old) as $s){
      // Finds the IPTC numbers
      $tag = str_replace("2#", "", $s);
      // Creating the string
      $iptc_new .= iptc_maketag(2, $tag, $iptc_old[$s][0]);
   }

// The original file and the new IPTC Text into $content
// Mode 0 - puts the image file into $content
// Mode 1 - puts the image file into $content and directly to the web client
// Mode 2 - puts the image file to web client
$mode = 0;
$content = iptcembed($iptc_new, $image_name_old, $mode);

// writes the new file
$fp = fopen($image_name_new, "w");
fwrite($fp, $content);
fclose($fp);

// Function to format the new IPTC text, (thanks to Thies C. Arntzen)
function iptc_maketag($rec,$dat,$val){
         $len = strlen($val);
         if ($len < 0x8000)
                  return chr(0x1c).chr($rec).chr($dat).
                  chr($len >> 8).
                  chr($len & 0xff).
                  $val;
         else
                  return chr(0x1c).chr($rec).chr($dat).
                  chr(0x80).chr(0x04).
                  chr(($len >> 24) & 0xff).
                  chr(($len >> 16) & 0xff).
                  chr(($len >> 8 ) & 0xff).
                  chr(($len ) & 0xff).
                  $val;
}

?>

--- The most common IPTC Fileds
005 - Object Name
007 - Edit Status
010 - Priority
015 - Category
020 - Supplemental Category
022 - Fixture Identifier
025 - Keywords
030 - Release Date
035 - Release Time
040 - Special Instructions
045 - Reference Service
047 - Reference Date
050 - Reference Number
055 - Created Date
060 - Created Time
065 - Originating Program
070 - Program Version
075 - Object Cycle
080 - Byline
085 - Byline Title
090 - City
095 - Province State
100 - Country Code
101 - Country
103 - Original Transmission Reference
105 - Headline
110 - Credit
115 - Source
116 - Copyright String
120 - Caption
121 - Local Caption

iptcparse> <imagexbm
Last updated: Fri, 30 Oct 2009
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites