/************************************************************************ JPEG image file format support. The I/O code in this file was originally based on the example.c skeleton code distributed with the JPEG library (release 6b). $Id: raster-jpeg.cxx 427 2004-09-27 04:45:31Z garland $ ************************************************************************/ #include #include namespace gfx { // Quality factors are expressed on a 0--100 scale int jpeg_output_quality = 100; } #ifdef HAVE_LIBJPEG #include extern "C" { #include } namespace gfx { bool write_jpeg_image(const char *filename, const ByteRaster& img) { FILE *outfile = fopen(filename, "wb"); if( !outfile ) return false; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); cinfo.image_width = img.width(); cinfo.image_height = img.height(); cinfo.input_components = img.channels(); if(img.channels()==1) cinfo.in_color_space = JCS_GRAYSCALE; else if(img.channels()==3) cinfo.in_color_space = JCS_RGB; else cinfo.in_color_space = JCS_UNKNOWN; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, jpeg_output_quality, TRUE); jpeg_start_compress(&cinfo, TRUE); int row_stride = img.width() * img.channels(); const unsigned char *scanline = img.head(); while( cinfo.next_scanline < cinfo.image_height ) { (void) jpeg_write_scanlines(&cinfo, (JSAMPLE **)&scanline, 1); scanline += row_stride; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); fclose(outfile); return true; } ByteRaster *read_jpeg_image(const char *filename) { FILE *infile = fopen(filename, "rb"); if( !infile ) return NULL; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, infile); (void) jpeg_read_header(&cinfo, TRUE); (void) jpeg_start_decompress(&cinfo); ByteRaster *img = new ByteRaster(cinfo.output_width, cinfo.output_height, cinfo.output_components); int row_stride = cinfo.output_width * cinfo.output_components; unsigned char *scanline = img->head(); while( cinfo.output_scanline < cinfo.output_height) { (void) jpeg_read_scanlines(&cinfo, (JSAMPLE **)&scanline, 1); scanline += row_stride; } (void) jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(infile); return img; } } // namespace gfx #else namespace gfx { bool write_jpeg_image(const char *, const ByteRaster&) { return false; } ByteRaster *read_jpeg_image(const char *) { return NULL; } } #endif