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
22 changes: 20 additions & 2 deletions ext/exiv2/exiv2.cpp
Original file line number Diff line number Diff line change
@@ -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());
Expand All @@ -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<std::string, std::string>::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.
Expand All @@ -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<const Exiv2::LangAltValue*>(&(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;
Expand Down
41 changes: 26 additions & 15 deletions spec/exiv2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -51,7 +51,7 @@
end
end
end

let(:image) do
image = Exiv2::ImageFactory.open("spec/files/test.jpg")
image.read_metadata
Expand Down Expand Up @@ -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([
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down