exiv2 0.0.1 → 0.0.2
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 +6 -2
- data/ext/exiv2/exiv2.cpp +46 -8
- data/lib/exiv2.rb +1 -0
- data/lib/exiv2/iptc_data.rb +22 -0
- data/lib/exiv2/version.rb +1 -1
- data/spec/exiv2_spec.rb +18 -2
- data/spec/files/test.jpg +0 -0
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -4,6 +4,8 @@ A simple wrapper around the C++ Exiv2 libary for reading image metadata.
|
|
4
4
|
|
5
5
|
See http://www.exiv2.org/
|
6
6
|
|
7
|
+
Requires that the exiv2 C++ library is installed.
|
8
|
+
|
7
9
|
== Usage
|
8
10
|
|
9
11
|
gem install exiv2
|
@@ -11,8 +13,10 @@ See http://www.exiv2.org/
|
|
11
13
|
require 'exiv2'
|
12
14
|
image = Exiv2::ImageFactory.open("image.jpg")
|
13
15
|
image.read_metadata
|
14
|
-
|
15
|
-
|
16
|
+
image.iptc_data.each do |key, value|
|
17
|
+
puts "#{key} = #{value}\n"
|
18
|
+
end
|
19
|
+
image.exif_data.each { ... }
|
16
20
|
|
17
21
|
== Why?
|
18
22
|
|
data/ext/exiv2/exiv2.cpp
CHANGED
@@ -11,20 +11,22 @@ static std::string to_std_string(VALUE string) {
|
|
11
11
|
return std::string(RSTRING(string)->ptr, RSTRING(string)->len);
|
12
12
|
}
|
13
13
|
|
14
|
-
//
|
14
|
+
// Shared method for implementing each on IptcData and ExifData.
|
15
15
|
template <class T>
|
16
|
-
static VALUE
|
17
|
-
|
16
|
+
static VALUE metadata_each(VALUE self) {
|
17
|
+
T* data;
|
18
|
+
Data_Get_Struct(self, T, data);
|
18
19
|
|
19
|
-
for(typename T::iterator i = data
|
20
|
+
for(typename T::iterator i = data->begin(); i != data->end(); i++) {
|
20
21
|
VALUE key = to_ruby_string(i->key());
|
21
22
|
VALUE value = to_ruby_string(i->value().toString());
|
22
|
-
|
23
|
+
rb_yield(rb_ary_new3(2, key, value));
|
23
24
|
}
|
24
25
|
|
25
|
-
return
|
26
|
+
return Qnil;
|
26
27
|
}
|
27
28
|
|
29
|
+
|
28
30
|
extern "C" {
|
29
31
|
typedef VALUE (*Method)(...);
|
30
32
|
|
@@ -41,8 +43,16 @@ extern "C" {
|
|
41
43
|
static VALUE image_factory_class;
|
42
44
|
static VALUE image_factory_open(VALUE klass, VALUE path);
|
43
45
|
|
46
|
+
static VALUE exif_data_class;
|
47
|
+
static VALUE exif_data_each(VALUE self);
|
48
|
+
|
49
|
+
static VALUE iptc_data_class;
|
50
|
+
static VALUE iptc_data_each(VALUE self);
|
51
|
+
|
44
52
|
|
45
53
|
void Init_exiv2() {
|
54
|
+
VALUE enumerable_module = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
55
|
+
|
46
56
|
exiv2_module = rb_define_module("Exiv2");
|
47
57
|
|
48
58
|
basic_error_class = rb_define_class_under(exiv2_module, "BasicError", rb_eRuntimeError);
|
@@ -54,6 +64,14 @@ extern "C" {
|
|
54
64
|
|
55
65
|
image_factory_class = rb_define_class_under(exiv2_module, "ImageFactory", rb_cObject);
|
56
66
|
rb_define_singleton_method(image_factory_class, "open", (Method)image_factory_open, 1);
|
67
|
+
|
68
|
+
exif_data_class = rb_define_class_under(exiv2_module, "ExifData", rb_cObject);
|
69
|
+
rb_include_module(exif_data_class, enumerable_module);
|
70
|
+
rb_define_method(exif_data_class, "each", (Method)exif_data_each, 0);
|
71
|
+
|
72
|
+
iptc_data_class = rb_define_class_under(exiv2_module, "IptcData", rb_cObject);
|
73
|
+
rb_include_module(iptc_data_class, enumerable_module);
|
74
|
+
rb_define_method(iptc_data_class, "each", (Method)iptc_data_each, 0);
|
57
75
|
}
|
58
76
|
|
59
77
|
|
@@ -81,14 +99,20 @@ extern "C" {
|
|
81
99
|
Exiv2::Image* image;
|
82
100
|
Data_Get_Struct(self, Exiv2::Image, image);
|
83
101
|
|
84
|
-
|
102
|
+
VALUE exif_data = Data_Wrap_Struct(exif_data_class, 0, 0, &image->exifData());
|
103
|
+
rb_iv_set(exif_data, "@image", self); // Make sure we don't GC the image until there are no references to the EXIF data left.
|
104
|
+
|
105
|
+
return exif_data;
|
85
106
|
}
|
86
107
|
|
87
108
|
static VALUE image_iptc_data(VALUE self) {
|
88
109
|
Exiv2::Image* image;
|
89
110
|
Data_Get_Struct(self, Exiv2::Image, image);
|
90
111
|
|
91
|
-
|
112
|
+
VALUE iptc_data = Data_Wrap_Struct(iptc_data_class, 0, 0, &image->iptcData());
|
113
|
+
rb_iv_set(iptc_data, "@image", self); // Make sure we don't GC the image until there are no references to the IPTC data left.
|
114
|
+
|
115
|
+
return iptc_data;
|
92
116
|
}
|
93
117
|
|
94
118
|
|
@@ -108,4 +132,18 @@ extern "C" {
|
|
108
132
|
return Data_Wrap_Struct(image_class, 0, image_free, image);
|
109
133
|
}
|
110
134
|
|
135
|
+
|
136
|
+
// Exiv2::ExifData methods
|
137
|
+
|
138
|
+
static VALUE exif_data_each(VALUE self) {
|
139
|
+
return metadata_each<Exiv2::ExifData>(self);
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
// Exiv2::IptcData methods
|
144
|
+
|
145
|
+
static VALUE iptc_data_each(VALUE self) {
|
146
|
+
return metadata_each<Exiv2::IptcData>(self);
|
147
|
+
}
|
148
|
+
|
111
149
|
}
|
data/lib/exiv2.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
class Exiv2::IptcData
|
2
|
+
def to_hash
|
3
|
+
result = {}
|
4
|
+
|
5
|
+
self.each do |key, value|
|
6
|
+
if result[key]
|
7
|
+
if result[key].is_a? Array
|
8
|
+
result[key] << value
|
9
|
+
else
|
10
|
+
result[key] = [result[key], value]
|
11
|
+
end
|
12
|
+
else
|
13
|
+
result[key] = value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#<Exiv2::IptcData: #{self.to_hash.inspect}>"
|
21
|
+
end
|
22
|
+
end
|
data/lib/exiv2/version.rb
CHANGED
data/spec/exiv2_spec.rb
CHANGED
@@ -4,8 +4,24 @@ describe Exiv2 do
|
|
4
4
|
it "should read IPTC data" do
|
5
5
|
image = Exiv2::ImageFactory.open("spec/files/test.jpg")
|
6
6
|
image.read_metadata
|
7
|
-
image.iptc_data
|
8
|
-
|
7
|
+
iptc_data = image.iptc_data
|
8
|
+
iptc_data.should be_a(Exiv2::IptcData)
|
9
|
+
iptc_data.inspect.should == '#<Exiv2::IptcData: {"Iptc.Application2.Caption"=>"Rhubarb rhubarb rhubard", "Iptc.Application2.Keywords"=>["fish", "custard"]}>'
|
10
|
+
iptc_data.to_a.should == [
|
11
|
+
["Iptc.Application2.Caption", "Rhubarb rhubarb rhubard"],
|
12
|
+
["Iptc.Application2.Keywords", "fish"],
|
13
|
+
["Iptc.Application2.Keywords", "custard"]
|
14
|
+
]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should convert iptc data into a hash" do
|
18
|
+
image = Exiv2::ImageFactory.open("spec/files/test.jpg")
|
19
|
+
image.read_metadata
|
20
|
+
iptc_hash = image.iptc_data.to_hash
|
21
|
+
iptc_hash.should be_a(Hash)
|
22
|
+
iptc_hash.should == {
|
23
|
+
"Iptc.Application2.Caption" => "Rhubarb rhubarb rhubard",
|
24
|
+
"Iptc.Application2.Keywords" => ["fish", "custard"]
|
9
25
|
}
|
10
26
|
end
|
11
27
|
|
data/spec/files/test.jpg
CHANGED
Binary file
|
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: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
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-01-
|
18
|
+
date: 2011-01-27 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- ext/exiv2/exiv2.cpp
|
67
67
|
- ext/exiv2/extconf.rb
|
68
68
|
- lib/exiv2.rb
|
69
|
+
- lib/exiv2/iptc_data.rb
|
69
70
|
- lib/exiv2/version.rb
|
70
71
|
- spec/exiv2_spec.rb
|
71
72
|
- spec/files/test.jpg
|