Project

General

Profile

Setting Exif data on PreviewImage?

Added by Ray NA over 10 years ago

Hi,

I have Nikon NEFs that I wish to extract the largest embedded preview jpg. I can do this, however, I want the preview image to contain the same EXIF info as the original NEF. I have not found a way in the API to do this with the preview image. Thereofre, I've had to write the file to disk, reopen and set the meta which is a ltitle inefficient.

Image::Auto_ptr  img = ImageFactory::open("/path/to/nikon.nef");
img->readMeta();
PreviewManager  prmgr(*img);
PreviewPropertyList prlist = prmg.getPreviewProperties();
if (prlist.empty()) {
return;
}
PreviewPropertyList::iterator preview = prlist.begin();
advance(preview, prlist.size()-1);
/* can't update/set the exif properties of the preview image
     *
     * INEFFICIENT?  write file, re-open file to set the exif data
*/
preview->writeFile("/path/to/preview-img");
Image::Auto_ptr img1 = ImageFactory::open("/path/to/preview-img");
img1->setExifData( img->exifData() );
img1->writeMeta();

I see PreviewImage::pData() and size(), so I can give these to the ImageFactory::open(const byte*, long) to give me an Image object. But how do I persist this Image boject to disk since Image has no method to set filename/write. Similarly for DataBuf.

/* the dbuf contents not updated since ImageFactory uses its own copy of
     * data provided
     * 
*/ so, how do we persist the img3 object to disk?
DataBuf  dbuf = preview->copy();
Image img3 = ImageFactory::open(dbuf.pData_, dbuf.size_);
img3->setExifData( img->exifData() );
img3->writeMeta();

Any suggestions for setting the Exif data of the preview image in memory?
Thanks


Replies (3)

RE: Setting Exif data on PreviewImage? - Added by Andreas Huggel over 10 years ago

Using the last method, try accessing the memory with Image::io(), reading it back into a DataBuf with BasicIo::read() and saving it with writeFile.
This is a nice use-case, thanks for posting. I wonder how many times the memory gets copied in the process.

Andreas

RE: Setting Exif data on PreviewImage? - Added by Ray NA over 10 years ago

Interesting, thanks for the pointer to Image::io() - I missed that. Would you see any issue with the following (i've got rid of most of the error checking so ignore that):

    Image::Auto_ptr  img = ImageFactory::open("/path/to/nikon.nef");
    img->readMeta();

    PreviewManager  prmgr(*img);
    PreviewPropertyList  prlist = prmg.getPreviewProperties();
    if (prlist.empty()) {
         return;
    }

    PreviewPropertyList::iterator  preview = prlist.begin();
    advance(preview, prlist.size()-1);

    /* let factory use (copy?) preview data create new image */
    Image::Auto_ptr  img1 = ImageFactory::open( preview->pData(), preview->size() );
    img1->setExifData( img->exifData() );
    img1->writeMeta();

    /* grab hold of underlying and updated data */
    BasicIo&  rawio = img1->io();
    rawio.seek(0);
    DataBuf  dbuf = rawio.read( rawio.size() );

    mode_t  msk = umask(0);
    umask(msk);
    int  fd = open("/path/to/preview-img", O_CREAT | O_TRUNC | O_WRONLY, 0666 & ~msk);
    write(fd, dbuf.pData_, dbuf.size_);
    close(fd);

Ideally I'd prefer to have direct access to the BasicIo's raw data (negating the copy for the DataBuf) but this is much preferable to the way I'm currently doing it by writing to disk/reading image/setting exif and persisting back to disk.

thanks very much

RE: Setting Exif data on PreviewImage? - Added by Andreas Huggel over 10 years ago

Ideally I'd prefer to have direct access to the BasicIo's raw data (negating the copy for the DataBuf)

Just realized that since this BasicIo is a MemIo, MemIo::mmap() does exactly what you're looking for! So there is not much overhead left after all.

-ahu.

    (1-3/3)