diff --git a/ext/exiv2/exiv2.cpp b/ext/exiv2/exiv2.cpp index ac74818..9122325 100644 --- a/ext/exiv2/exiv2.cpp +++ b/ext/exiv2/exiv2.cpp @@ -1,6 +1,12 @@ #include "exiv2/image.hpp" #include "ruby.h" +typedef VALUE (*Method)(...); + +static VALUE original_value(VALUE self) { + return rb_iv_get(self, "@value_"); +} + // Create a Ruby string from a C++ std::string. static VALUE to_ruby_string(const std::string& string) { VALUE str = rb_str_new(string.data(), string.length()); @@ -13,6 +19,15 @@ static VALUE to_ruby_string(const std::string& string) { return str; } +static VALUE map_to_hash(Exiv2::LangAltValue::ValueType map) { + VALUE hash = rb_hash_new(); + std::map::iterator iterator; + for (iterator = map.begin(); iterator != map.end(); ++iterator) { + rb_hash_aset(hash, to_ruby_string(iterator->first), to_ruby_string(iterator->second)); + } + return hash; +} + // Create a C++ std::string from a Ruby string. static std::string to_std_string(VALUE string) { string = StringValue(string); // Convert the Ruby object to a string if it isn't one. @@ -28,14 +43,17 @@ static VALUE metadata_each(VALUE self) { for(typename T::iterator i = data->begin(); i != data->end(); i++) { VALUE key = to_ruby_string(i->key()); VALUE value = to_ruby_string(i->value().toString()); + if (const Exiv2::LangAltValue* lang_alt_value = dynamic_cast(&(i->value()))) { + rb_iv_set(value, "@value_", map_to_hash(lang_alt_value->value_)); + } + rb_define_singleton_method(value, "original_value", (Method)original_value, 0); + rb_yield(rb_ary_new3(2, key, value)); } return Qnil; } -typedef VALUE (*Method)(...); - static VALUE exiv2_module; static VALUE basic_error_class; diff --git a/spec/exiv2_spec.rb b/spec/exiv2_spec.rb index 11d2af4..d039ea9 100644 --- a/spec/exiv2_spec.rb +++ b/spec/exiv2_spec.rb @@ -24,7 +24,7 @@ image.iptc_data["Iptc.Application2.Caption"] = "A New Caption" image.write_metadata image = nil - + image2 = Exiv2::ImageFactory.open("spec/files/test_tmp.jpg") image2.read_metadata expect(image2.iptc_data["Iptc.Application2.Caption"]).to eq("A New Caption") @@ -51,7 +51,7 @@ end end end - + let(:image) do image = Exiv2::ImageFactory.open("spec/files/test.jpg") image.read_metadata @@ -81,7 +81,7 @@ "Iptc.Application2.Keywords" => ["fish", "custard"] }) end - + it "should write IPTC data" do @iptc_data.add("Iptc.Application2.Keywords", "fishy") expect(@iptc_data.to_a).to eq([ @@ -91,22 +91,22 @@ ["Iptc.Application2.Keywords", "fishy"] ]) end - + it "should set IPTC data" do @iptc_data["Iptc.Application2.Caption"] = "A New Caption" expect(@iptc_data.to_hash["Iptc.Application2.Caption"]).to eq("A New Caption") end - + it "should set multiply IPTC data values" do @iptc_data["Iptc.Application2.Keywords"] = ["abc", "cde"] expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq(["abc", "cde"]) end - + it "should delete one value of IPTC data" do @iptc_data.delete("Iptc.Application2.Keywords") expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq("custard") end - + it "should delete all values of IPTC data" do @iptc_data.delete_all("Iptc.Application2.Keywords") expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq(nil) @@ -140,27 +140,38 @@ @xmp_data["Xmp.dc.title"] = "lang=\"x-default\" Changed!" expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq("lang=\"x-default\" Changed!") end - + it "should set XMP data" do @xmp_data["Xmp.dc.title"] = "A New Title" expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq("lang=\"x-default\" A New Title") end - + it "should set multiply XMP data values" do @xmp_data["Xmp.dc.title"] = ["abc", "cde"] expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq(["lang=\"x-default\" abc", "lang=\"x-default\" cde"]) end - + it "should delete one value of XMP data" do @xmp_data["Xmp.dc.title"] = ["abc", "cde"] @xmp_data.delete("Xmp.dc.title") expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq("lang=\"x-default\" cde") end - + it "should delete all values of XMP data" do @xmp_data.delete_all("Xmp.dc.title") expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq(nil) end + + it "adds #original_value to multi-lang field" do + @xmp_data["Xmp.dc.title"] = "A New Title" + expect(@xmp_data.to_hash["Xmp.dc.title"].original_value).to eq "x-default" => "A New Title" + end + + it "adds #original_value to multiple multi-lang fields" do + @xmp_data["Xmp.dc.title"] = ["abc", "cde"] + expect(@xmp_data.to_hash["Xmp.dc.title"][0].original_value).to eq "x-default" => "abc" + expect(@xmp_data.to_hash["Xmp.dc.title"][1].original_value).to eq "x-default" => "cde" + end end context "EXIF data" do @@ -202,23 +213,23 @@ "Exif.Image.ExifTag" => "52" }) end - + it "should set Exif data" do @exif_data["Exif.Image.Software"] = "ruby-exiv2" expect(@exif_data.to_hash["Exif.Image.Software"]).to eq("ruby-exiv2") end - + it "should set multiply Exif data values" do @exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"] expect(@exif_data.to_hash["Exif.Image.Software"]).to eq(["ruby-exiv2", "plasq skitch"]) end - + it "should delete one value of Exif data" do @exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"] @exif_data.delete("Exif.Image.Software") expect(@exif_data.to_hash["Exif.Image.Software"]).to eq("plasq skitch") end - + it "should delete all values of Exif data" do @exif_data.delete_all("Exif.Image.Software") expect(@exif_data.to_hash["Exif.Image.Software"]).to eq(nil)