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
@@ -0,0 +1,79 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
|
4
|
+
#include <assert.h>
|
5
|
+
|
6
|
+
#undef ARG_UNUSED
|
7
|
+
#ifdef __GNUC__
|
8
|
+
# define ARG_UNUSED __attribute__ ((unused))
|
9
|
+
#else
|
10
|
+
# define ARG_UNUSED
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#ifndef HAVE_UINT16_T
|
14
|
+
# if SIZEOF_SHORT == 2
|
15
|
+
typedef unsigned short uint16_t;
|
16
|
+
# elif SIZEOF_INT == 2
|
17
|
+
typedef unsigned int uint16_t;
|
18
|
+
# elif SIZEOF_CHAR == 2
|
19
|
+
typedef unsigned char uint16_t;
|
20
|
+
# elif SIZEOF_LONG == 2
|
21
|
+
typedef unsigned long uint16_t;
|
22
|
+
# else
|
23
|
+
# error needs 16-bit integer type
|
24
|
+
# endif
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#ifndef HAVE_UINT32_T
|
28
|
+
# if SIZEOF_INT == 4
|
29
|
+
typedef unsigned int uint32_t;
|
30
|
+
# elif SIZEOF_LONG == 4
|
31
|
+
typedef unsigned long uint32_t;
|
32
|
+
# elif SIZEOF_SHORT == 4
|
33
|
+
typedef unsigned short uint32_t;
|
34
|
+
# elif SIZEOF_LONG_LONG == 4
|
35
|
+
typedef unsigned LONG_LONG uint32_t;
|
36
|
+
# else
|
37
|
+
# error needs 32-bit integer type
|
38
|
+
# endif
|
39
|
+
#endif
|
40
|
+
|
41
|
+
RUBY_EXTERN VALUE rb_image_file_mImageFile;
|
42
|
+
RUBY_EXTERN VALUE rb_image_file_cImageFileImage;
|
43
|
+
RUBY_EXTERN VALUE rb_image_file_cImageFileJpegReader;
|
44
|
+
RUBY_EXTERN VALUE rb_image_file_eImageFileJpegReaderError;
|
45
|
+
|
46
|
+
#define mImageFile rb_image_file_mImageFile
|
47
|
+
#define cImageFileImage rb_image_file_cImageFileImage
|
48
|
+
#define cImageFileJpegReader rb_image_file_cImageFileJpegReader
|
49
|
+
#define eImageFileJpegReaderError rb_image_file_eImageFileJpegReaderError
|
50
|
+
|
51
|
+
typedef enum {
|
52
|
+
RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID = -1,
|
53
|
+
RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32 = 0,
|
54
|
+
RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24 = 1,
|
55
|
+
RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565 = 4,
|
56
|
+
} rb_image_file_image_pixel_format_t;
|
57
|
+
|
58
|
+
rb_image_file_image_pixel_format_t rb_image_file_image_symbol_to_pixel_format(VALUE symbol);
|
59
|
+
VALUE rb_image_file_image_pixel_format_to_symbol(rb_image_file_image_pixel_format_t const pf);
|
60
|
+
VALUE rb_image_file_image_get_buffer(VALUE obj);
|
61
|
+
|
62
|
+
void rb_image_file_Init_image_file_image(void);
|
63
|
+
void rb_image_file_Init_image_file_jpeg_reader(void);
|
64
|
+
|
65
|
+
static inline int
|
66
|
+
file_p(VALUE fname)
|
67
|
+
{
|
68
|
+
ID id_file_p;
|
69
|
+
CONST_ID(id_file_p, "file?");
|
70
|
+
return RTEST(rb_funcall(rb_cFile, id_file_p, 1, fname));
|
71
|
+
}
|
72
|
+
|
73
|
+
static inline void
|
74
|
+
check_file_not_found(VALUE fname)
|
75
|
+
{
|
76
|
+
if (!file_p(fname)) {
|
77
|
+
rb_raise(rb_eArgError, "file not found");
|
78
|
+
}
|
79
|
+
}
|
@@ -0,0 +1,938 @@
|
|
1
|
+
#include "internal.h"
|
2
|
+
|
3
|
+
#undef EXTERN
|
4
|
+
#include <jpeglib.h>
|
5
|
+
#include <jerror.h>
|
6
|
+
|
7
|
+
static size_t const INPUT_BUFFER_SIZE = 4096U;
|
8
|
+
|
9
|
+
VALUE cImageFileJpegReader = Qnil;
|
10
|
+
VALUE eImageFileJpegReaderError = Qnil;
|
11
|
+
|
12
|
+
static ID id_GRAYSCALE;
|
13
|
+
static ID id_RGB;
|
14
|
+
static ID id_YCbCr;
|
15
|
+
static ID id_CMYK;
|
16
|
+
static ID id_YCCK;
|
17
|
+
static ID id_ISLOW;
|
18
|
+
static ID id_IFAST;
|
19
|
+
static ID id_FLOAT;
|
20
|
+
static ID id_NONE;
|
21
|
+
static ID id_ORDERED;
|
22
|
+
static ID id_FS;
|
23
|
+
static ID id_new;
|
24
|
+
static ID id_close;
|
25
|
+
static ID id_read;
|
26
|
+
static ID id_pixel_format;
|
27
|
+
static ID id_width;
|
28
|
+
static ID id_height;
|
29
|
+
static ID id_row_stride;
|
30
|
+
|
31
|
+
static inline char const*
|
32
|
+
j_color_space_name(J_COLOR_SPACE const color_space)
|
33
|
+
{
|
34
|
+
switch (color_space) {
|
35
|
+
case JCS_GRAYSCALE:
|
36
|
+
return "JCS_GRAYSCALE";
|
37
|
+
|
38
|
+
case JCS_RGB:
|
39
|
+
return "JCS_RGB";
|
40
|
+
|
41
|
+
case JCS_UNKNOWN:
|
42
|
+
return "JCS_UNKNOWN";
|
43
|
+
|
44
|
+
case JCS_YCbCr:
|
45
|
+
return "JCS_YCbCr";
|
46
|
+
|
47
|
+
case JCS_CMYK:
|
48
|
+
return "JCS_CMYK";
|
49
|
+
|
50
|
+
case JCS_YCCK:
|
51
|
+
return "JCS_YCCK";
|
52
|
+
|
53
|
+
default:
|
54
|
+
break;
|
55
|
+
}
|
56
|
+
assert(0); /* MUST NOT REACH HERE */
|
57
|
+
return "(unknown color space)";
|
58
|
+
}
|
59
|
+
|
60
|
+
static rb_image_file_image_pixel_format_t
|
61
|
+
j_color_space_to_image_pixel_format(J_COLOR_SPACE const color_space)
|
62
|
+
{
|
63
|
+
switch (color_space) {
|
64
|
+
case JCS_GRAYSCALE:
|
65
|
+
case JCS_RGB:
|
66
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24;
|
67
|
+
|
68
|
+
case JCS_UNKNOWN:
|
69
|
+
case JCS_YCbCr:
|
70
|
+
case JCS_CMYK:
|
71
|
+
case JCS_YCCK:
|
72
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID;
|
73
|
+
|
74
|
+
default:
|
75
|
+
break;
|
76
|
+
}
|
77
|
+
assert(0); /* MUST NOT REACH HERE */
|
78
|
+
return RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID;
|
79
|
+
}
|
80
|
+
|
81
|
+
static J_COLOR_SPACE
|
82
|
+
image_pixel_format_to_j_color_space(rb_image_file_image_pixel_format_t const pf)
|
83
|
+
{
|
84
|
+
switch (pf) {
|
85
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID:
|
86
|
+
return JCS_UNKNOWN;
|
87
|
+
|
88
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
89
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
90
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
91
|
+
return JCS_RGB;
|
92
|
+
|
93
|
+
default:
|
94
|
+
break;
|
95
|
+
}
|
96
|
+
assert(0); /* MUST NOT REACH HERE */
|
97
|
+
return JCS_UNKNOWN;
|
98
|
+
}
|
99
|
+
|
100
|
+
static VALUE
|
101
|
+
color_space_to_symbol(J_COLOR_SPACE const color_space)
|
102
|
+
{
|
103
|
+
switch (color_space) {
|
104
|
+
case JCS_UNKNOWN:
|
105
|
+
return Qnil;
|
106
|
+
|
107
|
+
case JCS_GRAYSCALE:
|
108
|
+
return ID2SYM(id_GRAYSCALE);
|
109
|
+
|
110
|
+
case JCS_RGB:
|
111
|
+
return ID2SYM(id_RGB);
|
112
|
+
|
113
|
+
case JCS_YCbCr:
|
114
|
+
return ID2SYM(id_YCbCr);
|
115
|
+
|
116
|
+
case JCS_CMYK:
|
117
|
+
return ID2SYM(id_CMYK);
|
118
|
+
|
119
|
+
case JCS_YCCK:
|
120
|
+
return ID2SYM(id_YCCK);
|
121
|
+
|
122
|
+
default:
|
123
|
+
break;
|
124
|
+
}
|
125
|
+
assert(0); /* MUST NOT REACH HERE */
|
126
|
+
return Qnil;
|
127
|
+
}
|
128
|
+
|
129
|
+
static J_COLOR_SPACE
|
130
|
+
id_to_color_space(ID const id)
|
131
|
+
{
|
132
|
+
if (id == id_GRAYSCALE)
|
133
|
+
return JCS_GRAYSCALE;
|
134
|
+
if (id == id_RGB)
|
135
|
+
return JCS_RGB;
|
136
|
+
if (id == id_YCbCr)
|
137
|
+
return JCS_YCbCr;
|
138
|
+
if (id == id_CMYK)
|
139
|
+
return JCS_CMYK;
|
140
|
+
if (id == id_YCCK)
|
141
|
+
return JCS_YCCK;
|
142
|
+
return JCS_UNKNOWN;
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE
|
146
|
+
dct_method_to_symbol(J_DCT_METHOD const dct_method)
|
147
|
+
{
|
148
|
+
switch (dct_method) {
|
149
|
+
case JDCT_ISLOW:
|
150
|
+
return ID2SYM(id_ISLOW);
|
151
|
+
|
152
|
+
case JDCT_IFAST:
|
153
|
+
return ID2SYM(id_IFAST);
|
154
|
+
|
155
|
+
case JDCT_FLOAT:
|
156
|
+
return ID2SYM(id_FLOAT);
|
157
|
+
|
158
|
+
default:
|
159
|
+
break;
|
160
|
+
}
|
161
|
+
assert(0); /* DO NOT REACH HERE */
|
162
|
+
return Qnil;
|
163
|
+
}
|
164
|
+
|
165
|
+
static VALUE
|
166
|
+
dither_mode_to_symbol(J_DITHER_MODE const dither_mode)
|
167
|
+
{
|
168
|
+
switch (dither_mode) {
|
169
|
+
case JDITHER_NONE:
|
170
|
+
return ID2SYM(id_NONE);
|
171
|
+
|
172
|
+
case JDITHER_ORDERED:
|
173
|
+
return ID2SYM(id_ORDERED);
|
174
|
+
|
175
|
+
case JDITHER_FS:
|
176
|
+
return ID2SYM(id_FS);
|
177
|
+
|
178
|
+
default:
|
179
|
+
break;
|
180
|
+
}
|
181
|
+
assert(0); /* DO NOT REACH HERE */
|
182
|
+
return Qnil;
|
183
|
+
}
|
184
|
+
|
185
|
+
enum jpeg_reader_state {
|
186
|
+
READER_ALLOCATED = 0,
|
187
|
+
READER_INITIALIZED,
|
188
|
+
READER_RED_HEADER,
|
189
|
+
READER_STARTED_DECOMPRESS,
|
190
|
+
READER_FINISHED_DECOMPRESS
|
191
|
+
};
|
192
|
+
|
193
|
+
struct jpeg_reader_data {
|
194
|
+
struct jpeg_decompress_struct cinfo;
|
195
|
+
struct jpeg_error_mgr error;
|
196
|
+
VALUE source;
|
197
|
+
VALUE buffer;
|
198
|
+
enum jpeg_reader_state state;
|
199
|
+
unsigned close_source: 1;
|
200
|
+
unsigned start_of_file: 1;
|
201
|
+
};
|
202
|
+
|
203
|
+
static void
|
204
|
+
jpeg_reader_mark(void* ptr)
|
205
|
+
{
|
206
|
+
struct jpeg_reader_data* reader = (struct jpeg_reader_data*)ptr;
|
207
|
+
rb_gc_mark(reader->source);
|
208
|
+
rb_gc_mark(reader->buffer);
|
209
|
+
}
|
210
|
+
|
211
|
+
static void
|
212
|
+
jpeg_reader_free(void* ptr)
|
213
|
+
{
|
214
|
+
struct jpeg_reader_data* reader = (struct jpeg_reader_data*)ptr;
|
215
|
+
|
216
|
+
#if 0
|
217
|
+
if (reader->close_source && rb_respond_to(reader->source, id_close)) {
|
218
|
+
rb_funcall(reader->source, id_close, 0);
|
219
|
+
}
|
220
|
+
#endif
|
221
|
+
reader->source = Qnil;
|
222
|
+
jpeg_destroy_decompress(&reader->cinfo);
|
223
|
+
xfree(ptr);
|
224
|
+
}
|
225
|
+
|
226
|
+
static size_t
|
227
|
+
jpeg_reader_memsize(void const* ptr)
|
228
|
+
{
|
229
|
+
return ptr ? sizeof(struct jpeg_reader_data) : 0;
|
230
|
+
}
|
231
|
+
|
232
|
+
static rb_data_type_t const jpeg_reader_data_type = {
|
233
|
+
"image_file::jpeg_reader",
|
234
|
+
#if RUBY_VERSION >= 193
|
235
|
+
{
|
236
|
+
#endif
|
237
|
+
jpeg_reader_mark,
|
238
|
+
jpeg_reader_free,
|
239
|
+
jpeg_reader_memsize,
|
240
|
+
#if RUBY_VERSION >= 193
|
241
|
+
},
|
242
|
+
#endif
|
243
|
+
};
|
244
|
+
|
245
|
+
static VALUE
|
246
|
+
jpeg_reader_alloc(VALUE klass)
|
247
|
+
{
|
248
|
+
struct jpeg_reader_data* reader;
|
249
|
+
VALUE obj = TypedData_Make_Struct(
|
250
|
+
klass, struct jpeg_reader_data, &jpeg_reader_data_type, reader);
|
251
|
+
reader->source = Qnil;
|
252
|
+
reader->buffer = Qnil;
|
253
|
+
reader->state = READER_ALLOCATED;
|
254
|
+
reader->close_source = 0;
|
255
|
+
reader->start_of_file = 0;
|
256
|
+
return obj;
|
257
|
+
}
|
258
|
+
|
259
|
+
static struct jpeg_reader_data*
|
260
|
+
get_jpeg_reader_data(VALUE obj)
|
261
|
+
{
|
262
|
+
struct jpeg_reader_data* reader;
|
263
|
+
TypedData_Get_Struct(obj, struct jpeg_reader_data, &jpeg_reader_data_type, reader);
|
264
|
+
return reader;
|
265
|
+
}
|
266
|
+
|
267
|
+
static void
|
268
|
+
error_exit(j_common_ptr cinfo)
|
269
|
+
{
|
270
|
+
char message[JMSG_LENGTH_MAX];
|
271
|
+
(* cinfo->err->format_message)(cinfo, message);
|
272
|
+
rb_raise(eImageFileJpegReaderError, "%s", message);
|
273
|
+
}
|
274
|
+
|
275
|
+
static void
|
276
|
+
output_message(j_common_ptr cinfo)
|
277
|
+
{
|
278
|
+
char message[JMSG_LENGTH_MAX];
|
279
|
+
(* cinfo->err->format_message)(cinfo, message);
|
280
|
+
rb_warning("%s", message);
|
281
|
+
}
|
282
|
+
|
283
|
+
static struct jpeg_error_mgr*
|
284
|
+
init_error_mgr(struct jpeg_error_mgr* err)
|
285
|
+
{
|
286
|
+
jpeg_std_error(err);
|
287
|
+
err->error_exit = error_exit;
|
288
|
+
err->output_message = output_message;
|
289
|
+
return err;
|
290
|
+
}
|
291
|
+
|
292
|
+
static void
|
293
|
+
init_source(j_decompress_ptr cinfo)
|
294
|
+
{
|
295
|
+
VALUE obj;
|
296
|
+
struct jpeg_reader_data* reader;
|
297
|
+
|
298
|
+
assert(cinfo != NULL);
|
299
|
+
|
300
|
+
obj = (VALUE)cinfo->client_data;
|
301
|
+
reader = get_jpeg_reader_data(obj);
|
302
|
+
reader->start_of_file = 1;
|
303
|
+
}
|
304
|
+
|
305
|
+
static boolean
|
306
|
+
fill_input_buffer(j_decompress_ptr cinfo)
|
307
|
+
{
|
308
|
+
VALUE obj;
|
309
|
+
struct jpeg_reader_data* reader;
|
310
|
+
|
311
|
+
assert(cinfo != NULL);
|
312
|
+
|
313
|
+
obj = (VALUE)cinfo->client_data;
|
314
|
+
reader = get_jpeg_reader_data(obj);
|
315
|
+
|
316
|
+
reader->buffer = rb_funcall(reader->source, id_read, 1, INT2FIX(INPUT_BUFFER_SIZE));
|
317
|
+
if (NIL_P(reader->buffer)) { /* EOF */
|
318
|
+
if (reader->start_of_file) { /* empty file */
|
319
|
+
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
320
|
+
}
|
321
|
+
WARNMS(cinfo, JWRN_JPEG_EOF);
|
322
|
+
/* Insert fake EOI marker */
|
323
|
+
reader->buffer = rb_str_tmp_new(2);
|
324
|
+
RSTRING_PTR(reader->buffer)[0] = (JOCTET) 0xFF;
|
325
|
+
RSTRING_PTR(reader->buffer)[1] = (JOCTET) JPEG_EOI;
|
326
|
+
}
|
327
|
+
|
328
|
+
cinfo->src->next_input_byte = (JOCTET const*)RSTRING_PTR(reader->buffer);
|
329
|
+
cinfo->src->bytes_in_buffer = RSTRING_LEN(reader->buffer);
|
330
|
+
reader->start_of_file = 0;
|
331
|
+
|
332
|
+
return TRUE;
|
333
|
+
}
|
334
|
+
|
335
|
+
static void
|
336
|
+
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
337
|
+
{
|
338
|
+
if (num_bytes > 0) {
|
339
|
+
while (num_bytes > (long)cinfo->src->bytes_in_buffer) {
|
340
|
+
num_bytes -= (long)cinfo->src->bytes_in_buffer;
|
341
|
+
(* cinfo->src->fill_input_buffer)(cinfo);
|
342
|
+
}
|
343
|
+
cinfo->src->next_input_byte += num_bytes;
|
344
|
+
cinfo->src->bytes_in_buffer -= num_bytes;
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
void
|
349
|
+
term_source(j_decompress_ptr cinfo ARG_UNUSED)
|
350
|
+
{
|
351
|
+
/* nothing to do */
|
352
|
+
}
|
353
|
+
|
354
|
+
static void
|
355
|
+
init_source_mgr(struct jpeg_reader_data* reader)
|
356
|
+
{
|
357
|
+
struct jpeg_source_mgr* src = NULL;
|
358
|
+
|
359
|
+
assert(reader != NULL);
|
360
|
+
|
361
|
+
if (reader->cinfo.src == NULL) {
|
362
|
+
reader->cinfo.src = (struct jpeg_source_mgr*)
|
363
|
+
(* reader->cinfo.mem->alloc_small)(
|
364
|
+
(j_common_ptr)&reader->cinfo,
|
365
|
+
JPOOL_PERMANENT,
|
366
|
+
sizeof(struct jpeg_source_mgr));
|
367
|
+
}
|
368
|
+
|
369
|
+
src = (struct jpeg_source_mgr*)reader->cinfo.src;
|
370
|
+
src->init_source = init_source;
|
371
|
+
src->fill_input_buffer = fill_input_buffer;
|
372
|
+
src->skip_input_data = skip_input_data;
|
373
|
+
src->resync_to_restart = jpeg_resync_to_restart;
|
374
|
+
src->term_source = term_source;
|
375
|
+
src->bytes_in_buffer = 0;
|
376
|
+
src->next_input_byte = NULL;
|
377
|
+
}
|
378
|
+
|
379
|
+
static VALUE
|
380
|
+
jpeg_reader_initialize(VALUE obj, VALUE source)
|
381
|
+
{
|
382
|
+
struct jpeg_reader_data* reader;
|
383
|
+
reader = get_jpeg_reader_data(obj);
|
384
|
+
reader->cinfo.err = init_error_mgr(&reader->error);
|
385
|
+
jpeg_create_decompress(&reader->cinfo);
|
386
|
+
init_source_mgr(reader);
|
387
|
+
reader->source = source;
|
388
|
+
reader->cinfo.client_data = (void*)obj;
|
389
|
+
reader->state = READER_INITIALIZED;
|
390
|
+
return obj;
|
391
|
+
}
|
392
|
+
|
393
|
+
static VALUE
|
394
|
+
jpeg_reader_s_open(VALUE klass, VALUE path)
|
395
|
+
{
|
396
|
+
struct jpeg_reader_data* reader;
|
397
|
+
VALUE obj, io;
|
398
|
+
|
399
|
+
io = rb_file_open_str(path, "rb");
|
400
|
+
obj = rb_funcall(klass, id_new, 1, io);
|
401
|
+
reader = get_jpeg_reader_data(obj);
|
402
|
+
reader->close_source = 1;
|
403
|
+
|
404
|
+
return obj;
|
405
|
+
}
|
406
|
+
|
407
|
+
static VALUE
|
408
|
+
jpeg_reader_source_will_be_closed(VALUE obj)
|
409
|
+
{
|
410
|
+
struct jpeg_reader_data* reader;
|
411
|
+
reader = get_jpeg_reader_data(obj);
|
412
|
+
return reader->close_source ? Qtrue : Qfalse;
|
413
|
+
}
|
414
|
+
|
415
|
+
static inline void
|
416
|
+
reader_check_initialized(struct jpeg_reader_data* reader)
|
417
|
+
{
|
418
|
+
assert(reader != NULL);
|
419
|
+
if (reader->state < READER_INITIALIZED) {
|
420
|
+
rb_raise(eImageFileJpegReaderError, "reader not initialized");
|
421
|
+
}
|
422
|
+
}
|
423
|
+
|
424
|
+
static inline void
|
425
|
+
read_header(struct jpeg_reader_data* reader)
|
426
|
+
{
|
427
|
+
assert(reader != NULL);
|
428
|
+
reader_check_initialized(reader);
|
429
|
+
if (reader->state < READER_RED_HEADER) {
|
430
|
+
jpeg_read_header(&reader->cinfo, TRUE);
|
431
|
+
reader->state = READER_RED_HEADER;
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
435
|
+
static VALUE
|
436
|
+
jpeg_reader_get_image_width(VALUE obj)
|
437
|
+
{
|
438
|
+
struct jpeg_reader_data* reader;
|
439
|
+
reader = get_jpeg_reader_data(obj);
|
440
|
+
read_header(reader);
|
441
|
+
return ULONG2NUM(reader->cinfo.image_width);
|
442
|
+
}
|
443
|
+
|
444
|
+
static VALUE
|
445
|
+
jpeg_reader_get_image_height(VALUE obj)
|
446
|
+
{
|
447
|
+
struct jpeg_reader_data* reader;
|
448
|
+
reader = get_jpeg_reader_data(obj);
|
449
|
+
read_header(reader);
|
450
|
+
return ULONG2NUM(reader->cinfo.image_height);
|
451
|
+
}
|
452
|
+
|
453
|
+
static VALUE
|
454
|
+
jpeg_reader_get_num_components(VALUE obj)
|
455
|
+
{
|
456
|
+
struct jpeg_reader_data* reader;
|
457
|
+
reader = get_jpeg_reader_data(obj);
|
458
|
+
read_header(reader);
|
459
|
+
return LONG2NUM(reader->cinfo.num_components);
|
460
|
+
}
|
461
|
+
|
462
|
+
static VALUE
|
463
|
+
jpeg_reader_get_jpeg_color_space(VALUE obj)
|
464
|
+
{
|
465
|
+
struct jpeg_reader_data* reader;
|
466
|
+
reader = get_jpeg_reader_data(obj);
|
467
|
+
read_header(reader);
|
468
|
+
return color_space_to_symbol(reader->cinfo.jpeg_color_space);
|
469
|
+
}
|
470
|
+
|
471
|
+
static VALUE
|
472
|
+
jpeg_reader_get_out_color_space(VALUE obj)
|
473
|
+
{
|
474
|
+
struct jpeg_reader_data* reader;
|
475
|
+
reader = get_jpeg_reader_data(obj);
|
476
|
+
read_header(reader);
|
477
|
+
return color_space_to_symbol(reader->cinfo.out_color_space);
|
478
|
+
}
|
479
|
+
|
480
|
+
static VALUE
|
481
|
+
jpeg_reader_get_scale(VALUE obj)
|
482
|
+
{
|
483
|
+
struct jpeg_reader_data* reader;
|
484
|
+
VALUE num, denom;
|
485
|
+
reader = get_jpeg_reader_data(obj);
|
486
|
+
read_header(reader);
|
487
|
+
num = UINT2NUM(reader->cinfo.scale_num);
|
488
|
+
denom = UINT2NUM(reader->cinfo.scale_denom);
|
489
|
+
return rb_Rational(num, denom);
|
490
|
+
}
|
491
|
+
|
492
|
+
static VALUE
|
493
|
+
jpeg_reader_set_scale(VALUE obj, VALUE scale)
|
494
|
+
{
|
495
|
+
struct jpeg_reader_data* reader;
|
496
|
+
VALUE r;
|
497
|
+
reader = get_jpeg_reader_data(obj);
|
498
|
+
read_header(reader);
|
499
|
+
r = rb_Rational1(scale);
|
500
|
+
reader->cinfo.scale_num = NUM2UINT(RRATIONAL(r)->num);
|
501
|
+
reader->cinfo.scale_denom = NUM2UINT(RRATIONAL(r)->den);
|
502
|
+
return scale;
|
503
|
+
}
|
504
|
+
|
505
|
+
static VALUE
|
506
|
+
jpeg_reader_get_output_gamma(VALUE obj)
|
507
|
+
{
|
508
|
+
struct jpeg_reader_data* reader;
|
509
|
+
reader = get_jpeg_reader_data(obj);
|
510
|
+
read_header(reader);
|
511
|
+
return DBL2NUM(reader->cinfo.output_gamma);
|
512
|
+
}
|
513
|
+
|
514
|
+
static VALUE
|
515
|
+
jpeg_reader_set_output_gamma(VALUE obj, VALUE gamma)
|
516
|
+
{
|
517
|
+
struct jpeg_reader_data* reader;
|
518
|
+
VALUE f;
|
519
|
+
reader = get_jpeg_reader_data(obj);
|
520
|
+
read_header(reader);
|
521
|
+
f = rb_Float(gamma);
|
522
|
+
reader->cinfo.output_gamma = RFLOAT_VALUE(f);
|
523
|
+
return gamma;
|
524
|
+
}
|
525
|
+
|
526
|
+
static VALUE
|
527
|
+
jpeg_reader_is_buffered_image(VALUE obj)
|
528
|
+
{
|
529
|
+
struct jpeg_reader_data* reader;
|
530
|
+
reader = get_jpeg_reader_data(obj);
|
531
|
+
read_header(reader);
|
532
|
+
return reader->cinfo.buffered_image ? Qtrue : Qfalse;
|
533
|
+
}
|
534
|
+
|
535
|
+
static VALUE
|
536
|
+
jpeg_reader_get_dct_method(VALUE obj)
|
537
|
+
{
|
538
|
+
struct jpeg_reader_data* reader;
|
539
|
+
reader = get_jpeg_reader_data(obj);
|
540
|
+
read_header(reader);
|
541
|
+
return dct_method_to_symbol(reader->cinfo.dct_method);
|
542
|
+
}
|
543
|
+
|
544
|
+
static VALUE
|
545
|
+
jpeg_reader_is_quantize_colors(VALUE obj)
|
546
|
+
{
|
547
|
+
struct jpeg_reader_data* reader;
|
548
|
+
reader = get_jpeg_reader_data(obj);
|
549
|
+
read_header(reader);
|
550
|
+
return reader->cinfo.quantize_colors ? Qtrue : Qfalse;
|
551
|
+
}
|
552
|
+
|
553
|
+
static VALUE
|
554
|
+
jpeg_reader_get_dither_mode(VALUE obj)
|
555
|
+
{
|
556
|
+
struct jpeg_reader_data* reader;
|
557
|
+
reader = get_jpeg_reader_data(obj);
|
558
|
+
read_header(reader);
|
559
|
+
return dither_mode_to_symbol(reader->cinfo.dither_mode);
|
560
|
+
}
|
561
|
+
|
562
|
+
static inline void
|
563
|
+
calc_output_dimensions(struct jpeg_reader_data* reader)
|
564
|
+
{
|
565
|
+
assert(reader != NULL);
|
566
|
+
if (reader->state < READER_STARTED_DECOMPRESS) {
|
567
|
+
read_header(reader);
|
568
|
+
jpeg_calc_output_dimensions(&reader->cinfo);
|
569
|
+
}
|
570
|
+
}
|
571
|
+
|
572
|
+
static VALUE
|
573
|
+
jpeg_reader_get_output_width(VALUE obj)
|
574
|
+
{
|
575
|
+
struct jpeg_reader_data* reader;
|
576
|
+
reader = get_jpeg_reader_data(obj);
|
577
|
+
calc_output_dimensions(reader);
|
578
|
+
return UINT2NUM(reader->cinfo.output_width);
|
579
|
+
}
|
580
|
+
|
581
|
+
static VALUE
|
582
|
+
jpeg_reader_get_output_height(VALUE obj)
|
583
|
+
{
|
584
|
+
struct jpeg_reader_data* reader;
|
585
|
+
reader = get_jpeg_reader_data(obj);
|
586
|
+
calc_output_dimensions(reader);
|
587
|
+
return UINT2NUM(reader->cinfo.output_height);
|
588
|
+
}
|
589
|
+
|
590
|
+
static VALUE
|
591
|
+
jpeg_reader_get_output_components(VALUE obj)
|
592
|
+
{
|
593
|
+
struct jpeg_reader_data* reader;
|
594
|
+
reader = get_jpeg_reader_data(obj);
|
595
|
+
calc_output_dimensions(reader);
|
596
|
+
return INT2NUM(reader->cinfo.output_components);
|
597
|
+
}
|
598
|
+
|
599
|
+
static inline void
|
600
|
+
start_decompress(struct jpeg_reader_data* reader)
|
601
|
+
{
|
602
|
+
assert(reader != NULL);
|
603
|
+
if (reader->state < READER_STARTED_DECOMPRESS) {
|
604
|
+
read_header(reader);
|
605
|
+
jpeg_start_decompress(&reader->cinfo);
|
606
|
+
reader->state = READER_STARTED_DECOMPRESS;
|
607
|
+
}
|
608
|
+
}
|
609
|
+
|
610
|
+
static inline uint32_t
|
611
|
+
cmyk_to_rgb24(JSAMPROW cmyk)
|
612
|
+
{
|
613
|
+
double const c = cmyk[0]/255;
|
614
|
+
double const m = cmyk[1]/255;
|
615
|
+
double const y = cmyk[2]/255;
|
616
|
+
double const k = cmyk[3]/255;
|
617
|
+
double const r = c*(1 - k) + k;
|
618
|
+
double const g = m*(1 - k) + k;
|
619
|
+
double const b = y*(1 - k) + k;
|
620
|
+
return ((uint32_t)(r*255) << 16) | ((uint32_t)(g*255) << 8) | ((uint32_t)(b*255));
|
621
|
+
}
|
622
|
+
|
623
|
+
static inline uint16_t
|
624
|
+
cmyk_to_rgb16_565(JSAMPROW cmyk)
|
625
|
+
{
|
626
|
+
double const c = cmyk[0]/255;
|
627
|
+
double const m = cmyk[1]/255;
|
628
|
+
double const y = cmyk[2]/255;
|
629
|
+
double const k = cmyk[3]/255;
|
630
|
+
double const r = c*(1 - k) + k;
|
631
|
+
double const g = m*(1 - k) + k;
|
632
|
+
double const b = y*(1 - k) + k;
|
633
|
+
return ((uint16_t)(r*31) << 11) | ((uint16_t)(g*63) << 6) | ((uint16_t)(b*31));
|
634
|
+
}
|
635
|
+
|
636
|
+
static void
|
637
|
+
convert_scanlines_from_CMYK(
|
638
|
+
VALUE image_buffer, JSAMPARRAY rows,
|
639
|
+
long const sl_beg, long const sl_end,
|
640
|
+
rb_image_file_image_pixel_format_t const pixel_format,
|
641
|
+
long const width, long const stride)
|
642
|
+
{
|
643
|
+
long i, j;
|
644
|
+
JSAMPROW src;
|
645
|
+
|
646
|
+
assert(TYPE(image_buffer) == T_STRING);
|
647
|
+
assert(rows != NULL);
|
648
|
+
assert(sl_beg < sl_end);
|
649
|
+
assert(pixel_format != RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID);
|
650
|
+
|
651
|
+
switch (pixel_format) {
|
652
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
653
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
654
|
+
for (i = sl_beg; i < sl_end; ++i) {
|
655
|
+
uint32_t* dst = (uint32_t*)(RSTRING_PTR(image_buffer) + i*stride*4);
|
656
|
+
src = rows[i];
|
657
|
+
for (j = 0; j < width; ++j) {
|
658
|
+
uint32_t const pixel = cmyk_to_rgb24(src + 4*j);
|
659
|
+
*dst++ = pixel;
|
660
|
+
}
|
661
|
+
while (j++ < stride) *dst++ = 0;
|
662
|
+
}
|
663
|
+
break;
|
664
|
+
|
665
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
666
|
+
for (i = sl_beg; i < sl_end; ++i) {
|
667
|
+
uint16_t* dst = (uint16_t*)(RSTRING_PTR(image_buffer) + i*stride*2);
|
668
|
+
src = rows[i];
|
669
|
+
for (j = 0; j < width; ++j) {
|
670
|
+
uint16_t const pixel = cmyk_to_rgb16_565(src + 4*j);
|
671
|
+
*dst++ = pixel;
|
672
|
+
}
|
673
|
+
while (j++ < stride) *dst++ = 0;
|
674
|
+
}
|
675
|
+
break;
|
676
|
+
|
677
|
+
default:
|
678
|
+
rb_bug("invalid pixel format");
|
679
|
+
break;
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
683
|
+
static void
|
684
|
+
convert_scanlines_from_RGB(
|
685
|
+
VALUE image_buffer, JSAMPARRAY rows,
|
686
|
+
long const sl_beg, long const sl_end,
|
687
|
+
rb_image_file_image_pixel_format_t const pixel_format,
|
688
|
+
long const width, long const stride)
|
689
|
+
{
|
690
|
+
long i, j;
|
691
|
+
JSAMPROW src;
|
692
|
+
|
693
|
+
assert(TYPE(image_buffer) == T_STRING);
|
694
|
+
assert(rows != NULL);
|
695
|
+
assert(sl_beg < sl_end);
|
696
|
+
assert(pixel_format != RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID);
|
697
|
+
|
698
|
+
switch (pixel_format) {
|
699
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_ARGB32:
|
700
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24:
|
701
|
+
for (i = sl_beg; i < sl_end; ++i) {
|
702
|
+
uint32_t* dst = (uint32_t*)(RSTRING_PTR(image_buffer) + i*stride*4);
|
703
|
+
src = rows[i];
|
704
|
+
for (j = 0; j < width; ++j) {
|
705
|
+
uint32_t pixel = (uint32_t)(*src++) << 16;
|
706
|
+
pixel |= (uint32_t)(*src++) << 8;
|
707
|
+
pixel |= *src++;
|
708
|
+
*dst++ = pixel;
|
709
|
+
}
|
710
|
+
while (j++ < stride) *dst++ = 0;
|
711
|
+
}
|
712
|
+
break;
|
713
|
+
|
714
|
+
case RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB16_565:
|
715
|
+
for (i = sl_beg; i < sl_end; ++i) {
|
716
|
+
uint16_t* dst = (uint16_t*)(RSTRING_PTR(image_buffer) + i*stride*2);
|
717
|
+
src = rows[i];
|
718
|
+
for (j = 0; j < width; ++j) {
|
719
|
+
uint16_t pixel = (uint16_t)(*src++ >> 3) << 11;
|
720
|
+
pixel |= (uint16_t)(*src++ >> 2) << 5;
|
721
|
+
pixel |= *src++ >> 3;
|
722
|
+
*dst++ = pixel;
|
723
|
+
}
|
724
|
+
while (j++ < stride) *dst++ = 0;
|
725
|
+
}
|
726
|
+
break;
|
727
|
+
|
728
|
+
default:
|
729
|
+
rb_bug("invalid pixel format");
|
730
|
+
break;
|
731
|
+
}
|
732
|
+
}
|
733
|
+
|
734
|
+
static void
|
735
|
+
process_arguments_of_read_image(int argc, VALUE* argv, struct jpeg_reader_data* reader,
|
736
|
+
VALUE* params_ptr,
|
737
|
+
rb_image_file_image_pixel_format_t* pixel_format_ptr,
|
738
|
+
long* width_ptr,
|
739
|
+
long* height_ptr,
|
740
|
+
long* stride_ptr
|
741
|
+
)
|
742
|
+
{
|
743
|
+
VALUE params, width, height;
|
744
|
+
VALUE pixel_format = Qnil;
|
745
|
+
VALUE stride = Qnil;
|
746
|
+
|
747
|
+
rb_image_file_image_pixel_format_t pf;
|
748
|
+
long st;
|
749
|
+
|
750
|
+
assert(reader != NULL);
|
751
|
+
assert(reader->state < READER_STARTED_DECOMPRESS);
|
752
|
+
|
753
|
+
rb_scan_args(argc, argv, "01", ¶ms);
|
754
|
+
if (TYPE(params) == T_HASH) {
|
755
|
+
pixel_format = rb_hash_lookup(params, ID2SYM(id_pixel_format));
|
756
|
+
stride = rb_hash_lookup(params, ID2SYM(id_row_stride));
|
757
|
+
}
|
758
|
+
else {
|
759
|
+
rb_warning("invalid arguments are ignored.");
|
760
|
+
params = rb_hash_new();
|
761
|
+
}
|
762
|
+
|
763
|
+
if (!NIL_P(pixel_format) && TYPE(pixel_format) != T_SYMBOL) {
|
764
|
+
rb_warning("pixel_format is not a symbol.");
|
765
|
+
pixel_format = Qnil;
|
766
|
+
}
|
767
|
+
if (!NIL_P(pixel_format)) {
|
768
|
+
pf = rb_image_file_image_symbol_to_pixel_format(pixel_format);
|
769
|
+
if (RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID == pf) {
|
770
|
+
VALUE str = rb_id2str(SYM2ID(pixel_format));
|
771
|
+
rb_warning("invalid pixel_format (%s), use default instead.", StringValueCStr(str));
|
772
|
+
pixel_format = Qnil;
|
773
|
+
}
|
774
|
+
else {
|
775
|
+
J_COLOR_SPACE const jcs = image_pixel_format_to_j_color_space(pf);
|
776
|
+
if (JCS_UNKNOWN == jcs)
|
777
|
+
rb_warning("unknown pixel format, use default instead.");
|
778
|
+
else
|
779
|
+
reader->cinfo.out_color_space = jcs;
|
780
|
+
}
|
781
|
+
}
|
782
|
+
|
783
|
+
if (!NIL_P(stride) && TYPE(stride) != T_FIXNUM && TYPE(stride) != T_BIGNUM) {
|
784
|
+
rb_warning("stride is not an integer.");
|
785
|
+
stride = Qnil;
|
786
|
+
}
|
787
|
+
|
788
|
+
start_decompress(reader);
|
789
|
+
|
790
|
+
if (NIL_P(pixel_format)) {
|
791
|
+
pf = j_color_space_to_image_pixel_format(reader->cinfo.out_color_space);
|
792
|
+
if (RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_INVALID == pf) {
|
793
|
+
if (reader->cinfo.out_color_space != JCS_CMYK) {
|
794
|
+
char const* jcs_name = j_color_space_name(reader->cinfo.out_color_space);
|
795
|
+
rb_raise(eImageFileJpegReaderError,
|
796
|
+
"unsupported output color space (%s)", jcs_name);
|
797
|
+
}
|
798
|
+
pf = RB_IMAGE_FILE_IMAGE_PIXEL_FORMAT_RGB24;
|
799
|
+
}
|
800
|
+
rb_hash_aset(params, ID2SYM(id_pixel_format),
|
801
|
+
rb_image_file_image_pixel_format_to_symbol(pf));
|
802
|
+
}
|
803
|
+
else
|
804
|
+
rb_hash_aset(params, ID2SYM(id_pixel_format), pixel_format);
|
805
|
+
|
806
|
+
width = UINT2NUM(reader->cinfo.output_width);
|
807
|
+
rb_hash_aset(params, ID2SYM(id_width), width);
|
808
|
+
|
809
|
+
height = UINT2NUM(reader->cinfo.output_height);
|
810
|
+
rb_hash_aset(params, ID2SYM(id_height), height);
|
811
|
+
|
812
|
+
if (!NIL_P(stride)) {
|
813
|
+
st = NUM2LONG(stride);
|
814
|
+
if (st < (long)reader->cinfo.output_width) {
|
815
|
+
rb_warning("stride less than output_width.");
|
816
|
+
st = (long)reader->cinfo.output_width;
|
817
|
+
stride = LONG2NUM(st);
|
818
|
+
}
|
819
|
+
}
|
820
|
+
else
|
821
|
+
st = (long)reader->cinfo.output_width;
|
822
|
+
rb_hash_aset(params, ID2SYM(id_row_stride), stride);
|
823
|
+
|
824
|
+
*params_ptr = params;
|
825
|
+
*pixel_format_ptr = pf;
|
826
|
+
*width_ptr = (long)reader->cinfo.output_width;
|
827
|
+
*height_ptr = (long)reader->cinfo.output_height;
|
828
|
+
*stride_ptr = st;
|
829
|
+
}
|
830
|
+
|
831
|
+
static VALUE
|
832
|
+
jpeg_reader_read_image(int argc, VALUE* argv, VALUE obj)
|
833
|
+
{
|
834
|
+
struct jpeg_reader_data* reader;
|
835
|
+
VALUE params, image, image_buffer;
|
836
|
+
rb_image_file_image_pixel_format_t pf;
|
837
|
+
long wd, ht, st, i, nc;
|
838
|
+
|
839
|
+
VALUE row_buffer;
|
840
|
+
VALUE sample_buffer;
|
841
|
+
JSAMPARRAY rows;
|
842
|
+
|
843
|
+
reader = get_jpeg_reader_data(obj);
|
844
|
+
|
845
|
+
process_arguments_of_read_image(argc, argv, reader, ¶ms, &pf, &wd, &ht, &st);
|
846
|
+
assert(reader->state >= READER_STARTED_DECOMPRESS);
|
847
|
+
|
848
|
+
image = rb_funcall(cImageFileImage, id_new, 1, params);
|
849
|
+
image_buffer = rb_image_file_image_get_buffer(image);
|
850
|
+
|
851
|
+
row_buffer = rb_str_tmp_new(sizeof(JSAMPROW)*ht);
|
852
|
+
rows = (JSAMPARRAY)(RSTRING_PTR(row_buffer));
|
853
|
+
|
854
|
+
nc = (long)reader->cinfo.output_components;
|
855
|
+
sample_buffer = rb_str_tmp_new(sizeof(JSAMPLE)*ht*wd*nc);
|
856
|
+
for (i = 0; i < ht; ++i)
|
857
|
+
rows[i] = (JSAMPROW)(RSTRING_PTR(sample_buffer) + i*wd*nc);
|
858
|
+
|
859
|
+
while ((long)reader->cinfo.output_scanline < ht) {
|
860
|
+
long sl_beg, sl_end;
|
861
|
+
|
862
|
+
sl_beg = reader->cinfo.output_scanline;
|
863
|
+
jpeg_read_scanlines(
|
864
|
+
&reader->cinfo,
|
865
|
+
rows + reader->cinfo.output_scanline,
|
866
|
+
(JDIMENSION)ht - reader->cinfo.output_scanline);
|
867
|
+
sl_end = reader->cinfo.output_scanline;
|
868
|
+
|
869
|
+
switch (reader->cinfo.out_color_space) {
|
870
|
+
case JCS_RGB:
|
871
|
+
convert_scanlines_from_RGB(image_buffer, rows, sl_beg, sl_end, pf, wd, st);
|
872
|
+
break;
|
873
|
+
case JCS_CMYK:
|
874
|
+
convert_scanlines_from_CMYK(image_buffer, rows, sl_beg, sl_end, pf, wd, st);
|
875
|
+
break;
|
876
|
+
default:
|
877
|
+
break;
|
878
|
+
}
|
879
|
+
}
|
880
|
+
|
881
|
+
jpeg_finish_decompress(&reader->cinfo);
|
882
|
+
reader->state = READER_FINISHED_DECOMPRESS;
|
883
|
+
|
884
|
+
return image;
|
885
|
+
}
|
886
|
+
|
887
|
+
void
|
888
|
+
rb_image_file_Init_image_file_jpeg_reader(void)
|
889
|
+
{
|
890
|
+
cImageFileJpegReader = rb_define_class_under(mImageFile, "JpegReader", rb_cObject);
|
891
|
+
rb_define_alloc_func(cImageFileJpegReader, jpeg_reader_alloc);
|
892
|
+
rb_define_singleton_method(cImageFileJpegReader, "open", jpeg_reader_s_open, 1);
|
893
|
+
rb_define_method(cImageFileJpegReader, "initialize", jpeg_reader_initialize, 1);
|
894
|
+
rb_define_method(cImageFileJpegReader, "source_will_be_closed?", jpeg_reader_source_will_be_closed, 0);
|
895
|
+
|
896
|
+
rb_define_method(cImageFileJpegReader, "image_width", jpeg_reader_get_image_width, 0);
|
897
|
+
rb_define_method(cImageFileJpegReader, "image_height", jpeg_reader_get_image_height, 0);
|
898
|
+
rb_define_method(cImageFileJpegReader, "num_components", jpeg_reader_get_num_components, 0);
|
899
|
+
rb_define_method(cImageFileJpegReader, "jpeg_color_space", jpeg_reader_get_jpeg_color_space, 0);
|
900
|
+
|
901
|
+
rb_define_method(cImageFileJpegReader, "out_color_space", jpeg_reader_get_out_color_space, 0);
|
902
|
+
rb_define_method(cImageFileJpegReader, "scale", jpeg_reader_get_scale, 0);
|
903
|
+
rb_define_method(cImageFileJpegReader, "scale=", jpeg_reader_set_scale, 1);
|
904
|
+
rb_define_method(cImageFileJpegReader, "output_gamma", jpeg_reader_get_output_gamma, 0);
|
905
|
+
rb_define_method(cImageFileJpegReader, "output_gamma=", jpeg_reader_set_output_gamma, 1);
|
906
|
+
rb_define_method(cImageFileJpegReader, "buffered_image?", jpeg_reader_is_buffered_image, 0);
|
907
|
+
rb_define_method(cImageFileJpegReader, "dct_method", jpeg_reader_get_dct_method, 0);
|
908
|
+
rb_define_method(cImageFileJpegReader, "quantize_colors?", jpeg_reader_is_quantize_colors, 0);
|
909
|
+
rb_define_method(cImageFileJpegReader, "dither_mode", jpeg_reader_get_dither_mode, 0);
|
910
|
+
|
911
|
+
rb_define_method(cImageFileJpegReader, "output_width", jpeg_reader_get_output_width, 0);
|
912
|
+
rb_define_method(cImageFileJpegReader, "output_height", jpeg_reader_get_output_height, 0);
|
913
|
+
rb_define_method(cImageFileJpegReader, "output_components", jpeg_reader_get_output_components, 0);
|
914
|
+
|
915
|
+
rb_define_method(cImageFileJpegReader, "read_image", jpeg_reader_read_image, -1);
|
916
|
+
|
917
|
+
eImageFileJpegReaderError = rb_define_class_under(
|
918
|
+
cImageFileJpegReader, "Error", rb_eStandardError);
|
919
|
+
|
920
|
+
CONST_ID(id_GRAYSCALE, "GRAYSCALE");
|
921
|
+
CONST_ID(id_RGB, "RGB");
|
922
|
+
CONST_ID(id_YCbCr, "YCbCr");
|
923
|
+
CONST_ID(id_CMYK, "CMYK");
|
924
|
+
CONST_ID(id_YCCK, "YCCK");
|
925
|
+
CONST_ID(id_ISLOW, "ISLOW");
|
926
|
+
CONST_ID(id_IFAST, "IFAST");
|
927
|
+
CONST_ID(id_FLOAT, "FLOAT");
|
928
|
+
CONST_ID(id_NONE, "NONE");
|
929
|
+
CONST_ID(id_ORDERED, "ORDERED");
|
930
|
+
CONST_ID(id_FS, "FS");
|
931
|
+
CONST_ID(id_new, "new");
|
932
|
+
CONST_ID(id_close, "close");
|
933
|
+
CONST_ID(id_read, "read");
|
934
|
+
CONST_ID(id_pixel_format, "pixel_format");
|
935
|
+
CONST_ID(id_width, "width");
|
936
|
+
CONST_ID(id_height,"height");
|
937
|
+
CONST_ID(id_row_stride, "row_stride");
|
938
|
+
}
|