set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline) /* Process a quality-ratings parameter string, of the form * N[,N,...] * If there are more q-table slots than parameters, the last value is replicated. */ { int val = 75; /* default value */ int tblno; char ch; for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { if (*arg) { ch = ','; /* if not set by sscanf, will be ',' */ if (sscanf(arg, "%d%c", &val, &ch) < 1) return FALSE; if (ch != ',') /* syntax check */ return FALSE; /* Convert user 0-100 rating to percentage scaling */ cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); while (*arg && *arg++ != ',') /* advance to next segment of arg string */ ; } else { /* reached end of parameter, set remaining factors to last value */ cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val); } } jpeg_default_qtables(cinfo, force_baseline); return TRUE; }
bool JpegEncoder::write( const Mat& img, const std::vector<int>& params ) { m_last_error.clear(); struct fileWrapper { FILE* f; fileWrapper() : f(0) {} ~fileWrapper() { if(f) fclose(f); } }; volatile bool result = false; fileWrapper fw; int width = img.cols, height = img.rows; std::vector<uchar> out_buf(1 << 12); AutoBuffer<uchar> _buffer; uchar* buffer; struct jpeg_compress_struct cinfo; JpegErrorMgr jerr; JpegDestination dest; jpeg_create_compress(&cinfo); cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = error_exit; if( !m_buf ) { fw.f = fopen( m_filename.c_str(), "wb" ); if( !fw.f ) goto _exit_; jpeg_stdio_dest( &cinfo, fw.f ); } else { dest.dst = m_buf; dest.buf = &out_buf; jpeg_buffer_dest( &cinfo, &dest ); dest.pub.next_output_byte = &out_buf[0]; dest.pub.free_in_buffer = out_buf.size(); } if( setjmp( jerr.setjmp_buffer ) == 0 ) { cinfo.image_width = width; cinfo.image_height = height; int _channels = img.channels(); int channels = _channels > 1 ? 3 : 1; cinfo.input_components = channels; cinfo.in_color_space = channels > 1 ? JCS_RGB : JCS_GRAYSCALE; int quality = 95; int progressive = 0; int optimize = 0; int rst_interval = 0; int luma_quality = -1; int chroma_quality = -1; for( size_t i = 0; i < params.size(); i += 2 ) { if( params[i] == CV_IMWRITE_JPEG_QUALITY ) { quality = params[i+1]; quality = MIN(MAX(quality, 0), 100); } if( params[i] == CV_IMWRITE_JPEG_PROGRESSIVE ) { progressive = params[i+1]; } if( params[i] == CV_IMWRITE_JPEG_OPTIMIZE ) { optimize = params[i+1]; } if( params[i] == CV_IMWRITE_JPEG_LUMA_QUALITY ) { if (params[i+1] >= 0) { luma_quality = MIN(MAX(params[i+1], 0), 100); quality = luma_quality; if (chroma_quality < 0) { chroma_quality = luma_quality; } } } if( params[i] == CV_IMWRITE_JPEG_CHROMA_QUALITY ) { if (params[i+1] >= 0) { chroma_quality = MIN(MAX(params[i+1], 0), 100); } } if( params[i] == CV_IMWRITE_JPEG_RST_INTERVAL ) { rst_interval = params[i+1]; rst_interval = MIN(MAX(rst_interval, 0), 65535L); } } jpeg_set_defaults( &cinfo ); cinfo.restart_interval = rst_interval; jpeg_set_quality( &cinfo, quality, TRUE /* limit to baseline-JPEG values */ ); if( progressive ) jpeg_simple_progression( &cinfo ); if( optimize ) cinfo.optimize_coding = TRUE; #if JPEG_LIB_VERSION >= 70 if (luma_quality >= 0 && chroma_quality >= 0) { cinfo.q_scale_factor[0] = jpeg_quality_scaling(luma_quality); cinfo.q_scale_factor[1] = jpeg_quality_scaling(chroma_quality); if ( luma_quality != chroma_quality ) { /* disable subsampling - ref. Libjpeg.txt */ cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; } jpeg_default_qtables( &cinfo, TRUE ); } #endif // #if JPEG_LIB_VERSION >= 70 jpeg_start_compress( &cinfo, TRUE ); if( channels > 1 ) _buffer.allocate(width*channels); buffer = _buffer; for( int y = 0; y < height; y++ ) { uchar *data = img.data + img.step*y, *ptr = data; if( _channels == 3 ) { icvCvt_BGR2RGB_8u_C3R( data, 0, buffer, 0, cvSize(width,1) ); ptr = buffer; } else if( _channels == 4 ) { icvCvt_BGRA2BGR_8u_C4C3R( data, 0, buffer, 0, cvSize(width,1), 2 ); ptr = buffer; } jpeg_write_scanlines( &cinfo, &ptr, 1 ); } jpeg_finish_compress( &cinfo ); result = true; } _exit_: if(!result) { char jmsg_buf[JMSG_LENGTH_MAX]; jerr.pub.format_message((j_common_ptr)&cinfo, jmsg_buf); m_last_error = jmsg_buf; } jpeg_destroy_compress( &cinfo ); return result; }