Hi, I am the original author of Image::MetaData::JPEG. Unfortunately APP2 segments are not really supported by this package (you can only parse two formats, and cannot modify them at high level).

In general, once you have modified a segment, added or deleted records, etc., at low level, you have to call the segment update() method, in order to dump the logical representation of the segment into a binary block that will subsequently be written to file. This is not necessary if you use high-level functions to modify well-known blocks, because it is being taken care of by high-level code.

You can still add APP2 segments if you can provide the binary block yourself though. Have a look at the following commented piece of code:

use strict; use warnings; use Image::MetaData::JPEG; use Image::MetaData::JPEG::Record; use Image::MetaData::JPEG::data::Tables qw(:JPEGgrammar :Endianness :RecordTypes); #read the image filname from the command line arguments my $image = new Image::MetaData::JPEG($ARGV[0]); # This would be the correct procedure for adding records at low level # if the APP2 update routine existed at all (but it isn't implemented) # 1) create an empty APP2 segment # my $segref = # new Image::MetaData::JPEG::Segment('APP2', undef, 'NOPARSE'); # 2) store a record with a given key and value # my $head = "MPF0"; # $segref->store_record('MP_HEADER', $ASCII, \$head); # 3) IMPORTANT: update the binary block from the in memory # representation (this was the step you were missing) # $segref->update(); # But APP2 can "currently" only be parsed if it contains Flashpix # conversion information ("FPXR") or ICC profiles data. And there is # no update routine at all. So, either you extend the package or # create the entire binary block by hand in a local variable: # you skip parsing and just create the segment. my $buffer = "MPF0\0"; my $segref = new Image::MetaData::JPEG::Segment('APP2', \$buffer, 'NOPARSE'); # then insert it into the image $image->insert_segments($segref); # the segment is there, albeit without description, since unparsed foreach my $s ($image->get_segments('APP')) { print $s->get_description(); } # you can save to file nonetheless, unparsable segments aren't dropped my $new_file_name = 'tmp1.jpg'; $image->save($new_file_name); print "---------------------------------\n"; # now open the new file and check that APP2 is there (I avoid trying # to parse it, since parsing would fail with "Invalid APP2 segment" # in this case) my $new_image = new Image::MetaData::JPEG($new_file_name, 'APP[^2]'); foreach my $s ($new_image->get_segments('APP')) { print $s->get_description(); } print "---------------------------------\n"; # have a look at what's really inside your file: the APP2 segment # should be in the very first lines, unless your APP1 is huge. use Data::HexDump; my $hexdumper = new Data::HexDump; $hexdumper->file($new_file_name); $hexdumper->block_size(1024); print while $_ = $hexdumper->dump;

For instance, if you generate a test .jpg file with Gimp and subject it to the previous Perl processing, you will obtain something that starts like this: (commented hexadecimal dump)

FF E1 SOI ("Start of image") FF E0 APP0 segment starts here 00 10 length of APP0 (16, i.e., 14 to follow) ......... 14 data bytes in the APP0 segment FF E2 APP2 segment starts here 00 07 length of APP2 (7, i.e., 5 to follow) 4D 50 46 30 00 "MPF0\000" FF FE COM segment starts here 00 13 length of COM (19, i.e. 17 to follow) ......... "Created with GIMP", and so on

Unfortunately, this is all I can offer now. It is clear that Image::MetaData::JPEG has fallen behind JPEG development, and a lot of parsing / dumping / modifying routines should be added and maintained, for which I have no time at all. The reason why the package is so conservative and restrictive is that it aims at correctness and information preservation (it never adds invalid bytes, but will also never drop unparsable segments). I would be glad to transfer to a new maintainer if anyone is available.

Best regards, Stefano Bettelli


In reply to Re: Add a segment in a JPG image with Image::MetaData::JPEG by Anonymous Monk
in thread Add a segment in a JPG image with Image::MetaData::JPEG by neoldschool

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.