~ubuntu-branches/debian/squeeze/camlimages/squeeze

« back to all changes in this revision

Viewing changes to src/jpegwrite.c

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Le Gall, Ralf Treinen, Sylvain Le Gall
  • Date: 2009-03-05 00:19:32 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090305001932-f0hstlmun8hxvs0r
Tags: 1:3.0.1-1
[ Ralf Treinen ]
* Updated debian/watch.

[ Sylvain Le Gall ]
* New upstream version:
  * Remove useless patches
  * Adapt debian/rules and other debhelper files
  * Add debian/patches/fix_3_0_1 to fix various problem (probably due to
    OCaml 3.11 migration)
* Depends on version 2.12 of lablgtk2
* Add dh-ocaml build-dependency (rules/ocaml.mk)
* Add ${misc:Depends} to dependencies
* Update Homepage field into debian/control and debian/copyright
* Add license version for debian packaging
* Directly use eng.html rather than creating a linked index.html file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***********************************************************************/
 
2
/*                                                                     */
 
3
/*                           Objective Caml                            */
 
4
/*                                                                     */
 
5
/*            Fran�ois Pessaux, projet Cristal, INRIA Rocquencourt     */
 
6
/*            Pierre Weis, projet Cristal, INRIA Rocquencourt          */
 
7
/*            Jun Furuse, projet Cristal, INRIA Rocquencourt           */
 
8
/*                                                                     */
 
9
/*  Copyright 1999,2000                                                */
 
10
/*  Institut National de Recherche en Informatique et en Automatique.  */
 
11
/*  Distributed only by permission.                                    */
 
12
/*                                                                     */
 
13
/***********************************************************************/
 
14
#ifdef HAVE_CONFIG_H
 
15
#include "config.h"
 
16
#endif
 
17
 
 
18
#include <caml/mlvalues.h>
 
19
#include <caml/alloc.h>
 
20
#include <caml/memory.h>
 
21
#include <caml/fail.h>
 
22
 
 
23
#include <stdio.h>
 
24
#include <setjmp.h>
 
25
 
 
26
/*
 
27
 * Include file for users of JPEG library.
 
28
 * You will need to have included system headers that define at least
 
29
 * the typedefs FILE and size_t before you can include jpeglib.h.
 
30
 * (stdio.h is sufficient on ANSI-conforming systems.)
 
31
 * You may also wish to include "jerror.h".
 
32
 */
 
33
 
 
34
#include "jpeglib.h"
 
35
 
 
36
/*
 
37
 * Sample routine for JPEG compression.  We assume that the target file name
 
38
 * and a compression quality factor are passed in.
 
39
 */
 
40
 
 
41
extern char jpg_error_message[JMSG_LENGTH_MAX];
 
42
struct my_error_mgr {
 
43
  struct jpeg_error_mgr pub;    /* "public" fields */
 
44
 
 
45
  jmp_buf setjmp_buffer;        /* for return to caller */
 
46
};
 
47
typedef struct my_error_mgr * my_error_ptr;
 
48
extern void my_error_exit (j_common_ptr);
 
49
 
 
50
GLOBAL(value)
 
51
write_JPEG_file (value file,
 
52
                 value buffer,
 
53
                 value width, 
 
54
                 value height, 
 
55
                 value qual)
 
