예제 #1
0
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;
}
예제 #2
0
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;
}