Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 61 additions & 32 deletions ext/exiv2/exiv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static VALUE xmp_data_class;
static VALUE xmp_data_each(VALUE self);
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value);
static VALUE xmp_data_delete(VALUE self, VALUE key);
static VALUE xmp_register_ns(VALUE self, VALUE uri, VALUE ns);

extern "C" void Init_exiv2() {
VALUE enumerable_module = rb_const_get(rb_cObject, rb_intern("Enumerable"));
Expand Down Expand Up @@ -101,6 +102,7 @@ extern "C" void Init_exiv2() {
rb_define_method(xmp_data_class, "each", (Method)xmp_data_each, 0);
rb_define_method(xmp_data_class, "add", (Method)xmp_data_add, 2);
rb_define_method(xmp_data_class, "delete", (Method)xmp_data_delete, 1);
rb_define_method(xmp_data_class, "register", (Method)xmp_register_ns, 2);
}


Expand All @@ -111,17 +113,22 @@ static void image_free(Exiv2::Image* image) {
}

static VALUE image_read_metadata(VALUE self) {
VALUE result = Qnil;
Exiv2::Image* image;
Data_Get_Struct(self, Exiv2::Image, image);

try {
char buf[BUFSIZ];
setbuf(stderr, buf);
image->readMetadata();
if (buf[1]) {
result = rb_sprintf("%s", buf); // If stderr outputs, we direct that into a string and return as result
}
}
catch (Exiv2::BasicError<char> error) {
rb_raise(basic_error_class, "%s", error.what());
}

return Qnil;
return result;
}

static VALUE image_write_metadata(VALUE self) {
Expand Down Expand Up @@ -195,18 +202,23 @@ static VALUE exif_data_add(VALUE self, VALUE key, VALUE value) {
Exiv2::ExifData* data;
Data_Get_Struct(self, Exiv2::ExifData, data);

Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));

#if EXIV2_MAJOR_VERSION <= 0 && EXIV2_MINOR_VERSION <= 20
Exiv2::TypeId typeId = Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId());
#else
Exiv2::TypeId typeId = exifKey.defaultTypeId();
#endif

Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
v->read(to_std_string(value));

data->add(exifKey, v.get());
try {
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));

#if EXIV2_MAJOR_VERSION <= 0 && EXIV2_MINOR_VERSION <= 20
Exiv2::TypeId typeId = Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId());
#else
Exiv2::TypeId typeId = exifKey.defaultTypeId();
#endif

Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
v->read(to_std_string(value));

data->add(exifKey, v.get());
}
catch (Exiv2::BasicError<char> error) {
rb_raise(basic_error_class, "%s", error.what());
}
return Qtrue;
}

Expand All @@ -232,15 +244,19 @@ static VALUE iptc_data_each(VALUE self) {
static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value) {
Exiv2::IptcData* data;
Data_Get_Struct(self, Exiv2::IptcData, data);

Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
Exiv2::TypeId typeId = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());

Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
v->read(to_std_string(value));

if(data->add(iptcKey, v.get())) {
return Qfalse;
try {
Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
Exiv2::TypeId typeId = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());

Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
v->read(to_std_string(value));

if(data->add(iptcKey, v.get())) {
return Qfalse;
}
}
catch (Exiv2::BasicError<char> error) {
rb_raise(basic_error_class, "%s", error.what());
}
return Qtrue;
}
Expand All @@ -266,15 +282,18 @@ static VALUE xmp_data_each(VALUE self) {
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value) {
Exiv2::XmpData* data;
Data_Get_Struct(self, Exiv2::XmpData, data);

Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
Exiv2::TypeId typeId = Exiv2::XmpProperties::propertyType(xmpKey);

Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
v->read(to_std_string(value));

if(data->add(xmpKey, v.get())) {
return Qfalse;
try {
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
Exiv2::TypeId typeId = Exiv2::XmpProperties::propertyType(xmpKey);

Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
v->read(to_std_string(value));
if(data->add(xmpKey, v.get())) {
return Qfalse;
}
}
catch (Exiv2::BasicError<char> error) {
rb_raise(basic_error_class, "%s", error.what());
}
return Qtrue;
}
Expand All @@ -290,3 +309,13 @@ static VALUE xmp_data_delete(VALUE self, VALUE key) {

return Qtrue;
}

static VALUE xmp_register_ns(VALUE self, VALUE uri, VALUE ns) {
try {
Exiv2::XmpProperties::registerNs(to_std_string(uri), to_std_string(ns));
}
catch (Exiv2::BasicError<char> error) {
rb_raise(basic_error_class, "%s", error.what());
}
return Qtrue;
}
24 changes: 24 additions & 0 deletions spec/exiv2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@
@iptc_data.delete_all("Iptc.Application2.Keywords")
expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq(nil)
end

it "should throw error because the IPTC namespace does not exist" do
expect {
@iptc_data.add("Iptc.DoesNotExist.New", "ruby-exiv2")
}.to raise_error(Exiv2::BasicError)
end
end

context "XMP data" do
Expand Down Expand Up @@ -161,6 +167,18 @@
@xmp_data.delete_all("Xmp.dc.title")
expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq(nil)
end

it "should throw error because the XMP namespace does not exist" do
expect {
@xmp_data.add("Xmp.DoesNotExist.New", "ruby-exiv2")
}.to raise_error(Exiv2::BasicError)
end

it "should add XMP namespace to file" do
@xmp_data.register("http://newnamespace.com/new.namespace/", "ShouldNowExist")
@xmp_data.add("Xmp.ShouldNowExist.New", "ruby-exiv2")
expect(@xmp_data.to_hash["Xmp.ShouldNowExist.New"]).to eq("ruby-exiv2")
end
end

context "EXIF data" do
Expand Down Expand Up @@ -223,5 +241,11 @@
@exif_data.delete_all("Exif.Image.Software")
expect(@exif_data.to_hash["Exif.Image.Software"]).to eq(nil)
end

it "should throw error because the Exif namespace does not exist" do
expect {
@exif_data.add("Exif.DoesNotExist.New", "ruby-exiv2")
}.to raise_error(Exiv2::BasicError)
end
end
end