56
{
 
57
  JSAMPLE *image_buffer;
 
58
  int image_height;
 
59
  int image_width;
 
60
  char *filename;
 
61
  int quality;
 
62
 
 
63
  /* This struct contains the JPEG compression parameters and pointers to
 
64
   * working space (which is allocated as needed by the JPEG library).
 
65
   * It is possible to have several such structures, representing multiple
 
66
   * compression/decompression processes, in existence at once.  We refer
 
67
   * to any one struct (and its associated working data) as a "JPEG object".
 
68
   */
 
69
  struct jpeg_compress_struct cinfo;
 
70
  /* This struct represents a JPEG error handler.  It is declared separately
 
71
   * because applications often want to supply a specialized error handler
 
72
   * (see the second half of this file for an example).  But here we just
 
73
   * take the easy way out and use the standard error handler, which will
 
74
   * print a message on stderr and call exit() if compression fails.
 
75
   * Note that this struct must live as long as the main JPEG parameter
 
76
   * struct, to avoid dangling-pointer problems.
 
77
   */
 
78
  struct jpeg_error_mgr jerr;
 
79
  /* More stuff */
 
80
  FILE * outfile;               /* target file */
 
81
  JSAMPROW row_pointer[1];      /* pointer to JSAMPLE row[s] */
 
82
  int row_stride;               /* physical row width in image buffer */
 
83
 
 
84
  image_buffer = String_val(buffer);
 
85
  image_width = Int_val(width);
 
86
  image_height = Int_val(height);
 
87
  filename = String_val(file);
 
88
  quality= Int_val(qual);
 
89
 
 
90
  /* Step 1: allocate and initialize JPEG compression object */
 
91
 
 
92
  /* We have to set up the error handler first, in case the initialization
 
93
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
 
94
   * This routine fills in the contents of struct jerr, and returns jerr's
 
95
   * address which we place into the link field in cinfo.
 
96
   */
 
97
  cinfo.err = jpeg_std_error(&jerr);
 
98
  /* Now we can initialize the JPEG compression object. */
 
99
  jpeg_create_compress(&cinfo);
 
100
 
 
101
  /* Step 2: specify data destination (eg, a file) */
 
102
  /* Note: steps 2 and 3 can be done in either order. */
 
103
 
 
104
  /* Here we use the library-supplied code to send compressed data to a
 
105
   * stdio stream.  You can also write your own code to do something else.
 
106
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
 
107
   * requires it in order to write binary files.
 
108
   */
 
109
  if ((outfile = fopen(filename, "wb")) == NULL) {
 
110
    failwith ("can't open %s\n");
 
111
  }
 
112
  jpeg_stdio_dest(&cinfo, outfile);
 
113
 
 
114
  /* Step 3: set parameters for compression */
 
115
 
 
116
  /* First we supply a description of the input image.
 
117
   * Four fields of the cinfo struct must be filled in:
 
118
   */
 
119
  cinfo.image_width = image_width;      /* image width and height, in pixels */
 
120
  cinfo.image_height = image_height;
 
121
  cinfo.input_components = 3;           /* # of color components per pixel */
 
122
  cinfo.in_color_space = JCS_RGB;       /* colorspace of input image */
 
123
  /* Now use the library's routine to set default compression parameters.
 
124
   * (You must set at least cinfo.in_color_space before calling this,
 
125
   * since the defaults depend on the source color space.)
 
126
   */
 
127
  jpeg_set_defaults(&cinfo);
 
128
  /* Now you can set any non-default parameters you wish to.
 
129
   * Here we just illustrate the use of quality (quantization table) scaling:
 
130
   */
 
131
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
 
132
 
 
133
  /* Step 4: Start compressor */
 
134
 
 
135
  /* TRUE ensures that we will write a complete interchange-JPEG file.
 
136
   * Pass TRUE unless you are very sure of what you're doing.
 
137
   */
 
138
  jpeg_start_compress(&cinfo, TRUE);
 
139
 
 
140
  /* Step 5: while (scan lines remain to be written) */
 
141
  /*           jpeg_write_scanlines(...); */
 
142
 
 
143
  /* Here we use the library's state variable cinfo.next_scanline as the
 
144
   * loop counter, so that we don't have to keep track ourselves.
 
145
   * To keep things simple, we pass one scanline per call; you can pass
 
146
   * more if you wish, though.
 
147
   */
 
148
  row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
 
149
 
 
150
  while (cinfo.next_scanline < cinfo.image_height) {
 
151
    /* jpeg_write_scanlines expects an array of pointers to scanlines.
 
152
     * Here the array is only one element long, but you could pass
 
153
     * more than one scanline at a time if that's more convenient.
 
154
     */
 
155
    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
 
156
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
 
157
  }
 
158
 
 
159
  /* Step 6: Finish compression */
 
160
 
 
161
  jpeg_finish_compress(&cinfo);
 
162
  /* After finish_compress, we can close the output file. */
 
163
  fclose(outfile);
 
164
 
 
165
  /* Step 7: release JPEG compression object */
 
166
 
 
167
  /* This is an important step since it will release a good deal of memory. */
 
168
  jpeg_destroy_compress(&cinfo);
 
169
 
 
170
  /* And we're done! */
 
171
  return Val_unit;
 
172
}
 
