1
/***********************************************************************/
5
/* Fran�ois Pessaux, projet Cristal, INRIA Rocquencourt */
6
/* Pierre Weis, projet Cristal, INRIA Rocquencourt */
7
/* Jun Furuse, projet Cristal, INRIA Rocquencourt */
9
/* Copyright 1999,2000 */
10
/* Institut National de Recherche en Informatique et en Automatique. */
11
/* Distributed only by permission. */
13
/***********************************************************************/
15
#include <caml/mlvalues.h>
16
#include <caml/alloc.h>
17
#include <caml/memory.h>
18
#include <caml/fail.h>
20
#define jpeg_not_supported() \
21
failwith( "jpeg is not supported" ); \
30
* Include file for users of JPEG library.
31
* You will need to have included system headers that define at least
32
* the typedefs FILE and size_t before you can include jpeglib.h.
33
* (stdio.h is sufficient on ANSI-conforming systems.)
34
* You may also wish to include "jerror.h".
40
* <setjmp.h> is used for the optional error recovery mechanism shown in
41
* the second part of the example.
46
char jpg_error_message[JMSG_LENGTH_MAX];
49
struct jpeg_error_mgr pub; /* "public" fields */
51
jmp_buf setjmp_buffer; /* for return to caller */
54
typedef struct my_error_mgr * my_error_ptr;
57
my_error_exit (j_common_ptr cinfo)
59
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
60
my_error_ptr myerr = (my_error_ptr) cinfo->err;
62
/* Always display the message. */
63
/* We could postpone this until after returning, if we chose. */
64
fprintf(stderr,"setting message\n");
65
(*cinfo->err->format_message) (cinfo, jpg_error_message );
67
/* Return control to the setjmp point */
68
longjmp(myerr->setjmp_buffer, 1);
72
read_JPEG_file (value name)
78
/* This struct contains the JPEG decompression parameters and pointers to
79
* working space (which is allocated as needed by the JPEG library).
81
struct jpeg_decompress_struct cinfo;
82
/* We use our private extension JPEG error handler.
83
* Note that this struct must live as long as the main JPEG parameter
84
* struct, to avoid dangling-pointer problems.
86
struct my_error_mgr jerr;
88
FILE * infile; /* source file */
89
JSAMPARRAY buffer; /* Output row buffer */
90
int row_stride; /* physical row width in output buffer */
93
filename= String_val( name );
95
/* In this example we want to open the input file before doing anything else,
96
* so that the setjmp() error recovery below can assume the file is open.
97
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
98
* requires it in order to read binary files.
101
if ((infile = fopen(filename, "rb")) == NULL) {
102
failwith("failed to open jpeg file");
105
/* Step 1: allocate and initialize JPEG decompression object */
107
/* We set up the normal JPEG error routines, then override error_exit. */
108
cinfo.err = jpeg_std_error(&jerr.pub);
109
jerr.pub.error_exit = my_error_exit;
111
/* Establish the setjmp return context for my_error_exit to use. */
112
if (setjmp(jerr.setjmp_buffer)) {
113
/* If we get here, the JPEG code has signaled an error.
114
* We need to clean up the JPEG object, close the input file, and return.
116
fprintf(stderr, "Exiting...");
117
jpeg_destroy_decompress(&cinfo);
120
failwith(jpg_error_message);
122
/* Now we can initialize the JPEG decompression object. */
123
jpeg_create_decompress(&cinfo);
125
/* Step 2: specify data source (eg, a file) */
127
jpeg_stdio_src(&cinfo, infile);
129
/* Step 3: read file parameters with jpeg_read_header() */
131
(void) jpeg_read_header(&cinfo, TRUE);
133
/* We can ignore the return value from jpeg_read_header since
134
* (a) suspension is not possible with the stdio data source, and
135
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
136
* See libjpeg.doc for more info.
139
/* Step 4: set parameters for decompression */
141
/* In this example, we don't need to change any of the defaults set by
142
* jpeg_read_header(), so we do nothing here.
145
cinfo.out_color_space = JCS_RGB;
147
/* Step 5: Start decompressor */
149
(void) jpeg_start_decompress(&cinfo);
150
/* We can ignore the return value since suspension is not possible
151
* with the stdio data source.
154
/* We may need to do some setup of our own at this point before reading
155
* the data. After jpeg_start_decompress() we have the correct scaled
156
* output image dimensions available, as well as the output colormap
157
* if we asked for color quantization.
158
* In this example, we need to make an output work buffer of the right size.
160
/* JSAMPLEs per row in output buffer */
162
row_stride = cinfo.output_width * cinfo.output_components;
164
/* Make a one-row-high sample array that will go away when done with image */
165
buffer = (*cinfo.mem->alloc_sarray)
166
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride,
167
cinfo.output_height );
169
/* Step 6: while (scan lines remain to be read) */
170
/* jpeg_read_scanlines(...); */
172
/* Here we use the library's state variable cinfo.output_scanline as the
173
* loop counter, so that we don't have to keep track ourselves.
175
while (cinfo.output_scanline < cinfo.output_height) {
176
/* jpeg_read_scanlines expects an array of pointers to scanlines.
177
* Here the array is only one element long, but you could ask for
178
* more than one scanline at a time if that's more convenient.
180
jpeg_read_scanlines(&cinfo, buffer + cinfo.output_scanline, 1);
185
r[0] = Val_int(cinfo.output_width);
186
r[1] = Val_int(cinfo.output_height);
187
r[2] = alloc_string ( row_stride * cinfo.output_height );
188
for(i=0; i<cinfo.output_height; i++){
189
memcpy( String_val(r[2]) + i * row_stride,
190
buffer[i], row_stride);
192
res = alloc_tuple(3);
193
for(i=0; i<3; i++) Field(res, i) = r[i];
196
/* Step 7: Finish decompression */
198
(void) jpeg_finish_decompress(&cinfo);
199
/* We can ignore the return value since suspension is not possible
200
* with the stdio data source.
203
/* Step 8: Release JPEG decompression object */
205
/* This is an important step since it will release a good deal of memory. */
206
jpeg_destroy_decompress(&cinfo);
208
/* After finish_decompress, we can close the input file.
209
* Here we postpone it until after no more JPEG errors are possible,
210
* so as to simplify the setjmp error logic above. (Actually, I don't
211
* think that jpeg_destroy can do an error exit, but why assume anything...)
215
/* At this point you may want to check to see whether any corrupt-data
216
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
219
/* And we're done! */
223
value jpeg_set_scale_denom( jpegh, denom )
227
CAMLparam2(jpegh,denom);
228
struct jpeg_decompress_struct *cinfop;
230
cinfop = (struct jpeg_decompress_struct *) Field ( jpegh, 0 );
231
cinfop->scale_denom = Int_val( denom );
232
CAMLreturn(Val_unit);
235
value open_jpeg_file_for_read( name )
242
/* This struct contains the JPEG decompression parameters and pointers to
243
* working space (which is allocated as needed by the JPEG library).
245
struct jpeg_decompress_struct* cinfop;
246
/* We use our private extension JPEG error handler.
247
* Note that this struct must live as long as the main JPEG parameter
248
* struct, to avoid dangling-pointer problems.
250
struct my_error_mgr *jerrp;
252
FILE * infile; /* source file */
255
filename= String_val( name );
257
if ((infile = fopen(filename, "rb")) == NULL) {
258
failwith("failed to open jpeg file");
261
cinfop = malloc(sizeof (struct jpeg_decompress_struct));
262
jerrp = malloc(sizeof (struct my_error_mgr));
264
/* In this example we want to open the input file before doing anything else,
265
* so that the setjmp() error recovery below can assume the file is open.
266
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
267
* requires it in order to read binary files.
271
/* Step 1: allocate and initialize JPEG decompression object */
273
/* We set up the normal JPEG error routines, then override error_exit. */
274
cinfop->err = jpeg_std_error(&jerrp->pub);
275
jerrp->pub.error_exit = my_error_exit;
276
/* Establish the setjmp return context for my_error_exit to use. */
277
if (setjmp(jerrp->setjmp_buffer)) {
278
/* If we get here, the JPEG code has signaled an error.
279
* We need to clean up the JPEG object, close the input file, and return.
281
jpeg_destroy_decompress(cinfop);
284
failwith(jpg_error_message);
286
/* Now we can initialize the JPEG decompression object. */
287
jpeg_create_decompress(cinfop);
289
/* Step 2: specify data source (eg, a file) */
291
jpeg_stdio_src(cinfop, infile);
293
/* Step 3: read file parameters with jpeg_read_header() */
295
(void) jpeg_read_header(cinfop, TRUE);
299
r[0] = Val_int(cinfop->image_width);
300
r[1] = Val_int(cinfop->image_height);
301
r[2] = alloc_tuple(3);
302
Field(r[2], 0) = (value)cinfop;
303
Field(r[2], 1) = (value)infile;
304
Field(r[2], 2) = (value)jerrp;
305
res = alloc_tuple(3);
306
for(i=0; i<3; i++) Field(res, i) = r[i];
311
value open_jpeg_file_for_read_start( jpegh )
316
struct jpeg_decompress_struct* cinfop;
317
struct my_error_mgr *jerrp;
321
cinfop = (struct jpeg_decompress_struct *) Field( jpegh, 0 );
322
infile = (FILE *) Field( jpegh, 1 );
323
jerrp = (struct my_error_mgr *) Field( jpegh, 2 );
325
/* We can ignore the return value from jpeg_read_header since
326
* (a) suspension is not possible with the stdio data source, and
327
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
328
* See libjpeg.doc for more info.
331
/* Step 4: set parameters for decompression */
333
/* In this example, we don't need to change any of the defaults set by
334
* jpeg_read_header(), so we do nothing here.
337
cinfop->out_color_space = JCS_RGB;
339
/* Step 5: Start decompressor */
341
(void) jpeg_start_decompress(cinfop);
342
/* We can ignore the return value since suspension is not possible
343
* with the stdio data source.
346
/* We may need to do some setup of our own at this point before reading
347
* the data. After jpeg_start_decompress() we have the correct scaled
348
* output image dimensions available, as well as the output colormap
349
* if we asked for color quantization.
350
* In this example, we need to make an output work buffer of the right size.
352
/* JSAMPLEs per row in output buffer */
354
/* row_stride = cinfop->output_width * cinfop->output_components; */
358
r[0] = Val_int(cinfop->output_width);
359
r[1] = Val_int(cinfop->output_height);
360
r[2] = alloc_tuple(3);
361
Field(r[2], 0) = (value)cinfop;
362
Field(r[2], 1) = (value)infile;
363
Field(r[2], 2) = (value)jerrp;
364
res = alloc_tuple(3);
365
for(i=0; i<3; i++) Field(res, i) = r[i];
368
fprintf(stderr, "cinfop= %d infile= %d %d %d \n", cinfop, infile, cinfop->output_scanline, cinfop->output_height);
374
value read_jpeg_scanline( jpegh, buf )
377
CAMLparam2(jpegh,buf);
379
struct jpeg_decompress_struct *cinfop;
382
cinfop = (struct jpeg_decompress_struct *) Field( jpegh, 0 );
384
row[0] = String_val( buf );
387
fprintf(stderr, "scan %d %d ...\n", cinfop->output_scanline, cinfop->output_height);
390
jpeg_read_scanlines( cinfop, row, 1 );
391
CAMLreturn(Val_unit);
394
value close_jpeg_file_for_read( jpegh )
399
struct jpeg_decompress_struct *cinfop;
400
struct my_error_mgr *jerrp;
404
fprintf(stderr, "closing\n");
408
cinfop = (struct jpeg_decompress_struct *) Field( jpegh, 0 );
409
infile = (FILE *) Field( jpegh, 1 );
410
jerrp = (struct my_error_mgr *) Field( jpegh, 2 );
413
fprintf(stderr, "cinfop= %d infile= %d %d %d \n", cinfop, infile, cinfop->output_scanline, cinfop->output_height);
416
if( cinfop->output_scanline >= cinfop->output_height ){
418
fprintf(stderr, "finish\n");
421
jpeg_finish_decompress( cinfop );
424
fprintf(stderr, "destroy\n");
427
jpeg_destroy_decompress( cinfop );
432
fprintf(stderr, "file close\n");
437
CAMLreturn(Val_unit);
442
value read_JPEG_file (value name)
445
jpeg_not_supported();
448
value open_jpeg_file_for_read( name )
452
jpeg_not_supported();
455
value open_jpeg_file_for_read_start( jpegh )
459
jpeg_not_supported();
462
value read_jpeg_scanline( jpegh, buf )
465
CAMLparam2(jpegh,buf);
466
jpeg_not_supported();
469
value close_jpeg_file_for_read (value jpegh)
472
jpeg_not_supported();
475
value jpeg_set_scale_denom( jpegh, denom )
479
CAMLparam2(jpegh,denom);
480
jpeg_not_supported();
483
#endif /* HAVE_JPEG */