ruby-exiv2 1.3 → 1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README CHANGED
@@ -2,6 +2,7 @@ Library for handling exif image tags.
2
2
 
3
3
  Basic usage:
4
4
 
5
+ > gem install RubyInline
5
6
  > gem install ruby-exiv2
6
7
  > irb -r rubygems
7
8
 
data/Rakefile CHANGED
@@ -6,17 +6,11 @@ require 'rake/packagetask'
6
6
  require 'rake/contrib/rubyforgepublisher'
7
7
 
8
8
  PKG_NAME = "ruby-exiv2"
9
- PKG_VERSION = "1.3"
9
+ PKG_VERSION = "1.5"
10
10
  PKG_AUTHOR = "Max Lapshin"
11
11
  PKG_EMAIL = "max@maxidoors.ru"
12
- PKG_HOMEPAGE = "http://maxidoors.ru/"
12
+ PKG_HOMEPAGE = "http://github.com/maxlapshin/exiv2"
13
13
  PKG_SUMMARY = "Exiv2 (exif image tags handling) library driver"
14
- PKG_SVN = "http://svn.maxidoors.ru/ruby-exiv2"
15
- PKG_RDOC_OPTS = ['--main=README',
16
- '--line-numbers',
17
- '--webcvs='+PKG_SVN,
18
- '--charset=utf-8',
19
- '--promiscuous']
20
14
 
21
15
 
22
16
  spec = Gem::Specification.new do |s|
@@ -29,19 +23,16 @@ spec = Gem::Specification.new do |s|
29
23
  s.summary = PKG_SUMMARY
30
24
  s.require_path = "lib"
31
25
  s.rubyforge_project = PKG_NAME
32
- s.files = %w(README Rakefile setup.rb init.rb) +
26
+ s.files = %w(README Rakefile init.rb) +
33
27
  Dir.glob("{test}/**/*") +
34
- Dir.glob("ext/**/*.{h,cpp,rb,hpp}") +
35
- Dir.glob("lib/**/*.rb")
28
+ Dir.glob("lib/**/*.{rb,cpp,hpp}")
36
29
  s.test_files = FileList["{test}/**/*.rb"].to_a
37
30
  s.has_rdoc = true
38
31
  s.extra_rdoc_files = ["README"]
39
- s.rdoc_options = PKG_RDOC_OPTS
40
- s.extensions << 'ext/extconf.rb'
41
32
  end
42
33
 
43
34
  Rake::GemPackageTask.new(spec) do |pkg|
44
- pkg.need_tar = true
35
+ pkg.need_tar = false
45
36
  end
46
37
 
47
38
  task :default => [ :test ]
@@ -77,7 +68,6 @@ Rake::RDocTask.new("doc") do |rdoc|
77
68
  rdoc.rdoc_files.include('README')
78
69
  # rdoc.rdoc_files.include('CHANGELOG')
79
70
  # rdoc.rdoc_files.include('TODO')
80
- rdoc.options = PKG_RDOC_OPTS
81
71
  rdoc.rdoc_files.include "ruby-exiv2.cpp"
82
72
  end
83
73
 
@@ -109,18 +99,4 @@ task :push_docs do
109
99
  ].each { |p| p.upload }
110
100
  end
111
101
 
112
- desc "Build binary driver"
113
- task :build do
114
- puts `cd lib; [ -e Makefile ] || ruby extconf.rb; make`
115
- end
116
-
117
- desc "Rebuild binary driver"
118
- task :rebuild do
119
- puts `cd lib; ruby extconf.rb; make clean all`
120
- end
121
102
 
