exiv2 0.0.8 → 0.0.9
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +9 -0
- data/Gemfile.lock +20 -12
- data/README.md +116 -0
- data/ext/exiv2/exiv2.cpp +218 -220
- data/ext/exiv2/extconf.rb +6 -0
- data/lib/exiv2/version.rb +1 -1
- data/spec/exiv2_spec.rb +45 -45
- metadata +25 -26
- data/README.rdoc +0 -68
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 700d9adb55ce3e0eb64fa2f2f8749c607e22ebd896e82b92142c4a901f8c2f99
|
4
|
+
data.tar.gz: f74dc692a5e857177623ff7d62c88bd7f3dfb6e7e717fd47c9a05dbc6b921f2b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '025834b98bb969965ce0a4a0b87df41f5bb4c193cf16297753f4bfc8ca45ab94c6048f81e6429e53f1dcb90e73bfdada4a39da8b1a816c594bf1767ae8ca7b82'
|
7
|
+
data.tar.gz: 7b3f1468e28087b2f7b369a6b7b660656f31aef57b93ac048ad1f8333256f61c629a30d95834f2f50001b9720ebf2075110ab3b9b275923a5a9fa5be0fe5013f
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,23 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
exiv2 (0.0.
|
4
|
+
exiv2 (0.0.9)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.
|
10
|
-
rake (
|
11
|
-
rake-compiler (0.
|
9
|
+
diff-lcs (1.2.5)
|
10
|
+
rake (10.4.2)
|
11
|
+
rake-compiler (0.9.5)
|
12
12
|
rake
|
13
|
-
rspec (
|
14
|
-
rspec-core (~>
|
15
|
-
rspec-expectations (~>
|
16
|
-
rspec-mocks (~>
|
17
|
-
rspec-core (
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
rspec (3.4.0)
|
14
|
+
rspec-core (~> 3.4.0)
|
15
|
+
rspec-expectations (~> 3.4.0)
|
16
|
+
rspec-mocks (~> 3.4.0)
|
17
|
+
rspec-core (3.4.1)
|
18
|
+
rspec-support (~> 3.4.0)
|
19
|
+
rspec-expectations (3.4.0)
|
20
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
21
|
+
rspec-support (~> 3.4.0)
|
22
|
+
rspec-mocks (3.4.0)
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
+
rspec-support (~> 3.4.0)
|
25
|
+
rspec-support (3.4.1)
|
21
26
|
|
22
27
|
PLATFORMS
|
23
28
|
ruby
|
@@ -26,3 +31,6 @@ DEPENDENCIES
|
|
26
31
|
exiv2!
|
27
32
|
rake-compiler
|
28
33
|
rspec
|
34
|
+
|
35
|
+
BUNDLED WITH
|
36
|
+
1.10.6
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# Exiv2
|
2
|
+
|
3
|
+
[](https://travis-ci.org/envato/exiv2)
|
4
|
+
|
5
|
+
A simple wrapper around the C++ Exiv2 libary for reading and writing image metadata.
|
6
|
+
|
7
|
+
See http://www.exiv2.org/
|
8
|
+
|
9
|
+
Requires that the exiv2 C++ library is installed.
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```
|
14
|
+
gem install exiv2
|
15
|
+
```
|
16
|
+
|
17
|
+
if you get errors with header could not be found below:
|
18
|
+
|
19
|
+
```
|
20
|
+
exiv2.cpp:1:10: fatal error: 'exiv2/image.hpp' file not found
|
21
|
+
#include "exiv2/image.hpp"
|
22
|
+
```
|
23
|
+
|
24
|
+
please explicitly declare the header path
|
25
|
+
|
26
|
+
```
|
27
|
+
gem install exiv2 -- --with-exiv2-include="${EXIV2_PREFIX}/include" --with-exiv2-lib="${EXIV2_PREFIX}/lib"
|
28
|
+
```
|
29
|
+
|
30
|
+
on OSX with Homebrew's exiv2, the `EXIV2_PREFIX` can be set:
|
31
|
+
|
32
|
+
```
|
33
|
+
export EXIV2_PREFIX=$(brew --prefix exiv2)
|
34
|
+
```
|
35
|
+
|
36
|
+
If you get this error while trying to install as part of a bundle install, you can set these paths using:
|
37
|
+
```
|
38
|
+
bundle config build.exiv2 --with-exiv2-include="${EXIV2_PREFIX}/include" --with-exiv2-lib="${EXIV2_PREFIX}/lib"
|
39
|
+
```
|
40
|
+
|
41
|
+
|
42
|
+
If you are on new version of Command Line Tool (that is newer than 6.2, and bump into following error:
|
43
|
+
|
44
|
+
```
|
45
|
+
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:341:10: fatal error: '__debug' file not found
|
46
|
+
#include <__debug>
|
47
|
+
```
|
48
|
+
|
49
|
+
You can follow the quick hack by touching a new file `/Library/Developer/CommandLineTools/usr/include/c++/v1/__debug` with content:
|
50
|
+
|
51
|
+
```
|
52
|
+
#ifndef _LIBCPP_ASSERT
|
53
|
+
#define _LIBCPP_ASSERT(...) ((void)0)
|
54
|
+
#endif
|
55
|
+
```
|
56
|
+
|
57
|
+
Once everything is successfully installed, you can give it a go:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
require 'exiv2'
|
61
|
+
image = Exiv2::ImageFactory.open("image.jpg")
|
62
|
+
image.read_metadata
|
63
|
+
image.iptc_data.each do |key, value|
|
64
|
+
puts "#{key} = #{value}\n"
|
65
|
+
end
|
66
|
+
image.exif_data.each { ... }
|
67
|
+
image.xmp_data.each { ... }
|
68
|
+
|
69
|
+
iptc_data_hash = image.iptc_data.to_hash
|
70
|
+
xmp_data_hash = image.xmp_data.to_hash
|
71
|
+
|
72
|
+
image.exif_data.delete("Exif.Image.Software")
|
73
|
+
image.iptc_data.delete_all("Iptc.Application2.Keywords")
|
74
|
+
|
75
|
+
image.iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
76
|
+
image.iptc_data.add("Iptc.Application2.Keywords", "fishy")
|
77
|
+
|
78
|
+
image.write_metadata
|
79
|
+
```
|
80
|
+
|
81
|
+
## Why?
|
82
|
+
|
83
|
+
None of the existing Ruby libraries for reading and writing image metadata did quite what
|
84
|
+
we wanted, so we figured it wouldn't be too hard to wrap enough of Exiv2 to
|
85
|
+
meet our needs.
|
86
|
+
|
87
|
+
The intention is to just mirror the Exiv2 API in Ruby, so the path to extending
|
88
|
+
this to support more of Exiv2's functionality should be straightforward. Patches
|
89
|
+
are welcome.
|
90
|
+
|
91
|
+
## Compatibility
|
92
|
+
|
93
|
+
Tested on 2.4.x, 2.5.x and 2.6.x with Exiv2 0.27.1
|
94
|
+
|
95
|
+
## Developing
|
96
|
+
|
97
|
+
* Fork the project.
|
98
|
+
* Make your feature addition or bug fix.
|
99
|
+
* Add tests for it. This is important so I don't break it in a
|
100
|
+
future version unintentionally.
|
101
|
+
* Commit, do not mess with rakefile, version, or history.
|
102
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
103
|
+
* Send me a pull request. Bonus points for topic branches.
|
104
|
+
|
105
|
+
## Status
|
106
|
+
|
107
|
+
In early development. Very little of Exiv2's API is supported, and it hasn't
|
108
|
+
been heavily tested.
|
109
|
+
|
110
|
+
## Contributors
|
111
|
+
|
112
|
+
Pete Yandell, Mark Turnley, Lucas Parry, Norbert Wojtwoicz, Jan Graichen, John Barton
|
113
|
+
|
114
|
+
## Copyright
|
115
|
+
|
116
|
+
Copyright (c) 2014 Envato & Pete Yandell. See LICENSE for details.
|
data/ext/exiv2/exiv2.cpp
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#include "exiv2/image.hpp"
|
2
|
+
#include "exiv2/error.hpp"
|
2
3
|
#include "ruby.h"
|
3
4
|
|
4
5
|
// Create a Ruby string from a C++ std::string.
|
@@ -34,261 +35,258 @@ static VALUE metadata_each(VALUE self) {
|
|
34
35
|
return Qnil;
|
35
36
|
}
|
36
37
|
|
38
|
+
typedef VALUE (*Method)(...);
|
37
39
|
|
38
|
-
|
39
|
-
typedef VALUE (*Method)(...);
|
40
|
-
|
41
|
-
static VALUE exiv2_module;
|
42
|
-
|
43
|
-
static VALUE basic_error_class;
|
44
|
-
|
45
|
-
static VALUE image_class;
|
46
|
-
static void image_free(Exiv2::Image* image);
|
47
|
-
static VALUE image_read_metadata(VALUE self);
|
48
|
-
static VALUE image_write_metadata(VALUE self);
|
49
|
-
static VALUE image_iptc_data(VALUE self);
|
50
|
-
static VALUE image_xmp_data(VALUE self);
|
51
|
-
static VALUE image_exif_data(VALUE self);
|
52
|
-
|
53
|
-
static VALUE image_factory_class;
|
54
|
-
static VALUE image_factory_open(VALUE klass, VALUE path);
|
55
|
-
|
56
|
-
static VALUE exif_data_class;
|
57
|
-
static VALUE exif_data_each(VALUE self);
|
58
|
-
static VALUE exif_data_add(VALUE self, VALUE key, VALUE value);
|
59
|
-
static VALUE exif_data_delete(VALUE self, VALUE key);
|
60
|
-
|
61
|
-
static VALUE iptc_data_class;
|
62
|
-
static VALUE iptc_data_each(VALUE self);
|
63
|
-
static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value);
|
64
|
-
static VALUE iptc_data_delete(VALUE self, VALUE key);
|
65
|
-
|
66
|
-
static VALUE xmp_data_class;
|
67
|
-
static VALUE xmp_data_each(VALUE self);
|
68
|
-
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value);
|
69
|
-
static VALUE xmp_data_delete(VALUE self, VALUE key);
|
70
|
-
|
71
|
-
void Init_exiv2() {
|
72
|
-
VALUE enumerable_module = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
73
|
-
|
74
|
-
exiv2_module = rb_define_module("Exiv2");
|
75
|
-
|
76
|
-
basic_error_class = rb_define_class_under(exiv2_module, "BasicError", rb_eRuntimeError);
|
77
|
-
|
78
|
-
image_class = rb_define_class_under(exiv2_module, "Image", rb_cObject);
|
79
|
-
rb_define_method(image_class, "read_metadata", (Method)image_read_metadata, 0);
|
80
|
-
rb_define_method(image_class, "write_metadata", (Method)image_write_metadata, 0);
|
81
|
-
rb_define_method(image_class, "iptc_data", (Method)image_iptc_data, 0);
|
82
|
-
rb_define_method(image_class, "xmp_data", (Method)image_xmp_data, 0);
|
83
|
-
rb_define_method(image_class, "exif_data", (Method)image_exif_data, 0);
|
84
|
-
|
85
|
-
image_factory_class = rb_define_class_under(exiv2_module, "ImageFactory", rb_cObject);
|
86
|
-
rb_define_singleton_method(image_factory_class, "open", (Method)image_factory_open, 1);
|
87
|
-
|
88
|
-
exif_data_class = rb_define_class_under(exiv2_module, "ExifData", rb_cObject);
|
89
|
-
rb_include_module(exif_data_class, enumerable_module);
|
90
|
-
rb_define_method(exif_data_class, "each", (Method)exif_data_each, 0);
|
91
|
-
rb_define_method(exif_data_class, "add", (Method)exif_data_add, 2);
|
92
|
-
rb_define_method(exif_data_class, "delete", (Method)exif_data_delete, 1);
|
93
|
-
|
94
|
-
iptc_data_class = rb_define_class_under(exiv2_module, "IptcData", rb_cObject);
|
95
|
-
rb_include_module(iptc_data_class, enumerable_module);
|
96
|
-
rb_define_method(iptc_data_class, "each", (Method)iptc_data_each, 0);
|
97
|
-
rb_define_method(iptc_data_class, "add", (Method)iptc_data_add, 2);
|
98
|
-
rb_define_method(iptc_data_class, "delete", (Method)iptc_data_delete, 1);
|
99
|
-
|
100
|
-
xmp_data_class = rb_define_class_under(exiv2_module, "XmpData", rb_cObject);
|
101
|
-
rb_include_module(xmp_data_class, enumerable_module);
|
102
|
-
rb_define_method(xmp_data_class, "each", (Method)xmp_data_each, 0);
|
103
|
-
rb_define_method(xmp_data_class, "add", (Method)xmp_data_add, 2);
|
104
|
-
rb_define_method(xmp_data_class, "delete", (Method)xmp_data_delete, 1);
|
105
|
-
}
|
40
|
+
static VALUE exiv2_module;
|
106
41
|
|
42
|
+
static VALUE basic_error_class;
|
43
|
+
|
44
|
+
static VALUE image_class;
|
45
|
+
static void image_free(Exiv2::Image* image);
|
46
|
+
static VALUE image_read_metadata(VALUE self);
|
47
|
+
static VALUE image_write_metadata(VALUE self);
|
48
|
+
static VALUE image_iptc_data(VALUE self);
|
49
|
+
static VALUE image_xmp_data(VALUE self);
|
50
|
+
static VALUE image_exif_data(VALUE self);
|
51
|
+
|
52
|
+
static VALUE image_factory_class;
|
53
|
+
static VALUE image_factory_open(VALUE klass, VALUE path);
|
54
|
+
|
55
|
+
static VALUE exif_data_class;
|
56
|
+
static VALUE exif_data_each(VALUE self);
|
57
|
+
static VALUE exif_data_add(VALUE self, VALUE key, VALUE value);
|
58
|
+
static VALUE exif_data_delete(VALUE self, VALUE key);
|
59
|
+
|
60
|
+
static VALUE iptc_data_class;
|
61
|
+
static VALUE iptc_data_each(VALUE self);
|
62
|
+
static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value);
|
63
|
+
static VALUE iptc_data_delete(VALUE self, VALUE key);
|
64
|
+
|
65
|
+
static VALUE xmp_data_class;
|
66
|
+
static VALUE xmp_data_each(VALUE self);
|
67
|
+
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value);
|
68
|
+
static VALUE xmp_data_delete(VALUE self, VALUE key);
|
69
|
+
|
70
|
+
extern "C" void Init_exiv2() {
|
71
|
+
VALUE enumerable_module = rb_const_get(rb_cObject, rb_intern("Enumerable"));
|
72
|
+
|
73
|
+
exiv2_module = rb_define_module("Exiv2");
|
74
|
+
|
75
|
+
basic_error_class = rb_define_class_under(exiv2_module, "BasicError", rb_eRuntimeError);
|
76
|
+
|
77
|
+
image_class = rb_define_class_under(exiv2_module, "Image", rb_cObject);
|
78
|
+
rb_define_method(image_class, "read_metadata", (Method)image_read_metadata, 0);
|
79
|
+
rb_define_method(image_class, "write_metadata", (Method)image_write_metadata, 0);
|
80
|
+
rb_define_method(image_class, "iptc_data", (Method)image_iptc_data, 0);
|
81
|
+
rb_define_method(image_class, "xmp_data", (Method)image_xmp_data, 0);
|
82
|
+
rb_define_method(image_class, "exif_data", (Method)image_exif_data, 0);
|
83
|
+
|
84
|
+
image_factory_class = rb_define_class_under(exiv2_module, "ImageFactory", rb_cObject);
|
85
|
+
rb_define_singleton_method(image_factory_class, "open", (Method)image_factory_open, 1);
|
86
|
+
|
87
|
+
exif_data_class = rb_define_class_under(exiv2_module, "ExifData", rb_cObject);
|
88
|
+
rb_include_module(exif_data_class, enumerable_module);
|
89
|
+
rb_define_method(exif_data_class, "each", (Method)exif_data_each, 0);
|
90
|
+
rb_define_method(exif_data_class, "add", (Method)exif_data_add, 2);
|
91
|
+
rb_define_method(exif_data_class, "delete", (Method)exif_data_delete, 1);
|
92
|
+
|
93
|
+
iptc_data_class = rb_define_class_under(exiv2_module, "IptcData", rb_cObject);
|
94
|
+
rb_include_module(iptc_data_class, enumerable_module);
|
95
|
+
rb_define_method(iptc_data_class, "each", (Method)iptc_data_each, 0);
|
96
|
+
rb_define_method(iptc_data_class, "add", (Method)iptc_data_add, 2);
|
97
|
+
rb_define_method(iptc_data_class, "delete", (Method)iptc_data_delete, 1);
|
107
98
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
99
|
+
xmp_data_class = rb_define_class_under(exiv2_module, "XmpData", rb_cObject);
|
100
|
+
rb_include_module(xmp_data_class, enumerable_module);
|
101
|
+
rb_define_method(xmp_data_class, "each", (Method)xmp_data_each, 0);
|
102
|
+
rb_define_method(xmp_data_class, "add", (Method)xmp_data_add, 2);
|
103
|
+
rb_define_method(xmp_data_class, "delete", (Method)xmp_data_delete, 1);
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
// Exiv2::Image Methods
|
108
|
+
|
109
|
+
static void image_free(Exiv2::Image* image) {
|
110
|
+
delete image;
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE image_read_metadata(VALUE self) {
|
114
|
+
Exiv2::Image* image;
|
115
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
116
|
+
|
117
|
+
try {
|
118
|
+
image->readMetadata();
|
126
119
|
}
|
127
|
-
|
128
|
-
|
129
|
-
Exiv2::Image* image;
|
130
|
-
Data_Get_Struct(self, Exiv2::Image, image);
|
131
|
-
|
132
|
-
try {
|
133
|
-
image->writeMetadata();
|
134
|
-
}
|
135
|
-
catch (Exiv2::BasicError<char> error) {
|
136
|
-
rb_raise(basic_error_class, "%s", error.what());
|
137
|
-
}
|
138
|
-
|
139
|
-
return Qnil;
|
120
|
+
catch (Exiv2::BasicError<char> error) {
|
121
|
+
rb_raise(basic_error_class, "%s", error.what());
|
140
122
|
}
|
141
123
|
|
142
|
-
|
143
|
-
|
144
|
-
Data_Get_Struct(self, Exiv2::Image, image);
|
124
|
+
return Qnil;
|
125
|
+
}
|
145
126
|
|
146
|
-
|
147
|
-
|
127
|
+
static VALUE image_write_metadata(VALUE self) {
|
128
|
+
Exiv2::Image* image;
|
129
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
148
130
|
|
149
|
-
|
131
|
+
try {
|
132
|
+
image->writeMetadata();
|
150
133
|
}
|
134
|
+
catch (Exiv2::BasicError<char> error) {
|
135
|
+
rb_raise(basic_error_class, "%s", error.what());
|
136
|
+
}
|
137
|
+
|
138
|
+
return Qnil;
|
139
|
+
}
|
151
140
|
|
152
|
-
|
153
|
-
|
154
|
-
|
141
|
+
static VALUE image_exif_data(VALUE self) {
|
142
|
+
Exiv2::Image* image;
|
143
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
155
144
|
|
156
|
-
|
157
|
-
|
145
|
+
VALUE exif_data = Data_Wrap_Struct(exif_data_class, 0, 0, &image->exifData());
|
146
|
+
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.
|
158
147
|
|
159
|
-
|
160
|
-
|
148
|
+
return exif_data;
|
149
|
+
}
|
161
150
|
|
151
|
+
static VALUE image_iptc_data(VALUE self) {
|
152
|
+
Exiv2::Image* image;
|
153
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
162
154
|
|
163
|
-
|
164
|
-
|
165
|
-
Data_Get_Struct(self, Exiv2::Image, image);
|
155
|
+
VALUE iptc_data = Data_Wrap_Struct(iptc_data_class, 0, 0, &image->iptcData());
|
156
|
+
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.
|
166
157
|
|
167
|
-
|
168
|
-
|
158
|
+
return iptc_data;
|
159
|
+
}
|
169
160
|
|
170
|
-
|
161
|
+
|
162
|
+
static VALUE image_xmp_data(VALUE self) {
|
163
|
+
Exiv2::Image* image;
|
164
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
165
|
+
|
166
|
+
VALUE xmp_data = Data_Wrap_Struct(xmp_data_class, 0, 0, &image->xmpData());
|
167
|
+
rb_iv_set(xmp_data, "@image", self); // Make sure we don't GC the image until there are no references to the XMP data left.
|
168
|
+
|
169
|
+
return xmp_data;
|
170
|
+
}
|
171
|
+
// Exiv2::ImageFactory methods
|
172
|
+
|
173
|
+
static VALUE image_factory_open(VALUE klass, VALUE path) {
|
174
|
+
Exiv2::Image* image;
|
175
|
+
|
176
|
+
try {
|
177
|
+
Exiv2::Image::AutoPtr image_auto_ptr = Exiv2::ImageFactory::open(to_std_string(path));
|
178
|
+
image = image_auto_ptr.release(); // Release the AutoPtr, so we can keep the image around.
|
171
179
|
}
|
172
|
-
|
173
|
-
|
174
|
-
static VALUE image_factory_open(VALUE klass, VALUE path) {
|
175
|
-
Exiv2::Image* image;
|
176
|
-
|
177
|
-
try {
|
178
|
-
Exiv2::Image::AutoPtr image_auto_ptr = Exiv2::ImageFactory::open(to_std_string(path));
|
179
|
-
image = image_auto_ptr.release(); // Release the AutoPtr, so we can keep the image around.
|
180
|
-
}
|
181
|
-
catch (Exiv2::BasicError<char> error) {
|
182
|
-
rb_raise(basic_error_class, "%s", error.what());
|
183
|
-
}
|
184
|
-
|
185
|
-
return Data_Wrap_Struct(image_class, 0, image_free, image);
|
180
|
+
catch (Exiv2::BasicError<char> error) {
|
181
|
+
rb_raise(basic_error_class, "%s", error.what());
|
186
182
|
}
|
187
183
|
|
184
|
+
return Data_Wrap_Struct(image_class, 0, image_free, image);
|
185
|
+
}
|
188
186
|
|
189
|
-
// Exiv2::ExifData methods
|
190
187
|
|
191
|
-
|
192
|
-
|
193
|
-
|
188
|
+
// Exiv2::ExifData methods
|
189
|
+
|
190
|
+
static VALUE exif_data_each(VALUE self) {
|
191
|
+
return metadata_each<Exiv2::ExifData>(self);
|
192
|
+
}
|
193
|
+
|
194
|
+
static VALUE exif_data_add(VALUE self, VALUE key, VALUE value) {
|
195
|
+
Exiv2::ExifData* data;
|
196
|
+
Data_Get_Struct(self, Exiv2::ExifData, data);
|
197
|
+
|
198
|
+
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));
|
194
199
|
|
195
|
-
static VALUE exif_data_add(VALUE self, VALUE key, VALUE value) {
|
196
|
-
Exiv2::ExifData* data;
|
197
|
-
Data_Get_Struct(self, Exiv2::ExifData, data);
|
198
|
-
|
199
|
-
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));
|
200
|
-
|
201
200
|
#if EXIV2_MAJOR_VERSION <= 0 && EXIV2_MINOR_VERSION <= 20
|
202
|
-
|
201
|
+
Exiv2::TypeId typeId = Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId());
|
203
202
|
#else
|
204
|
-
|
203
|
+
Exiv2::TypeId typeId = exifKey.defaultTypeId();
|
205
204
|
#endif
|
206
|
-
|
207
|
-
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
208
|
-
v->read(to_std_string(value));
|
209
|
-
|
210
|
-
data->add(exifKey, v.get());
|
211
|
-
return Qtrue;
|
212
|
-
}
|
213
205
|
|
214
|
-
|
215
|
-
|
216
|
-
Data_Get_Struct(self, Exiv2::ExifData, data);
|
217
|
-
|
218
|
-
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));
|
219
|
-
Exiv2::ExifData::iterator pos = data->findKey(exifKey);
|
220
|
-
if(pos == data->end()) return Qfalse;
|
221
|
-
data->erase(pos);
|
222
|
-
|
223
|
-
return Qtrue;
|
224
|
-
}
|
206
|
+
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
207
|
+
v->read(to_std_string(value));
|
225
208
|
|
209
|
+
data->add(exifKey, v.get());
|
210
|
+
return Qtrue;
|
211
|
+
}
|
226
212
|
|
227
|
-
|
213
|
+
static VALUE exif_data_delete(VALUE self, VALUE key) {
|
214
|
+
Exiv2::ExifData* data;
|
215
|
+
Data_Get_Struct(self, Exiv2::ExifData, data);
|
228
216
|
|
229
|
-
|
230
|
-
|
231
|
-
|
217
|
+
Exiv2::ExifKey exifKey = Exiv2::ExifKey(to_std_string(key));
|
218
|
+
Exiv2::ExifData::iterator pos = data->findKey(exifKey);
|
219
|
+
if(pos == data->end()) return Qfalse;
|
220
|
+
data->erase(pos);
|
232
221
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
222
|
+
return Qtrue;
|
223
|
+
}
|
224
|
+
|
225
|
+
|
226
|
+
// Exiv2::IptcData methods
|
227
|
+
|
228
|
+
static VALUE iptc_data_each(VALUE self) {
|
229
|
+
return metadata_each<Exiv2::IptcData>(self);
|
230
|
+
}
|
231
|
+
|
232
|
+
static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value) {
|
233
|
+
Exiv2::IptcData* data;
|
234
|
+
Data_Get_Struct(self, Exiv2::IptcData, data);
|
235
|
+
|
236
|
+
Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
|
237
|
+
Exiv2::TypeId typeId = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
|
248
238
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
Exiv2::IptcData::iterator pos = data->findKey(iptcKey);
|
255
|
-
if(pos == data->end()) return Qfalse;
|
256
|
-
data->erase(pos);
|
257
|
-
|
258
|
-
return Qtrue;
|
239
|
+
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
240
|
+
v->read(to_std_string(value));
|
241
|
+
|
242
|
+
if(data->add(iptcKey, v.get())) {
|
243
|
+
return Qfalse;
|
259
244
|
}
|
245
|
+
return Qtrue;
|
246
|
+
}
|
247
|
+
|
248
|
+
static VALUE iptc_data_delete(VALUE self, VALUE key) {
|
249
|
+
Exiv2::IptcData* data;
|
250
|
+
Data_Get_Struct(self, Exiv2::IptcData, data);
|
251
|
+
|
252
|
+
Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
|
253
|
+
Exiv2::IptcData::iterator pos = data->findKey(iptcKey);
|
254
|
+
if(pos == data->end()) return Qfalse;
|
255
|
+
data->erase(pos);
|
256
|
+
|
257
|
+
return Qtrue;
|
258
|
+
}
|
260
259
|
|
261
|
-
|
260
|
+
// Exiv2::XmpData methods
|
261
|
+
|
262
|
+
static VALUE xmp_data_each(VALUE self) {
|
263
|
+
return metadata_each<Exiv2::XmpData>(self);
|
264
|
+
}
|
265
|
+
|
266
|
+
static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value) {
|
267
|
+
Exiv2::XmpData* data;
|
268
|
+
Data_Get_Struct(self, Exiv2::XmpData, data);
|
262
269
|
|
263
|
-
|
264
|
-
|
265
|
-
}
|
270
|
+
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
|
271
|
+
Exiv2::TypeId typeId = Exiv2::XmpProperties::propertyType(xmpKey);
|
266
272
|
|
267
|
-
|
268
|
-
|
269
|
-
Data_Get_Struct(self, Exiv2::XmpData, data);
|
270
|
-
|
271
|
-
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
|
272
|
-
Exiv2::TypeId typeId = Exiv2::XmpProperties::propertyType(xmpKey);
|
273
|
-
|
274
|
-
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
275
|
-
v->read(to_std_string(value));
|
276
|
-
|
277
|
-
if(data->add(xmpKey, v.get())) {
|
278
|
-
return Qfalse;
|
279
|
-
}
|
280
|
-
return Qtrue;
|
281
|
-
}
|
273
|
+
Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
|
274
|
+
v->read(to_std_string(value));
|
282
275
|
|
283
|
-
|
284
|
-
|
285
|
-
Data_Get_Struct(self, Exiv2::XmpData, data);
|
286
|
-
|
287
|
-
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
|
288
|
-
Exiv2::XmpData::iterator pos = data->findKey(xmpKey);
|
289
|
-
if(pos == data->end()) return Qfalse;
|
290
|
-
data->erase(pos);
|
291
|
-
|
292
|
-
return Qtrue;
|
276
|
+
if(data->add(xmpKey, v.get())) {
|
277
|
+
return Qfalse;
|
293
278
|
}
|
279
|
+
return Qtrue;
|
280
|
+
}
|
281
|
+
|
282
|
+
static VALUE xmp_data_delete(VALUE self, VALUE key) {
|
283
|
+
Exiv2::XmpData* data;
|
284
|
+
Data_Get_Struct(self, Exiv2::XmpData, data);
|
285
|
+
|
286
|
+
Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
|
287
|
+
Exiv2::XmpData::iterator pos = data->findKey(xmpKey);
|
288
|
+
if(pos == data->end()) return Qfalse;
|
289
|
+
data->erase(pos);
|
290
|
+
|
291
|
+
return Qtrue;
|
294
292
|
}
|
data/ext/exiv2/extconf.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
require 'mkmf'
|
2
|
+
|
3
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
4
|
+
RbConfig::MAKEFILE_CONFIG['CCFLAGS'] = ENV['CCFLAGS'] if ENV['CCFLAGS']
|
5
|
+
RbConfig::MAKEFILE_CONFIG['CXX'] = ENV['CXX'] if ENV['CXX']
|
6
|
+
RbConfig::MAKEFILE_CONFIG['CXXFLAGS'] = ENV['CXXFLAGS'] if ENV['CXXFLAGS']
|
7
|
+
|
2
8
|
dir_config("exiv2")
|
3
9
|
have_library("exiv2")
|
4
10
|
create_makefile("exiv2/exiv2")
|
data/lib/exiv2/version.rb
CHANGED
data/spec/exiv2_spec.rb
CHANGED
@@ -8,13 +8,13 @@ describe Exiv2 do
|
|
8
8
|
it "should handle a Pathname being passed to open" do
|
9
9
|
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/test.jpg").to_s)
|
10
10
|
image.read_metadata
|
11
|
-
image.iptc_data.to_hash.
|
11
|
+
expect(image.iptc_data.to_hash).not_to be_empty
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should raise an error when trying to open a non-existant file" do
|
15
15
|
expect {
|
16
16
|
Exiv2::ImageFactory.open("tmp/no-such-file.jpg")
|
17
|
-
}.
|
17
|
+
}.to raise_error(Exiv2::BasicError)
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should write metadata" do
|
@@ -27,7 +27,7 @@ describe Exiv2 do
|
|
27
27
|
|
28
28
|
image2 = Exiv2::ImageFactory.open("spec/files/test_tmp.jpg")
|
29
29
|
image2.read_metadata
|
30
|
-
image2.iptc_data["Iptc.Application2.Caption"].
|
30
|
+
expect(image2.iptc_data["Iptc.Application2.Caption"]).to eq("A New Caption")
|
31
31
|
FileUtils.rm("spec/files/test_tmp.jpg")
|
32
32
|
end
|
33
33
|
|
@@ -36,9 +36,9 @@ describe Exiv2 do
|
|
36
36
|
image.read_metadata
|
37
37
|
description = image.exif_data["Exif.Image.ImageDescription"]
|
38
38
|
if description.respond_to? :encoding # Only in Ruby 1.9+
|
39
|
-
description.encoding.
|
39
|
+
expect(description.encoding).to eq(Encoding::UTF_8)
|
40
40
|
end
|
41
|
-
description.
|
41
|
+
expect(description).to eq('UTF-8 description. ☃ł㌎')
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'reads UTF-8 data in each' do
|
@@ -46,8 +46,8 @@ describe Exiv2 do
|
|
46
46
|
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/photo_with_utf8_description.jpg").to_s)
|
47
47
|
image.read_metadata
|
48
48
|
image.exif_data.each do |key,value|
|
49
|
-
key.encoding.
|
50
|
-
value.encoding.
|
49
|
+
expect(key.encoding).to eq(Encoding::UTF_8)
|
50
|
+
expect(value.encoding).to eq(Encoding::UTF_8)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -64,52 +64,52 @@ describe Exiv2 do
|
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should read IPTC data" do
|
67
|
-
@iptc_data.
|
68
|
-
@iptc_data.inspect.
|
69
|
-
@iptc_data.to_a.
|
67
|
+
expect(@iptc_data).to be_a(Exiv2::IptcData)
|
68
|
+
expect(@iptc_data.inspect).to eq('#<Exiv2::IptcData: {"Iptc.Application2.Caption"=>"Rhubarb rhubarb rhubard", "Iptc.Application2.Keywords"=>["fish", "custard"]}>')
|
69
|
+
expect(@iptc_data.to_a).to eq([
|
70
70
|
["Iptc.Application2.Caption", "Rhubarb rhubarb rhubard"],
|
71
71
|
["Iptc.Application2.Keywords", "fish"],
|
72
72
|
["Iptc.Application2.Keywords", "custard"]
|
73
|
-
]
|
73
|
+
])
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should convert iptc data into a hash" do
|
77
77
|
iptc_hash = @iptc_data.to_hash
|
78
|
-
iptc_hash.
|
79
|
-
iptc_hash.
|
78
|
+
expect(iptc_hash).to be_a(Hash)
|
79
|
+
expect(iptc_hash).to eq({
|
80
80
|
"Iptc.Application2.Caption" => "Rhubarb rhubarb rhubard",
|
81
81
|
"Iptc.Application2.Keywords" => ["fish", "custard"]
|
82
|
-
}
|
82
|
+
})
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should write IPTC data" do
|
86
86
|
@iptc_data.add("Iptc.Application2.Keywords", "fishy")
|
87
|
-
@iptc_data.to_a.
|
87
|
+
expect(@iptc_data.to_a).to eq([
|
88
88
|
["Iptc.Application2.Caption", "Rhubarb rhubarb rhubard"],
|
89
89
|
["Iptc.Application2.Keywords", "fish"],
|
90
90
|
["Iptc.Application2.Keywords", "custard"],
|
91
91
|
["Iptc.Application2.Keywords", "fishy"]
|
92
|
-
]
|
92
|
+
])
|
93
93
|
end
|
94
94
|
|
95
95
|
it "should set IPTC data" do
|
96
96
|
@iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
97
|
-
@iptc_data.to_hash["Iptc.Application2.Caption"].
|
97
|
+
expect(@iptc_data.to_hash["Iptc.Application2.Caption"]).to eq("A New Caption")
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should set multiply IPTC data values" do
|
101
101
|
@iptc_data["Iptc.Application2.Keywords"] = ["abc", "cde"]
|
102
|
-
@iptc_data.to_hash["Iptc.Application2.Keywords"].
|
102
|
+
expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq(["abc", "cde"])
|
103
103
|
end
|
104
104
|
|
105
105
|
it "should delete one value of IPTC data" do
|
106
106
|
@iptc_data.delete("Iptc.Application2.Keywords")
|
107
|
-
@iptc_data.to_hash["Iptc.Application2.Keywords"].
|
107
|
+
expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq("custard")
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should delete all values of IPTC data" do
|
111
111
|
@iptc_data.delete_all("Iptc.Application2.Keywords")
|
112
|
-
@iptc_data.to_hash["Iptc.Application2.Keywords"].
|
112
|
+
expect(@iptc_data.to_hash["Iptc.Application2.Keywords"]).to eq(nil)
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
@@ -119,47 +119,47 @@ describe Exiv2 do
|
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should read XMP data" do
|
122
|
-
@xmp_data.
|
123
|
-
@xmp_data.inspect.
|
124
|
-
@xmp_data.to_a.
|
122
|
+
expect(@xmp_data).to be_a(Exiv2::XmpData)
|
123
|
+
expect(@xmp_data.inspect).to eq('#<Exiv2::XmpData: {"Xmp.dc.description"=>"lang=\"x-default\" This is a description", "Xmp.dc.title"=>"lang=\"x-default\" Pickled"}>')
|
124
|
+
expect(@xmp_data.to_a).to eq([
|
125
125
|
["Xmp.dc.title", "lang=\"x-default\" Pickled"],
|
126
126
|
["Xmp.dc.description", "lang=\"x-default\" This is a description"]
|
127
|
-
]
|
127
|
+
])
|
128
128
|
end
|
129
129
|
|
130
130
|
it "should convert xmp data into a hash" do
|
131
131
|
xmp_hash = @xmp_data.to_hash
|
132
|
-
xmp_hash.
|
133
|
-
xmp_hash.
|
132
|
+
expect(xmp_hash).to be_a(Hash)
|
133
|
+
expect(xmp_hash).to eq({
|
134
134
|
"Xmp.dc.title" => "lang=\"x-default\" Pickled",
|
135
135
|
"Xmp.dc.description" => "lang=\"x-default\" This is a description"
|
136
|
-
}
|
136
|
+
})
|
137
137
|
end
|
138
138
|
|
139
139
|
it "should write XMP data" do
|
140
140
|
@xmp_data["Xmp.dc.title"] = "lang=\"x-default\" Changed!"
|
141
|
-
@xmp_data.to_hash["Xmp.dc.title"].
|
141
|
+
expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq("lang=\"x-default\" Changed!")
|
142
142
|
end
|
143
143
|
|
144
144
|
it "should set XMP data" do
|
145
145
|
@xmp_data["Xmp.dc.title"] = "A New Title"
|
146
|
-
@xmp_data.to_hash["Xmp.dc.title"].
|
146
|
+
expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq("lang=\"x-default\" A New Title")
|
147
147
|
end
|
148
148
|
|
149
149
|
it "should set multiply XMP data values" do
|
150
150
|
@xmp_data["Xmp.dc.title"] = ["abc", "cde"]
|
151
|
-
@xmp_data.to_hash["Xmp.dc.title"].
|
151
|
+
expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq(["lang=\"x-default\" abc", "lang=\"x-default\" cde"])
|
152
152
|
end
|
153
153
|
|
154
154
|
it "should delete one value of XMP data" do
|
155
155
|
@xmp_data["Xmp.dc.title"] = ["abc", "cde"]
|
156
156
|
@xmp_data.delete("Xmp.dc.title")
|
157
|
-
@xmp_data.to_hash["Xmp.dc.title"].
|
157
|
+
expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq("lang=\"x-default\" cde")
|
158
158
|
end
|
159
159
|
|
160
160
|
it "should delete all values of XMP data" do
|
161
161
|
@xmp_data.delete_all("Xmp.dc.title")
|
162
|
-
@xmp_data.to_hash["Xmp.dc.title"].
|
162
|
+
expect(@xmp_data.to_hash["Xmp.dc.title"]).to eq(nil)
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
@@ -169,59 +169,59 @@ describe Exiv2 do
|
|
169
169
|
end
|
170
170
|
|
171
171
|
it "should read Exif data" do
|
172
|
-
@exif_data.
|
173
|
-
@exif_data.inspect.
|
174
|
-
@exif_data.to_a.
|
172
|
+
expect(@exif_data).to be_a(Exiv2::ExifData)
|
173
|
+
expect(@exif_data.inspect).to eq('#<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"}>')
|
174
|
+
expect(@exif_data.to_a).to eq([
|
175
175
|
["Exif.Image.Software", "plasq skitch"],
|
176
176
|
["Exif.Image.ExifTag", "52"],
|
177
177
|
["Exif.Photo.ExifVersion", "48 50 49 48"],
|
178
178
|
["Exif.Photo.PixelXDimension", "32"],
|
179
179
|
["Exif.Photo.PixelYDimension", "32"]
|
180
|
-
]
|
180
|
+
])
|
181
181
|
end
|
182
182
|
|
183
183
|
it "should convert xmp data into a hash" do
|
184
184
|
exif_hash = @exif_data.to_hash
|
185
|
-
exif_hash.
|
186
|
-
exif_hash.
|
185
|
+
expect(exif_hash).to be_a(Hash)
|
186
|
+
expect(exif_hash).to eq({
|
187
187
|
"Exif.Photo.PixelXDimension" => "32",
|
188
188
|
"Exif.Photo.ExifVersion" => "48 50 49 48",
|
189
189
|
"Exif.Image.Software" => "plasq skitch",
|
190
190
|
"Exif.Photo.PixelYDimension" => "32",
|
191
191
|
"Exif.Image.ExifTag" => "52"
|
192
|
-
}
|
192
|
+
})
|
193
193
|
end
|
194
194
|
|
195
195
|
it "should write Exif data" do
|
196
196
|
@exif_data.add("Exif.Image.Software", "ruby-exiv2")
|
197
|
-
@exif_data.to_hash.
|
197
|
+
expect(@exif_data.to_hash).to eq({
|
198
198
|
"Exif.Photo.PixelXDimension" => "32",
|
199
199
|
"Exif.Photo.ExifVersion" => "48 50 49 48",
|
200
200
|
"Exif.Image.Software" => ["plasq skitch", "ruby-exiv2"],
|
201
201
|
"Exif.Photo.PixelYDimension" => "32",
|
202
202
|
"Exif.Image.ExifTag" => "52"
|
203
|
-
}
|
203
|
+
})
|
204
204
|
end
|
205
205
|
|
206
206
|
it "should set Exif data" do
|
207
207
|
@exif_data["Exif.Image.Software"] = "ruby-exiv2"
|
208
|
-
@exif_data.to_hash["Exif.Image.Software"].
|
208
|
+
expect(@exif_data.to_hash["Exif.Image.Software"]).to eq("ruby-exiv2")
|
209
209
|
end
|
210
210
|
|
211
211
|
it "should set multiply Exif data values" do
|
212
212
|
@exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"]
|
213
|
-
@exif_data.to_hash["Exif.Image.Software"].
|
213
|
+
expect(@exif_data.to_hash["Exif.Image.Software"]).to eq(["ruby-exiv2", "plasq skitch"])
|
214
214
|
end
|
215
215
|
|
216
216
|
it "should delete one value of Exif data" do
|
217
217
|
@exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"]
|
218
218
|
@exif_data.delete("Exif.Image.Software")
|
219
|
-
@exif_data.to_hash["Exif.Image.Software"].
|
219
|
+
expect(@exif_data.to_hash["Exif.Image.Software"]).to eq("plasq skitch")
|
220
220
|
end
|
221
221
|
|
222
222
|
it "should delete all values of Exif data" do
|
223
223
|
@exif_data.delete_all("Exif.Image.Software")
|
224
|
-
@exif_data.to_hash["Exif.Image.Software"].
|
224
|
+
expect(@exif_data.to_hash["Exif.Image.Software"]).to eq(nil)
|
225
225
|
end
|
226
226
|
end
|
227
227
|
end
|
metadata
CHANGED
@@ -1,38 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exiv2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.9
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Pete Yandell
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2019-05-27 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: rake-compiler
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
|
-
- -
|
31
|
+
- - ">="
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: '0'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
36
41
|
description: A simple wrapper around the C++ Exiv2 libary for reading image metadata
|
37
42
|
email:
|
38
43
|
- pete@envato.com
|
@@ -41,12 +46,13 @@ extensions:
|
|
41
46
|
- ext/exiv2/extconf.rb
|
42
47
|
extra_rdoc_files: []
|
43
48
|
files:
|
44
|
-
- .gitignore
|
45
|
-
- .rspec
|
49
|
+
- ".gitignore"
|
50
|
+
- ".rspec"
|
51
|
+
- ".travis.yml"
|
46
52
|
- Gemfile
|
47
53
|
- Gemfile.lock
|
48
54
|
- LICENSE
|
49
|
-
- README.
|
55
|
+
- README.md
|
50
56
|
- Rakefile
|
51
57
|
- exiv2.gemspec
|
52
58
|
- ext/exiv2/exiv2.cpp
|
@@ -62,34 +68,27 @@ files:
|
|
62
68
|
- spec/files/test.jpg
|
63
69
|
homepage: https://github.com/envato/exiv2
|
64
70
|
licenses: []
|
71
|
+
metadata: {}
|
65
72
|
post_install_message:
|
66
73
|
rdoc_options: []
|
67
74
|
require_paths:
|
68
75
|
- lib
|
69
76
|
- ext
|
70
77
|
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
78
|
requirements:
|
73
|
-
- -
|
79
|
+
- - ">="
|
74
80
|
- !ruby/object:Gem::Version
|
75
81
|
version: '0'
|
76
|
-
segments:
|
77
|
-
- 0
|
78
|
-
hash: 1767711018481939965
|
79
82
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
83
|
requirements:
|
82
|
-
- -
|
84
|
+
- - ">="
|
83
85
|
- !ruby/object:Gem::Version
|
84
86
|
version: '0'
|
85
|
-
segments:
|
86
|
-
- 0
|
87
|
-
hash: 1767711018481939965
|
88
87
|
requirements: []
|
89
88
|
rubyforge_project: exiv2
|
90
|
-
rubygems_version:
|
89
|
+
rubygems_version: 2.7.7
|
91
90
|
signing_key:
|
92
|
-
specification_version:
|
91
|
+
specification_version: 4
|
93
92
|
summary: A simple wrapper around Exiv2
|
94
93
|
test_files:
|
95
94
|
- spec/exiv2_spec.rb
|
data/README.rdoc
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
= Exiv2
|
2
|
-
|
3
|
-
A simple wrapper around the C++ Exiv2 libary for reading and writing image metadata.
|
4
|
-
|
5
|
-
See http://www.exiv2.org/
|
6
|
-
|
7
|
-
Requires that the exiv2 C++ library is installed.
|
8
|
-
|
9
|
-
== Usage
|
10
|
-
|
11
|
-
gem install exiv2
|
12
|
-
|
13
|
-
require 'exiv2'
|
14
|
-
image = Exiv2::ImageFactory.open("image.jpg")
|
15
|
-
image.read_metadata
|
16
|
-
image.iptc_data.each do |key, value|
|
17
|
-
puts "#{key} = #{value}\n"
|
18
|
-
end
|
19
|
-
image.exif_data.each { ... }
|
20
|
-
image.xmp_data.each { ... }
|
21
|
-
|
22
|
-
iptc_data_hash = image.iptc_data.to_hash
|
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
|
32
|
-
|
33
|
-
== Why?
|
34
|
-
|
35
|
-
None of the existing Ruby libraries for reading and writing image metadata did quite what
|
36
|
-
we wanted, so we figured it wouldn't be too hard to wrap enough of Exiv2 to
|
37
|
-
meet our needs.
|
38
|
-
|
39
|
-
The intention is to just mirror the Exiv2 API in Ruby, so the path to extending
|
40
|
-
this to support more of Exiv2's functionality should be straightforward. Patches
|
41
|
-
are welcome.
|
42
|
-
|
43
|
-
== Compatibility
|
44
|
-
|
45
|
-
Tested with Ruby 1.8.7 and 1.9.3, and Exiv2 0.20 and 0.21
|
46
|
-
|
47
|
-
== Developing
|
48
|
-
|
49
|
-
* Fork the project.
|
50
|
-
* Make your feature addition or bug fix.
|
51
|
-
* Add tests for it. This is important so I don't break it in a
|
52
|
-
future version unintentionally.
|
53
|
-
* Commit, do not mess with rakefile, version, or history.
|
54
|
-
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
55
|
-
* Send me a pull request. Bonus points for topic branches.
|
56
|
-
|
57
|
-
== Status
|
58
|
-
|
59
|
-
In early development. Very little of Exiv2's API is supported, and it hasn't
|
60
|
-
been heavily tested.
|
61
|
-
|
62
|
-
== Contributors
|
63
|
-
|
64
|
-
Pete Yandell, Mark Turnley, Lucas Parry, Norbert Wojtwoicz, Jan Graichen, John Barton
|
65
|
-
|
66
|
-
== Copyright
|
67
|
-
|
68
|
-
Copyright (c) 2010 Envato & Pete Yandell. See LICENSE for details.
|