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 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
+ [![License MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/envato/exiv2/blob/master/LICENSE)
4
+ [![Gem Version](https://img.shields.io/gem/v/exiv2.svg?maxAge=2592000)](https://rubygems.org/gems/exiv2)
5
+ [![Gem Downloads](https://img.shields.io/gem/dt/exiv2.svg?maxAge=2592000)](https://rubygems.org/gems/exiv2)
6
+ [![Build Status](https://github.com/envato/exiv2/workflows/tests/badge.svg?branch=master)](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
- extern "C" {
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
- // Exiv2::Image Methods
109
-
110
- static void image_free(Exiv2::Image* image) {
111
- delete image;
112
- }
113
-
114
- static VALUE image_read_metadata(VALUE self) {
115
- Exiv2::Image* image;
116
- Data_Get_Struct(self, Exiv2::Image, image);
117
-
118
- try {
119
- image->readMetadata();
120
- }
121
- catch (Exiv2::BasicError<char> error) {
122
- rb_raise(basic_error_class, "%s", error.what());
123
- }
124
-
125
- return Qnil;
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
- static VALUE image_write_metadata(VALUE self) {
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
- static VALUE image_exif_data(VALUE self) {
143
- Exiv2::Image* image;
144
- Data_Get_Struct(self, Exiv2::Image, image);
124
+ return Qnil;
125
+ }
145
126
 
146
- VALUE exif_data = Data_Wrap_Struct(exif_data_class, 0, 0, &image->exifData());
147
- 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.
127
+ static VALUE image_write_metadata(VALUE self) {
128
+ Exiv2::Image* image;
129
+ Data_Get_Struct(self, Exiv2::Image, image);
148
130
 
149
- return exif_data;
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
- static VALUE image_iptc_data(VALUE self) {
153
- Exiv2::Image* image;
154
- Data_Get_Struct(self, Exiv2::Image, image);
141
+ static VALUE image_exif_data(VALUE self) {
142
+ Exiv2::Image* image;
143
+ Data_Get_Struct(self, Exiv2::Image, image);
155
144
 
156
- VALUE iptc_data = Data_Wrap_Struct(iptc_data_class, 0, 0, &image->iptcData());
157
- 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.
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
- return iptc_data;
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
- static VALUE image_xmp_data(VALUE self) {
164
- Exiv2::Image* image;
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
- VALUE xmp_data = Data_Wrap_Struct(xmp_data_class, 0, 0, &image->xmpData());
168
- 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.
158
+ return iptc_data;
159
+ }
169
160
 
170
- return xmp_data;
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
- // Exiv2::ImageFactory methods
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
- static VALUE exif_data_each(VALUE self) {
192
- return metadata_each<Exiv2::ExifData>(self);
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
- Exiv2::TypeId typeId = Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId());
201
+ Exiv2::TypeId typeId = Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId());
203
202
  #else
204
- Exiv2::TypeId typeId = exifKey.defaultTypeId();
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
- static VALUE exif_data_delete(VALUE self, VALUE key) {
215
- Exiv2::ExifData* data;
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
- // Exiv2::IptcData methods
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
- static VALUE iptc_data_each(VALUE self) {
230
- return metadata_each<Exiv2::IptcData>(self);
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
- static VALUE iptc_data_add(VALUE self, VALUE key, VALUE value) {
234
- Exiv2::IptcData* data;
235
- Data_Get_Struct(self, Exiv2::IptcData, data);
236
-
237
- Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
238
- Exiv2::TypeId typeId = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
239
-
240
- Exiv2::Value::AutoPtr v = Exiv2::Value::create(typeId);
241
- v->read(to_std_string(value));
242
-
243
- if(data->add(iptcKey, v.get())) {
244
- return Qfalse;
245
- }
246
- return Qtrue;
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
- static VALUE iptc_data_delete(VALUE self, VALUE key) {
250
- Exiv2::IptcData* data;
251
- Data_Get_Struct(self, Exiv2::IptcData, data);
252
-
253
- Exiv2::IptcKey iptcKey = Exiv2::IptcKey(to_std_string(key));
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
- // Exiv2::XmpData methods
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
- static VALUE xmp_data_each(VALUE self) {
264
- return metadata_each<Exiv2::XmpData>(self);
265
- }
270
+ Exiv2::XmpKey xmpKey = Exiv2::XmpKey(to_std_string(key));
271
+ Exiv2::TypeId typeId = Exiv2::XmpProperties::propertyType(xmpKey);
266
272
 
267
- static VALUE xmp_data_add(VALUE self, VALUE key, VALUE value) {
268
- Exiv2::XmpData* data;
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
- static VALUE xmp_data_delete(VALUE self, VALUE key) {
284
- Exiv2::XmpData* data;
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
- dir_config("exiv2")
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
@@ -1,4 +1,4 @@
1
1
  # coding: utf-8
2
2
  module Exiv2
3
- VERSION = "0.0.8"
3
+ VERSION = "0.1.0"
4
4
  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.8
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: 2012-02-24 00:00:00.000000000Z
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: &2157752580 !ruby/object:Gem::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: *2157752580
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: &2157751940 !ruby/object:Gem::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: *2157751940
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.rdoc
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
- post_install_message:
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
- rubyforge_project: exiv2
90
- rubygems_version: 1.8.10
91
- signing_key:
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
@@ -1,13 +0,0 @@
1
- Makefile
2
- mkmf.log
3
- .DS_Store
4
- *.gem
5
- *.bundle
6
- *.rbc
7
- *.a
8
- *.o
9
- *.so
10
- *.dSYM
11
- pkg
12
- tmp
13
- bin
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --colour
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- gemspec
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
data/spec/files/test.jpg DELETED
Binary file