ruby-exiv2 0.6 → 0.7
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 +9 -5
- data/Rakefile +1 -1
- data/ext/exif.cpp +68 -4
- data/ext/exiv2.hpp +1 -1
- data/ext/extconf.rb +15 -4
- data/ext/iptc.cpp +70 -6
- data/ext/marshall.cpp +32 -88
- data/lib/exiv2.rb +20 -1
- data/test/image.rb +33 -22
- metadata +4 -3
data/README
CHANGED
@@ -3,10 +3,14 @@ Library for handling exif image tags.
|
|
3
3
|
Basic usage:
|
4
4
|
|
5
5
|
> gem install ruby-exiv2
|
6
|
+
> irb -r rubygems
|
7
|
+
irb(main):001:0> require 'exiv2'
|
8
|
+
=> true
|
9
|
+
irb(main):002:0> @img = Exiv2::Image.new("a.jpg")
|
10
|
+
=> #<Exiv2::Image:0x4c524c>
|
11
|
+
irb(main):003:0> @exif = @img.exif
|
12
|
+
=> #<Exiv2::Exif:0x4bc160>
|
13
|
+
irb(main):004:0> @img.exif["Exif.Photo.PixelXDimension"]
|
14
|
+
=> 1024
|
6
15
|
|
7
16
|
|
8
|
-
require 'exiv2'
|
9
|
-
@img = Exiv2::Image.new("a.jpg")
|
10
|
-
@exif = @img.exif
|
11
|
-
puts @img.exif["Exif.Photo.PixelXDimension"]
|
12
|
-
=> 3024
|
data/Rakefile
CHANGED
data/ext/exif.cpp
CHANGED
@@ -1,5 +1,71 @@
|
|
1
1
|
#include "exiv2.hpp"
|
2
2
|
|
3
|
+
/*
|
4
|
+
* First, I have to get out type by key. If such key is forbidden, I will refuse to marshall it.
|
5
|
+
* Then, I will cast ruby VALUE to C++ value, according to type_id
|
6
|
+
* then I will just set apropreciated hash entry to this casted value
|
7
|
+
*/
|
8
|
+
static bool marshall_value(Exiv2::ExifData &data, const char* key, VALUE value) {
|
9
|
+
Exiv2::TypeId type_id;
|
10
|
+
try {
|
11
|
+
Exiv2::ExifKey exif_key(key);
|
12
|
+
type_id = Exiv2::ExifTags::tagType(exif_key.tag(), exif_key.ifdId());
|
13
|
+
}
|
14
|
+
catch(Exiv2::Error& e) {
|
15
|
+
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);
|
16
|
+
}
|
17
|
+
switch(type_id) {
|
18
|
+
case Exiv2::invalidTypeId:
|
19
|
+
{
|
20
|
+
rb_warn("Trying to marshall invalid type id");
|
21
|
+
return Qnil;
|
22
|
+
}
|
23
|
+
|
24
|
+
case Exiv2::unsignedByte:
|
25
|
+
case Exiv2::unsignedShort:
|
26
|
+
case Exiv2::unsignedLong:
|
27
|
+
case Exiv2::signedShort:
|
28
|
+
case Exiv2::signedLong:
|
29
|
+
{
|
30
|
+
data[key] = NUM2INT(value);
|
31
|
+
return true;
|
32
|
+
}
|
33
|
+
|
34
|
+
case Exiv2::asciiString:
|
35
|
+
case Exiv2::string:
|
36
|
+
case Exiv2::undefined:
|
37
|
+
{
|
38
|
+
data[key] = std::string(STR(value));
|
39
|
+
return true;
|
40
|
+
}
|
41
|
+
|
42
|
+
case Exiv2::unsignedRational:
|
43
|
+
case Exiv2::signedRational:
|
44
|
+
{
|
45
|
+
if(rb_respond_to(value, rb_intern("numerator"))) {
|
46
|
+
int numerator = NUM2INT(rb_funcall(value, rb_intern("numerator"), 0));
|
47
|
+
int denominator = NUM2INT(rb_funcall(value, rb_intern("denominator"), 0));
|
48
|
+
data[key] = Exiv2::Rational(numerator, denominator);
|
49
|
+
return true;
|
50
|
+
}
|
51
|
+
data[key] = Exiv2::Rational(NUM2INT(value), 1);
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
|
55
|
+
case Exiv2::invalid6:
|
56
|
+
case Exiv2::date:
|
57
|
+
case Exiv2::time:
|
58
|
+
case Exiv2::comment:
|
59
|
+
case Exiv2::directory:
|
60
|
+
case Exiv2::lastTypeId:
|
61
|
+
{
|
62
|
+
data[key] = std::string(STR(value));
|
63
|
+
return true;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
return false;
|
67
|
+
}
|
68
|
+
|
3
69
|
|
4
70
|
|
5
71
|
|
@@ -42,9 +108,8 @@ static VALUE exiv2_exif_set(VALUE self, VALUE key, VALUE value) {
|
|
42
108
|
Data_Get_Struct(self, rbImage, image);
|
43
109
|
|
44
110
|
VALUE strkey = rb_funcall(key, rb_intern("to_s"), 0);
|
45
|
-
Exiv2::ExifData &exifData = image->image->exifData();
|
46
111
|
|
47
|
-
if(!marshall_value(exifData, STR(strkey), value)) {
|
112
|
+
if(!marshall_value(image->image->exifData(), STR(strkey), value)) {
|
48
113
|
THROW("Couldn't write %s", STR(strkey));
|
49
114
|
}
|
50
115
|
|
@@ -157,7 +222,7 @@ static VALUE exiv2_exif_empty(VALUE self) {
|
|
157
222
|
}
|
158
223
|
|
159
224
|
|
160
|
-
|
225
|
+
#ifdef HAVE_IFDTAGLIST
|
161
226
|
static void tag_leave(Exiv2::TagInfo* info) {
|
162
227
|
|
163
228
|
}
|
@@ -177,7 +242,6 @@ static int iterate_tag_collection(const Exiv2::TagInfo* collection, bool to_yiel
|
|
177
242
|
return i;
|
178
243
|
}
|
179
244
|
|
180
|
-
#ifdef HAVE_IFDTAGLIST
|
181
245
|
static VALUE exiv2_tags_each(VALUE self) {
|
182
246
|
__BEGIN
|
183
247
|
iterate_tag_collection(Exiv2::ExifTags::ifdTagList());
|
data/ext/exiv2.hpp
CHANGED
@@ -102,9 +102,9 @@ struct rbImage {
|
|
102
102
|
Exiv2::Image::AutoPtr image;
|
103
103
|
};
|
104
104
|
|
105
|
-
bool marshall_value(Exiv2::ExifData &exifData, const char* key, VALUE value);
|
106
105
|
VALUE unmarshall_value(const Exiv2::Value& value);
|
107
106
|
|
107
|
+
|
108
108
|
void Init_image();
|
109
109
|
void Init_exif();
|
110
110
|
void Init_iptc();
|
data/ext/extconf.rb
CHANGED
@@ -1,14 +1,25 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "mkmf"
|
4
|
+
require 'optparse'
|
4
5
|
CONFIG["CPP"] = "g++ -E "
|
5
6
|
CONFIG["CC"] = "g++ "
|
7
|
+
CONFIG["LDSHARED"].gsub!(/^cc /,"g++ ")
|
8
|
+
|
9
|
+
|
10
|
+
$CPPFLAGS << " -Wall -I/usr/include/exiv2 "
|
11
|
+
$LDFLAGS << " -lstdc++ "
|
12
|
+
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
opts.on("-E PATH", "--exiv2-dir=PATH", "Prefix, where libexiv2 is installed: /usr/local") do |path|
|
15
|
+
$LDFLAGS << "-L" + path + "/lib "
|
16
|
+
$CPPFLAGS << "-I" + path + "/include "
|
17
|
+
$CPPFLAGS << "-I" + path + "/include/exiv2 "
|
18
|
+
end
|
19
|
+
opts.parse!(ARGV.include?("--") ? ARGV[ARGV.index("--")+1..-1] : ARGV.clone)
|
20
|
+
end
|
6
21
|
|
7
22
|
|
8
|
-
#
|
9
|
-
# -I/usr/local/include/exiv2
|
10
|
-
$CPPFLAGS << " -Wall -I/usr/include/exiv2 -I/Users/max/Sites/exif/include/exiv2 "
|
11
|
-
$LDFLAGS << " -lstdc++ -L/Users/max/Sites/exif/lib "
|
12
23
|
have_header "exif.hpp"
|
13
24
|
|
14
25
|
|
data/ext/iptc.cpp
CHANGED
@@ -1,5 +1,70 @@
|
|
1
1
|
#include "exiv2.hpp"
|
2
2
|
|
3
|
+
/*
|
4
|
+
* First, I have to get out type by key. If such key is forbidden, I will refuse to marshall it.
|
5
|
+
* Then, I will cast ruby VALUE to C++ value, according to type_id
|
6
|
+
* then I will just set apropreciated hash entry to this casted value
|
7
|
+
*/
|
8
|
+
static bool marshall_value(Exiv2::IptcData &data, const char* key, VALUE value) {
|
9
|
+
Exiv2::TypeId type_id;
|
10
|
+
try {
|
11
|
+
Exiv2::IptcKey iptcKey(key);
|
12
|
+
type_id = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
|
13
|
+
}
|
14
|
+
catch(Exiv2::Error& e) {
|
15
|
+
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);
|
16
|
+
}
|
17
|
+
switch(type_id) {
|
18
|
+
case Exiv2::invalidTypeId:
|
19
|
+
{
|
20
|
+
rb_warn("Trying to marshall invalid type id");
|
21
|
+
return Qnil;
|
22
|
+
}
|
23
|
+
|
24
|
+
case Exiv2::unsignedByte:
|
25
|
+
case Exiv2::unsignedShort:
|
26
|
+
case Exiv2::unsignedLong:
|
27
|
+
case Exiv2::signedShort:
|
28
|
+
case Exiv2::signedLong:
|
29
|
+
{
|
30
|
+
data[key] = NUM2INT(value);
|
31
|
+
return true;
|
32
|
+
}
|
33
|
+
|
34
|
+
case Exiv2::asciiString:
|
35
|
+
case Exiv2::string:
|
36
|
+
case Exiv2::undefined:
|
37
|
+
{
|
38
|
+
data[key] = std::string(STR(value));
|
39
|
+
return true;
|
40
|
+
}
|
41
|
+
|
42
|
+
case Exiv2::unsignedRational:
|
43
|
+
case Exiv2::signedRational:
|
44
|
+
{
|
45
|
+
if(rb_respond_to(value, rb_intern("numerator"))) {
|
46
|
+
int numerator = NUM2INT(rb_funcall(value, rb_intern("numerator"), 0));
|
47
|
+
int denominator = NUM2INT(rb_funcall(value, rb_intern("denominator"), 0));
|
48
|
+
data[key] = numerator / denominator;
|
49
|
+
return true;
|
50
|
+
}
|
51
|
+
data[key] = int(NUM2INT(value));
|
52
|
+
return true;
|
53
|
+
}
|
54
|
+
|
55
|
+
case Exiv2::invalid6:
|
56
|
+
case Exiv2::date:
|
57
|
+
case Exiv2::time:
|
58
|
+
case Exiv2::comment:
|
59
|
+
case Exiv2::directory:
|
60
|
+
case Exiv2::lastTypeId:
|
61
|
+
{
|
62
|
+
data[key] = std::string(STR(value));
|
63
|
+
return true;
|
64
|
+
}
|
65
|
+
}
|
66
|
+
return false;
|
67
|
+
}
|
3
68
|
|
4
69
|
|
5
70
|
/*
|
@@ -29,7 +94,7 @@ static VALUE exiv2_iptc_get(VALUE self, VALUE key) {
|
|
29
94
|
__NIL_END
|
30
95
|
}
|
31
96
|
|
32
|
-
#if
|
97
|
+
#if 1
|
33
98
|
/*
|
34
99
|
* @iptc["Iptc.Application2.ObjectName"] = "GreeenDude"
|
35
100
|
* [] — is a universal accessor
|
@@ -40,15 +105,15 @@ static VALUE exiv2_iptc_set(VALUE self, VALUE key, VALUE value) {
|
|
40
105
|
Data_Get_Struct(self, rbImage, image);
|
41
106
|
|
42
107
|
VALUE strkey = rb_funcall(key, rb_intern("to_s"), 0);
|
43
|
-
Exiv2::IptcData &iptcData = image->image->iptcData();
|
44
108
|
|
45
|
-
if(!marshall_value(iptcData, STR(strkey), value)) {
|
109
|
+
if(!marshall_value(image->image->iptcData(), STR(strkey), value)) {
|
46
110
|
THROW("Couldn't write %s", STR(strkey));
|
47
111
|
}
|
48
112
|
|
49
113
|
image->dirty = true;
|
50
114
|
return value;
|
51
115
|
__NIL_END
|
116
|
+
|
52
117
|
}
|
53
118
|
#endif
|
54
119
|
|
@@ -72,7 +137,6 @@ static VALUE exiv2_iptc_each(int argc, VALUE *argv, VALUE self) {
|
|
72
137
|
for(Exiv2::IptcData::const_iterator i = iptcData.begin(); i != end; ++i) {
|
73
138
|
VALUE key = rb_str_new(i->key().c_str(), i->key().length());
|
74
139
|
VALUE val = unmarshall_value(i->value());
|
75
|
-
//VALUE val = rb_str_new(i->toString().c_str(), i->toString().length());
|
76
140
|
if(prefix != Qnil && INT2FIX(0) != rb_funcall(key, rb_intern("index"), 1, prefix)) {
|
77
141
|
continue;
|
78
142
|
}
|
@@ -82,7 +146,7 @@ static VALUE exiv2_iptc_each(int argc, VALUE *argv, VALUE self) {
|
|
82
146
|
__END
|
83
147
|
}
|
84
148
|
|
85
|
-
#if
|
149
|
+
#if 1
|
86
150
|
/*
|
87
151
|
* Delete iptc value by it's name
|
88
152
|
*/
|
@@ -165,7 +229,7 @@ void Init_iptc() {
|
|
165
229
|
cIptc = rb_define_class_under(mExiv2, "Iptc", rb_cObject);
|
166
230
|
rb_define_method(cIptc, "each", VALUEFUNC(exiv2_iptc_each), -1);
|
167
231
|
rb_define_method(cIptc, "[]", VALUEFUNC(exiv2_iptc_get), 1);
|
168
|
-
#if
|
232
|
+
#if 1
|
169
233
|
rb_define_method(cIptc, "[]=", VALUEFUNC(exiv2_iptc_set), 2);
|
170
234
|
rb_define_method(cIptc, "delete", VALUEFUNC(exiv2_iptc_delete), 1);
|
171
235
|
#endif
|
data/ext/marshall.cpp
CHANGED
@@ -1,42 +1,48 @@
|
|
1
1
|
#include "exiv2.hpp"
|
2
2
|
|
3
3
|
|
4
|
-
|
4
|
+
class Unmarshaller {
|
5
|
+
public:
|
6
|
+
virtual VALUE unmarshall(const Exiv2::Value& value, long pos = 0) = 0;
|
7
|
+
virtual ~Unmarshaller() {};
|
8
|
+
};
|
5
9
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
static VALUE unmarshall_rational_value(const Exiv2::Value& value, long pos = 0) {
|
12
|
-
Exiv2::Rational r = value.toRational(pos);
|
13
|
-
ID rational_id = rb_intern("Rational");
|
14
|
-
if(rb_const_defined(rb_cObject, rational_id)) {
|
15
|
-
VALUE rational = rb_const_get(rb_cObject, rational_id);
|
16
|
-
return rb_funcall(rational, rb_intern("new!"), 2, INT2NUM(r.first), INT2NUM(r.second));
|
10
|
+
class unmarshall_long_value : public Unmarshaller {
|
11
|
+
public:
|
12
|
+
virtual VALUE unmarshall(const Exiv2::Value& value, long pos = 0) {
|
13
|
+
return INT2NUM(value.toLong(pos));
|
17
14
|
}
|
18
|
-
|
19
|
-
|
20
|
-
}
|
15
|
+
};
|
21
16
|
|
17
|
+
class unmarshall_rational_value : public Unmarshaller {
|
18
|
+
public:
|
19
|
+
virtual VALUE unmarshall(const Exiv2::Value& value, long pos = 0) {
|
20
|
+
Exiv2::Rational r = value.toRational(pos);
|
21
|
+
ID rational_id = rb_intern("Rational");
|
22
|
+
if(rb_const_defined(rb_cObject, rational_id)) {
|
23
|
+
VALUE rational = rb_const_get(rb_cObject, rational_id);
|
24
|
+
return rb_funcall(rational, rb_intern("new!"), 2, INT2NUM(r.first), INT2NUM(r.second));
|
25
|
+
}
|
26
|
+
return INT2NUM(r.first/r.second);
|
27
|
+
}
|
28
|
+
};
|
22
29
|
|
23
|
-
static VALUE unmarshall_multiple_values(const Exiv2::Value& value,
|
30
|
+
static VALUE unmarshall_multiple_values(const Exiv2::Value& value, Unmarshaller& f) {
|
24
31
|
if(value.count() <= 0) {
|
25
32
|
rb_warn("Empty value (no entries)");
|
26
33
|
return Qnil;
|
27
34
|
}
|
28
|
-
|
35
|
+
|
29
36
|
|
30
37
|
if(value.count() == 1) {
|
31
|
-
return f(value);
|
38
|
+
return f.unmarshall(value);
|
32
39
|
}
|
33
|
-
|
40
|
+
|
34
41
|
VALUE retval = rb_ary_new2(value.count());
|
35
42
|
for(int i = 0; i < value.count(); i++) {
|
36
|
-
rb_ary_store(retval, i, f(value, i));
|
43
|
+
rb_ary_store(retval, i, f.unmarshall(value, i));
|
37
44
|
}
|
38
45
|
return retval;
|
39
|
-
|
40
46
|
}
|
41
47
|
|
42
48
|
|
@@ -59,7 +65,8 @@ VALUE unmarshall_value(const Exiv2::Value& value) {
|
|
59
65
|
case Exiv2::signedShort:
|
60
66
|
case Exiv2::signedLong:
|
61
67
|
{
|
62
|
-
|
68
|
+
unmarshall_long_value m;
|
69
|
+
return unmarshall_multiple_values(value, m);
|
63
70
|
}
|
64
71
|
|
65
72
|
case Exiv2::asciiString:
|
@@ -73,7 +80,8 @@ VALUE unmarshall_value(const Exiv2::Value& value) {
|
|
73
80
|
case Exiv2::unsignedRational:
|
74
81
|
case Exiv2::signedRational:
|
75
82
|
{
|
76
|
-
|
83
|
+
unmarshall_rational_value m;
|
84
|
+
return unmarshall_multiple_values(value, m);
|
77
85
|
|
78
86
|
Exiv2::Rational r = value.toRational();
|
79
87
|
ID rational_id = rb_intern("Rational");
|
@@ -103,68 +111,4 @@ VALUE unmarshall_value(const Exiv2::Value& value) {
|
|
103
111
|
return Qfalse;
|
104
112
|
}
|
105
113
|
|
106
|
-
|
107
|
-
* First, I have to get out type by key. If such key is forbidden, I will refuse to marshall it.
|
108
|
-
* Then, I will cast ruby VALUE to C++ value, according to type_id
|
109
|
-
* then I will just set apropreciated hash entry to this casted value
|
110
|
-
*/
|
111
|
-
bool marshall_value(Exiv2::ExifData &exifData, const char* key, VALUE value) {
|
112
|
-
Exiv2::TypeId type_id;
|
113
|
-
try {
|
114
|
-
Exiv2::ExifKey exif_key(key);
|
115
|
-
type_id = Exiv2::ExifTags::tagType(exif_key.tag(), exif_key.ifdId());
|
116
|
-
}
|
117
|
-
catch(Exiv2::Error& e) {
|
118
|
-
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);
|
119
|
-
}
|
120
|
-
switch(type_id) {
|
121
|
-
case Exiv2::invalidTypeId:
|
122
|
-
{
|
123
|
-
rb_warn("Trying to marshall invalid type id");
|
124
|
-
return Qnil;
|
125
|
-
}
|
126
|
-
|
127
|
-
case Exiv2::unsignedByte:
|
128
|
-
case Exiv2::unsignedShort:
|
129
|
-
case Exiv2::unsignedLong:
|
130
|
-
case Exiv2::signedShort:
|
131
|
-
case Exiv2::signedLong:
|
132
|
-
{
|
133
|
-
exifData[key] = NUM2INT(value);
|
134
|
-
return true;
|
135
|
-
}
|
136
|
-
|
137
|
-
case Exiv2::asciiString:
|
138
|
-
case Exiv2::string:
|
139
|
-
case Exiv2::undefined:
|
140
|
-
{
|
141
|
-
exifData[key] = std::string(STR(value));
|
142
|
-
return true;
|
143
|
-
}
|
144
|
-
|
145
|
-
case Exiv2::unsignedRational:
|
146
|
-
case Exiv2::signedRational:
|
147
|
-
{
|
148
|
-
if(rb_respond_to(value, rb_intern("numerator"))) {
|
149
|
-
int numerator = NUM2INT(rb_funcall(value, rb_intern("numerator"), 0));
|
150
|
-
int denominator = NUM2INT(rb_funcall(value, rb_intern("denominator"), 0));
|
151
|
-
exifData[key] = Exiv2::Rational(numerator, denominator);
|
152
|
-
return true;
|
153
|
-
}
|
154
|
-
exifData[key] = Exiv2::Rational(NUM2INT(value), 1);
|
155
|
-
return true;
|
156
|
-
}
|
157
|
-
|
158
|
-
case Exiv2::invalid6:
|
159
|
-
case Exiv2::date:
|
160
|
-
case Exiv2::time:
|
161
|
-
case Exiv2::comment:
|
162
|
-
case Exiv2::directory:
|
163
|
-
case Exiv2::lastTypeId:
|
164
|
-
{
|
165
|
-
exifData[key] = std::string(STR(value));
|
166
|
-
return true;
|
167
|
-
}
|
168
|
-
}
|
169
|
-
return false;
|
170
|
-
}
|
114
|
+
|
data/lib/exiv2.rb
CHANGED
@@ -1,2 +1,21 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require File.dirname(__FILE__)+'/exiv2_bin'
|
3
|
+
rescue LoadError
|
4
|
+
require File.dirname(__FILE__)+'/../ext/exiv2_bin'
|
5
|
+
end
|
2
6
|
|
7
|
+
module Exiv2
|
8
|
+
class Image
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
return exif[key] if key[0...4] == "Exif"
|
12
|
+
return iptc[key] if key[0...4] == "Iptc"
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(key, value)
|
16
|
+
return exif[key] = value if key[0...4] == "Exif"
|
17
|
+
return iptc[key] = value if key[0...4] == "Iptc"
|
18
|
+
raise Exiv2::Error, "Unknown key for writing: #{key.inspect}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/test/image.rb
CHANGED
@@ -25,56 +25,56 @@ class ImageTest < Test::Unit::TestCase
|
|
25
25
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
26
26
|
open(filename) do |image_file|
|
27
27
|
assert @img = Exiv2::Image.new(image_file), "Image should be opened from IO::File"
|
28
|
-
assert_equal "FinePixS2Pro", @img
|
29
|
-
assert_equal nil, @img
|
28
|
+
assert_equal "FinePixS2Pro", @img["Exif.Image.Model"]
|
29
|
+
assert_equal nil, @img["zeze"]
|
30
30
|
assert_raise(Exiv2::Error, "Setting of invalid tag should raise an exception") do
|
31
|
-
@img
|
31
|
+
@img["zeze"] = "lala"
|
32
32
|
end
|
33
|
-
assert_equal 3024, @img
|
33
|
+
assert_equal 3024, @img["Exif.Photo.PixelXDimension"]
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
38
38
|
assert @img = Exiv2::Image.new(filename), "Image should be opened from filename"
|
39
|
-
assert_equal "FinePixS2Pro", @img
|
40
|
-
assert_equal nil, @img
|
41
|
-
assert_equal 3024, @img
|
39
|
+
assert_equal "FinePixS2Pro", @img["Exif.Image.Model"]
|
40
|
+
assert_equal nil, @img["zeze"]
|
41
|
+
assert_equal 3024, @img["Exif.Photo.PixelXDimension"]
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
def test_write_string
|
46
46
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
47
47
|
assert @img = Exiv2::Image.new(filename)
|
48
|
-
assert_equal "FinePixS2Pro", @img
|
49
|
-
assert_equal "*istDs", @img
|
48
|
+
assert_equal "FinePixS2Pro", @img["Exif.Image.Model"]
|
49
|
+
assert_equal "*istDs", @img["Exif.Image.Model"] = "*istDs"
|
50
50
|
assert @img.save
|
51
51
|
|
52
52
|
assert @img = Exiv2::Image.new(filename)
|
53
|
-
assert_equal "*istDs", @img
|
53
|
+
assert_equal "*istDs", @img["Exif.Image.Model"]
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
57
|
def test_write_int
|
58
58
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
59
59
|
assert @img = Exiv2::Image.new(filename)
|
60
|
-
assert_equal 3024, @img
|
61
|
-
assert_equal 25, @img
|
60
|
+
assert_equal 3024, @img["Exif.Photo.PixelXDimension"]
|
61
|
+
assert_equal 25, @img["Exif.Photo.PixelXDimension"] = 25
|
62
62
|
assert @img.save
|
63
63
|
|
64
64
|
assert @img = Exiv2::Image.new(filename)
|
65
|
-
assert_equal 25, @img
|
65
|
+
assert_equal 25, @img["Exif.Photo.PixelXDimension"]
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
def test_write_rational
|
70
70
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
71
71
|
assert @img = Exiv2::Image.new(filename)
|
72
|
-
assert_equal Rational.new!(72, 1), @img
|
73
|
-
assert_equal Rational.new!(27, 11), @img
|
72
|
+
assert_equal Rational.new!(72, 1), @img["Exif.Image.XResolution"]
|
73
|
+
assert_equal Rational.new!(27, 11), @img["Exif.Image.XResolution"] = Rational.new!(27, 11)
|
74
74
|
assert @img.save
|
75
75
|
|
76
76
|
assert @img = Exiv2::Image.new(filename)
|
77
|
-
assert_equal Rational.new!(27, 11), @img
|
77
|
+
assert_equal Rational.new!(27, 11), @img["Exif.Image.XResolution"]
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
@@ -84,7 +84,7 @@ class ImageTest < Test::Unit::TestCase
|
|
84
84
|
assert @img = Exiv2::Image.new(filename)
|
85
85
|
|
86
86
|
assert_raise(TypeError, "Setting of non-convertable values should raise an TypeError") do
|
87
|
-
@img
|
87
|
+
@img["Exif.Image.XResolution"] = "lala"
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
@@ -141,14 +141,14 @@ class ImageTest < Test::Unit::TestCase
|
|
141
141
|
def test_read_undefined
|
142
142
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
143
143
|
assert @img = Exiv2::Image.new(filename)
|
144
|
-
assert_equal "48 49 48 48 ", @img
|
144
|
+
assert_equal "48 49 48 48 ", @img["Exif.Iop.InteroperabilityVersion"]
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
148
|
def test_read_ascii
|
149
149
|
open_test_file "exiv2-fujifilm-finepix-s2pro.jpg" do |filename|
|
150
150
|
assert @img = Exiv2::Image.new(filename)
|
151
|
-
assert_equal "R98", @img
|
151
|
+
assert_equal "R98", @img["Exif.Iop.InteroperabilityIndex"]
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -163,8 +163,8 @@ class ImageTest < Test::Unit::TestCase
|
|
163
163
|
open_test_file "gps-test.jpg" do |filename|
|
164
164
|
assert @img = Exiv2::Image.new(filename)
|
165
165
|
require 'rational'
|
166
|
-
assert_equal [Rational.new!(41, 1), Rational.new!(53, 1), Rational.new!(4091, 100)], @img
|
167
|
-
assert_equal [Rational.new!(12, 1), Rational.new!(28, 1), Rational.new!(5996, 100)], @img
|
166
|
+
assert_equal [Rational.new!(41, 1), Rational.new!(53, 1), Rational.new!(4091, 100)], @img["Exif.GPSInfo.GPSLatitude"]
|
167
|
+
assert_equal [Rational.new!(12, 1), Rational.new!(28, 1), Rational.new!(5996, 100)], @img["Exif.GPSInfo.GPSLongitude"]
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
@@ -186,7 +186,18 @@ class ImageTest < Test::Unit::TestCase
|
|
186
186
|
def test_iptc_get
|
187
187
|
open_test_file "smiley1.jpg" do |filename|
|
188
188
|
assert @img = Exiv2::Image.new(filename)
|
189
|
-
assert_equal "Seattle", @img
|
189
|
+
assert_equal "Seattle", @img["Iptc.Application2.City"]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_iptc_get
|
194
|
+
open_test_file "smiley1.jpg" do |filename|
|
195
|
+
assert @img = Exiv2::Image.new(filename)
|
196
|
+
assert_equal "Moscow", @img["Iptc.Application2.City"] = "Moscow"
|
197
|
+
assert @img.save
|
198
|
+
|
199
|
+
assert @img = Exiv2::Image.new(filename)
|
200
|
+
assert_equal "Moscow", @img["Iptc.Application2.City"]
|
190
201
|
end
|
191
202
|
end
|
192
203
|
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-exiv2
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: "0.
|
7
|
-
date: 2007-
|
6
|
+
version: "0.7"
|
7
|
+
date: 2007-02-19 00:00:00 +03:00
|
8
8
|
summary: Exiv2 (exif image tags handling) library driver
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- Max Lapshin
|
30
31
|
files:
|