exiv2 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|