image-file 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.
- data/.autotest +16 -0
- data/.document +3 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/Gemfile +10 -0
- data/History.markdown +13 -0
- data/License.txt +23 -0
- data/README.markdown +4 -0
- data/Rakefile +14 -0
- data/autotest/discover.rb +1 -0
- data/examples/pdf.rb +15 -0
- data/ext/image_file/depend +7 -0
- data/ext/image_file/extconf.rb +25 -0
- data/ext/image_file/image.c +411 -0
- data/ext/image_file/image_file.c +12 -0
- data/ext/image_file/internal.h +79 -0
- data/ext/image_file/jpeg_reader.c +938 -0
- data/image-file.gemspec +25 -0
- data/lib/.gitignore +3 -0
- data/lib/image_file/version.rb +8 -0
- data/pkg/.gitignore +2 -0
- data/spec/image_file/image_spec.rb +48 -0
- data/spec/image_file/jpeg_reader_spec.rb +115 -0
- data/spec/image_file_spec.rb +15 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/recompile_cat.jpg +0 -0
- data/spec/support/recompile_cat.png +0 -0
- data/spec/support/recompile_cat_CMYK.jpg +0 -0
- data/tmp/.gitignore +2 -0
- metadata +100 -0
data/.autotest
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'autotest/restart'
|
2
|
+
|
3
|
+
Autotest.add_hook :initialize do |at|
|
4
|
+
at.unit_diff = 'cat'
|
5
|
+
end
|
6
|
+
|
7
|
+
Autotest.add_hook :ran_command do |at|
|
8
|
+
log_file = File.expand_path('../tmp/autotest.log', __FILE__)
|
9
|
+
File.open(log_file, 'wb') {|f|
|
10
|
+
content = at.results.join
|
11
|
+
content.gsub!(/\x1B\[(\d+)m/, '')
|
12
|
+
f.write(content)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
# vim: filetype=ruby
|
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--format documentation
|
data/Gemfile
ADDED
data/History.markdown
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
image-file release history
|
2
|
+
==========================
|
3
|
+
|
4
|
+
0.1.0 / 2010-12-16
|
5
|
+
------------------
|
6
|
+
|
7
|
+
* The first release
|
8
|
+
* Features
|
9
|
+
* support reading JPEG files of RGB color space.
|
10
|
+
* support creating Cairo::Surface from ImageFile::Image.
|
11
|
+
|
12
|
+
* Known Bugs
|
13
|
+
* reading JPEG files of CMYK color space is broken.
|
data/License.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2010 Kenta Murata
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/README.markdown
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
Bundler::GemHelper.install_tasks
|
4
|
+
|
5
|
+
require 'rake/extensiontask'
|
6
|
+
Rake::ExtensionTask.new('image_file')
|
7
|
+
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
|
10
|
+
desc "Run all examples"
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
12
|
+
|
13
|
+
task :default => [:spec]
|
14
|
+
task :spec => [:compile]
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/examples/pdf.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'image_file'
|
2
|
+
require 'cairo'
|
3
|
+
|
4
|
+
image = ImageFile::JpegReader.open(ARGV[0]).read_image
|
5
|
+
|
6
|
+
image_surface = image.create_cairo_surface
|
7
|
+
|
8
|
+
pdf = Cairo::PDFSurface.new(ARGV[1], image.width, image.height)
|
9
|
+
context = Cairo::Context.new(pdf)
|
10
|
+
|
11
|
+
context.set_source image_surface
|
12
|
+
context.paint
|
13
|
+
context.show_page
|
14
|
+
|
15
|
+
pdf.finish
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'pkg-config'
|
4
|
+
|
5
|
+
ver = RUBY_VERSION.split(/\./).join.to_i
|
6
|
+
$defs << "-DRUBY_VERSION=#{ver}"
|
7
|
+
|
8
|
+
$CFLAGS << ' -Wall -Wextra -Wshadow'
|
9
|
+
|
10
|
+
dir_config('jpeg')
|
11
|
+
have_header('jpeglib.h')
|
12
|
+
have_library('jpeg')
|
13
|
+
|
14
|
+
if PKGConfig.have_package('cairo', 1, 2, 0)
|
15
|
+
unless have_header('rb_cairo.h')
|
16
|
+
if cairo = Gem.searcher.find('cairo')
|
17
|
+
extconf_rb = File.expand_path(cairo.extensions[0], cairo.full_gem_path)
|
18
|
+
rb_cairo_h = File.expand_path('../rb_cairo.h', extconf_rb)
|
19
|
+
$CFLAGS << " -I#{File.dirname(rb_cairo_h)}"
|
20
|
+
have_header('rb_cairo.h')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
create_makefile('image_file')
|
@@ -0,0 +1,411 @@
|
|
1
|
+
#include "internal.h"
|
2
|
+
|
3
|
+
#ifdef HAVE_RB_CAIRO_H
|
4
|
+
# include <rb_cairo.h>
|
5
|
+
#endif
|
6
|
+
|
7
|
+
VALUE cImageFileImage = Qnil;
|
8
|
+
|
9
|
+
static ID id_ARGB32;
|
10
|
+
static ID id_RGB24;
|
11
|
+
static ID id_RGB16_565;
|
12
|
+
|
13
|
+
struct image_data {
|
14
|
+
VALUE buffer;
|
15
|
+
rb_image_file_image_pixel_format_t pixel_format;
|
16
|
+
long width;
|
17
|
+
long height;
|
18
|
+
long stride;
|
19
|
+
};
|
20
|
+
|
21
|
+
static void
|
22
|
+
image_mark(void* ptr)
|
23
|
+
{
|
24
|
+
struct image_data* image = (struct image_data*)ptr;
|
25
|
+
rb_gc_mark(image->buffer);
|
26
|
+
}
|
27
|
+
|
28
|
+
static void
|
29
|
+
image_free(void* ptr)
|
30
|
+
{
|
31
|
+
struct image_data* image = (struct image_data*)ptr;
|
32
|
+
image->buffer = Qnil;
|
33
|
+
xfree(image);
|
34
|
+
}
|
35
|
+
|
36
|
+
static size_t
|
37
|
+
image_memsize(void const* ptr)
|
38
|
+
{
|
39
|
+
return ptr ? sizeof(struct image_data) : 0;
|
40
|
+
}
|
41
|
+
|
42
|
+
static rb_data_type_t const image_data_type = {
|
43
|
+
"image_file::image",
|
44
|
+
#if RUBY_VERSION >= 193
|
45
|
+
{
|
46
|
+
#endif
|
47
|
+
image_mark,
|
48
|
+
image_free,
|
49
|
+
image_memsize,
|
50
|
+
#if RUBY_VERSION >= 193
|
51
|
+
},
|
52
|
+
#endif
|
53
|
+
};
|
54
|
+
|
55
|
+
static VALUE
|
56
|
+
image_alloc(VALUE const klass)
|
57
|
+
{
|
58
|
+
struct image_data* image;
|
59
|
+
VALUE obj = TypedData_Make_Struct(klass, struct image_data, &image_data_type, image);
|
60
|
+
image->buffer = Qnil;
|
61
|
+
image->pixel_format = RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID;
|
62
|
+
image->width = 0;
|
63
|
+
image->height = 0;
|
64
|
+
image->stride = 0;
|
65
|
+
return obj;
|
66
|
+
}
|
67
|
+
|
68
|
+
static inline struct image_data*
|
69
|
+
get_image_data(VALUE const obj)
|
70
|
+
{
|
71
|
+
struct image_data* image;
|
72
|
+
TypedData_Get_Struct(obj, struct image_data, &image_data_type, image);
|
73
|
+
return image;
|
74
|
+
}
|
75
|
+
|
76
|
+
#ifdef HAVE_RB_CAIRO_H
|
77
|
+
static cairo_format_t
|
78
|
+
pixel_format_to_cairo_format(rb_image_file_image_pixel_format_t const pf)
|
79
|
+
{
|
80
|
+
switch (pf) {
|
81
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID:
|
82
|
+
break;
|
83
|
+
|
84
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
85
|
+
return CAIRO_FORMAT_ARGB32;
|
86
|
+
|
87
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
88
|
+
return CAIRO_FORMAT_RGB24;
|
89
|
+
|
90
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
91
|
+
return CAIRO_FORMAT_RGB16_565;
|
92
|
+
|
93
|
+
default:
|
94
|
+
break;
|
95
|
+
}
|
96
|
+
rb_bug("unknown pixel format (%d)", pf);
|
97
|
+
return -1;
|
98
|
+
}
|
99
|
+
#endif /* HAVE_RB_CAIRO_H */
|
100
|
+
|
101
|
+
static inline int
|
102
|
+
pixel_format_size(rb_image_file_image_pixel_format_t const pf)
|
103
|
+
{
|
104
|
+
switch (pf) {
|
105
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID:
|
106
|
+
return -1;
|
107
|
+
|
108
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
109
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
110
|
+
return 4;
|
111
|
+
|
112
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
113
|
+
return 2;
|
114
|
+
|
115
|
+
default:
|
116
|
+
break;
|
117
|
+
}
|
118
|
+
assert(0); /* MUST NOT REACH HERE */
|
119
|
+
return -1;
|
120
|
+
}
|
121
|
+
|
122
|
+
static long
|
123
|
+
minimum_buffer_size(rb_image_file_image_pixel_format_t const pf, long const st, long const ht)
|
124
|
+
{
|
125
|
+
long len = st * ht;
|
126
|
+
|
127
|
+
assert(st > 0);
|
128
|
+
assert(ht > 0);
|
129
|
+
|
130
|
+
switch (pf) {
|
131
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID:
|
132
|
+
return -1;
|
133
|
+
|
134
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
135
|
+
return len * 4;
|
136
|
+
|
137
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
138
|
+
return len * 4;
|
139
|
+
|
140
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
141
|
+
return len * 2;
|
142
|
+
|
143
|
+
default:
|
144
|
+
break;
|
145
|
+
}
|
146
|
+
assert(0); /* MUST NOT REACH HERE */
|
147
|
+
return -1;
|
148
|
+
}
|
149
|
+
|
150
|
+
VALUE
|
151
|
+
rb_image_file_image_pixel_format_to_symbol(rb_image_file_image_pixel_format_t const pf)
|
152
|
+
{
|
153
|
+
switch (pf) {
|
154
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID:
|
155
|
+
return Qnil;
|
156
|
+
|
157
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
158
|
+
return ID2SYM(id_ARGB32);
|
159
|
+
|
160
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
161
|
+
return ID2SYM(id_RGB24);
|
162
|
+
|
163
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
164
|
+
return ID2SYM(id_RGB16_565);
|
165
|
+
|
166
|
+
default:
|
167
|
+
break;
|
168
|
+
}
|
169
|
+
assert(0); /* MUST NOT REACH HERE */
|
170
|
+
return Qnil;
|
171
|
+
}
|
172
|
+
|
173
|
+
static inline rb_image_file_image_pixel_format_t
|
174
|
+
id_to_pixel_format(ID const id)
|
175
|
+
{
|
176
|
+
if (id == id_ARGB32)
|
177
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32;
|
178
|
+
|
179
|
+
if (id == id_RGB24)
|
180
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24;
|
181
|
+
|
182
|
+
if (id == id_RGB16_565)
|
183
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565;
|
184
|
+
|
185
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID;
|
186
|
+
}
|
187
|
+
|
188
|
+
rb_image_file_image_pixel_format_t
|
189
|
+
rb_image_file_image_symbol_to_pixel_format(VALUE symbol)
|
190
|
+
{
|
191
|
+
Check_Type(symbol, T_SYMBOL);
|
192
|
+
return id_to_pixel_format(SYM2ID(symbol));
|
193
|
+
}
|
194
|
+
|
195
|
+
static rb_image_file_image_pixel_format_t
|
196
|
+
check_pixel_format(VALUE const pixel_format)
|
197
|
+
{
|
198
|
+
rb_image_file_image_pixel_format_t pf;
|
199
|
+
|
200
|
+
Check_Type(pixel_format, T_SYMBOL);
|
201
|
+
pf = id_to_pixel_format(SYM2ID(pixel_format));
|
202
|
+
if (RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID == pf)
|
203
|
+
rb_raise(rb_eArgError, "unknown pixel format");
|
204
|
+
|
205
|
+
return pf;
|
206
|
+
}
|
207
|
+
|
208
|
+
static void
|
209
|
+
process_arguments_of_image_initialize(int const argc, VALUE* const argv,
|
210
|
+
VALUE* buffer_ptr,
|
211
|
+
rb_image_file_image_pixel_format_t* pixel_format_ptr,
|
212
|
+
long* width_ptr,
|
213
|
+
long* height_ptr,
|
214
|
+
long* stride_ptr
|
215
|
+
)
|
216
|
+
{
|
217
|
+
VALUE params;
|
218
|
+
VALUE buffer = Qnil;
|
219
|
+
VALUE pixel_format = Qnil;
|
220
|
+
VALUE width = Qnil;
|
221
|
+
VALUE height = Qnil;
|
222
|
+
VALUE stride = Qnil;
|
223
|
+
|
224
|
+
rb_image_file_image_pixel_format_t pf;
|
225
|
+
long wd, ht, st;
|
226
|
+
long min_len;
|
227
|
+
|
228
|
+
ID id_pixel_format, id_data, id_width, id_height, id_row_stride;
|
229
|
+
CONST_ID(id_data, "data");
|
230
|
+
CONST_ID(id_pixel_format, "pixel_format");
|
231
|
+
CONST_ID(id_width, "width");
|
232
|
+
CONST_ID(id_height, "height");
|
233
|
+
CONST_ID(id_row_stride, "row_stride");
|
234
|
+
|
235
|
+
rb_scan_args(argc, argv, "01", ¶ms);
|
236
|
+
if (TYPE(params) == T_HASH) {
|
237
|
+
buffer = rb_hash_lookup(params, ID2SYM(id_data));
|
238
|
+
pixel_format = rb_hash_lookup(params, ID2SYM(id_pixel_format));
|
239
|
+
width = rb_hash_lookup(params, ID2SYM(id_width));
|
240
|
+
height = rb_hash_lookup(params, ID2SYM(id_height));
|
241
|
+
stride = rb_hash_lookup(params, ID2SYM(id_row_stride));
|
242
|
+
}
|
243
|
+
|
244
|
+
if (!NIL_P(buffer)) {
|
245
|
+
Check_Type(buffer, T_STRING);
|
246
|
+
buffer = rb_str_dup(buffer);
|
247
|
+
}
|
248
|
+
|
249
|
+
if (NIL_P(pixel_format))
|
250
|
+
rb_raise(rb_eArgError, "missing image pixel format");
|
251
|
+
if (TYPE(pixel_format) == T_STRING)
|
252
|
+
pixel_format = rb_str_intern(pixel_format);
|
253
|
+
pf = check_pixel_format(pixel_format);
|
254
|
+
|
255
|
+
if (NIL_P(width))
|
256
|
+
rb_raise(rb_eArgError, "missing image width");
|
257
|
+
wd = NUM2LONG(width);
|
258
|
+
if (wd <= 0)
|
259
|
+
rb_raise(rb_eArgError, "zero or negative image width");
|
260
|
+
|
261
|
+
if (NIL_P(height))
|
262
|
+
rb_raise(rb_eArgError, "missing image height");
|
263
|
+
ht = NUM2LONG(height);
|
264
|
+
if (ht <= 0)
|
265
|
+
rb_raise(rb_eArgError, "zero or negative image height");
|
266
|
+
|
267
|
+
if (NIL_P(stride)) {
|
268
|
+
#ifdef HAVE_RB_CAIRO_H
|
269
|
+
st = cairo_format_stride_for_width(pixel_format_to_cairo_format(pf), (int)wd) / pixel_format_size(pf);
|
270
|
+
stride = INT2NUM(st);
|
271
|
+
#else
|
272
|
+
stride = width;
|
273
|
+
#endif
|
274
|
+
}
|
275
|
+
st = NUM2LONG(stride);
|
276
|
+
if (st <= 0)
|
277
|
+
rb_raise(rb_eArgError, "zero or negative image row-stride");
|
278
|
+
else if (st < wd) {
|
279
|
+
rb_warning("the given row-stride is less than the given image width.");
|
280
|
+
st = wd;
|
281
|
+
}
|
282
|
+
|
283
|
+
min_len = minimum_buffer_size(pf, st, ht);
|
284
|
+
if (NIL_P(buffer)) {
|
285
|
+
buffer = rb_str_new(NULL, min_len);
|
286
|
+
}
|
287
|
+
else if (RSTRING_LEN(buffer) < min_len) {
|
288
|
+
void rb_str_modify_expand(VALUE, long);
|
289
|
+
rb_warning("the size of the given data is too short for the given size of image");
|
290
|
+
rb_str_modify_expand(buffer, min_len - RSTRING_LEN(buffer));
|
291
|
+
}
|
292
|
+
|
293
|
+
*buffer_ptr = buffer;
|
294
|
+
*pixel_format_ptr = pf;
|
295
|
+
*width_ptr = wd;
|
296
|
+
*height_ptr = ht;
|
297
|
+
*stride_ptr = st;
|
298
|
+
}
|
299
|
+
|
300
|
+
static VALUE
|
301
|
+
image_initialize(int argc, VALUE* argv, VALUE obj)
|
302
|
+
{
|
303
|
+
struct image_data* image;
|
304
|
+
VALUE buffer;
|
305
|
+
rb_image_file_image_pixel_format_t pf;
|
306
|
+
long wd, ht, st;
|
307
|
+
|
308
|
+
process_arguments_of_image_initialize(argc, argv, &buffer, &pf, &wd, &ht, &st);
|
309
|
+
assert(!NIL_P(buffer));
|
310
|
+
assert(pf != RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID);
|
311
|
+
assert(wd > 0);
|
312
|
+
assert(ht > 0);
|
313
|
+
assert(st >= wd);
|
314
|
+
|
315
|
+
image = get_image_data(obj);
|
316
|
+
image->buffer = buffer;
|
317
|
+
image->pixel_format = pf;
|
318
|
+
image->width = wd;
|
319
|
+
image->height = ht;
|
320
|
+
image->stride = st;
|
321
|
+
|
322
|
+
return obj;
|
323
|
+
}
|
324
|
+
|
325
|
+
VALUE
|
326
|
+
rb_image_file_image_get_buffer(VALUE obj)
|
327
|
+
{
|
328
|
+
struct image_data* image = get_image_data(obj);
|
329
|
+
return image->buffer;
|
330
|
+
}
|
331
|
+
|
332
|
+
static VALUE
|
333
|
+
image_get_pixel_format(VALUE obj)
|
334
|
+
{
|
335
|
+
struct image_data* image = get_image_data(obj);
|
336
|
+
return rb_image_file_image_pixel_format_to_symbol(image->pixel_format);
|
337
|
+
}
|
338
|
+
|
339
|
+
static VALUE
|
340
|
+
image_get_width(VALUE obj)
|
341
|
+
{
|
342
|
+
struct image_data* image = get_image_data(obj);
|
343
|
+
return LONG2NUM(image->width);
|
344
|
+
}
|
345
|
+
|
346
|
+
static VALUE
|
347
|
+
image_get_height(VALUE obj)
|
348
|
+
{
|
349
|
+
struct image_data* image = get_image_data(obj);
|
350
|
+
return LONG2NUM(image->height);
|
351
|
+
}
|
352
|
+
|
353
|
+
static VALUE
|
354
|
+
image_get_row_stride(VALUE obj)
|
355
|
+
{
|
356
|
+
struct image_data* image = get_image_data(obj);
|
357
|
+
return LONG2NUM(image->stride);
|
358
|
+
}
|
359
|
+
|
360
|
+
|
361
|
+
#ifdef HAVE_RB_CAIRO_H
|
362
|
+
static cairo_user_data_key_t const cairo_data_key = {};
|
363
|
+
|
364
|
+
static void
|
365
|
+
image_surface_did_destroyed(void* data)
|
366
|
+
{
|
367
|
+
xfree(data);
|
368
|
+
}
|
369
|
+
|
370
|
+
static VALUE
|
371
|
+
image_create_cairo_surface(VALUE obj)
|
372
|
+
{
|
373
|
+
cairo_surface_t* cairo_surface;
|
374
|
+
cairo_format_t cairo_format;
|
375
|
+
unsigned char* data;
|
376
|
+
VALUE surface;
|
377
|
+
struct image_data* image = get_image_data(obj);
|
378
|
+
|
379
|
+
data = xmalloc(sizeof(unsigned char)*RSTRING_LEN(image->buffer));
|
380
|
+
MEMCPY(data, RSTRING_PTR(image->buffer), unsigned char, RSTRING_LEN(image->buffer));
|
381
|
+
|
382
|
+
cairo_format = pixel_format_to_cairo_format(image->pixel_format);
|
383
|
+
cairo_surface = cairo_image_surface_create_for_data(
|
384
|
+
data, cairo_format, (int)image->width, (int)image->height,
|
385
|
+
(int)image->stride*pixel_format_size(image->pixel_format));
|
386
|
+
cairo_surface_set_user_data(cairo_surface, &cairo_data_key, data, image_surface_did_destroyed);
|
387
|
+
surface = CRSURFACE2RVAL_WITH_DESTROY(cairo_surface);
|
388
|
+
return surface;
|
389
|
+
}
|
390
|
+
#endif
|
391
|
+
|
392
|
+
void
|
393
|
+
rb_image_file_Init_image_file_image(void)
|
394
|
+
{
|
395
|
+
cImageFileImage = rb_define_class_under(mImageFile, "Image", rb_cObject);
|
396
|
+
rb_define_alloc_func(cImageFileImage, image_alloc);
|
397
|
+
rb_define_method(cImageFileImage, "initialize", image_initialize, -1);
|
398
|
+
|
399
|
+
rb_define_method(cImageFileImage, "pixel_format", image_get_pixel_format, 0);
|
400
|
+
rb_define_method(cImageFileImage, "width", image_get_width, 0);
|
401
|
+
rb_define_method(cImageFileImage, "height", image_get_height, 0);
|
402
|
+
rb_define_method(cImageFileImage, "row_stride", image_get_row_stride, 0);
|
403
|
+
|
404
|
+
#ifdef HAVE_RB_CAIRO_H
|
405
|
+
rb_define_method(cImageFileImage, "create_cairo_surface", image_create_cairo_surface, 0);
|
406
|
+
#endif
|
407
|
+
|
408
|
+
CONST_ID(id_ARGB32, "ARGB32");
|
409
|
+
CONST_ID(id_RGB24, "RGB24");
|
410
|
+
CONST_ID(id_RGB16_565, "RGB16_565");
|
411
|
+
}
|