exiv2 0.0.8 → 0.1.0
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/README.md +119 -0
- data/ext/exiv2/exiv2.cpp +218 -220
- data/ext/exiv2/extconf.rb +9 -1
- data/lib/exiv2/version.rb +1 -1
- metadata +31 -41
- data/.gitignore +0 -13
- data/.rspec +0 -1
- data/Gemfile +0 -3
- data/Gemfile.lock +0 -28
- data/README.rdoc +0 -68
- data/Rakefile +0 -16
- data/exiv2.gemspec +0 -25
- data/spec/exiv2_spec.rb +0 -227
- data/spec/files/photo_with_utf8_description.jpg +0 -0
- data/spec/files/test.jpg +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7000b7708b6281fe8686a00aaff68027dbfa95023a51cfbbd651188b8b48740b
|
4
|
+
data.tar.gz: 3a6c7cbbfa1b6d6a5ca44b31f93819c79687570081951aa1ee0bb9a69766d83e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9267361af64e277e724f18256108f01997daa8b873cac39984e37a5e12267551ea4da29353424b6fd1afaba9a0f6afbaf63fc17143e93d75e84bfcbbb5526302
|
7
|
+
data.tar.gz: 59d8a2cfebab35d5760f832420eab1cc89cbbd67dda0017512de843b4aa89bc89c176440de8df95bbc9c60d9e0bcdb36589c6995944381ed24733d5e905e3d11
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
# Exiv2
|
2
|
+
|
3
|
+
[](https://github.com/envato/exiv2/blob/master/LICENSE)
|
4
|
+
[](https://rubygems.org/gems/exiv2)
|
5
|
+
[](https://rubygems.org/gems/exiv2)
|
6
|
+
[](https://github.com/envato/exiv2/actions?query=branch%3Amaster+workflow%3Atests)
|
7
|
+
|
8
|
+
A simple wrapper around the C++ Exiv2 libary for reading and writing image metadata.
|
9
|
+
|
10
|
+
See http://www.exiv2.org/
|
11
|
+
|
12
|
+
Requires that the exiv2 C++ library is installed.
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
```
|
17
|
+
gem install exiv2
|
18
|
+
```
|
19
|
+
|
20
|
+
if you get errors with header could not be found below:
|
21
|
+
|
22
|
+
```
|
23
|
+
exiv2.cpp:1:10: fatal error: 'exiv2/image.hpp' file not found
|
24
|
+
#include "exiv2/image.hpp"
|
25
|
+
```
|
26
|
+
|
27
|
+
please explicitly declare the header path
|
28
|
+
|
29
|
+
```
|
30
|
+
gem install exiv2 -- --with-exiv2-include="${EXIV2_PREFIX}/include" --with-exiv2-lib="${EXIV2_PREFIX}/lib"
|
31
|
+
```
|
32
|
+
|
33
|
+
on OSX with Homebrew's exiv2, the `EXIV2_PREFIX` can be set:
|
34
|
+
|
35
|
+
```
|
36
|
+
export EXIV2_PREFIX=$(brew --prefix exiv2)
|
37
|
+
```
|
38
|
+
|
39
|
+
If you get this error while trying to install as part of a bundle install, you can set these paths using:
|
40
|
+
```
|
41
|
+
bundle config build.exiv2 --with-exiv2-include="${EXIV2_PREFIX}/include" --with-exiv2-lib="${EXIV2_PREFIX}/lib"
|
42
|
+
```
|
43
|
+
|
44
|
+
|
45
|
+
If you are on new version of Command Line Tool (that is newer than 6.2, and bump into following error:
|
46
|
+
|
47
|
+
```
|
48
|
+
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/iterator:341:10: fatal error: '__debug' file not found
|
49
|
+
#include <__debug>
|
50
|
+
```
|
51
|
+
|
52
|
+
You can follow the quick hack by touching a new file `/Library/Developer/CommandLineTools/usr/include/c++/v1/__debug` with content:
|
53
|
+
|
54
|
+
```
|
55
|
+
#ifndef _LIBCPP_ASSERT
|
56
|
+
#define _LIBCPP_ASSERT(...) ((void)0)
|
57
|
+
#endif
|
58
|
+
```
|
59
|
+
|
60
|
+
Once everything is successfully installed, you can give it a go:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
require 'exiv2'
|
64
|
+
image = Exiv2::ImageFactory.open("image.jpg")
|
65
|
+
image.read_metadata
|
66
|
+
image.iptc_data.each do |key, value|
|
67
|
+
puts "#{key} = #{value}\n"
|
68
|
+
end
|
69
|
+
image.exif_data.each { ... }
|
70
|
+
image.xmp_data.each { ... }
|
71
|
+
|
72
|
+
iptc_data_hash = image.iptc_data.to_hash
|
73
|
+
xmp_data_hash = image.xmp_data.to_hash
|
74
|
+
|
75
|
+
image.exif_data.delete("Exif.Image.Software")
|
76
|
+
image.iptc_data.delete_all("Iptc.Application2.Keywords")
|
77
|
+
|
78
|
+
image.iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
79
|
+
image.iptc_data.add("Iptc.Application2.Keywords", "fishy")
|
80
|
+
|
81
|
+
image.write_metadata
|
82
|
+
```
|
83
|
+
|
84
|
+
## Why?
|
85
|
+
|
86
|
+
None of the existing Ruby libraries for reading and writing image metadata did quite what
|
87
|
+
we wanted, so we figured it wouldn't be too hard to wrap enough of Exiv2 to
|
88
|
+
meet our needs.
|
89
|
+
|
90
|
+
The intention is to just mirror the Exiv2 API in Ruby, so the path to extending
|
91
|
+
this to support more of Exiv2's functionality should be straightforward. Patches
|
92
|
+
are welcome.
|
93
|
+
|
94
|
+
## Compatibility
|
95
|
+
|
96
|
+
Tested on 2.4.x, 2.5.x and 2.6.x with Exiv2 0.27.1
|
97
|
+
|
98
|
+
## Developing
|
99
|
+
|
100
|
+
* Fork the project.
|
101
|
+
* Make your feature addition or bug fix.
|
102
|
+
* Add tests for it. This is important so I don't break it in a
|
103
|
+
future version unintentionally.
|
104
|
+
* Commit, do not mess with rakefile, version, or history.
|
105
|
+
(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)
|
106
|
+
* Send me a pull request. Bonus points for topic branches.
|
107
|
+
|
108
|
+
## Status
|
109
|
+
|
110
|
+
In early development. Very little of Exiv2's API is supported, and it hasn't
|
111
|
+
been heavily tested.
|
112
|
+
|
113
|
+
## Contributors
|
114
|
+
|
115
|
+
Pete Yandell, Mark Turnley, Lucas Parry, Norbert Wojtwoicz, Jan Graichen, John Barton
|
116
|
+
|
117
|
+
## Copyright
|
118
|
+
|
119
|
+
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,12 @@
|
|
1
1
|
require 'mkmf'
|
2
|
-
|
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
|
+
|
8
|
+
if dir_config("exiv2") == [nil, nil]
|
9
|
+
pkg_config("exiv2")
|
10
|
+
end
|
3
11
|
have_library("exiv2")
|
4
12
|
create_makefile("exiv2/exiv2")
|
data/lib/exiv2/version.rb
CHANGED
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.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Pete Yandell
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2023-02-05 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,14 +46,8 @@ extensions:
|
|
41
46
|
- ext/exiv2/extconf.rb
|
42
47
|
extra_rdoc_files: []
|
43
48
|
files:
|
44
|
-
- .gitignore
|
45
|
-
- .rspec
|
46
|
-
- Gemfile
|
47
|
-
- Gemfile.lock
|
48
49
|
- LICENSE
|
49
|
-
- README.
|
50
|
-
- Rakefile
|
51
|
-
- exiv2.gemspec
|
50
|
+
- README.md
|
52
51
|
- ext/exiv2/exiv2.cpp
|
53
52
|
- ext/exiv2/extconf.rb
|
54
53
|
- lib/exiv2.rb
|
@@ -57,41 +56,32 @@ files:
|
|
57
56
|
- lib/exiv2/shared_methods.rb
|
58
57
|
- lib/exiv2/version.rb
|
59
58
|
- lib/exiv2/xmp_data.rb
|
60
|
-
- spec/exiv2_spec.rb
|
61
|
-
- spec/files/photo_with_utf8_description.jpg
|
62
|
-
- spec/files/test.jpg
|
63
59
|
homepage: https://github.com/envato/exiv2
|
64
60
|
licenses: []
|
65
|
-
|
61
|
+
metadata:
|
62
|
+
bug_tracker_uri: https://github.com/envato/exiv2/issues
|
63
|
+
changelog_uri: https://github.com/envato/exiv2/releases
|
64
|
+
documentation_uri: https://www.rubydoc.info/gems/exiv2/0.1.0
|
65
|
+
homepage_uri: https://github.com/envato/exiv2
|
66
|
+
source_code_uri: https://github.com/envato/exiv2/tree/v0.1.0
|
67
|
+
post_install_message:
|
66
68
|
rdoc_options: []
|
67
69
|
require_paths:
|
68
70
|
- lib
|
69
71
|
- ext
|
70
72
|
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
73
|
requirements:
|
73
|
-
- -
|
74
|
+
- - ">="
|
74
75
|
- !ruby/object:Gem::Version
|
75
76
|
version: '0'
|
76
|
-
segments:
|
77
|
-
- 0
|
78
|
-
hash: 1767711018481939965
|
79
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
78
|
requirements:
|
82
|
-
- -
|
79
|
+
- - ">="
|
83
80
|
- !ruby/object:Gem::Version
|
84
81
|
version: '0'
|
85
|
-
segments:
|
86
|
-
- 0
|
87
|
-
hash: 1767711018481939965
|
88
82
|
requirements: []
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
specification_version: 3
|
83
|
+
rubygems_version: 3.4.6
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
93
86
|
summary: A simple wrapper around Exiv2
|
94
|
-
test_files:
|
95
|
-
- spec/exiv2_spec.rb
|
96
|
-
- spec/files/photo_with_utf8_description.jpg
|
97
|
-
- spec/files/test.jpg
|
87
|
+
test_files: []
|
data/.gitignore
DELETED
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--colour
|
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
exiv2 (0.0.8)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: http://rubygems.org/
|
8
|
-
specs:
|
9
|
-
diff-lcs (1.1.2)
|
10
|
-
rake (0.8.7)
|
11
|
-
rake-compiler (0.7.5)
|
12
|
-
rake
|
13
|
-
rspec (2.4.0)
|
14
|
-
rspec-core (~> 2.4.0)
|
15
|
-
rspec-expectations (~> 2.4.0)
|
16
|
-
rspec-mocks (~> 2.4.0)
|
17
|
-
rspec-core (2.4.0)
|
18
|
-
rspec-expectations (2.4.0)
|
19
|
-
diff-lcs (~> 1.1.2)
|
20
|
-
rspec-mocks (2.4.0)
|
21
|
-
|
22
|
-
PLATFORMS
|
23
|
-
ruby
|
24
|
-
|
25
|
-
DEPENDENCIES
|
26
|
-
exiv2!
|
27
|
-
rake-compiler
|
28
|
-
rspec
|
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.
|
data/Rakefile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'rspec/core/rake_task'
|
2
|
-
RSpec::Core::RakeTask.new(:spec)
|
3
|
-
task :default => :spec
|
4
|
-
|
5
|
-
require 'rake/extensiontask'
|
6
|
-
Rake::ExtensionTask.new('exiv2') do |ext|
|
7
|
-
ext.lib_dir = "lib/exiv2"
|
8
|
-
if ENV['EXIV2_DIR']
|
9
|
-
ext.config_options << "--with-exiv2-dir=#{ENV['EXIV2_DIR']}"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
Rake::Task[:spec].prerequisites << :compile
|
13
|
-
|
14
|
-
require 'bundler'
|
15
|
-
Bundler::GemHelper.install_tasks
|
16
|
-
|
data/exiv2.gemspec
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "exiv2/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "exiv2"
|
7
|
-
s.version = Exiv2::VERSION
|
8
|
-
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Pete Yandell"]
|
10
|
-
s.email = ["pete@envato.com"]
|
11
|
-
s.homepage = "https://github.com/envato/exiv2"
|
12
|
-
s.summary = %q{A simple wrapper around Exiv2}
|
13
|
-
s.description = %q{A simple wrapper around the C++ Exiv2 libary for reading image metadata}
|
14
|
-
|
15
|
-
s.rubyforge_project = "exiv2"
|
16
|
-
|
17
|
-
s.add_development_dependency "rspec"
|
18
|
-
s.add_development_dependency "rake-compiler"
|
19
|
-
|
20
|
-
s.files = `git ls-files`.split("\n")
|
21
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
-
s.require_paths = ["lib", "ext"]
|
24
|
-
s.extensions = ["ext/exiv2/extconf.rb"]
|
25
|
-
end
|
data/spec/exiv2_spec.rb
DELETED
@@ -1,227 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
require 'bundler/setup'
|
3
|
-
require 'exiv2'
|
4
|
-
require 'fileutils'
|
5
|
-
|
6
|
-
describe Exiv2 do
|
7
|
-
|
8
|
-
it "should handle a Pathname being passed to open" do
|
9
|
-
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/test.jpg").to_s)
|
10
|
-
image.read_metadata
|
11
|
-
image.iptc_data.to_hash.should_not be_empty
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should raise an error when trying to open a non-existant file" do
|
15
|
-
expect {
|
16
|
-
Exiv2::ImageFactory.open("tmp/no-such-file.jpg")
|
17
|
-
}.should raise_error(Exiv2::BasicError)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should write metadata" do
|
21
|
-
FileUtils.cp("spec/files/test.jpg", "spec/files/test_tmp.jpg")
|
22
|
-
image = Exiv2::ImageFactory.open("spec/files/test_tmp.jpg")
|
23
|
-
image.read_metadata
|
24
|
-
image.iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
25
|
-
image.write_metadata
|
26
|
-
image = nil
|
27
|
-
|
28
|
-
image2 = Exiv2::ImageFactory.open("spec/files/test_tmp.jpg")
|
29
|
-
image2.read_metadata
|
30
|
-
image2.iptc_data["Iptc.Application2.Caption"].should == "A New Caption"
|
31
|
-
FileUtils.rm("spec/files/test_tmp.jpg")
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'reads UTF-8 data' do
|
35
|
-
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/photo_with_utf8_description.jpg").to_s)
|
36
|
-
image.read_metadata
|
37
|
-
description = image.exif_data["Exif.Image.ImageDescription"]
|
38
|
-
if description.respond_to? :encoding # Only in Ruby 1.9+
|
39
|
-
description.encoding.should == Encoding::UTF_8
|
40
|
-
end
|
41
|
-
description.should == 'UTF-8 description. ☃ł㌎'
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'reads UTF-8 data in each' do
|
45
|
-
if String.new.respond_to? :encoding # Only in Ruby 1.9+
|
46
|
-
image = Exiv2::ImageFactory.open(Pathname.new("spec/files/photo_with_utf8_description.jpg").to_s)
|
47
|
-
image.read_metadata
|
48
|
-
image.exif_data.each do |key,value|
|
49
|
-
key.encoding.should == Encoding::UTF_8
|
50
|
-
value.encoding.should == Encoding::UTF_8
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
let(:image) do
|
56
|
-
image = Exiv2::ImageFactory.open("spec/files/test.jpg")
|
57
|
-
image.read_metadata
|
58
|
-
image
|
59
|
-
end
|
60
|
-
|
61
|
-
context "IPTC data" do
|
62
|
-
before do
|
63
|
-
@iptc_data = image.iptc_data
|
64
|
-
end
|
65
|
-
|
66
|
-
it "should read IPTC data" do
|
67
|
-
@iptc_data.should be_a(Exiv2::IptcData)
|
68
|
-
@iptc_data.inspect.should == '#<Exiv2::IptcData: {"Iptc.Application2.Caption"=>"Rhubarb rhubarb rhubard", "Iptc.Application2.Keywords"=>["fish", "custard"]}>'
|
69
|
-
@iptc_data.to_a.should == [
|
70
|
-
["Iptc.Application2.Caption", "Rhubarb rhubarb rhubard"],
|
71
|
-
["Iptc.Application2.Keywords", "fish"],
|
72
|
-
["Iptc.Application2.Keywords", "custard"]
|
73
|
-
]
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should convert iptc data into a hash" do
|
77
|
-
iptc_hash = @iptc_data.to_hash
|
78
|
-
iptc_hash.should be_a(Hash)
|
79
|
-
iptc_hash.should == {
|
80
|
-
"Iptc.Application2.Caption" => "Rhubarb rhubarb rhubard",
|
81
|
-
"Iptc.Application2.Keywords" => ["fish", "custard"]
|
82
|
-
}
|
83
|
-
end
|
84
|
-
|
85
|
-
it "should write IPTC data" do
|
86
|
-
@iptc_data.add("Iptc.Application2.Keywords", "fishy")
|
87
|
-
@iptc_data.to_a.should == [
|
88
|
-
["Iptc.Application2.Caption", "Rhubarb rhubarb rhubard"],
|
89
|
-
["Iptc.Application2.Keywords", "fish"],
|
90
|
-
["Iptc.Application2.Keywords", "custard"],
|
91
|
-
["Iptc.Application2.Keywords", "fishy"]
|
92
|
-
]
|
93
|
-
end
|
94
|
-
|
95
|
-
it "should set IPTC data" do
|
96
|
-
@iptc_data["Iptc.Application2.Caption"] = "A New Caption"
|
97
|
-
@iptc_data.to_hash["Iptc.Application2.Caption"].should == "A New Caption"
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should set multiply IPTC data values" do
|
101
|
-
@iptc_data["Iptc.Application2.Keywords"] = ["abc", "cde"]
|
102
|
-
@iptc_data.to_hash["Iptc.Application2.Keywords"].should == ["abc", "cde"]
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should delete one value of IPTC data" do
|
106
|
-
@iptc_data.delete("Iptc.Application2.Keywords")
|
107
|
-
@iptc_data.to_hash["Iptc.Application2.Keywords"].should == "custard"
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should delete all values of IPTC data" do
|
111
|
-
@iptc_data.delete_all("Iptc.Application2.Keywords")
|
112
|
-
@iptc_data.to_hash["Iptc.Application2.Keywords"].should == nil
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
context "XMP data" do
|
117
|
-
before do
|
118
|
-
@xmp_data = image.xmp_data
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should read XMP data" do
|
122
|
-
@xmp_data.should be_a(Exiv2::XmpData)
|
123
|
-
@xmp_data.inspect.should == '#<Exiv2::XmpData: {"Xmp.dc.description"=>"lang=\"x-default\" This is a description", "Xmp.dc.title"=>"lang=\"x-default\" Pickled"}>'
|
124
|
-
@xmp_data.to_a.should == [
|
125
|
-
["Xmp.dc.title", "lang=\"x-default\" Pickled"],
|
126
|
-
["Xmp.dc.description", "lang=\"x-default\" This is a description"]
|
127
|
-
]
|
128
|
-
end
|
129
|
-
|
130
|
-
it "should convert xmp data into a hash" do
|
131
|
-
xmp_hash = @xmp_data.to_hash
|
132
|
-
xmp_hash.should be_a(Hash)
|
133
|
-
xmp_hash.should == {
|
134
|
-
"Xmp.dc.title" => "lang=\"x-default\" Pickled",
|
135
|
-
"Xmp.dc.description" => "lang=\"x-default\" This is a description"
|
136
|
-
}
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should write XMP data" do
|
140
|
-
@xmp_data["Xmp.dc.title"] = "lang=\"x-default\" Changed!"
|
141
|
-
@xmp_data.to_hash["Xmp.dc.title"].should == "lang=\"x-default\" Changed!"
|
142
|
-
end
|
143
|
-
|
144
|
-
it "should set XMP data" do
|
145
|
-
@xmp_data["Xmp.dc.title"] = "A New Title"
|
146
|
-
@xmp_data.to_hash["Xmp.dc.title"].should == "lang=\"x-default\" A New Title"
|
147
|
-
end
|
148
|
-
|
149
|
-
it "should set multiply XMP data values" do
|
150
|
-
@xmp_data["Xmp.dc.title"] = ["abc", "cde"]
|
151
|
-
@xmp_data.to_hash["Xmp.dc.title"].should == ["lang=\"x-default\" abc", "lang=\"x-default\" cde"]
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should delete one value of XMP data" do
|
155
|
-
@xmp_data["Xmp.dc.title"] = ["abc", "cde"]
|
156
|
-
@xmp_data.delete("Xmp.dc.title")
|
157
|
-
@xmp_data.to_hash["Xmp.dc.title"].should == "lang=\"x-default\" cde"
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should delete all values of XMP data" do
|
161
|
-
@xmp_data.delete_all("Xmp.dc.title")
|
162
|
-
@xmp_data.to_hash["Xmp.dc.title"].should == nil
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
context "EXIF data" do
|
167
|
-
before do
|
168
|
-
@exif_data = image.exif_data
|
169
|
-
end
|
170
|
-
|
171
|
-
it "should read Exif data" do
|
172
|
-
@exif_data.should be_a(Exiv2::ExifData)
|
173
|
-
@exif_data.inspect.should == '#<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
|
-
@exif_data.to_a.should == [
|
175
|
-
["Exif.Image.Software", "plasq skitch"],
|
176
|
-
["Exif.Image.ExifTag", "52"],
|
177
|
-
["Exif.Photo.ExifVersion", "48 50 49 48"],
|
178
|
-
["Exif.Photo.PixelXDimension", "32"],
|
179
|
-
["Exif.Photo.PixelYDimension", "32"]
|
180
|
-
]
|
181
|
-
end
|
182
|
-
|
183
|
-
it "should convert xmp data into a hash" do
|
184
|
-
exif_hash = @exif_data.to_hash
|
185
|
-
exif_hash.should be_a(Hash)
|
186
|
-
exif_hash.should == {
|
187
|
-
"Exif.Photo.PixelXDimension" => "32",
|
188
|
-
"Exif.Photo.ExifVersion" => "48 50 49 48",
|
189
|
-
"Exif.Image.Software" => "plasq skitch",
|
190
|
-
"Exif.Photo.PixelYDimension" => "32",
|
191
|
-
"Exif.Image.ExifTag" => "52"
|
192
|
-
}
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should write Exif data" do
|
196
|
-
@exif_data.add("Exif.Image.Software", "ruby-exiv2")
|
197
|
-
@exif_data.to_hash.should == {
|
198
|
-
"Exif.Photo.PixelXDimension" => "32",
|
199
|
-
"Exif.Photo.ExifVersion" => "48 50 49 48",
|
200
|
-
"Exif.Image.Software" => ["plasq skitch", "ruby-exiv2"],
|
201
|
-
"Exif.Photo.PixelYDimension" => "32",
|
202
|
-
"Exif.Image.ExifTag" => "52"
|
203
|
-
}
|
204
|
-
end
|
205
|
-
|
206
|
-
it "should set Exif data" do
|
207
|
-
@exif_data["Exif.Image.Software"] = "ruby-exiv2"
|
208
|
-
@exif_data.to_hash["Exif.Image.Software"].should == "ruby-exiv2"
|
209
|
-
end
|
210
|
-
|
211
|
-
it "should set multiply Exif data values" do
|
212
|
-
@exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"]
|
213
|
-
@exif_data.to_hash["Exif.Image.Software"].should == ["ruby-exiv2", "plasq skitch"]
|
214
|
-
end
|
215
|
-
|
216
|
-
it "should delete one value of Exif data" do
|
217
|
-
@exif_data["Exif.Image.Software"] = ["ruby-exiv2", "plasq skitch"]
|
218
|
-
@exif_data.delete("Exif.Image.Software")
|
219
|
-
@exif_data.to_hash["Exif.Image.Software"].should == "plasq skitch"
|
220
|
-
end
|
221
|
-
|
222
|
-
it "should delete all values of Exif data" do
|
223
|
-
@exif_data.delete_all("Exif.Image.Software")
|
224
|
-
@exif_data.to_hash["Exif.Image.Software"].should == nil
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
Binary file
|
data/spec/files/test.jpg
DELETED
Binary file
|