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