exiv2 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +15 -3
- data/Rakefile +4 -0
- data/ext/exiv2/exiv2.cpp +117 -2
- data/lib/exiv2/shared_methods.rb +27 -1
- data/lib/exiv2/version.rb +1 -1
- data/spec/exiv2_spec.rb +103 -2
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Exiv2
|
2
2
|
|
3
|
-
A simple wrapper around the C++ Exiv2 libary for reading image metadata.
|
3
|
+
A simple wrapper around the C++ Exiv2 libary for reading and writing image metadata.
|
4
4
|
|
5
5
|
See http://www.exiv2.org/
|
6
6
|
|
@@ -21,10 +21,18 @@ Requires that the exiv2 C++ library is installed.
|
|
21
21
|
|
22
22
|
iptc_data_hash = image.iptc_data.to_hash
|
23
23
|
xmp_data_hash = image.xmp_data.to_hash
|
24
|
+
|
25
|
+
image.exif_data.delete("Exif.Image.Software")
|
26
|
+
image.iptc_data.delete_all("Iptc.Application2.Keywords")
|
27
|
+
|
28
|
+
image.iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
29
|
+
image.iptc_data.add("Iptc.Application2.Keywords", "fishy")
|
30
|
+
|
31
|
+
image.write_metadata
|
24
32
|
|
25
33
|
== Why?
|
26
34
|
|
27
|
-
None of the existing Ruby libraries for reading image metadata did quite what
|
35
|
+
None of the existing Ruby libraries for reading and writing image metadata did quite what
|
28
36
|
we wanted, so we figured it wouldn't be too hard to wrap enough of Exiv2 to
|
29
37
|
meet our needs.
|
30
38
|
|
@@ -34,7 +42,7 @@ are welcome.
|
|
34
42
|
|
35
43
|
== Compatibility
|
36
44
|
|
37
|
-
Tested with Ruby 1.8.7 and Exiv2 0.21
|
45
|
+
Tested with Ruby 1.8.7 and 1.9.3, and Exiv2 0.20 and 0.21
|
38
46
|
|
39
47
|
== Developing
|
40
48
|
|
@@ -51,6 +59,10 @@ Tested with Ruby 1.8.7 and Exiv2 0.21.
|
|
51
59
|
In early development. Very little of Exiv2's API is supported, and it hasn't
|
52
60
|
been heavily tested.
|
53
61
|
|
62
|
+
== Contributors
|
63
|
+
|
64
|
+
Pete Yandell, Mark Turnley, Lucas Parry, Norbert Wojtwoicz, Jan Graichen, John Barton
|
65
|
+
|
54
66
|
== Copyright
|
55
67
|
|
56
68
|
Copyright (c) 2010 Envato & Pete Yandell. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -5,8 +5,12 @@ task :default => :spec
|
|
5
5
|
require 'rake/extensiontask'
|
6
6
|
Rake::ExtensionTask.new('exiv2') do |ext|
|
7
7
|
ext.lib_dir = "lib/exiv2"
|
8
|
+
if ENV['EXIV2_DIR']
|
9
|
+
ext.config_options << "--with-exiv2-dir=#{ENV['EXIV2_DIR']}"
|
10
|
+
end
|
8
11
|
end
|
9
12
|
Rake::Task[:spec].prerequisites << :compile
|
10
13
|
|
11
14
|
require 'bundler'
|
12
15
|
Bundler::GemHelper.install_tasks
|
16
|
+
|
data/ext/exiv2/exiv2.cpp
CHANGED
@@ -9,7 +9,7 @@ static VALUE to_ruby_string(const std::string& string) {
|
|
9
9
|
// Create a C++ std::string from a Ruby string.
|
10
10
|
static std::string to_std_string(VALUE string) {
|
11
11
|
string = StringValue(string); // Convert the Ruby object to a string if it isn't one.
|
12
|
-
return std::string(
|
12
|
+
return std::string(RSTRING_PTR(string), RSTRING_LEN(string));
|
13
13
|
}
|
14
14
|
|
15
15
|
// Shared method for implementing each on XmpData, IptcData and ExifData.
|
@@ -38,6 +38,7 @@ extern "C" {
|
|
38
38
|
static VALUE image_class;
|
39
39
|
static void image_free(Exiv2::Image* image);
|
40
40
|
static VALUE image_read_metadata(VALUE self);
|
41
|
+
static VALUE image_write_metadata(VALUE self);
|
41
42
|
static VALUE image_iptc_data(VALUE self);
|
42
43
|
static VALUE image_xmp_data(VALUE self);
|
43
44
|
static VALUE image_exif_data(VALUE self);
|
@@ -47,12 +48,18 @@ extern "C" {
|
|
47
48
|
|
48
49
|
static VALUE exif_data_class;
|
49
50
|
static VALUE exif_data_each(VALUE self);
|
51
|
+
static VALUE exif_data_add(VALUE self, VALUE key, VALUE value);
|
52
|
+
static VALUE exif_data_delete(VALUE self, VALUE key);
|
50
53
|
|
51
54
|
static VALUE iptc_data_class;
|
52
55
|
static VALUE iptc_data_each(VALUE self);
|
56
|
+
static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value);
|
57
|
+
static VALUE iptc_data_delete(VALUE self, VALUE key);
|
53
58
|
|
54
59
|
static VALUE xmp_data_class;
|
55
60
|
static VALUE xmp_data_each(VALUE self);
|
61
|
+
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value);
|
62
|
+
static VALUE xmp_data_delete(VALUE self, VALUE key);
|
56
63
|
|
57
64
|
void Init_exiv2() {
|
58
65
|
VALUE enumerable_module = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
@@ -63,6 +70,7 @@ extern "C" {
|
|
63
70
|
|
64
71
|
image_class = rb_define_class_under(exiv2_module, "Image", rb_cObject);
|
65
72
|
rb_define_method(image_class, "read_metadata", (Method)image_read_metadata, 0);
|
73
|
+
rb_define_method(image_class, "write_metadata", (Method)image_write_metadata, 0);
|
66
74
|
rb_define_method(image_class, "iptc_data", (Method)image_iptc_data, 0);
|
67
75
|
rb_define_method(image_class, "xmp_data", (Method)image_xmp_data, 0);
|
68
76
|
rb_define_method(image_class, "exif_data", (Method)image_exif_data, 0);
|
@@ -73,14 +81,20 @@ extern "C" {
|
|
73
81
|
exif_data_class = rb_define_class_under(exiv2_module, "ExifData", rb_cObject);
|
74
82
|
rb_include_module(exif_data_class, enumerable_module);
|
75
83
|
rb_define_method(exif_data_class, "each", (Method)exif_data_each, 0);
|
84
|
+
rb_define_method(exif_data_class, "add", (Method)exif_data_add, 2);
|
85
|
+
rb_define_method(exif_data_class, "delete", (Method)exif_data_delete, 1);
|
76
86
|
|
77
87
|
iptc_data_class = rb_define_class_under(exiv2_module, "IptcData", rb_cObject);
|
78
88
|
rb_include_module(iptc_data_class, enumerable_module);
|
79
89
|
rb_define_method(iptc_data_class, "each", (Method)iptc_data_each, 0);
|
90
|
+
rb_define_method(iptc_data_class, "add", (Method)iptc_data_add, 2);
|
91
|
+
rb_define_method(iptc_data_class, "delete", (Method)iptc_data_delete, 1);
|
80
92
|
|
81
93
|
xmp_data_class = rb_define_class_under(exiv2_module, "XmpData", rb_cObject);
|
82
94
|
rb_include_module(xmp_data_class, enumerable_module);
|
83
95
|
rb_define_method(xmp_data_class, "each", (Method)xmp_data_each, 0);
|
96
|
+
rb_define_method(xmp_data_class, "add", (Method)xmp_data_add, 2);
|
97
|
+
rb_define_method(xmp_data_class, "delete", (Method)xmp_data_delete, 1);
|
84
98
|
}
|
85
99
|
|
86
100
|
|
@@ -103,6 +117,20 @@ extern "C" {
|
|
103
117
|
|
104
118
|
return Qnil;
|
105
119
|
}
|
120
|
+
|
121
|
+
static VALUE image_write_metadata(VALUE self) {
|
122
|
+
Exiv2::Image* image;
|
123
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
124
|
+
|
125
|
+
try {
|
126
|
+
image->writeMetadata();
|
127
|
+
}
|
128
|
+
catch (Exiv2::BasicError<char> error) {
|
129
|
+
rb_raise(basic_error_class, "%s", error.what());
|
130
|
+
}
|
131
|
+
|
132
|
+
return Qnil;
|
133
|
+
}
|
106
134
|
|
107
135
|
static VALUE image_exif_data(VALUE self) {
|
108
136
|
Exiv2::Image* image;
|
@@ -157,16 +185,103 @@ extern "C" {
|
|
157
185
|
return metadata_each<Exiv2::ExifData>(self);
|
158
186
|
}
|
159
187
|
|
188
|
+
static VALUE exif_data_add(VALUE self, VALUE key, VALUE value) {
|
189
|
+
Exiv2::ExifData* data;
|
190
|
+
Data_Get_Struct(self, Exiv2::ExifData, data);
|
191
|
+
|
192
|
+
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));
|
193
|
+
|
194
|
+
#if EXIV2_MAJOR_VERSION <= 0 && EXIV2_MINOR_VERSION <= 20
|
195
|
+
Exiv2::TypeId typeId = Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId());
|
196
|
+
#else
|
197
|
+
Exiv2::TypeId typeId = exifKey.defaultTypeId();
|
198
|
+
#endif
|
199
|
+
|
200
|
+
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
201
|
+
v->read(to_std_string(value));
|
202
|
+
|
203
|
+
data->add(exifKey, v.get());
|
204
|
+
return Qtrue;
|
205
|
+
}
|
206
|
+
|
207
|
+
static VALUE exif_data_delete(VALUE self, VALUE key) {
|
208
|
+
Exiv2::ExifData* data;
|
209
|
+
Data_Get_Struct(self, Exiv2::ExifData, data);
|
210
|
+
|
211
|
+
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));
|
212
|
+
Exiv2::ExifData::iterator pos = data->findKey(exifKey);
|
213
|
+
if(pos == data->end()) return Qfalse;
|
214
|
+
data->erase(pos);
|
215
|
+
|
216
|
+
return Qtrue;
|
217
|
+
}
|
218
|
+
|
160
219
|
|
161
220
|
// Exiv2::IptcData methods
|
162
221
|
|
163
222
|
static VALUE iptc_data_each(VALUE self) {
|
164
223
|
return metadata_each<Exiv2::IptcData>(self);
|
165
224
|
}
|
225
|
+
|
226
|
+
static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value) {
|
227
|
+
Exiv2::IptcData* data;
|
228
|
+
Data_Get_Struct(self, Exiv2::IptcData, data);
|
229
|
+
|
230
|
+
Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
|
231
|
+
Exiv2::TypeId typeId = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
|
232
|
+
|
233
|
+
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
234
|
+
v->read(to_std_string(value));
|
235
|
+
|
236
|
+
if(data->add(iptcKey, v.get())) {
|
237
|
+
return Qfalse;
|
238
|
+
}
|
239
|
+
return Qtrue;
|
240
|
+
}
|
241
|
+
|
242
|
+
static VALUE iptc_data_delete(VALUE self, VALUE key) {
|
243
|
+
Exiv2::IptcData* data;
|
244
|
+
Data_Get_Struct(self, Exiv2::IptcData, data);
|
245
|
+
|
246
|
+
Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
|
247
|
+
Exiv2::IptcData::iterator pos = data->findKey(iptcKey);
|
248
|
+
if(pos == data->end()) return Qfalse;
|
249
|
+
data->erase(pos);
|
250
|
+
|
251
|
+
return Qtrue;
|
252
|
+
}
|
166
253
|
|
167
254
|
// Exiv2::XmpData methods
|
168
255
|
|
169
256
|
static VALUE xmp_data_each(VALUE self) {
|
170
257
|
return metadata_each<Exiv2::XmpData>(self);
|
171
|
-
}
|
258
|
+
}
|
259
|
+
|
260
|
+
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value) {
|
261
|
+
Exiv2::XmpData* data;
|
262
|
+
Data_Get_Struct(self, Exiv2::XmpData, data);
|
263
|
+
|
264
|
+
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
|
265
|
+
Exiv2::TypeId typeId = Exiv2::XmpProperties::propertyType(xmpKey);
|
266
|
+
|
267
|
+
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
268
|
+
v->read(to_std_string(value));
|
269
|
+
|
270
|
+
if(data->add(xmpKey, v.get())) {
|
271
|
+
return Qfalse;
|
272
|
+
}
|
273
|
+
return Qtrue;
|
274
|
+
}
|
275
|
+
|
276
|
+
static VALUE xmp_data_delete(VALUE self, VALUE key) {
|
277
|
+
Exiv2::XmpData* data;
|
278
|
+
Data_Get_Struct(self, Exiv2::XmpData, data);
|
279
|
+
|
280
|
+
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
|
281
|
+
Exiv2::XmpData::iterator pos = data->findKey(xmpKey);
|
282
|
+
if(pos == data->end()) return Qfalse;
|
283
|
+
data->erase(pos);
|
284
|
+
|
285
|
+
return Qtrue;
|
286
|
+
}
|
172
287
|
}
|
data/lib/exiv2/shared_methods.rb
CHANGED
@@ -17,6 +17,32 @@ module SharedMethods
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def inspect
|
20
|
-
|
20
|
+
items = []
|
21
|
+
self.to_hash.sort.each do |k,v|
|
22
|
+
items << %Q["#{k}"=>#{v.inspect}]
|
23
|
+
end
|
24
|
+
"#<#{self.class.name}: {#{items.join(', ')}}>"
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](key)
|
28
|
+
self.to_hash[key]
|
29
|
+
end
|
30
|
+
|
31
|
+
def []=(key, value)
|
32
|
+
delete_all(key)
|
33
|
+
if value.is_a?(Array)
|
34
|
+
value.each do |v|
|
35
|
+
self.add(key, v)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
self.add(key, value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete_all(key)
|
43
|
+
del = true
|
44
|
+
while(del) do
|
45
|
+
del = self.delete(key)
|
46
|
+
end
|
21
47
|
end
|
22
48
|
end
|
data/lib/exiv2/version.rb
CHANGED
data/spec/exiv2_spec.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'exiv2'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
describe Exiv2 do
|
4
5
|
|
5
6
|
it "should handle a Pathname being passed to open" do
|
6
|
-
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/test.jpg"))
|
7
|
+
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/test.jpg").to_s)
|
7
8
|
image.read_metadata
|
8
9
|
image.iptc_data.to_hash.should_not be_empty
|
9
10
|
end
|
@@ -14,6 +15,20 @@ describe Exiv2 do
|
|
14
15
|
}.should raise_error(Exiv2::BasicError)
|
15
16
|
end
|
16
17
|
|
18
|
+
it "should write metadata" do
|
19
|
+
FileUtils.cp("spec/files/test.jpg", "spec/files/test_tmp.jpg")
|
20
|
+
image = Exiv2::ImageFactory.open("spec/files/test_tmp.jpg")
|
21
|
+
image.read_metadata
|
22
|
+
image.iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
23
|
+
image.write_metadata
|
24
|
+
image = nil
|
25
|
+
|
26
|
+
image2 = Exiv2::ImageFactory.open("spec/files/test_tmp.jpg")
|
27
|
+
image2.read_metadata
|
28
|
+
image2.iptc_data["Iptc.Application2.Caption"].should == "A New Caption"
|
29
|
+
FileUtils.rm("spec/files/test_tmp.jpg")
|
30
|
+
end
|
31
|
+
|
17
32
|
let(:image) do
|
18
33
|
image = Exiv2::ImageFactory.open("spec/files/test.jpg")
|
19
34
|
image.read_metadata
|
@@ -43,6 +58,36 @@ describe Exiv2 do
|
|
43
58
|
"Iptc.Application2.Keywords" => ["fish", "custard"]
|
44
59
|
}
|
45
60
|
end
|
61
|
+
|
62
|
+
it "should write IPTC data" do
|
63
|
+
@iptc_data.add("Iptc.Application2.Keywords", "fishy")
|
64
|
+
@iptc_data.to_a.should == [
|
65
|
+
["Iptc.Application2.Caption", "Rhubarb rhubarb rhubard"],
|
66
|
+
["Iptc.Application2.Keywords", "fish"],
|
67
|
+
["Iptc.Application2.Keywords", "custard"],
|
68
|
+
["Iptc.Application2.Keywords", "fishy"]
|
69
|
+
]
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should set IPTC data" do
|
73
|
+
@iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
74
|
+
@iptc_data.to_hash["Iptc.Application2.Caption"].should == "A New Caption"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should set multiply IPTC data values" do
|
78
|
+
@iptc_data["Iptc.Application2.Keywords"] = ["abc", "cde"]
|
79
|
+
@iptc_data.to_hash["Iptc.Application2.Keywords"].should == ["abc", "cde"]
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should delete one value of IPTC data" do
|
83
|
+
@iptc_data.delete("Iptc.Application2.Keywords")
|
84
|
+
@iptc_data.to_hash["Iptc.Application2.Keywords"].should == "custard"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should delete all values of IPTC data" do
|
88
|
+
@iptc_data.delete_all("Iptc.Application2.Keywords")
|
89
|
+
@iptc_data.to_hash["Iptc.Application2.Keywords"].should == nil
|
90
|
+
end
|
46
91
|
end
|
47
92
|
|
48
93
|
context "XMP data" do
|
@@ -68,6 +113,31 @@ describe Exiv2 do
|
|
68
113
|
}
|
69
114
|
end
|
70
115
|
|
116
|
+
it "should write XMP data" do
|
117
|
+
@xmp_data["Xmp.dc.title"] = "lang=\"x-default\" Changed!"
|
118
|
+
@xmp_data.to_hash["Xmp.dc.title"].should == "lang=\"x-default\" Changed!"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should set XMP data" do
|
122
|
+
@xmp_data["Xmp.dc.title"] = "A New Title"
|
123
|
+
@xmp_data.to_hash["Xmp.dc.title"].should == "lang=\"x-default\" A New Title"
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should set multiply XMP data values" do
|
127
|
+
@xmp_data["Xmp.dc.title"] = ["abc", "cde"]
|
128
|
+
@xmp_data.to_hash["Xmp.dc.title"].should == ["lang=\"x-default\" abc", "lang=\"x-default\" cde"]
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should delete one value of XMP data" do
|
132
|
+
@xmp_data["Xmp.dc.title"] = ["abc", "cde"]
|
133
|
+
@xmp_data.delete("Xmp.dc.title")
|
134
|
+
@xmp_data.to_hash["Xmp.dc.title"].should == "lang=\"x-default\" cde"
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should delete all values of XMP data" do
|
138
|
+
@xmp_data.delete_all("Xmp.dc.title")
|
139
|
+
@xmp_data.to_hash["Xmp.dc.title"].should == nil
|
140
|
+
end
|
71
141
|
end
|
72
142
|
|
73
143
|
context "EXIF data" do
|
@@ -77,7 +147,7 @@ describe Exiv2 do
|
|
77
147
|
|
78
148
|
it "should read Exif data" do
|
79
149
|
@exif_data.should be_a(Exiv2::ExifData)
|
80
|
-
@exif_data.inspect.should ==
|
150
|
+
@exif_data.inspect.should == '#<Exiv2::ExifData: {"Exif.Image.ExifTag"=>"52", "Exif.Image.Software"=>"plasq skitch", "Exif.Photo.ExifVersion"=>"48 50 49 48", "Exif.Photo.PixelXDimension"=>"32", "Exif.Photo.PixelYDimension"=>"32"}>'
|
81
151
|
@exif_data.to_a.should == [
|
82
152
|
["Exif.Image.Software", "plasq skitch"],
|
83
153
|
["Exif.Image.ExifTag", "52"],
|
@@ -99,5 +169,36 @@ describe Exiv2 do
|
|
99
169
|
}
|
100
170
|
end
|
101
171
|
|
172
|
+
it "should write Exif data" do
|
173
|
+
@exif_data.add("Exif.Image.Software", "ruby-exiv2")
|
174
|
+
@exif_data.to_hash.should == {
|
175
|
+
"Exif.Photo.PixelXDimension" => "32",
|
176
|
+
"Exif.Photo.ExifVersion" => "48 50 49 48",
|
177
|
+
"Exif.Image.Software" => ["plasq skitch", "ruby-exiv2"],
|
178
|
+
"Exif.Photo.PixelYDimension" => "32",
|
179
|
+
"Exif.Image.ExifTag" => "52"
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should set Exif data" do
|
184
|
+
@exif_data["Exif.Image.Software"] = "ruby-exiv2"
|
185
|
+
@exif_data.to_hash["Exif.Image.Software"].should == "ruby-exiv2"
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should set multiply Exif data values" do
|
189
|
+
@exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"]
|
190
|
+
@exif_data.to_hash["Exif.Image.Software"].should == ["ruby-exiv2", "plasq skitch"]
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should delete one value of Exif data" do
|
194
|
+
@exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"]
|
195
|
+
@exif_data.delete("Exif.Image.Software")
|
196
|
+
@exif_data.to_hash["Exif.Image.Software"].should == "plasq skitch"
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should delete all values of Exif data" do
|
200
|
+
@exif_data.delete_all("Exif.Image.Software")
|
201
|
+
@exif_data.to_hash["Exif.Image.Software"].should == nil
|
202
|
+
end
|
102
203
|
end
|
103
204
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exiv2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Pete Yandell
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-11-11 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|