173
 
 
174
 
 
175
/*
 
176
 * SOME FINE POINTS:
 
177
 *
 
178
 * In the above loop, we ignored the return value of jpeg_write_scanlines,
 
179
 * which is the number of scanlines actually written.  We could get away
 
180
 * with this because we were only relying on the value of cinfo.next_scanline,
 
181
 * which will be incremented correctly.  If you maintain additional loop
 
182
 * variables then you should be careful to increment them properly.
 
183
 * Actually, for output to a stdio stream you needn't worry, because
 
184
 * then jpeg_write_scanlines will write all the lines passed (or else exit
 
185
 * with a fatal error).  Partial writes can only occur if you use a data
 
186
 * destination module that can demand suspension of the compressor.
 
187
 * (If you don't know what that's for, you don't need it.)
 
188
 *
 
189
 * If the compressor requires full-image buffers (for entropy-coding
 
190
 * optimization or a multi-scan JPEG file), it will create temporary
 
191
 * files for anything that doesn't fit within the maximum-memory setting.
 
192
 * (Note that temp files are NOT needed if you use the default parameters.)
 
193
 * On some systems you may need to set up a signal handler to ensure that
 
194
 * temporary files are deleted if the program is interrupted.  See libjpeg.doc.
 
195
 *
 
196
 * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG
 
197
 * files to be compatible with everyone else's.  If you cannot readily read
 
198
 * your data in that order, you'll need an intermediate array to hold the
 
199
 * image.  See rdtarga.c or rdbmp.c for examples of handling bottom-to-top
 
200
 * source data using the JPEG code's internal virtual-array mechanisms.
 
201
 */
 
202
 
 
203
value open_jpeg_file_for_write_colorspace( name, width, height, qual, colorspace )
 
204
     value name;
 
205
     value width;
 
206
     value height;
 
207
     value qual;
 
208
     J_COLOR_SPACE colorspace;
 
209
{
 
210
  char *filename;
 
211
  int image_height;
 
212
  int image_width;
 
213
  int quality;
 
214
 
 
215
  struct jpeg_compress_struct* cinfop;
 
216
  struct my_error_mgr *jerrp;
 
217
  /* More stuff */
 
218
  FILE * outfile;               /* source file */
 
219
  value res;
 
220
 
 
221
  image_width= Int_val( width );
 
222
  image_height= Int_val( height );
 
223
  filename= String_val( name );
 
224
  quality= Int_val(qual);
 
225
 
 
226
  if ((outfile = fopen(filename, "wb")) == NULL) {
 
227
    failwith("failed to open jpeg file");
 
228
  }
 
229
 
 
230
  cinfop = malloc(sizeof (struct jpeg_compress_struct));
 
231
  jerrp = malloc(sizeof (struct my_error_mgr));
 
232
  cinfop->err = jpeg_std_error(&jerrp->pub);
 
233
  jerrp->pub.error_exit = my_error_exit;
 
234
 
 
235
  if (setjmp(jerrp->setjmp_buffer)) {
 
236
    /* If we get here, the JPEG code has signaled an error.
 
237
     * We need to clean up the JPEG object, close the input file, and return.
 
238
     */
 
239
    jpeg_destroy_compress(cinfop);
 
240
    free(jerrp);
 
241
    fclose(outfile);
 
242
    failwith(jpg_error_message);
 
243
  }
 
244
 
 
245
  jpeg_create_compress(cinfop);
 
246
  jpeg_stdio_dest(cinfop, outfile);
 
247
 
 
248
  cinfop->image_width= image_width; 
 
249
  cinfop->image_height= image_height; 
 
250
  cinfop->input_components = (colorspace == JCS_RGB ? 3 : 4);
 
251
  cinfop->in_color_space= colorspace /* JCS_RGB or JCS_CMYK */;
 
252
  jpeg_set_defaults(cinfop);
 
253
  jpeg_set_quality(cinfop, quality, TRUE);
 
254
  jpeg_start_compress(cinfop, TRUE);
 
255
 
 
256
  { 
 
257
    res = alloc_tuple(3);
 
258
    Field(res, 0) = (value)cinfop;
 
259
    Field(res, 1) = (value)outfile;
 
260
    Field(res, 2) = (value)jerrp;
 
261
  }
 
262
  /*
 
263
  fprintf(stderr, "cinfop= %d outfile= %d %d %d \n", cinfop, infile, cinfop->output_scanline, cinfop->output_height); 
 
264
  fflush(stderr);
 
265
  */
 
266
  return res;
 
267
}
 
