static void set_xmp_prop(const char * filename, const std::string & value_name, const std::string & prop_value, bool no_reconcile, bool is_an_xmp, bool write_in_place, FILE *outio) { xmp::ScopedPtr<XmpPtr> xmp(get_xmp_from_file(filename, no_reconcile, is_an_xmp)); std::string prefix; size_t idx = value_name.find(':'); if(idx != std::string::npos) { prefix = std::string(value_name, 0, idx); } xmp::ScopedPtr<XmpStringPtr> ns(xmp_string_new()); xmp_prefix_namespace_uri(prefix.c_str(), ns); if(!xmp_set_property(xmp, xmp_string_cstr(ns), value_name.c_str() + idx + 1, prop_value.c_str(), 0)) { fprintf(stderr, "set error = %d\n", xmp_get_error()); } if(write_in_place) { xmp::ScopedPtr<XmpFilePtr> f(xmp_files_open_new(filename, (XmpOpenFileOptions)(XMP_OPEN_FORUPDATE | (no_reconcile ? XMP_OPEN_ONLYXMP : 0)))); if(!xmp_files_can_put_xmp(f, xmp)) { fprintf(stderr, "can put xmp error = %d\n", xmp_get_error()); } if(!xmp_files_put_xmp(f, xmp)) { fprintf(stderr, "put xmp error = %d\n", xmp_get_error()); } if(!xmp_files_close(f, XMP_CLOSE_SAFEUPDATE)) { fprintf(stderr, "close error = %d\n", xmp_get_error()); } } }
/** dump the XMP xml to the output IO */ static void dump_xmp(const char *filename, bool no_reconcile, bool is_an_xmp, FILE *outio) { printf("dump_xmp for file %s\n", filename); xmp::ScopedPtr<XmpPtr> xmp(get_xmp_from_file(filename, no_reconcile, is_an_xmp)); xmp::ScopedPtr<XmpStringPtr> output(xmp_string_new()); xmp_serialize_and_format(xmp, output, XMP_SERIAL_OMITPACKETWRAPPER, 0, "\n", " ", 0); fprintf(outio, "%s", xmp_string_cstr(output)); }
/** get an xmp prop and dump it to the output IO */ static void get_xmp_prop(const char * filename, const std::string & value_name, bool no_reconcile, bool is_an_xmp, FILE *outio) { xmp::ScopedPtr<XmpPtr> xmp(get_xmp_from_file(filename, no_reconcile, is_an_xmp)); std::string prefix; size_t idx = value_name.find(':'); if(idx != std::string::npos) { prefix = std::string(value_name, 0, idx); } xmp::ScopedPtr<XmpStringPtr> property(xmp_string_new()); xmp::ScopedPtr<XmpStringPtr> ns(xmp_string_new()); xmp_prefix_namespace_uri(prefix.c_str(), ns); xmp_get_property(xmp, xmp_string_cstr(ns), value_name.c_str(), property, NULL); fprintf(outio, "%s\n", xmp_string_cstr(property)); }
void Jp2Image::doWriteMetadata(BasicIo& outIo) { if (!io_->isopen()) throw Error(20); if (!outIo.isopen()) throw Error(21); #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Writing JPEG-2000 file " << io_->path() << "\n"; std::cout << "Exiv2::Jp2Image::doWriteMetadata: tmp file created " << outIo.path() << "\n"; #endif // Ensure that this is the correct image type if (!isJp2Type(*io_, true)) { if (io_->error() || io_->eof()) throw Error(20); throw Error(22); } // Write JPEG2000 Signature. if (outIo.write(Jp2Signature, 12) != 12) throw Error(21); Jp2BoxHeader box = {0,0}; byte boxDataSize[4]; byte boxUUIDtype[4]; DataBuf bheaderBuf(8); // Box header : 4 bytes (data size) + 4 bytes (box type). // FIXME: Andreas, why the loop do not stop when EOF is taken from _io. The loop go out by an exception // generated by a zero size data read. while(io_->tell() < io_->size()) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Position: " << io_->tell() << " / " << io_->size() << "\n"; #endif // Read chunk header. std::memset(bheaderBuf.pData_, 0x00, bheaderBuf.size_); long bufRead = io_->read(bheaderBuf.pData_, bheaderBuf.size_); if (io_->error()) throw Error(14); if (bufRead != bheaderBuf.size_) throw Error(20); // Decode box header. box.boxLength = getLong(bheaderBuf.pData_, bigEndian); box.boxType = getLong(bheaderBuf.pData_ + 4, bigEndian); #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Find box type: " << bheaderBuf.pData_ + 4 << " lenght: " << box.boxLength << "\n"; #endif if (box.boxLength == 0) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Null Box size has been found. " "This is the last box of file.\n"; #endif box.boxLength = io_->size() - io_->tell() + 8; } if (box.boxLength == 1) { // FIXME. Special case. the real box size is given in another place. } // Read whole box : Box header + Box data (not fixed size - can be null). DataBuf boxBuf(box.boxLength); // Box header (8 bytes) + box data. memcpy(boxBuf.pData_, bheaderBuf.pData_, 8); // Copy header. bufRead = io_->read(boxBuf.pData_ + 8, box.boxLength - 8); // Extract box data. if (io_->error()) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Error reading source file\n"; #endif throw Error(14); } if (bufRead != (long)(box.boxLength - 8)) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Cannot read source file data\n"; #endif throw Error(20); } switch(box.boxType) { case kJp2BoxTypeJp2Header: { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write JP2Header box (lenght: " << box.boxLength << ")\n"; #endif if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21); // Write all updated metadata here, just after JP2Header. if (exifData_.count() > 0) { // Update Exif data to a new UUID box Blob blob; ExifParser::encode(blob, littleEndian, exifData_); if (blob.size()) { const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; DataBuf rawExif(static_cast<long>(sizeof(ExifHeader) + blob.size())); memcpy(rawExif.pData_, ExifHeader, sizeof(ExifHeader)); memcpy(rawExif.pData_ + sizeof(ExifHeader), &blob[0], blob.size()); DataBuf boxData(8 + 16 + rawExif.size_); ul2Data(boxDataSize, boxData.size_, Exiv2::bigEndian); ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian); memcpy(boxData.pData_, boxDataSize, 4); memcpy(boxData.pData_ + 4, boxUUIDtype, 4); memcpy(boxData.pData_ + 8, kJp2UuidExif, 16); memcpy(boxData.pData_ + 8 + 16, rawExif.pData_, rawExif.size_); #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with Exif metadata (lenght: " << boxData.size_ << ")\n"; #endif if (outIo.write(boxData.pData_, boxData.size_) != boxData.size_) throw Error(21); } } if (iptcData_.count() > 0) { // Update Iptc data to a new UUID box DataBuf rawIptc = IptcParser::encode(iptcData_); if (rawIptc.size_ > 0) { DataBuf boxData(8 + 16 + rawIptc.size_); ul2Data(boxDataSize, boxData.size_, Exiv2::bigEndian); ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian); memcpy(boxData.pData_, boxDataSize, 4); memcpy(boxData.pData_ + 4, boxUUIDtype, 4); memcpy(boxData.pData_ + 8, kJp2UuidIptc, 16); memcpy(boxData.pData_ + 8 + 16, rawIptc.pData_, rawIptc.size_); #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with Iptc metadata (lenght: " << boxData.size_ << ")\n"; #endif if (outIo.write(boxData.pData_, boxData.size_) != boxData.size_) throw Error(21); } } if (writeXmpFromPacket() == false) { if (XmpParser::encode(xmpPacket_, xmpData_) > 1) { #ifndef SUPPRESS_WARNINGS EXV_ERROR << "Failed to encode XMP metadata.\n"; #endif } } if (xmpPacket_.size() > 0) { // Update Xmp data to a new UUID box DataBuf xmp(reinterpret_cast<const byte*>(xmpPacket_.data()), static_cast<long>(xmpPacket_.size())); DataBuf boxData(8 + 16 + xmp.size_); ul2Data(boxDataSize, boxData.size_, Exiv2::bigEndian); ul2Data(boxUUIDtype, kJp2BoxTypeUuid, Exiv2::bigEndian); memcpy(boxData.pData_, boxDataSize, 4); memcpy(boxData.pData_ + 4, boxUUIDtype, 4); memcpy(boxData.pData_ + 8, kJp2UuidXmp, 16); memcpy(boxData.pData_ + 8 + 16, xmp.pData_, xmp.size_); #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: Write box with XMP metadata (lenght: " << boxData.size_ << ")\n"; #endif if (outIo.write(boxData.pData_, boxData.size_) != boxData.size_) throw Error(21); } break; } case kJp2BoxTypeUuid: { if(memcmp(boxBuf.pData_ + 8, kJp2UuidExif, sizeof(16)) == 0) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: strip Exif Uuid box\n"; #endif } else if(memcmp(boxBuf.pData_ + 8, kJp2UuidIptc, sizeof(16)) == 0) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: strip Iptc Uuid box\n"; #endif } else if(memcmp(boxBuf.pData_ + 8, kJp2UuidXmp, sizeof(16)) == 0) { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: strip Xmp Uuid box\n"; #endif } else { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: write Uuid box (lenght: " << box.boxLength << ")\n"; #endif if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21); } break; } default: { #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: write box (lenght: " << box.boxLength << ")\n"; #endif if (outIo.write(boxBuf.pData_, boxBuf.size_) != boxBuf.size_) throw Error(21); break; } } } #ifdef DEBUG std::cout << "Exiv2::Jp2Image::doWriteMetadata: EOF\n"; #endif } // Jp2Image::doWriteMetadata