8

I would like to write a script that can tag images and save the tag on the FILE, not in an external database. I would also need to read the tags from the file via php as well.

Why do I want to do this?

Right clicking on an image and selecting properties and then clicking on details, THEN clicking on tags and THEN adding your tags is tedious to say the least. I can't find any shortcut for adding tags quickly in windows so I want to write my own script that can do that.

Is this possible?

I don't know if it is, whenever I search for images and tags in the same line I get image tags for html tutorials or people saving tags in an external database. I can't really find any good resources, if anyone can suggest some I can look at I would be grateful.

What do I have so far?

I can list all the images on my hdd and click on an image and a popup will appear for me to enter a tag. I then send this tag to a php file waiting for me to do something with it...

Why don't I want to save the tags in an external database?

I won't be running my localhost all the time. If I copy the images the tags should go with.

Any information about this would be great.

Chris
  • 987
  • 6
  • 24
  • 3
    Are your image tags exif? http://php.net/manual/en/book.exif.php could be interesting – user3154108 Oct 28 '15 at 11:28
  • Thank you for the link, I think that might just work. However not all images come from the same source and some have different file types like png which I am not sure how to tag. I know the png specification can hold text but I am not sure how to add a tag yet. I am at work at the moment but will test that lib when I get home. – Chris Oct 28 '15 at 11:40
  • 1
    I don't see "tags" for PNG images on Windows 7. For jpg files they appear to be using Adobe XMP to store tags as well as storing it as an EXIF field (not sure which one yet, sorry). – drew010 Feb 27 '16 at 23:52
  • Adobe XMP looks interesting, however I see there is only a lib for java and actionscript available, but I am going to play around with it. Thanks – Chris Feb 28 '16 at 08:44
  • Check out [this article](https://sharpbang.wordpress.com/2013/08/18/adding-exif-data-using-php/). It has some code and references to the required libraries. – max Feb 28 '16 at 18:14
  • 3
    Does it have to be vanilla PHP or are you happy executing an external program to do the tagging? If so, [ExifTool](http://www.sno.phy.queensu.ca/~phil/exiftool/) is a feature rich Perl command line application and available for Windows as a standalone executable. – Matt Raines Feb 29 '16 at 08:59
  • Exif is your answer. Find a library that manages exif tags in PHP – Muhammed Feb 29 '16 at 14:29
  • Maybe this is a direction for you: http://stackoverflow.com/a/1216367/4210443 – eXe Mar 01 '16 at 19:42
  • Thank you for all the suggestions, I will check them all out when I get home. Yes Matt, I am willing to use a standalone executable. – Chris Mar 02 '16 at 08:10

2 Answers2

3

You can use

  • iptcembed to embed binary IPTC data into a JPEG image
  • exif-read-data to read the EXIF headers from JPEG or TIFF
  • How to read a Title tag from a JPEG file

    getimagesize('./phplogo.jpg', $info);
    $title = '';
    if (isset($info["APP13"])) {
       $iptc  = iptcparse ($info["APP13"]);
       $title = (isset($iptc["2#085"][0])) ? $iptc["2#085"][0] : NULL;
    }
    print $title;
    

    How to add Title tag to a JPEG
    Notes: You have only to manipulate $iptc array and to specify to file path
    this is a working example from iptcembed

    // 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';
    
    // Set the IPTC tags
    $iptc = array(
        '2#085' => 'Anis TITLE'
    );
    
    // Convert the IPTC tags into binary code
    $data = '';
    
    foreach($iptc as $tag => $string)
    {
        $tag = substr($tag, 2);
        $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);
    

    Here the complet list of IPTC indexes

    DEFINE('IPTC_OBJECT_NAME',                      '2#005');
    DEFINE('IPTC_EDIT_STATUS',                      '2#007');
    DEFINE('IPTC_PRIORITY',                         '2#010');
    DEFINE('IPTC_CATEGORY',                         '2#015');
    DEFINE('IPTC_SUPPLEMENTAL_CATEGORY',            '2#020');
    DEFINE('IPTC_FIXTURE_IDENTIFIER',               '2#022');
    DEFINE('IPTC_KEYWORDS',                         '2#025');
    DEFINE('IPTC_RELEASE_DATE',                     '2#030');
    DEFINE('IPTC_RELEASE_TIME',                     '2#035');
    DEFINE('IPTC_SPECIAL_INSTRUCTIONS',             '2#040');
    DEFINE('IPTC_REFERENCE_SERVICE',                '2#045');
    DEFINE('IPTC_REFERENCE_DATE',                   '2#047');
    DEFINE('IPTC_REFERENCE_NUMBER',                 '2#050');
    DEFINE('IPTC_CREATED_DATE',                     '2#055');
    DEFINE('IPTC_CREATED_TIME',                     '2#060');
    DEFINE('IPTC_ORIGINATING_PROGRAM',              '2#065');
    DEFINE('IPTC_PROGRAM_VERSION',                  '2#070');
    DEFINE('IPTC_OBJECT_CYCLE',                     '2#075');
    DEFINE('IPTC_BYLINE',                           '2#080');
    DEFINE('IPTC_BYLINE_TITLE',                     '2#085');
    DEFINE('IPTC_CITY',                             '2#090');
    DEFINE('IPTC_PROVINCE_STATE',                   '2#095');
    DEFINE('IPTC_COUNTRY_CODE',                     '2#100');
    DEFINE('IPTC_COUNTRY',                          '2#101');
    DEFINE('IPTC_ORIGINAL_TRANSMISSION_REFERENCE',  '2#103');
    DEFINE('IPTC_HEADLINE',                         '2#105');
    DEFINE('IPTC_CREDIT',                           '2#110');
    DEFINE('IPTC_SOURCE',                           '2#115');
    DEFINE('IPTC_COPYRIGHT_STRING',                 '2#116');
    DEFINE('IPTC_CAPTION',                          '2#120');
    DEFINE('IPTC_LOCAL_CAPTION',                    '2#121');
    
    Halayem Anis
    • 7,654
    • 2
    • 25
    • 45
    • When I try to read the tags with exif_read_data I get this: ["Keywords"]=> string(22) "??????????????????????" ["UndefinedTag:0xEA1C"] got any idea? – Chris Mar 02 '16 at 18:24
    • Thank you for adding example code to your answer. I have no problem with adding the tags using iptcembed, however I am having trouble getting the keywords. If I use exif_read_data I get garbage like I mentioned in the comment above. If I use the example code for 2#025 (keywords / tags) it does not work. If I var_dump $info["APP13"] I get a really long string, but iptcparse returns with FALSE. Windows does read the data correctly and I can see that the tags are being added. I just can't get to them again. Any tips? Thank you for all your effort. – Chris Mar 03 '16 at 12:23
    • I got it working, I used this: $test = exif_read_data('1.jpg', 0, true); $test = mb_convert_encoding($test['IFD0']['Keywords'], 'UTF-8', 'byte2le'); var_dump($test); – Chris Mar 03 '16 at 13:38
    2

    You could use PHPExiftool to write metadata in a file as follows (quote from the github page):

    <?php
    
    require __DIR__ . '/vendor/autoload.php';
    
    use Monolog\Logger;
    use PHPExiftool\Writer;
    use PHPExiftool\Driver\Metadata\Metadata;
    use PHPExiftool\Driver\Metadata\MetadataBag;
    use PHPExiftool\Driver\Tag\IPTC\ObjectName;
    use PHPExiftool\Driver\Value\Mono;
    
    $logger = new Logger('exiftool');
    $Writer = Writer::create($logger);
    
    $bag = new MetadataBag();
    $bag->add(new Metadata(new ObjectName(), new Mono('Pretty cool subject')));
    
    $Writer->write('image.jpg', $bag);
    

    And in case you would like to keep track of the metadatas you've written you could easily use php's md5_file() function to get an identifier of the file whose metadatas you've modified and then write a line in a text file with the resulted hash followed by the metadatas you've written separated by a delimitor such as "," (comma). Each line in that text file would represent a file modified by your script.

    Ruben Marrero
    • 1,392
    • 1
    • 10
    • 23
    • Thank you, this looks very promising. I am most definitely going to test this when I get home. If it works I will mark this response as the answer. That will be in about 8 hours roughly. – Chris Mar 02 '16 at 08:08
    • I have never been good at making github code work... everyone seems to be using composer which I have no idea how to operate. I have been getting success with the answer Halayem Anis posted, except that I can't read the data again though. I did find another wrapper for the Exiftool which is more up to date, so I will give that a shot. Thank you for the suggestion. – Chris Mar 02 '16 at 19:02
    • You should look for a "getting started" on composer, it's definitely worth it. – WhoIsJohnDoe Mar 03 '16 at 01:22