268
 
 
269
value open_jpeg_file_for_write( name, width, height, qual )
 
270
     value name;
 
271
     value width;
 
272
     value height;
 
273
     value qual;
 
274
{
 
275
  return
 
276
    open_jpeg_file_for_write_colorspace( name, width, height, qual, JCS_RGB );
 
277
}
 
278
 
 
279
value open_jpeg_file_for_write_cmyk( name, width, height, qual )
 
280
     value name;
 
281
     value width;
 
282
     value height;
 
283
     value qual;
 
284
{
 
285
  return
 
286
    open_jpeg_file_for_write_colorspace( name, width, height, qual, JCS_CMYK );
 
287
}
 
288
 
 
289
value write_jpeg_scanline( jpegh, buf )
 
290
value jpegh, buf;
 
291
{
 
292
  struct jpeg_compress_struct *cinfop;
 
293
  JSAMPROW row[1];
 
294
 
 
295
  cinfop = (struct jpeg_compress_struct *) Field( jpegh, 0 );
 
296
 
 
297
  row[0] = String_val( buf );
 
298
 
 
299
  jpeg_write_scanlines( cinfop, row, 1 );
 
300
  return Val_unit;
 
301
}
 
302
 
 
303
value close_jpeg_file_for_write( jpegh )
 
304
     value jpegh;
 
305
{
 
306
  struct jpeg_compress_struct *cinfop;
 
307
  struct my_error_mgr *jerrp;
 
308
  FILE *outfile;
 
309
 
 
310
#ifdef DEBUG_JPEG
 
311
  fprintf(stderr, "closing\n");
 
312
  fflush(stderr);
 
313
#endif
 
314
 
 
315
  cinfop = (struct jpeg_compress_struct *) Field( jpegh, 0 );
 
316
  outfile = (FILE *) Field( jpegh, 1 );
 
317
  jerrp = (struct my_error_mgr *) Field( jpegh, 2 );
 
318
 
 
319
#ifdef DEBUG_JPEG
 
320
  fprintf(stderr, "cinfop= %d outfile= %d %d %d \n", cinfop, outfile, cinfop->next_scanline, cinfop->image_height); 
 
321
#endif
 
322
 
 
323
   if( cinfop->next_scanline >= cinfop->image_height ){ 
 
324
#ifdef DEBUG_JPEG
 
325
     fprintf(stderr, "finish\n");
 
326
     fflush(stderr);
 
327
#endif
 
328
     jpeg_finish_compress( cinfop );
 
329
   }
 
330
#ifdef DEBUG_JPEG
 
331
  fprintf(stderr, "destroy\n");
 
332
  fflush(stderr);
 
333
#endif
 
334
  jpeg_destroy_compress( cinfop ); 
 
335
  
 
336
  free(cinfop);
 
337
  free(jerrp);
 
338
#ifdef DEBUG_JPEG
 
339
  fprintf(stderr, "file close\n");
 
340
  fflush(stderr);
 
341
#endif
 
342
  fclose(outfile);
 
343
 
 
344
  return Val_unit;
 
345
}