bool JpegEncoder::write( const Mat& img, const vector<int>& params )
{
    m_last_error.clear();

    struct fileWrapper
    {
        FILE* f;

        fileWrapper() : f(0) {}
        ~fileWrapper() { if(f) fclose(f); }
    };
    bool result = false;
    fileWrapper fw;
    int width = img.cols, height = img.rows;

    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;

        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);
            }
        }

        jpeg_set_defaults( &cinfo );
        jpeg_set_quality( &cinfo, quality,
                          TRUE /* limit to baseline-JPEG values */ );
        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;
}
예제 #2
0
파일: grfmt_tiff.cpp 프로젝트: Skolo/opencv
bool  TiffEncoder::write( const Mat& img, const vector<int>& /*params*/)
#endif
{
    int channels = img.channels();
    int width = img.cols, height = img.rows;
    int depth = img.depth();

    if (depth != CV_8U && depth != CV_16U)
        return false;

    int bytesPerChannel = depth == CV_8U ? 1 : 2;
    int fileStep = width * channels * bytesPerChannel;

    WLByteStream strm;

    if( m_buf )
    {
        if( !strm.open(*m_buf) )
            return false;
    }
    else
    {
#ifdef HAVE_TIFF
      return writeLibTiff(img, params);
#else
      if( !strm.open(m_filename) )
          return false;
#endif
    }

    int rowsPerStrip = (1 << 13)/fileStep;

    if( rowsPerStrip < 1 )
        rowsPerStrip = 1;

    if( rowsPerStrip > height )
        rowsPerStrip = height;

    int i, stripCount = (height + rowsPerStrip - 1) / rowsPerStrip;

    if( m_buf )
        m_buf->reserve( alignSize(stripCount*8 + fileStep*height + 256, 256) );

/*#if defined _DEBUG || !defined WIN32
    int uncompressedRowSize = rowsPerStrip * fileStep;
#endif*/
    int directoryOffset = 0;

    AutoBuffer<int> stripOffsets(stripCount);
    AutoBuffer<short> stripCounts(stripCount);
    AutoBuffer<uchar> _buffer(fileStep+32);
    uchar* buffer = _buffer;
    int  stripOffsetsOffset = 0;
    int  stripCountsOffset = 0;
    int  bitsPerSample = 8 * bytesPerChannel;
    int  y = 0;

    strm.putBytes( fmtSignTiffII, 4 );
    strm.putDWord( directoryOffset );

    // write an image data first (the most reasonable way
    // for compressed images)
    for( i = 0; i < stripCount; i++ )
    {
        int limit = y + rowsPerStrip;

        if( limit > height )
            limit = height;

        stripOffsets[i] = strm.getPos();

        for( ; y < limit; y++ )
        {
            if( channels == 3 )
            {
                if (depth == CV_8U)
                    icvCvt_BGR2RGB_8u_C3R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
                else
                    icvCvt_BGR2RGB_16u_C3R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
            }
            else
            {
              if( channels == 4 )
              {
                if (depth == CV_8U)
                    icvCvt_BGRA2RGBA_8u_C4R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
                else
                    icvCvt_BGRA2RGBA_16u_C4R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
              }
            }

            strm.putBytes( channels > 1 ? buffer : img.data + img.step*y, fileStep );
        }

        stripCounts[i] = (short)(strm.getPos() - stripOffsets[i]);
        /*assert( stripCounts[i] == uncompressedRowSize ||
                stripCounts[i] < uncompressedRowSize &&
                i == stripCount - 1);*/
    }

    if( stripCount > 2 )
    {
        stripOffsetsOffset = strm.getPos();
        for( i = 0; i < stripCount; i++ )
            strm.putDWord( stripOffsets[i] );

        stripCountsOffset = strm.getPos();
        for( i = 0; i < stripCount; i++ )
            strm.putWord( stripCounts[i] );
    }
    else if(stripCount == 2)
    {
        stripOffsetsOffset = strm.getPos();
        for (i = 0; i < stripCount; i++)
        {
            strm.putDWord (stripOffsets [i]);
        }
        stripCountsOffset = stripCounts [0] + (stripCounts [1] << 16);
    }
    else
    {
        stripOffsetsOffset = stripOffsets[0];
        stripCountsOffset = stripCounts[0];
    }

    if( channels > 1 )
    {
        int bitsPerSamplePos = strm.getPos();
        strm.putWord(bitsPerSample);
        strm.putWord(bitsPerSample);
        strm.putWord(bitsPerSample);
        if( channels == 4 )
            strm.putWord(bitsPerSample);
        bitsPerSample = bitsPerSamplePos;
    }

    directoryOffset = strm.getPos();

    // write header
    strm.putWord( 9 );

    /* warning: specification 5.0 of Tiff want to have tags in
       ascending order. This is a non-fatal error, but this cause
       warning with some tools. So, keep this in ascending order */

    writeTag( strm, TIFF_TAG_WIDTH, TIFF_TYPE_LONG, 1, width );
    writeTag( strm, TIFF_TAG_HEIGHT, TIFF_TYPE_LONG, 1, height );
    writeTag( strm, TIFF_TAG_BITS_PER_SAMPLE,
              TIFF_TYPE_SHORT, channels, bitsPerSample );
    writeTag( strm, TIFF_TAG_COMPRESSION, TIFF_TYPE_LONG, 1, TIFF_UNCOMP );
    writeTag( strm, TIFF_TAG_PHOTOMETRIC, TIFF_TYPE_SHORT, 1, channels > 1 ? 2 : 1 );

    writeTag( strm, TIFF_TAG_STRIP_OFFSETS, TIFF_TYPE_LONG,
              stripCount, stripOffsetsOffset );

    writeTag( strm, TIFF_TAG_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, channels );
    writeTag( strm, TIFF_TAG_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, rowsPerStrip );

    writeTag( strm, TIFF_TAG_STRIP_COUNTS,
              stripCount > 1 ? TIFF_TYPE_SHORT : TIFF_TYPE_LONG,
              stripCount, stripCountsOffset );

    strm.putDWord(0);
    strm.close();

    if( m_buf )
    {
        (*m_buf)[4] = (uchar)directoryOffset;
        (*m_buf)[5] = (uchar)(directoryOffset >> 8);
        (*m_buf)[6] = (uchar)(directoryOffset >> 16);
        (*m_buf)[7] = (uchar)(directoryOffset >> 24);
    }
    else
    {
예제 #3
0
파일: grfmt_pxm.cpp 프로젝트: 4auka/opencv
bool  PxMEncoder::write( const Mat& img, const std::vector<int>& params )
{
    bool isBinary = true;

    int  width = img.cols, height = img.rows;
    int  _channels = img.channels(), depth = (int)img.elemSize1()*8;
    int  channels = _channels > 1 ? 3 : 1;
    int  fileStep = width*(int)img.elemSize();
    int  x, y;

    for( size_t i = 0; i < params.size(); i += 2 )
        if( params[i] == CV_IMWRITE_PXM_BINARY )
            isBinary = params[i+1] != 0;

    WLByteStream strm;

    if( m_buf )
    {
        if( !strm.open(*m_buf) )
            return false;
        int t = CV_MAKETYPE(img.depth(), channels);
        m_buf->reserve( alignSize(256 + (isBinary ? fileStep*height :
            ((t == CV_8UC1 ? 4 : t == CV_8UC3 ? 4*3+2 :
            t == CV_16UC1 ? 6 : 6*3+2)*width+1)*height), 256));
    }
    else if( !strm.open(m_filename) )
        return false;

    int  lineLength;
    int  bufferSize = 128; // buffer that should fit a header

    if( isBinary )
        lineLength = width * (int)img.elemSize();
    else
        lineLength = (6 * channels + (channels > 1 ? 2 : 0)) * width + 32;

    if( bufferSize < lineLength )
        bufferSize = lineLength;

    AutoBuffer<char> _buffer(bufferSize);
    char* buffer = _buffer;

    // write header;
    sprintf( buffer, "P%c\n%d %d\n%d\n",
             '2' + (channels > 1 ? 1 : 0) + (isBinary ? 3 : 0),
             width, height, (1 << depth) - 1 );

    strm.putBytes( buffer, (int)strlen(buffer) );

    for( y = 0; y < height; y++ )
    {
        uchar* data = img.data + img.step*y;
        if( isBinary )
        {
            if( _channels == 3 )
            {
                if( depth == 8 )
                    icvCvt_BGR2RGB_8u_C3R( (uchar*)data, 0,
                        (uchar*)buffer, 0, cvSize(width,1) );
                else
                    icvCvt_BGR2RGB_16u_C3R( (ushort*)data, 0,
                        (ushort*)buffer, 0, cvSize(width,1) );
            }

            // swap endianness if necessary
            if( depth == 16 && !isBigEndian() )
            {
                if( _channels == 1 )
                    memcpy( buffer, data, fileStep );
                for( x = 0; x < width*channels*2; x += 2 )
                {
                    uchar v = buffer[x];
                    buffer[x] = buffer[x + 1];
                    buffer[x + 1] = v;
                }
            }
            strm.putBytes( (channels > 1 || depth > 8) ? buffer : (char*)data, fileStep );
        }
        else
        {
            char* ptr = buffer;

            if( channels > 1 )
            {
                if( depth == 8 )
                {
                    for( x = 0; x < width*channels; x += channels )
                    {
                        sprintf( ptr, "% 4d", data[x + 2] );
                        ptr += 4;
                        sprintf( ptr, "% 4d", data[x + 1] );
                        ptr += 4;
                        sprintf( ptr, "% 4d", data[x] );
                        ptr += 4;
                        *ptr++ = ' ';
                        *ptr++ = ' ';
                    }
                }
                else
                {
                    for( x = 0; x < width*channels; x += channels )
                    {
                        sprintf( ptr, "% 6d", ((ushort *)data)[x + 2] );
                        ptr += 6;
                        sprintf( ptr, "% 6d", ((ushort *)data)[x + 1] );
                        ptr += 6;
                        sprintf( ptr, "% 6d", ((ushort *)data)[x] );
                        ptr += 6;
                        *ptr++ = ' ';
                        *ptr++ = ' ';
                    }
                }
            }
            else
            {
                if( depth == 8 )
                {
                    for( x = 0; x < width; x++ )
                    {
                        sprintf( ptr, "% 4d", data[x] );
                        ptr += 4;
                    }
                }
                else
                {
                    for( x = 0; x < width; x++ )
                    {
                        sprintf( ptr, "% 6d", ((ushort *)data)[x] );
                        ptr += 6;
                    }
                }
            }

            *ptr++ = '\n';

            strm.putBytes( buffer, (int)(ptr - buffer) );
        }
    }

    strm.close();
    return true;
}
예제 #4
0
파일: grfmt_tiff.cpp 프로젝트: Skolo/opencv
bool  TiffEncoder::writeLibTiff( const Mat& img, const vector<int>& /*params*/)
{
    int channels = img.channels();
    int width = img.cols, height = img.rows;
    int depth = img.depth();

    int bitsPerChannel = -1;
    switch (depth)
    {
        case CV_8U:
        {
            bitsPerChannel = 8;
            break;
        }
        case CV_16U:
        {
            bitsPerChannel = 16;
            break;
        }
        default:
        {
            return false;
        }
    }

    const int bitsPerByte = 8;
    size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
    int rowsPerStrip = (int)((1 << 13)/fileStep);

    if( rowsPerStrip < 1 )
        rowsPerStrip = 1;

    if( rowsPerStrip > height )
        rowsPerStrip = height;


    // do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
    // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
    TIFF* pTiffHandle = TIFFOpen(m_filename.c_str(), "w");
    if (!pTiffHandle)
    {
        return false;
    }

    // defaults for now, maybe base them on params in the future
    int   compression  = COMPRESSION_LZW;
    int   predictor    = PREDICTOR_HORIZONTAL;

    int   colorspace = channels > 1 ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;

    if ( !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width)
      || !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height)
      || !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel)
      || !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression)
      || !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace)
      || !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels)
      || !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
      || !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)
      || !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor)
       )
    {
        TIFFClose(pTiffHandle);
        return false;
    }

    // row buffer, because TIFFWriteScanline modifies the original data!
    size_t scanlineSize = TIFFScanlineSize(pTiffHandle);
    AutoBuffer<uchar> _buffer(scanlineSize+32);
    uchar* buffer = _buffer;
    if (!buffer)
    {
        TIFFClose(pTiffHandle);
        return false;
    }

    for (int y = 0; y < height; ++y)
    {
        switch(channels)
        {
            case 1:
            {
                memcpy(buffer, img.data + img.step * y, scanlineSize);
                break;
            }

            case 3:
            {
                if (depth == CV_8U)
                    icvCvt_BGR2RGB_8u_C3R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
                else
                    icvCvt_BGR2RGB_16u_C3R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
                break;
            }

            case 4:
            {
                if (depth == CV_8U)
                    icvCvt_BGRA2RGBA_8u_C4R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
                else
                    icvCvt_BGRA2RGBA_16u_C4R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
                break;
            }

            default:
            {
                TIFFClose(pTiffHandle);
                return false;
            }
        }

        int writeResult = TIFFWriteScanline(pTiffHandle, buffer, y, 0);
        if (writeResult != 1)
        {
            TIFFClose(pTiffHandle);
            return false;
        }
    }

    TIFFClose(pTiffHandle);
    return true;
}
예제 #5
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;
}