122
- desc "Mark files in SVN"
123
- task :release => [:clobber, :package] do
124
- svn_aware_revision = 'r_' + PKG_VERSION.gsub(/-|\./, '_')
125
- puts `svn copy #{PKG_SVN}/trunk #{PKG_SVN}/tags/#{svn_aware_revision} -m "release #{svn_aware_revision}"`
126
- end
@@ -89,7 +89,7 @@ void rb_exiv2_throw(const char* file, long unsigned int line, const char *fmt, .
89
89
  #if defined(__cplusplus)
90
90
  extern "C" {
91
91
  #endif
92
- void Init_exiv2(void);
92
+ //void Init_exiv2(void);
93
93
  extern VALUE mExiv2, cImage, cExif, cTag, cIptc, eError;
94
94
 
95
95
  #if defined(__cplusplus)
@@ -105,9 +105,9 @@ struct rbImage {
105
105
  VALUE unmarshall_value(const Exiv2::Value& value);
106
106
 
107
107
 
108
- void Init_image();
109
- void Init_exif();
110
- void Init_iptc();
108
+ //void Init_image();
109
+ //void Init_exif();
110
+ //void Init_iptc();
111
111
 
112
112
 
113
113
  #endif /* EXIV2_HPP_ */
@@ -1,38 +1,32 @@
1
- begin
2
- require File.dirname(__FILE__)+'/exiv2_bin'
3
- rescue LoadError
4
- require File.dirname(__FILE__)+'/../ext/exiv2_bin'
5
- end
6
1
  require 'enumerator'
7
2
  require 'rubygems'
3
+ require 'inline'
8
4
  require 'active_support'
5
+ require 'erb'
9
6
 
10
7
  module Exiv2
11
- #
12
- class Image
13
-
14
- # method [] is used to read exif or iptc data
15
- def [](key)
16
- return exif[key] if key[0...4] == "Exif"
17
- return iptc[key] if key[0...4] == "Iptc"
18
- end
19
-
20
- # method []= is used to set exif or iptc data
21
- def []=(key, value)
22
- return exif[key] = value if key[0...4] == "Exif"
23
- return iptc[key] = value if key[0...4] == "Iptc"
24
- raise Exiv2::Error, "Unknown key for writing: #{key.inspect}"
25
- end
26
-
27
- # clues together Iptc.Application2.DateCreated and Iptc.Application2.TimeCreated if possible
28
- def created_at
29
- date = iptc["Iptc.Application2.DateCreated"]
30
- time = iptc["Iptc.Application2.TimeCreated"]
31
- return date unless time
32
- Time.utc(date.year, date.month, date.day, time.hour, time.min, time.sec)
33
- end
8
+ def self.prepare_builder(builder)
9
+ Config::CONFIG["CPP"] = "g++ -E "
10
+ Config::CONFIG["CC"] = "g++ "
11
+ Config::CONFIG["LDSHARED"].gsub!(/^cc /,"g++ ")
12
+ builder.include "<exiv2.hpp>"
13
+ builder.add_compile_flags "-x c++ -I#{File.dirname(__FILE__)} -I/usr/local/include/exiv2", '-lstdc++ -lexiv2'
14
+ builder.include_ruby_last
34
15
  end
35
16
 
17
+ def self.load(&block)
18
+ ERB.new(File.read(File.dirname(__FILE__)+"/exiv2/" + block.call)).result(block.binding)
19
+ end
20
+ end
21
+
22
+ require 'exiv2/image'
23
+ require 'exiv2/exif'
24
+ require 'exiv2/iptc'
25
+ require 'exiv2/tag'
26
+
27
+ module Exiv2
28
+ class Error < StandardError; end
29
+
36
30
  class SubTagAccess
37
31
  def initialize(class_name, sub_tag, parent)
38
32
  @class_name = class_name.split("::").last
@@ -0,0 +1,19 @@
1
+ module Exiv2
2
+ class Exif
3
+ inline do |builder|
4
+ kind = "Exif"
5
+ Exiv2::prepare_builder(builder)
6
+ builder.prefix(Exiv2::load {"metadata/marshall.cpp"})
7
+ builder.prefix(Exiv2::load {"metadata/unmarshall.cpp"})
8
+ builder.prefix(Exiv2::load {"throw.cpp"})
9
+
10
+ builder.c(Exiv2::load {"metadata/get.cpp"}, {:method_name => "[]"})
11
+ builder.c(Exiv2::load {"metadata/set.cpp"}, {:method_name => "[]="})
12
+ builder.c_raw(Exiv2::load {"metadata/each.cpp"}, {:method_name => "each"})
13
+ builder.c(Exiv2::load {"metadata/delete.cpp"}, {:method_name => "delete"})
14
+ builder.c(Exiv2::load {"metadata/clear.cpp"}, {:method_name => "clear"})
15
+ builder.c(Exiv2::load {"metadata/count.cpp"}, {:method_name => "count"})
16
+ builder.c(Exiv2::load {"metadata/is_empty.cpp"}, {:method_name => "empty?"})
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,205 @@
1
+ module Exiv2
2
+ class Image
3
+ # method [] is used to read exif or iptc data
4
+ def [](key)
5
+ return exif[key] if key[0...4] == "Exif"
6
+ return iptc[key] if key[0...4] == "Iptc"
7
+ end
8
+
9
+ # method []= is used to set exif or iptc data
10
+ def []=(key, value)
11
+ return exif[key] = value if key[0...4] == "Exif"
12
+ return iptc[key] = value if key[0...4] == "Iptc"
13
+ raise Exiv2::Error, "Unknown key for writing: #{key.inspect}"
14
+ end
15
+
16
+ # clues together Iptc.Application2.DateCreated and Iptc.Application2.TimeCreated if possible
17
+ def created_at
18
+ date = iptc["Iptc.Application2.DateCreated"]
19
+ time = iptc["Iptc.Application2.TimeCreated"]
20
+ return date unless time
21
+ Time.utc(date.year, date.month, date.day, time.hour, time.min, time.sec)
22
+ end
23
+
24
+
25
+
26
+
27
+
28
+ inline do |builder|
29
+ Exiv2.prepare_builder(builder)
30
+ builder.prefix <<-PREFIX
31
+ VALUE mExiv2, cImage, cExif, cTag, cIptc, cThumbnail, eError;
32
+
33
+
34
+ static void image_real_save(rbImage* image) {
35
+ if(image->dirty) {
36
+ image->image->writeMetadata();
37
+ image->dirty = false;
38
+ }
39
+ }
40
+
41
+ static void image_leave(rbImage* image) {
42
+ }
43
+
44
+ static void image_delete(rbImage* image) {
45
+ __BEGIN
46
+ image_real_save(image);
47
+ delete image;
48
+ __VOID_END
49
+ }
50
+ PREFIX
51
+
52
+ builder.c_singleton <<-EOF, :method_name => "new"
53
+ static VALUE exiv2_image_alloc_and_initialize(VALUE file) {
54
+ __BEGIN
55
+ rbImage* image = new rbImage();
56
+ VALUE rb_image = Data_Wrap_Struct(self, 0, image_delete, image);
57
+ image->dirty = false;
58
+
59
+
60
+ try {
61
+ if(!strcmp(rb_class2name(rb_class_of(file)), "StringIO")) {
62
+ rb_iv_set(rb_image, "@content", file);
63
+ VALUE string = rb_funcall(file, rb_intern("string"), 0);
64
+ image->image = Exiv2::ImageFactory::open(CBSTR(string), LEN(string));
65
+ } else if(rb_respond_to(file, rb_intern("read"))) {
66
+ VALUE file_content = rb_funcall(file, rb_intern("read"), 0);
67
+ rb_iv_set(rb_image, "@file_content", file_content);
68
+ image->image = Exiv2::ImageFactory::open(CBSTR(file_content), LEN(file_content));
69
+ } else if(TYPE(file) == T_STRING) {
70
+ image->image = Exiv2::ImageFactory::open(CSTR(file));
71
+ }
72
+ image->image->readMetadata();
73
+ }
74
+ catch(const Exiv2::AnyError&) {
75
+ rb_raise(eError, "Cannot open file %s", STR(file));
76
+ }
77
+ return rb_image;
78
+ __END
79
+ }
80
+ EOF
81
+
82
+ builder.c_singleton <<-EOF, :method_name => "load_string"
83
+ static VALUE exiv2_image_load_string(VALUE string) {
84
+ __BEGIN
85
+ Check_Type(string, T_STRING);
86
+ rbImage* image = new rbImage();
87
+ image->dirty = false;
88
+ VALUE img = Data_Wrap_Struct(self, 0, image_delete, image);
89
+
90
+ image->image = Exiv2::ImageFactory::open(CBSTR(string), LEN(string));
91
+ return img;
92
+ __END
93
+ }
94
+ EOF
95
+
96
+ builder.c <<-EOF, :method_name => "save"
97
+ static VALUE exiv2_image_save() {
98
+ __BEGIN
99
+ rbImage* image;
100
+ Data_Get_Struct(self, rbImage, image);
101
+ image_real_save(image);
102
+ return self;
103
+ __END
104
+ }
105
+ EOF
106
+
107
+ builder.c <<-EOF, :method_name => "clear"
108
+ static VALUE exiv2_image_clear() {
109
+ __BEGIN
110
+ rbImage* image;
111
+ Data_Get_Struct(self, rbImage, image);
112
+ image->image->clearMetadata();
113
+ image->dirty = true;
114
+ return self;
115
+ __END
116
+ }
117
+ EOF
118
+
119
+ %w(exif iptc).each do |kind|
120
+ builder.add_to_init "rb_define_method(c, \"#{kind.classify}\", (VALUE(*)(ANYARGS))exiv2_image_#{kind}, 0);"
121
+ builder.c <<-EOF, :method_name => kind
122
+ static VALUE exiv2_image_#{kind}() {
123
+ __BEGIN
124
+ rbImage* image;
125
+ VALUE klass = rb_path2class("Exiv2::#{kind.classify}");
126
+ Data_Get_Struct(self, rbImage, image);
127
+ VALUE reader = Data_Wrap_Struct(klass, 0, image_leave, image);
128
+ rb_iv_set(reader, "@image", self);
129
+ return reader;
130
+ __END
131
+ }
132
+ EOF
133
+ end
134
+
135
+ builder.c <<-EOF, :method_name => "comment"
136
+ static VALUE exiv2_image_get_comment() {
137
+ __BEGIN
138
+ rbImage* image;
139
+ Data_Get_Struct(self, rbImage, image);
140
+ std::string comment = image->image->comment();
141
+ return rb_str_new(comment.c_str(), comment.length());
142
+ __END
143
+ }
144
+ EOF
145
+
146
+ builder.c <<-EOF, :method_name => "comment="
147
+ static VALUE exiv2_image_set_comment(VALUE comment) {
148
+ __BEGIN
149
+ rbImage* image;
150
+ Data_Get_Struct(self, rbImage, image);
151
+ switch(TYPE(comment)) {
152
+ case T_STRING: {
153
+ image->image->setComment(CSTR(comment));
154
+ image->dirty = true;
155
+ break;
156
+ }
157
+ case T_NIL: {
158
+ image->image->clearComment();
159
+ image->dirty = true;
160
+ break;
161
+ }
162
+ default: {
163
+ rb_raise(rb_eStandardError, "Can only set comment to string, or clear it with nil value");
164
+ }
165
+ }
166
+ return comment;
167
+ __END
168
+ }
169
+ EOF
170
+
171
+ builder.c <<-EOF, :method_name => "thumbnail"
172
+ static VALUE exiv2_image_thumbnail(VALUE file_name) {
173
+ __BEGIN
174
+ Check_Type(file_name, T_STRING);
175
+
176
+ rbImage* image;
177
+ Data_Get_Struct(self, rbImage, image);
178
+
179
+ Exiv2::ExifData &exifData = image->image->exifData();
180
+ // exifData.writeThumbnail(STR(file_name));
181
+ if(rb_block_given_p()) {
182
+ rb_yield(file_name);
183
+ }
184
+ return self;
185
+ __END
186
+ }
187
+ EOF
188
+
189
+ builder.c <<-EOF, :method_name => "thumbnail="
190
+ static VALUE exiv2_image_thumbnail_set(VALUE file_name) {
191
+ __BEGIN
192
+ Check_Type(file_name, T_STRING);
193
+
194
+ rbImage* image;
195
+ Data_Get_Struct(self, rbImage, image);
196
+
197
+ Exiv2::ExifData &exifData = image->image->exifData();
198
+ // exifData.setJpegThumbnail(STR(file_name));
199
+ return self;
200
+ __END
201
+ }
202
+ EOF
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,19 @@
1
+ module Exiv2
2
+ class Iptc
3
+ inline do |builder|
4
+ kind = "Iptc"
5
+ Exiv2::prepare_builder(builder)
6
+ builder.prefix(Exiv2::load {"metadata/marshall.cpp"})
7
+ builder.prefix(Exiv2::load {"metadata/unmarshall.cpp"})
8
+ builder.prefix(Exiv2::load {"throw.cpp"})
9
+
10
+ builder.c(Exiv2::load {"metadata/get.cpp"}, {:method_name => "[]"})
11
+ builder.c(Exiv2::load {"metadata/set.cpp"}, {:method_name => "[]="})
12
+ builder.c_raw(Exiv2::load {"metadata/each.cpp"}, {:method_name => "each"})
13
+ builder.c(Exiv2::load {"metadata/delete.cpp"}, {:method_name => "delete"})
14
+ builder.c(Exiv2::load {"metadata/clear.cpp"}, {:method_name => "clear"})
15
+ builder.c(Exiv2::load {"metadata/count.cpp"}, {:method_name => "count"})
16
+ builder.c(Exiv2::load {"metadata/is_empty.cpp"}, {:method_name => "empty?"})
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ static VALUE exiv2_metadata_clear() {
2
+ __BEGIN
3
+ rbImage* image;
4
+ Data_Get_Struct(self, rbImage, image);
5
+
6
+ Exiv2::<%= kind %>Data &data = image->image-><%= kind.downcase %>Data();
7
+
8
+ if(data.empty()) {
9
+ return Qnil;
10
+ }
11
+ data.clear();
12
+ return self;
13
+ __END
14
+ }
@@ -0,0 +1,10 @@
1
+ static VALUE exiv2_metadata_count() {
2
+ __BEGIN
3
+ rbImage* image;
4
+ Data_Get_Struct(self, rbImage, image);
5
+
6
+ Exiv2::<%= kind %>Data &data = image->image-><%= kind.downcase %>Data();
7
+
8
+ return INT2FIX(data.count());
9
+ __END
10
+ }
@@ -0,0 +1,23 @@
1
+ static VALUE exiv2_metadata_delete(VALUE rb_key) {
2
+ __BEGIN
3
+ rbImage* image;
4
+ Data_Get_Struct(self, rbImage, image);
5
+
6
+ VALUE strkey = rb_funcall(rb_key, rb_intern("to_s"), 0);
7
+ Exiv2::<%= kind %>Data &data = image->image-><%= kind.downcase %>Data();
8
+
9
+ if(data.empty()) {
10
+ return Qnil;
11
+ }
12
+
13
+ Exiv2::<%= kind %>Key key(STR(strkey));
14
+ Exiv2::<%= kind %>Data::iterator pos = data.findKey(key);
15
+ if (pos == data.end()) {
16
+ return Qnil;
17
+ }
18
+
19
+ std::string v = pos->toString();
20
+ data.erase(pos);
21
+ return rb_str_new(v.c_str(), v.length());
22
+ __NIL_END
23
+ }