exiv2 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +12 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +28 -0
- data/LICENSE +20 -0
- data/README.rdoc +48 -0
- data/Rakefile +12 -0
- data/exiv2.gemspec +25 -0
- data/ext/exiv2/exiv2.cpp +111 -0
- data/ext/exiv2/extconf.rb +4 -0
- data/lib/exiv2.rb +1 -0
- data/lib/exiv2/version.rb +3 -0
- data/spec/exiv2_spec.rb +17 -0
- data/spec/files/test.jpg +0 -0
- metadata +109 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
exiv2 (0.0.1)
|
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/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Envato & Pete Yandell.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
= Exiv2
|
2
|
+
|
3
|
+
A simple wrapper around the C++ Exiv2 libary for reading image metadata.
|
4
|
+
|
5
|
+
See http://www.exiv2.org/
|
6
|
+
|
7
|
+
== Usage
|
8
|
+
|
9
|
+
gem install exiv2
|
10
|
+
|
11
|
+
require 'exiv2'
|
12
|
+
image = Exiv2::ImageFactory.open("image.jpg")
|
13
|
+
image.read_metadata
|
14
|
+
puts image.exif_data.inspect
|
15
|
+
puts image.iptc_data.inspect
|
16
|
+
|
17
|
+
== Why?
|
18
|
+
|
19
|
+
None of the existing Ruby libraries for reading image metadata did quite what
|
20
|
+
we wanted, so we figured it wouldn't be too hard to wrap enough of Exiv2 to
|
21
|
+
meet our needs.
|
22
|
+
|
23
|
+
The intention is to just mirror the Exiv2 API in Ruby, so the path to extending
|
24
|
+
this to support more of Exiv2's functionality should be straightforward. Patches
|
25
|
+
are welcome.
|
26
|
+
|
27
|
+
== Compatibility
|
28
|
+
|
29
|
+
Tested with Ruby 1.8.7 and Exiv2 0.21.
|
30
|
+
|
31
|
+
== Developing
|
32
|
+
|
33
|
+
* Fork the project.
|
34
|
+
* Make your feature addition or bug fix.
|
35
|
+
* Add tests for it. This is important so I don't break it in a
|
36
|
+
future version unintentionally.
|
37
|
+
* Commit, do not mess with rakefile, version, or history.
|
38
|
+
(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)
|
39
|
+
* Send me a pull request. Bonus points for topic branches.
|
40
|
+
|
41
|
+
== Status
|
42
|
+
|
43
|
+
In early development. Very little of Exiv2's API is supported, and it hasn't
|
44
|
+
been heavily tested.
|
45
|
+
|
46
|
+
== Copyright
|
47
|
+
|
48
|
+
Copyright (c) 2010 Envato & Pete Yandell. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
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
|
+
end
|
9
|
+
Rake::Task[:spec].prerequisites << :compile
|
10
|
+
|
11
|
+
require 'bundler'
|
12
|
+
Bundler::GemHelper.install_tasks
|
data/exiv2.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
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/ext/exiv2/exiv2.cpp
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
#include "exiv2/image.hpp"
|
2
|
+
#include "ruby.h"
|
3
|
+
|
4
|
+
// Create a Ruby string from a C++ std::string.
|
5
|
+
static VALUE to_ruby_string(const std::string& string) {
|
6
|
+
return rb_str_new(string.data(), string.length());
|
7
|
+
}
|
8
|
+
|
9
|
+
// Create a C++ std::string from a Ruby string.
|
10
|
+
static std::string to_std_string(VALUE string) {
|
11
|
+
return std::string(RSTRING(string)->ptr, RSTRING(string)->len);
|
12
|
+
}
|
13
|
+
|
14
|
+
// Extract data from an Exiv2::IptcData or an Exiv2::ExifData into a Ruby hash.
|
15
|
+
template <class T>
|
16
|
+
static VALUE data_to_hash(T& data) {
|
17
|
+
VALUE hash = rb_hash_new();
|
18
|
+
|
19
|
+
for(typename T::iterator i = data.begin(); i != data.end(); i++) {
|
20
|
+
VALUE key = to_ruby_string(i->key());
|
21
|
+
VALUE value = to_ruby_string(i->value().toString());
|
22
|
+
rb_hash_aset(hash, key, value);
|
23
|
+
}
|
24
|
+
|
25
|
+
return hash;
|
26
|
+
}
|
27
|
+
|
28
|
+
extern "C" {
|
29
|
+
typedef VALUE (*Method)(...);
|
30
|
+
|
31
|
+
static VALUE exiv2_module;
|
32
|
+
|
33
|
+
static VALUE basic_error_class;
|
34
|
+
|
35
|
+
static VALUE image_class;
|
36
|
+
static void image_free(Exiv2::Image* image);
|
37
|
+
static VALUE image_read_metadata(VALUE self);
|
38
|
+
static VALUE image_iptc_data(VALUE self);
|
39
|
+
static VALUE image_exif_data(VALUE self);
|
40
|
+
|
41
|
+
static VALUE image_factory_class;
|
42
|
+
static VALUE image_factory_open(VALUE klass, VALUE path);
|
43
|
+
|
44
|
+
|
45
|
+
void Init_exiv2() {
|
46
|
+
exiv2_module = rb_define_module("Exiv2");
|
47
|
+
|
48
|
+
basic_error_class = rb_define_class_under(exiv2_module, "BasicError", rb_eRuntimeError);
|
49
|
+
|
50
|
+
image_class = rb_define_class_under(exiv2_module, "Image", rb_cObject);
|
51
|
+
rb_define_method(image_class, "read_metadata", (Method)image_read_metadata, 0);
|
52
|
+
rb_define_method(image_class, "iptc_data", (Method)image_iptc_data, 0);
|
53
|
+
rb_define_method(image_class, "exif_data", (Method)image_exif_data, 0);
|
54
|
+
|
55
|
+
image_factory_class = rb_define_class_under(exiv2_module, "ImageFactory", rb_cObject);
|
56
|
+
rb_define_singleton_method(image_factory_class, "open", (Method)image_factory_open, 1);
|
57
|
+
}
|
58
|
+
|
59
|
+
|
60
|
+
// Exiv2::Image Methods
|
61
|
+
|
62
|
+
static void image_free(Exiv2::Image* image) {
|
63
|
+
delete image;
|
64
|
+
}
|
65
|
+
|
66
|
+
static VALUE image_read_metadata(VALUE self) {
|
67
|
+
Exiv2::Image* image;
|
68
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
69
|
+
|
70
|
+
try {
|
71
|
+
image->readMetadata();
|
72
|
+
}
|
73
|
+
catch (Exiv2::BasicError<char> error) {
|
74
|
+
rb_raise(basic_error_class, "%s", error.what());
|
75
|
+
}
|
76
|
+
|
77
|
+
return Qnil;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE image_exif_data(VALUE self) {
|
81
|
+
Exiv2::Image* image;
|
82
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
83
|
+
|
84
|
+
return data_to_hash<Exiv2::ExifData>(image->exifData());
|
85
|
+
}
|
86
|
+
|
87
|
+
static VALUE image_iptc_data(VALUE self) {
|
88
|
+
Exiv2::Image* image;
|
89
|
+
Data_Get_Struct(self, Exiv2::Image, image);
|
90
|
+
|
91
|
+
return data_to_hash<Exiv2::IptcData>(image->iptcData());
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
// Exiv2::ImageFactory methods
|
96
|
+
|
97
|
+
static VALUE image_factory_open(VALUE klass, VALUE path) {
|
98
|
+
Exiv2::Image* image;
|
99
|
+
|
100
|
+
try {
|
101
|
+
Exiv2::Image::AutoPtr image_auto_ptr = Exiv2::ImageFactory::open(to_std_string(path));
|
102
|
+
image = image_auto_ptr.release(); // Release the AutoPtr, so we can keep the image around.
|
103
|
+
}
|
104
|
+
catch (Exiv2::BasicError<char> error) {
|
105
|
+
rb_raise(basic_error_class, "%s", error.what());
|
106
|
+
}
|
107
|
+
|
108
|
+
return Data_Wrap_Struct(image_class, 0, image_free, image);
|
109
|
+
}
|
110
|
+
|
111
|
+
}
|
data/lib/exiv2.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'exiv2/exiv2'
|
data/spec/exiv2_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'exiv2'
|
2
|
+
|
3
|
+
describe Exiv2 do
|
4
|
+
it "should read IPTC data" do
|
5
|
+
image = Exiv2::ImageFactory.open("spec/files/test.jpg")
|
6
|
+
image.read_metadata
|
7
|
+
image.iptc_data.should == {
|
8
|
+
"Iptc.Application2.Caption" => "Rhubarb rhubarb rhubard"
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise an error when trying to open a non-existant file" do
|
13
|
+
expect {
|
14
|
+
Exiv2::ImageFactory.open("tmp/no-such-file.jpg")
|
15
|
+
}.should raise_error(Exiv2::BasicError)
|
16
|
+
end
|
17
|
+
end
|
data/spec/files/test.jpg
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exiv2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Pete Yandell
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-24 00:00:00 +11:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rake-compiler
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
description: A simple wrapper around the C++ Exiv2 libary for reading image metadata
|
50
|
+
email:
|
51
|
+
- pete@envato.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions:
|
55
|
+
- ext/exiv2/extconf.rb
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- .gitignore
|
60
|
+
- Gemfile
|
61
|
+
- Gemfile.lock
|
62
|
+
- LICENSE
|
63
|
+
- README.rdoc
|
64
|
+
- Rakefile
|
65
|
+
- exiv2.gemspec
|
66
|
+
- ext/exiv2/exiv2.cpp
|
67
|
+
- ext/exiv2/extconf.rb
|
68
|
+
- lib/exiv2.rb
|
69
|
+
- lib/exiv2/version.rb
|
70
|
+
- spec/exiv2_spec.rb
|
71
|
+
- spec/files/test.jpg
|
72
|
+
has_rdoc: true
|
73
|
+
homepage: https://github.com/envato/exiv2
|
74
|
+
licenses: []
|
75
|
+
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
- ext
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
hash: 3
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
requirements: []
|
101
|
+
|
102
|
+
rubyforge_project: exiv2
|
103
|
+
rubygems_version: 1.3.7
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: A simple wrapper around Exiv2
|
107
|
+
test_files:
|
108
|
+
- spec/exiv2_spec.rb
|
109
|
+
- spec/files/test.jpg
|