Setting Exif data on PreviewImage?
Added by Ray NA almost 11 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 almost 11 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 almost 11 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 almost 11 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.