ruby-exiv2 1.3 → 1.5
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 +1 -0
- data/Rakefile +5 -29
- data/{ext → lib}/exiv2.hpp +4 -4
- data/lib/exiv2.rb +22 -28
- data/lib/exiv2/exif.rb +19 -0
- data/lib/exiv2/image.rb +205 -0
- data/lib/exiv2/iptc.rb +19 -0
- data/lib/exiv2/metadata/clear.cpp +14 -0
- data/lib/exiv2/metadata/count.cpp +10 -0
- data/lib/exiv2/metadata/delete.cpp +23 -0
- data/lib/exiv2/metadata/each.cpp +26 -0
- data/lib/exiv2/metadata/get.cpp +21 -0
- data/lib/exiv2/metadata/is_empty.cpp +10 -0
- data/lib/exiv2/metadata/marshall.cpp +85 -0
- data/lib/exiv2/metadata/set.cpp +16 -0
- data/{ext/marshall.cpp → lib/exiv2/metadata/unmarshall.cpp} +0 -1
- data/lib/exiv2/tag.rb +110 -0
- data/lib/exiv2/throw.cpp +12 -0
- data/test/{image.rb → test_image.rb} +14 -2
- metadata +58 -48
- data/ext/exif.cpp +0 -369
- data/ext/exiv2.cpp +0 -78
- data/ext/extconf.rb +0 -75
- data/ext/image.cpp +0 -230
- data/ext/iptc.cpp +0 -253
- data/setup.rb +0 -1585
@@ -0,0 +1,26 @@
|
|
1
|
+
static VALUE exiv2_metadata_each(int argc, VALUE *argv, VALUE self) {
|
2
|
+
__BEGIN
|
3
|
+
rbImage* image;
|
4
|
+
Data_Get_Struct(self, rbImage, image);
|
5
|
+
|
6
|
+
VALUE prefix;
|
7
|
+
rb_scan_args(argc, argv, "01", &prefix);
|
8
|
+
|
9
|
+
Exiv2::<%= kind %>Data &data = image->image-><%= kind.downcase %>Data();
|
10
|
+
if(data.empty()) {
|
11
|
+
return Qnil;
|
12
|
+
}
|
13
|
+
|
14
|
+
Exiv2::<%= kind %>Data::const_iterator end = data.end();
|
15
|
+
for(Exiv2::<%= kind %>Data::const_iterator i = data.begin(); i != end; ++i) {
|
16
|
+
VALUE key = rb_str_new(i->key().c_str(), i->key().length());
|
17
|
+
VALUE val = unmarshall_value(i->value());
|
18
|
+
//VALUE val = rb_str_new(i->toString().c_str(), i->toString().length());
|
19
|
+
if(prefix != Qnil && INT2FIX(0) != rb_funcall(key, rb_intern("index"), 1, prefix)) {
|
20
|
+
continue;
|
21
|
+
}
|
22
|
+
rb_yield(rb_ary_new3(2, key, val));
|
23
|
+
}
|
24
|
+
return self;
|
25
|
+
__END
|
26
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
static VALUE exiv2_metadata_get(VALUE rb_key) {
|
2
|
+
__BEGIN
|
3
|
+
rbImage* image;
|
4
|
+
Data_Get_Struct(self, rbImage, image);
|
5
|
+
|
6
|
+
VALUE strkey = rb_funcall(rb_key, rb_intern("to_s"), 0);
|
7
|
+
Exiv2::<%= kind %>Data &data = image->image-><%= kind.downcase %>Data();
|
8
|
+
|
9
|
+
if(data.empty()) {
|
10
|
+
return Qnil;
|
11
|
+
}
|
12
|
+
|
13
|
+
Exiv2::<%= kind %>Key key(STR(strkey));
|
14
|
+
Exiv2::<%= kind %>Data::const_iterator pos = data.findKey(key);
|
15
|
+
if (pos == data.end()) {
|
16
|
+
return Qnil;
|
17
|
+
}
|
18
|
+
|
19
|
+
return unmarshall_value(pos->value());
|
20
|
+
__NIL_END
|
21
|
+
}
|
@@ -0,0 +1,85 @@
|
|
1
|
+
static bool marshall_value(Exiv2::<%= kind %>Data &data, const char* key, VALUE value) {
|
2
|
+
Exiv2::TypeId type_id;
|
3
|
+
try {
|
4
|
+
<% if kind == "Exif" %>
|
5
|
+
Exiv2::ExifKey data_key(key);
|
6
|
+
type_id = Exiv2::ExifTags::tagType(data_key.tag(), data_key.ifdId());
|
7
|
+
<% elsif kind == "Iptc" %>
|
8
|
+
Exiv2::IptcKey iptcKey(key);
|
9
|
+
type_id = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
|
10
|
+
<% end %>
|
11
|
+
}
|
12
|
+
catch(Exiv2::Error& e) {
|
13
|
+
rb_raise(eError, "Cannot set tag %s because it doesn't exists. Look at http://www.exiv2.org/tags.html for list of supported tags", key);
|
14
|
+
}
|
15
|
+
switch(type_id) {
|
16
|
+
case Exiv2::invalidTypeId:
|
17
|
+
{
|
18
|
+
rb_warn("Trying to marshall invalid type id");
|
19
|
+
return Qnil;
|
20
|
+
}
|
21
|
+
|
22
|
+
case Exiv2::unsignedByte:
|
23
|
+
case Exiv2::unsignedShort:
|
24
|
+
case Exiv2::unsignedLong:
|
25
|
+
case Exiv2::signedShort:
|
26
|
+
case Exiv2::signedLong:
|
27
|
+
{
|
28
|
+
data[key] = NUM2INT(value);
|
29
|
+
return true;
|
30
|
+
}
|
31
|
+
|
32
|
+
case Exiv2::asciiString:
|
33
|
+
case Exiv2::string:
|
34
|
+
case Exiv2::undefined:
|
35
|
+
{
|
36
|
+
data[key] = std::string(STR(value));
|
37
|
+
return true;
|
38
|
+
}
|
39
|
+
|
40
|
+
case Exiv2::unsignedRational:
|
41
|
+
case Exiv2::signedRational:
|
42
|
+
{
|
43
|
+
if(rb_respond_to(value, rb_intern("numerator"))) {
|
44
|
+
int numerator = NUM2INT(rb_funcall(value, rb_intern("numerator"), 0));
|
45
|
+
int denominator = NUM2INT(rb_funcall(value, rb_intern("denominator"), 0));
|
46
|
+
<% if kind == "Exif" %>
|
47
|
+
data[key] = Exiv2::Rational(numerator, denominator);
|
48
|
+
<% else %>
|
49
|
+
data[key] = numerator / denominator;
|
50
|
+
<% end %>
|
51
|
+
return true;
|
52
|
+
}
|
53
|
+
<% if kind == "Exif" %>
|
54
|
+
data[key] = Exiv2::Rational(NUM2INT(value), 1);
|
55
|
+
<% else %>
|
56
|
+
data[key] = int(NUM2INT(value));
|
57
|
+
<% end %>
|
58
|
+
return true;
|
59
|
+
}
|
60
|
+
case Exiv2::date: {
|
61
|
+
int year = NUM2INT(rb_funcall(value, rb_intern("year"), 0));
|
62
|
+
int month = NUM2INT(rb_funcall(value, rb_intern("month"), 0));
|
63
|
+
int day = NUM2INT(rb_funcall(value, rb_intern("day"), 0));
|
64
|
+
data[key] = Exiv2::DateValue(year, month, day);
|
65
|
+
return true;
|
66
|
+
}
|
67
|
+
case Exiv2::time: {
|
68
|
+
int hour = NUM2INT(rb_funcall(value, rb_intern("hour"), 0));
|
69
|
+
int minute = NUM2INT(rb_funcall(value, rb_intern("min"), 0));
|
70
|
+
int second = NUM2INT(rb_funcall(value, rb_intern("sec"), 0));
|
71
|
+
data[key] = Exiv2::TimeValue(hour, minute, second);
|
72
|
+
return true;
|
73
|
+
}
|
74
|
+
|
75
|
+
case Exiv2::comment:
|
76
|
+
case Exiv2::directory:
|
77
|
+
case Exiv2::lastTypeId:
|
78
|
+
{
|
79
|
+
data[key] = std::string(STR(value));
|
80
|
+
return true;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
return false;
|
84
|
+
}
|
85
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
static VALUE exiv2_metadata_set(VALUE key, VALUE value) {
|
2
|
+
__BEGIN
|
3
|
+
rbImage* image;
|
4
|
+
Data_Get_Struct(self, rbImage, image);
|
5
|
+
|
6
|
+
VALUE strkey = rb_funcall(key, rb_intern("to_s"), 0);
|
7
|
+
|
8
|
+
if(!marshall_value(image->image-><%= kind.downcase %>Data(), STR(strkey), value)) {
|
9
|
+
THROW("Couldn't write %s", STR(strkey));
|
10
|
+
}
|
11
|
+
|
12
|
+
image->dirty = true;
|
13
|
+
return value;
|
14
|
+
__NIL_END
|
15
|
+
|
16
|
+
}
|
@@ -105,7 +105,6 @@ VALUE unmarshall_value(const Exiv2::Value& value) {
|
|
105
105
|
return rb_funcall(rb_cTime, rb_intern("utc"), 6, INT2FIX(1970), INT2FIX(1), INT2FIX(1), INT2FIX(time.hour+time.tzHour), INT2FIX(time.minute+time.tzMinute), INT2FIX(time.second));
|
106
106
|
}
|
107
107
|
|
108
|
-
case Exiv2::invalid6:
|
109
108
|
case Exiv2::comment:
|
110
109
|
case Exiv2::directory:
|
111
110
|
case Exiv2::lastTypeId:
|
data/lib/exiv2/tag.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
module Exiv2
|
2
|
+
class Tag
|
3
|
+
inline do |builder|
|
4
|
+
Exiv2.prepare_builder(builder)
|
5
|
+
builder.prefix <<-EOF
|
6
|
+
VALUE cTag;
|
7
|
+
static void tag_leave(Exiv2::TagInfo* info) {
|
8
|
+
|
9
|
+
}
|
10
|
+
|
11
|
+
static VALUE create_exiv2_tag(Exiv2::TagInfo* info) {
|
12
|
+
return Data_Wrap_Struct(cTag, 0, tag_leave, info);
|
13
|
+
}
|
14
|
+
|
15
|
+
static int iterate_tag_collection(const Exiv2::TagInfo* collection, bool to_yield = true) {
|
16
|
+
Exiv2::TagInfo* _collection = const_cast<Exiv2::TagInfo *>(collection);
|
17
|
+
int i;
|
18
|
+
for (i=0; _collection[i].tag_ != 0xffff; ++i) {
|
19
|
+
if(to_yield) {
|
20
|
+
rb_yield(create_exiv2_tag(_collection + i));
|
21
|
+
}
|
22
|
+
}
|
23
|
+
return i;
|
24
|
+
}
|
25
|
+
EOF
|
26
|
+
|
27
|
+
builder.add_to_init "cTag = c;"
|
28
|
+
|
29
|
+
builder.c_singleton <<-EOF
|
30
|
+
static VALUE each() {
|
31
|
+
__BEGIN
|
32
|
+
iterate_tag_collection(Exiv2::ExifTags::ifdTagList());
|
33
|
+
iterate_tag_collection(Exiv2::ExifTags::exifTagList());
|
34
|
+
iterate_tag_collection(Exiv2::ExifTags::iopTagList());
|
35
|
+
iterate_tag_collection(Exiv2::ExifTags::gpsTagList());
|
36
|
+
return self;
|
37
|
+
__END
|
38
|
+
}
|
39
|
+
EOF
|
40
|
+
|
41
|
+
builder.c_singleton <<-EOF
|
42
|
+
static VALUE count() {
|
43
|
+
__BEGIN
|
44
|
+
return INT2NUM(
|
45
|
+
iterate_tag_collection(Exiv2::ExifTags::ifdTagList(), false) +
|
46
|
+
iterate_tag_collection(Exiv2::ExifTags::exifTagList(), false) +
|
47
|
+
iterate_tag_collection(Exiv2::ExifTags::iopTagList(), false) +
|
48
|
+
iterate_tag_collection(Exiv2::ExifTags::gpsTagList(), false)
|
49
|
+
);
|
50
|
+
__END
|
51
|
+
}
|
52
|
+
EOF
|
53
|
+
|
54
|
+
builder.c <<-EOF
|
55
|
+
static VALUE name() {
|
56
|
+
__BEGIN
|
57
|
+
Exiv2::TagInfo* tag;
|
58
|
+
Data_Get_Struct(self, Exiv2::TagInfo, tag);
|
59
|
+
|
60
|
+
return tag->name_ ? rb_str_new2(tag->name_) : Qnil;
|
61
|
+
__END
|
62
|
+
}
|
63
|
+
EOF
|
64
|
+
|
65
|
+
builder.c <<-EOF
|
66
|
+
static VALUE title() {
|
67
|
+
__BEGIN
|
68
|
+
Exiv2::TagInfo* tag;
|
69
|
+
Data_Get_Struct(self, Exiv2::TagInfo, tag);
|
70
|
+
|
71
|
+
return tag->title_ ? rb_str_new2(tag->title_) : Qnil;
|
72
|
+
__END
|
73
|
+
}
|
74
|
+
EOF
|
75
|
+
|
76
|
+
builder.c <<-EOF
|
77
|
+
static VALUE desc() {
|
78
|
+
__BEGIN
|
79
|
+
Exiv2::TagInfo* tag;
|
80
|
+
Data_Get_Struct(self, Exiv2::TagInfo, tag);
|
81
|
+
|
82
|
+
return tag->desc_ ? rb_str_new2(tag->desc_) : Qnil;
|
83
|
+
__END
|
84
|
+
}
|
85
|
+
EOF
|
86
|
+
|
87
|
+
builder.c <<-EOF
|
88
|
+
static VALUE section() {
|
89
|
+
__BEGIN
|
90
|
+
Exiv2::TagInfo* tag;
|
91
|
+
Data_Get_Struct(self, Exiv2::TagInfo, tag);
|
92
|
+
|
93
|
+
return rb_str_new2(Exiv2::ExifTags::sectionName(tag->sectionId_));
|
94
|
+
__END
|
95
|
+
}
|
96
|
+
EOF
|
97
|
+
|
98
|
+
builder.c <<-EOF
|
99
|
+
static VALUE ifd() {
|
100
|
+
__BEGIN
|
101
|
+
Exiv2::TagInfo* tag;
|
102
|
+
Data_Get_Struct(self, Exiv2::TagInfo, tag);
|
103
|
+
|
104
|
+
return rb_str_new2(Exiv2::ExifTags::ifdName(tag->ifdId_));
|
105
|
+
__END
|
106
|
+
}
|
107
|
+
EOF
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
data/lib/exiv2/throw.cpp
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
void rb_exiv2_throw(const char *file, long unsigned int line, const char *fmt, ...) {
|
2
|
+
char* message;
|
3
|
+
va_list ap;
|
4
|
+
va_start(ap, fmt);
|
5
|
+
vasprintf(&message, fmt, ap);
|
6
|
+
va_end(ap);
|
7
|
+
|
8
|
+
char error_message[strlen(message) + 80];
|
9
|
+
snprintf(error_message, sizeof(error_message), "%s. File: %s, line: %lu", message, file, line);
|
10
|
+
free(message);
|
11
|
+
rb_raise(eError, error_message);
|
12
|
+
}
|
@@ -126,7 +126,7 @@ class ImageTest < Test::Unit::TestCase
|
|
126
126
|
assert key
|
127
127
|
assert value
|
128
128
|
end
|
129
|
-
assert_equal
|
129
|
+
assert_equal 77, i
|
130
130
|
|
131
131
|
i = 0
|
132
132
|
@img.exif.each "Exif.Fujifilm" do |key, value|
|
@@ -170,7 +170,7 @@ class ImageTest < Test::Unit::TestCase
|
|
170
170
|
|
171
171
|
def test_tag_access
|
172
172
|
return unless Exiv2::Tag.respond_to?(:count)
|
173
|
-
assert_equal
|
173
|
+
assert_equal 201, Exiv2::Tag.count
|
174
174
|
exif_tag = nil
|
175
175
|
Exiv2::Tag.each do |tag|
|
176
176
|
exif_tag = tag
|
@@ -232,4 +232,16 @@ class ImageTest < Test::Unit::TestCase
|
|
232
232
|
assert_equal 160, @img.Exif.Photo.PixelXDimension
|
233
233
|
end
|
234
234
|
end
|
235
|
+
|
236
|
+
def test_string_io
|
237
|
+
open_test_file "smiley1.jpg" do |filename|
|
238
|
+
File.open(filename, "r") {|f| @content = StringIO.new(f.read, "r+") }
|
239
|
+
assert @img = Exiv2::Image.new(@content)
|
240
|
+
assert @img.Exif
|
241
|
+
assert_equal ["Flash", "PixelXDimension", "PixelYDimension"], @img.Exif.Photo.methods
|
242
|
+
assert_equal 140, @img.Exif.Photo.PixelYDimension
|
243
|
+
assert @img.Exif.Photo.PixelXDimension = 160
|
244
|
+
assert_equal 160, @img.Exif.Photo.PixelXDimension
|
245
|
+
end
|
246
|
+
end
|
235
247
|
end
|
metadata
CHANGED
@@ -1,67 +1,77 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.0
|
3
|
-
specification_version: 1
|
4
2
|
name: ruby-exiv2
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "1.
|
7
|
-
date: 2007-04-24 00:00:00 +04:00
|
8
|
-
summary: Exiv2 (exif image tags handling) library driver
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: max@maxidoors.ru
|
12
|
-
homepage: http://maxidoors.ru/
|
13
|
-
rubyforge_project: ruby-exiv2
|
14
|
-
description:
|
15
|
-
autorequire:
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: "1.5"
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Max Lapshin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-12-02 00:00:00 +03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: max@maxidoors.ru
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
31
24
|
files:
|
32
25
|
- README
|
33
26
|
- Rakefile
|
34
|
-
- setup.rb
|
35
27
|
- init.rb
|
36
28
|
- test/data
|
37
|
-
- test/image.rb
|
38
29
|
- test/data/exiv2-fujifilm-finepix-s2pro.jpg
|
39
30
|
- test/data/gps-test.jpg
|
40
31
|
- test/data/RIA3001.jpg
|
41
32
|
- test/data/smiley1.jpg
|
42
|
-
-
|
43
|
-
-
|
44
|
-
-
|
45
|
-
-
|
46
|
-
-
|
47
|
-
- ext/extconf.rb
|
48
|
-
- ext/exiv2.hpp
|
33
|
+
- test/test_image.rb
|
34
|
+
- lib/exiv2/exif.rb
|
35
|
+
- lib/exiv2/image.rb
|
36
|
+
- lib/exiv2/iptc.rb
|
37
|
+
- lib/exiv2/tag.rb
|
49
38
|
- lib/exiv2.rb
|
50
|
-
|
51
|
-
-
|
52
|
-
|
53
|
-
-
|
54
|
-
-
|
55
|
-
-
|
56
|
-
-
|
57
|
-
-
|
58
|
-
|
59
|
-
-
|
60
|
-
|
39
|
+
- lib/exiv2/metadata/clear.cpp
|
40
|
+
- lib/exiv2/metadata/count.cpp
|
41
|
+
- lib/exiv2/metadata/delete.cpp
|
42
|
+
- lib/exiv2/metadata/each.cpp
|
43
|
+
- lib/exiv2/metadata/get.cpp
|
44
|
+
- lib/exiv2/metadata/is_empty.cpp
|
45
|
+
- lib/exiv2/metadata/marshall.cpp
|
46
|
+
- lib/exiv2/metadata/set.cpp
|
47
|
+
- lib/exiv2/metadata/unmarshall.cpp
|
48
|
+
- lib/exiv2/throw.cpp
|
49
|
+
- lib/exiv2.hpp
|
50
|
+
has_rdoc: true
|
51
|
+
homepage: http://github.com/maxlapshin/exiv2
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
61
54
|
|
62
|
-
|
63
|
-
-
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
64
69
|
requirements: []
|
65
70
|
|
66
|
-
|
67
|
-
|
71
|
+
rubyforge_project: ruby-exiv2
|
72
|
+
rubygems_version: 1.3.1
|
73
|
+
signing_key:
|
74
|
+
specification_version: 2
|
75
|
+
summary: Exiv2 (exif image tags handling) library driver
|
76
|
+
test_files:
|
77
|
+
- test/test_image.rb
|