18 // libjpeg needs it, but libpng wants to do the include itself
22 // the class' methods themselves...
25 // forward decls for implementation
26 static int read_JPEG_file (const char * filename
,
28 unsigned* widthp
, unsigned* heightp
);
29 static void write_JPEG_file (int fd
, const pixel
*const buffer
,
30 unsigned width
, unsigned height
,
32 static int write_PNG_file(int fd
, const sImLib::Image
* const imgp
,
35 Image::Image(const std::string
& _filename
)
36 : filename(_filename
) {
37 if (!read_JPEG_file(filename
.c_str(), &data
, &width
, &height
)) {
38 fprintf(stderr
, "cannot read jpeg file\n");
42 // see rng for empfile creation
44 if (gettimeofday(&tv
, NULL
) < 0) {
45 fprintf(stderr
, "cannot read time to seed rng: %s\n", strerror(errno
));
51 Image::Image(const Image
& image
)
53 , height(image
.height
)
54 , filename(image
.filename
) {
55 unsigned size
= width
* height
* sizeof(pixel
);
56 data
= (pixel
*)malloc(size
);
57 memcpy(data
, image
.data
, size
);
64 int Image::write_jpeg(const std::string
& out_filename
, int quality
) const {
65 int fd
= open(out_filename
.c_str(), O_WRONLY
|O_CREAT
,
66 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
);
68 fprintf(stderr
, "can't open %s: %s\n", out_filename
.c_str(), strerror(errno
));
71 this->write_jpeg(fd
, quality
);
75 int Image::write_jpeg(int fd
, int quality
) const {
76 write_JPEG_file(fd
, data
, width
, height
, quality
);
80 int Image::write_png(const std::string
& out_filename
, bool quick
) const {
81 int fd
= open(out_filename
.c_str(), O_WRONLY
|O_CREAT
,
82 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IWGRP
| S_IROTH
| S_IWOTH
);
84 fprintf(stderr
, "can't open %s: %s\n", out_filename
.c_str(), strerror(errno
));
87 return this->write_png(fd
, quick
);
90 int Image::write_png(int fd
, bool quick
) const {
91 return write_PNG_file(fd
, this, quick
);
94 void Image::display() const {
95 // Write to temporary image file
96 const char pattern
[] = "/tmp/goir-tmp%05lu.png";
97 char tmpname
[sizeof(pattern
) + 1];
98 sprintf(tmpname
, pattern
, random() % 100000);
99 int tmpfd
= open(tmpname
, O_WRONLY
|O_CREAT
,
100 O_EXCL
|S_IRUSR
|S_IWUSR
);
101 this->write_png(tmpfd
, true);
103 // display using imagemagick
104 const char cmdname
[]="gm display";
105 char cmd
[sizeof(pattern
) + sizeof(cmdname
) + 2];
106 snprintf(cmd
, sizeof(cmd
), "%s %s", cmdname
, tmpname
);
114 void Image::draw_line(const int x0
, const int y0
, const int x1
, const int y1
,
115 const pixel
& color
, const float opacity
) {
116 assert (opacity
>= 0.0 && opacity
<= 1.0);
118 sImLib_forline(this, ptrd
, x0
, y0
, x1
, y1
, memcpy(ptrd
, &color
, 3) );
120 const float copacity
= 1.0 - opacity
;
121 const float scaled_color
[3] = { color
[0]*opacity
,
124 sImLib_forline(this, ptrd
, x0
, y0
, x1
, y1
,
125 for (unsigned k
=0; k
<3; k
++)
126 (*ptrd
)[k
] = (component
)(scaled_color
[k
] + copacity
* *(ptrd
)[k
]);
131 //////////////////////////////////////////////////
132 // Code mostly stolen from libjpeg's own example.
135 * Sample routine for JPEG compression. We assume that the target file name
136 * and a compression quality factor are passed in.
139 static void write_JPEG_file (int fd
, const pixel
*const buffer
,
140 unsigned width
, unsigned height
,
143 /* This struct contains the JPEG compression parameters and pointers to
144 * working space (which is allocated as needed by the JPEG library).
145 * It is possible to have several such structures, representing multiple
146 * compression/decompression processes, in existence at once. We refer
147 * to any one struct (and its associated working data) as a "JPEG object".
149 struct jpeg_compress_struct cinfo
;
150 /* This struct represents a JPEG error handler. It is declared separately
151 * because applications often want to supply a specialized error handler
152 * (see the second half of this file for an example). But here we just
153 * take the easy way out and use the standard error handler, which will
154 * print a message on stderr and call exit() if compression fails.
155 * Note that this struct must live as long as the main JPEG parameter
156 * struct, to avoid dangling-pointer problems.
158 struct jpeg_error_mgr jerr
;
160 FILE * outfile
; /* target file */
161 JSAMPROW row_pointer
[1]; /* pointer to JSAMPLE row[s] */
163 /* Step 1: allocate and initialize JPEG compression object */
165 /* We have to set up the error handler first, in case the initialization
166 * step fails. (Unlikely, but it could happen if you are out of memory.)
167 * This routine fills in the contents of struct jerr, and returns jerr's
168 * address which we place into the link field in cinfo.
170 cinfo
.err
= jpeg_std_error(&jerr
);
171 /* Now we can initialize the JPEG compression object. */
172 jpeg_create_compress(&cinfo
);
174 /* Step 2: specify data destination (eg, a file) */
175 /* Note: steps 2 and 3 can be done in either order. */
177 /* Here we use the library-supplied code to send compressed data to a
178 * stdio stream. You can also write your own code to do something else.
179 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
180 * requires it in order to write binary files.
182 if ((outfile
= fdopen(fd
, "wb")) == NULL
) {
183 fprintf(stderr
, "can't fdopen %d: %s\n", fd
, strerror(errno
));
186 jpeg_stdio_dest(&cinfo
, outfile
);
188 /* Step 3: set parameters for compression */
190 /* First we supply a description of the input image.
191 * Four fields of the cinfo struct must be filled in:
193 cinfo
.image_width
= width
; /* image width and height, in pixels */
194 cinfo
.image_height
= height
;
195 cinfo
.input_components
= 3; /* # of color components per pixel */
196 cinfo
.in_color_space
= JCS_RGB
; /* colorspace of input image */
197 /* Now use the library's routine to set default compression parameters.
198 * (You must set at least cinfo.in_color_space before calling this,
199 * since the defaults depend on the source color space.)
201 jpeg_set_defaults(&cinfo
);
202 /* Now you can set any non-default parameters you wish to.
203 * Here we just illustrate the use of quality (quantization table) scaling:
205 jpeg_set_quality(&cinfo
, quality
, TRUE
/* limit to baseline-JPEG values */);
207 /* Step 4: Start compressor */
209 /* TRUE ensures that we will write a complete interchange-JPEG file.
210 * Pass TRUE unless you are very sure of what you're doing.
212 jpeg_start_compress(&cinfo
, TRUE
);
214 /* Step 5: while (scan lines remain to be written) */
215 /* jpeg_write_scanlines(...); */
217 /* Here we use the library's state variable cinfo.next_scanline as the
218 * loop counter, so that we don't have to keep track ourselves.
219 * To keep things simple, we pass one scanline per call; you can pass
220 * more if you wish, though.
222 while (cinfo
.next_scanline
< cinfo
.image_height
) {
223 /* jpeg_write_scanlines expects an array of pointers to scanlines.
224 * Here the array is only one element long, but you could pass
225 * more than one scanline at a time if that's more convenient.
227 row_pointer
[0] = (JSAMPLE
*) & buffer
[cinfo
.next_scanline
* width
];
228 (void) jpeg_write_scanlines(&cinfo
, row_pointer
, 1);
231 /* Step 6: Finish compression */
233 jpeg_finish_compress(&cinfo
);
234 /* After finish_compress, we can close the output file. */
237 /* Step 7: release JPEG compression object */
239 /* This is an important step since it will release a good deal of memory. */
240 jpeg_destroy_compress(&cinfo
);
242 /* And we're done! */
249 * The JPEG library's standard error handler (jerror.c) is divided into
250 * several "methods" which you can override individually. This lets you
251 * adjust the behavior without duplicating a lot of code, which you might
252 * have to update with each future release.
254 * Our example here shows how to override the "error_exit" method so that
255 * control is returned to the library's caller when a fatal error occurs,
256 * rather than calling exit() as the standard error_exit method does.
258 * We use C's setjmp/longjmp facility to return control. This means that the
259 * routine which calls the JPEG library must first execute a setjmp() call to
260 * establish the return point. We want the replacement error_exit to do a
261 * longjmp(). But we need to make the setjmp buffer accessible to the
262 * error_exit routine. To do this, we make a private extension of the
263 * standard JPEG error handler object. (If we were using C++, we'd say we
264 * were making a subclass of the regular error handler.)
266 * Here's the extended error handler struct:
269 struct my_error_mgr
{
270 struct jpeg_error_mgr pub
; /* "public" fields */
272 jmp_buf setjmp_buffer
; /* for return to caller */
275 typedef struct my_error_mgr
* my_error_ptr
;
278 * Here's the routine that will replace the standard error_exit method:
282 my_error_exit (j_common_ptr cinfo
)
284 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
285 my_error_ptr myerr
= (my_error_ptr
) cinfo
->err
;
287 /* Always display the message. */
288 /* We could postpone this until after returning, if we chose. */
289 (*cinfo
->err
->output_message
) (cinfo
);
291 /* Return control to the setjmp point */
292 longjmp(myerr
->setjmp_buffer
, 1);
297 * Sample routine for JPEG decompression. We assume that the source file name
298 * is passed in. We want to return 1 on success, 0 on error.
300 static int read_JPEG_file (const char * filename
, pixel
** outbufferp
,
301 unsigned* widthp
, unsigned* heightp
)
303 /* This struct contains the JPEG decompression parameters and pointers to
304 * working space (which is allocated as needed by the JPEG library).
306 struct jpeg_decompress_struct cinfo
;
307 /* We use our private extension JPEG error handler.
308 * Note that this struct must live as long as the main JPEG parameter
309 * struct, to avoid dangling-pointer problems.
311 struct my_error_mgr jerr
;
313 FILE * infile
; /* source file */
314 JSAMPARRAY buffer
; /* Output row buffer */
315 int row_stride
; /* physical row width in output buffer */
316 pixel
* buffer_lineptr
;
318 /* In this example we want to open the input file before doing anything else,
319 * so that the setjmp() error recovery below can assume the file is open.
320 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
321 * requires it in order to read binary files.
324 if ((infile
= fopen(filename
, "rb")) == NULL
) {
325 fprintf(stderr
, "can't open %s\n", filename
);
329 /* Step 1: allocate and initialize JPEG decompression object */
331 /* We set up the normal JPEG error routines, then override error_exit. */
332 cinfo
.err
= jpeg_std_error(&jerr
.pub
);
333 jerr
.pub
.error_exit
= my_error_exit
;
334 /* Establish the setjmp return context for my_error_exit to use. */
335 if (setjmp(jerr
.setjmp_buffer
)) {
336 /* If we get here, the JPEG code has signaled an error.
337 * We need to clean up the JPEG object, close the input file, and return.
339 jpeg_destroy_decompress(&cinfo
);
343 /* Now we can initialize the JPEG decompression object. */
344 jpeg_create_decompress(&cinfo
);
345 /* Step 2: specify data source (eg, a file) */
347 jpeg_stdio_src(&cinfo
, infile
);
349 /* Step 3: read file parameters with jpeg_read_header() */
351 (void) jpeg_read_header(&cinfo
, TRUE
);
352 /* We can ignore the return value from jpeg_read_header since
353 * (a) suspension is not possible with the stdio data source, and
354 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
355 * See libjpeg.doc for more info.
358 /* Step 4: set parameters for decompression */
360 /* In this example, we don't need to change any of the defaults set by
361 * jpeg_read_header(), so we do nothing here.
364 /* Step 5: Start decompressor */
366 (void) jpeg_start_decompress(&cinfo
);
367 /* We can ignore the return value since suspension is not possible
368 * with the stdio data source.
371 /* We may need to do some setup of our own at this point before reading
372 * the data. After jpeg_start_decompress() we have the correct scaled
373 * output image dimensions available, as well as the output colormap
374 * if we asked for color quantization.
375 * In this example, we need to make an output work buffer of the right size.
377 *widthp
= cinfo
.output_width
;
378 *heightp
= cinfo
.output_height
;
379 assert (cinfo
.output_components
== 3); // FIXME: lacks support for greyscale
380 assert (sizeof(pixel
) == 3);
381 *outbufferp
= (pixel
*)malloc(cinfo
.output_width
* cinfo
.output_height
*
383 buffer_lineptr
= *outbufferp
;
385 /* JSAMPLEs per row in output buffer */
386 row_stride
= cinfo
.output_width
* cinfo
.output_components
;
387 /* Make a one-row-high sample array that will go away when done with image */
388 buffer
= (*cinfo
.mem
->alloc_sarray
)
389 ((j_common_ptr
) &cinfo
, JPOOL_IMAGE
, row_stride
, 1);
391 /* Step 6: while (scan lines remain to be read) */
392 /* jpeg_read_scanlines(...); */
394 /* Here we use the library's state variable cinfo.output_scanline as the
395 * loop counter, so that we don't have to keep track ourselves.
397 while (cinfo
.output_scanline
< cinfo
.output_height
) {
398 /* jpeg_read_scanlines expects an array of pointers to scanlines.
399 * Here the array is only one element long, but you could ask for
400 * more than one scanline at a time if that's more convenient.
402 (void) jpeg_read_scanlines(&cinfo
, buffer
, 1);
403 /* Copy into our own buffer */
404 memcpy(buffer_lineptr
, buffer
[0], row_stride
);
405 buffer_lineptr
+= cinfo
.output_width
;
408 /* Step 7: Finish decompression */
410 (void) jpeg_finish_decompress(&cinfo
);
411 /* We can ignore the return value since suspension is not possible
412 * with the stdio data source.
415 /* Step 8: Release JPEG decompression object */
417 /* This is an important step since it will release a good deal of memory. */
418 jpeg_destroy_decompress(&cinfo
);
420 /* After finish_decompress, we can close the input file.
421 * Here we postpone it until after no more JPEG errors are possible,
422 * so as to simplify the setjmp error logic above. (Actually, I don't
423 * think that jpeg_destroy can do an error exit, but why assume anything...)
427 /* At this point you may want to check to see whether any corrupt-data
428 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
431 /* And we're done! */
436 ///////////////////////////////////////////////////////////////
437 // Code mostly stolen from libpng's public-domain own example.
439 /* write a png file */
440 static int write_PNG_file(int fd
, const sImLib::Image
* const imgp
,
448 fp
= fdopen(fd
, "wb");
452 /* Create and initialize the png_struct with the desired error handler
453 * functions. If you want to use the default stderr and longjump method,
454 * you can supply NULL for the last three parameters. We also check that
455 * the library version is compatible with the one used at compile time,
456 * in case we are using dynamically linked libraries. REQUIRED.
458 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
,
469 /* Allocate/initialize the image information data. REQUIRED */
470 info_ptr
= png_create_info_struct(png_ptr
);
471 if (info_ptr
== NULL
)
474 png_destroy_write_struct(&png_ptr
, png_infopp_NULL
);
478 /* Set error handling. REQUIRED if you aren't supplying your own
479 * error handling functions in the png_create_write_struct() call.
481 if (setjmp(png_jmpbuf(png_ptr
)))
483 /* If we get here, we had a problem reading the file */
485 // FIXME: should copy cleanup calls from end of function here ?
486 png_destroy_write_struct(&png_ptr
, &info_ptr
);
490 /* Fill in image info */
491 png_set_IHDR(png_ptr
, info_ptr
, imgp
->width
, imgp
->height
, 8,
492 PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
,
493 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
496 png_set_compression_level(png_ptr
, 1);
497 png_set_filter(png_ptr
, PNG_FILTER_TYPE_BASE
, PNG_FILTER_NONE
);
501 png_bytep
* row_pointers
=
502 (png_bytep
*)png_malloc(png_ptr
, imgp
->height
*png_sizeof(png_bytep
));
503 for (unsigned i
=0; i
<imgp
->height
; i
++)
504 row_pointers
[i
] = (png_bytep
)imgp
->ptr(0,i
);
505 png_set_rows(png_ptr
, info_ptr
, row_pointers
);
507 /* set up the output control if you are using standard C streams */
508 png_init_io(png_ptr
, fp
);
510 /* This is the easy way. Use it if you already have all the
511 * image info living info in the structure. You could "|" many
512 * PNG_TRANSFORM flags into the png_transforms integer here.
514 png_write_png(png_ptr
, info_ptr
, PNG_TRANSFORM_IDENTITY
, png_voidp_NULL
);
516 /* clean up after the write, and free any memory allocated */
517 png_free(png_ptr
, row_pointers
);
518 png_destroy_info_struct(png_ptr
, &info_ptr
);
519 png_destroy_write_struct(&png_ptr
, &info_ptr
);