jpeg.cpp

00001 
00002 /***************************************************************************
00003  *  jpeg.cp - JPEG writer
00004  *
00005  *  Generated: Wed Jun 28 11:36:54 2006 (my brother's 18th birthday)
00006  *  Copyright  2005-2009  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <core/exception.h>
00025 #include <fvutils/writers/jpeg.h>
00026 #include <fvutils/color/yuvrgb.h>
00027 
00028 #include <cstdio>
00029 #include <cerrno>
00030 #include <cstdlib>
00031 #include <cstring>
00032 #include <string.h>
00033 extern "C" {
00034 #include <jpeglib.h>
00035 }
00036 
00037 using namespace fawkes;
00038 
00039 namespace firevision {
00040 #if 0 /* just to make Emacs auto-indent happy */
00041 }
00042 #endif
00043 
00044 /** @class JpegWriter <fvutils/writers/jpeg.h>
00045  * JPEG file writer.
00046  * @author Tim Niemueller
00047  */
00048 
00049 /** Constructor.
00050  * @param quality quality, value between 0 and 100
00051  */
00052 JpegWriter::JpegWriter(int quality)
00053   : Writer("jpg")
00054 {
00055   buffer = NULL;
00056   
00057   this->quality  = (quality > 0) ? quality : -quality;
00058 }
00059 
00060 /** Constructor.
00061  * @param filename file name to write to
00062  * @param quality quality, value between 0 and 100
00063  */
00064 JpegWriter::JpegWriter(const char *filename, int quality)
00065   : Writer("jpg")
00066 {
00067   set_filename(filename);
00068 
00069   buffer = NULL;
00070 
00071   this->quality  = (quality > 0) ? quality : -quality;
00072 }
00073 
00074 
00075 /** Destructor. */
00076 JpegWriter::~JpegWriter()
00077 {
00078 }
00079 
00080 
00081 void
00082 JpegWriter::set_buffer(colorspace_t cspace, unsigned char *buffer)
00083 {
00084   if (cspace == YUV422_PLANAR) {
00085     this->buffer = buffer;
00086   } else {
00087     throw Exception("Incompatible colorspace, can only hand YUV422_PLANAR images");
00088   }
00089 }
00090 
00091 
00092 void
00093 JpegWriter::write()
00094 {
00095   if ( buffer == NULL ) {
00096     throw Exception("JpegWriter::read() error: buffer == NULL");
00097   }
00098 
00099   if ((outfile = fopen(filename, "wb")) == NULL) {
00100     Exception e("Cannot open JPEG file for writing", errno);
00101     e.append("File %s could not be opened", filename);
00102     throw e;
00103   }
00104 
00105   int row_stride;
00106   struct jpeg_compress_struct cinfo;
00107   struct jpeg_error_mgr         jerr;
00108 
00109   cinfo.err = jpeg_std_error( &jerr );
00110   jpeg_create_compress( &cinfo );
00111   jpeg_stdio_dest( &cinfo, outfile );
00112 
00113   cinfo.image_width  = width;
00114   cinfo.image_height = height;
00115   cinfo.input_components = 3;
00116   cinfo.in_color_space = JCS_RGB;
00117 
00118   jpeg_set_defaults(&cinfo);
00119   jpeg_set_quality(&cinfo, quality, true /* limit to baseline-JPEG values */);
00120 
00121   jpeg_start_compress( &cinfo, true );
00122   row_stride = cinfo.image_width * cinfo.input_components;
00123 
00124   row_buffer = (unsigned char *)malloc( row_stride );
00125 
00126   while ( cinfo.next_scanline < cinfo.image_height ) {
00127     convert_line_yuv422planar_to_rgb( buffer, row_buffer,
00128                                       cinfo.image_width, cinfo.image_height,
00129                                       cinfo.next_scanline, 0 );
00130     jpeg_write_scanlines( &cinfo, &row_buffer, 1 );
00131   }
00132 
00133   free(row_buffer);
00134 
00135   jpeg_finish_compress( &cinfo );
00136 
00137   jpeg_destroy_compress( &cinfo );
00138   fclose( outfile );
00139 
00140 }
00141 
00142 } // end namespace firevision