From 3163cfb8454f5a0a3957eac33042903ceb16c9a0 Mon Sep 17 00:00:00 2001 From: Vadim Pisarevsky Date: Sun, 21 Nov 2010 21:50:45 +0000 Subject: [PATCH] added 16-bit tiff support, enabled LZW codec in tiff (tickets #588, #590) --- 3rdparty/zlib/zutil.c | 2 +- modules/highgui/src/grfmt_pxm.cpp | 2 +- modules/highgui/src/grfmt_tiff.cpp | 121 +++++++++++++++++++++++++++++-------- modules/highgui/src/utils.cpp | 43 +++++++++++-- modules/highgui/src/utils.hpp | 14 ++++- 5 files changed, 148 insertions(+), 34 deletions(-) diff --git a/3rdparty/zlib/zutil.c b/3rdparty/zlib/zutil.c index 898ed34..a7443a5 100644 --- a/3rdparty/zlib/zutil.c +++ b/3rdparty/zlib/zutil.c @@ -115,7 +115,7 @@ uLong ZEXPORT zlibCompileFlags() #ifdef DEBUG # ifndef verbose -# define verbose 0 +# define verbose -1 # endif int ZLIB_INTERNAL z_verbose = verbose; diff --git a/modules/highgui/src/grfmt_pxm.cpp b/modules/highgui/src/grfmt_pxm.cpp index 015f6d5..33837b1 100644 --- a/modules/highgui/src/grfmt_pxm.cpp +++ b/modules/highgui/src/grfmt_pxm.cpp @@ -324,7 +324,7 @@ bool PxMDecoder::readData( Mat& img ) else if( img.depth() == CV_8U ) icvCvt_BGR2Gray_8u_C3C1R( src, 0, data, 0, cvSize(m_width,1), 2 ); else - icvCvt_BGR2Gray_16u_C3C1R( (ushort *)src, 0, (ushort *)data, 0, cvSize(m_width,1), 2 ); + icvCvt_BGRA2Gray_16u_CnC1R( (ushort *)src, 0, (ushort *)data, 0, cvSize(m_width,1), 3, 2 ); } } result = true; diff --git a/modules/highgui/src/grfmt_tiff.cpp b/modules/highgui/src/grfmt_tiff.cpp index 357f83b..6ede59f 100644 --- a/modules/highgui/src/grfmt_tiff.cpp +++ b/modules/highgui/src/grfmt_tiff.cpp @@ -122,15 +122,19 @@ bool TiffDecoder::readHeader() if( TIFFRGBAImageOK( tif, errmsg ) && TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &width ) && TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &height ) && - TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric ) && - (!TIFFGetField( tif, TIFFTAG_COMPRESSION, &compression ) || - (compression != COMPRESSION_LZW && - compression != COMPRESSION_OJPEG))) + TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric )) { + int bpp=8, ncn = photometric > 1 ? 3 : 1; + TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp ); + TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn ); + m_width = width; m_height = height; - m_type = photometric > 1 ? CV_8UC3 : CV_8UC1; - + if( bpp > 8 && + ((photometric != 2 && photometric != 1) || + (ncn != 1 && ncn != 3 && ncn != 4))) + bpp = 8; + m_type = CV_MAKETYPE(bpp > 8 ? CV_16U : CV_8U, photometric > 1 ? 3 : 1); result = true; } } @@ -148,6 +152,9 @@ bool TiffDecoder::readData( Mat& img ) bool color = img.channels() > 1; uchar* data = img.data; int step = (int)img.step; + + if( img.depth() != CV_8U && img.depth() != CV_16U ) + return false; if( m_tif && m_width && m_height ) { @@ -155,6 +162,12 @@ bool TiffDecoder::readData( Mat& img ) int tile_width0 = m_width, tile_height0 = 0; int x, y, i; int is_tiled = TIFFIsTiled(tif); + int photometric; + TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric ); + int bpp = 8, ncn = photometric > 1 ? 3 : 1; + TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp ); + TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn ); + int dst_bpp = img.depth() == CV_8U ? 8 : 16; if( (!is_tiled && TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 )) || @@ -168,8 +181,10 @@ bool TiffDecoder::readData( Mat& img ) if( tile_height0 <= 0 ) tile_height0 = m_height; - AutoBuffer _buffer(tile_height0*tile_width0*4); + AutoBuffer _buffer(tile_height0*tile_width0*8); uchar* buffer = _buffer; + ushort* buffer16 = (ushort*)buffer; + int tileidx = 0; for( y = 0; y < m_height; y += tile_height0, data += step*tile_height0 ) { @@ -178,33 +193,89 @@ bool TiffDecoder::readData( Mat& img ) if( y + tile_height > m_height ) tile_height = m_height - y; - for( x = 0; x < m_width; x += tile_width0 ) + for( x = 0; x < m_width; x += tile_width0, tileidx++ ) { int tile_width = tile_width0, ok; if( x + tile_width > m_width ) tile_width = m_width - x; - if( !is_tiled ) - ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer ); - else - ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer ); - - if( !ok ) + if( dst_bpp == 8 ) { - close(); - return false; + if( !is_tiled ) + ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer ); + else + ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer ); + + if( !ok ) + { + close(); + return false; + } + + for( i = 0; i < tile_height; i++ ) + if( color ) + icvCvt_BGRA2BGR_8u_C4C3R( buffer + i*tile_width*4, 0, + data + x*3 + step*(tile_height - i - 1), 0, + cvSize(tile_width,1), 2 ); + else + icvCvt_BGRA2Gray_8u_C4C1R( buffer + i*tile_width*4, 0, + data + x + step*(tile_height - i - 1), 0, + cvSize(tile_width,1), 2 ); } - - for( i = 0; i < tile_height; i++ ) - if( color ) - icvCvt_BGRA2BGR_8u_C4C3R( buffer + i*tile_width*4, 0, - data + x*3 + step*(tile_height - i - 1), 0, - cvSize(tile_width,1), 2 ); + else + { + if( !is_tiled ) + ok = TIFFReadEncodedStrip( tif, tileidx, (uint32*)buffer, -1 ); else - icvCvt_BGRA2Gray_8u_C4C1R( buffer + i*tile_width*4, 0, - data + x + step*(tile_height - i - 1), 0, - cvSize(tile_width,1), 2 ); + ok = TIFFReadEncodedTile( tif, tileidx, (uint32*)buffer, -1 ); + + if( !ok ) + { + close(); + return false; + } + + for( i = 0; i < tile_height; i++ ) + { + if( color ) + { + if( ncn == 1 ) + { + icvCvt_Gray2BGR_16u_C1C3R(buffer16 + i*tile_width*ncn, 0, + (ushort*)(data + step*i) + x*3, 0, + cvSize(tile_width,1) ); + } + else if( ncn == 3 ) + { + icvCvt_RGB2BGR_16u_C3R(buffer16 + i*tile_width*ncn, 0, + (ushort*)(data + step*i) + x*3, 0, + cvSize(tile_width,1) ); + } + else + { + icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width*ncn, 0, + (ushort*)(data + step*i) + x*3, 0, + cvSize(tile_width,1), 2 ); + } + } + else + { + if( ncn == 1 ) + { + memcpy((ushort*)(data + step*i)+x, + buffer16 + i*tile_width*ncn, + tile_width*sizeof(buffer16[0])); + } + else + { + icvCvt_BGRA2Gray_16u_CnC1R(buffer16 + i*tile_width*ncn, 0, + (ushort*)(data + step*i) + x, 0, + cvSize(tile_width,1), ncn, 2 ); + } + } + } + } } } diff --git a/modules/highgui/src/utils.cpp b/modules/highgui/src/utils.cpp index 8f479ed..9c20065 100644 --- a/modules/highgui/src/utils.cpp +++ b/modules/highgui/src/utils.cpp @@ -66,21 +66,21 @@ void icvCvt_BGR2Gray_8u_C3C1R( const uchar* rgb, int rgb_step, } -void icvCvt_BGR2Gray_16u_C3C1R( const ushort* rgb, int rgb_step, +void icvCvt_BGRA2Gray_16u_CnC1R( const ushort* rgb, int rgb_step, ushort* gray, int gray_step, - CvSize size, int _swap_rb ) + CvSize size, int ncn, int _swap_rb ) { int i; int swap_rb = _swap_rb ? 2 : 0; for( ; size.height--; gray += gray_step ) { - for( i = 0; i < size.width; i++, rgb += 3 ) + for( i = 0; i < size.width; i++, rgb += ncn ) { int t = descale( rgb[swap_rb]*cB + rgb[1]*cG + rgb[swap_rb^2]*cR, SCALE ); gray[i] = (ushort)t; } - rgb += rgb_step - size.width*3; + rgb += rgb_step - size.width*ncn; } } @@ -119,6 +119,21 @@ void icvCvt_Gray2BGR_8u_C1C3R( const uchar* gray, int gray_step, } +void icvCvt_Gray2BGR_16u_C1C3R( const ushort* gray, int gray_step, + ushort* bgr, int bgr_step, CvSize size ) +{ + int i; + for( ; size.height--; gray += gray_step/sizeof(gray[0]) ) + { + for( i = 0; i < size.width; i++, bgr += 3 ) + { + bgr[0] = bgr[1] = bgr[2] = gray[i]; + } + bgr += bgr_step/sizeof(bgr[0]) - size.width*3; + } +} + + void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step, uchar* bgr, int bgr_step, CvSize size, int _swap_rb ) @@ -139,6 +154,26 @@ void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step, } +void icvCvt_BGRA2BGR_16u_C4C3R( const ushort* bgra, int bgra_step, + ushort* bgr, int bgr_step, + CvSize size, int _swap_rb ) +{ + int i; + int swap_rb = _swap_rb ? 2 : 0; + for( ; size.height--; ) + { + for( i = 0; i < size.width; i++, bgr += 3, bgra += 4 ) + { + uchar t0 = bgra[swap_rb], t1 = bgra[1]; + bgr[0] = t0; bgr[1] = t1; + t0 = bgra[swap_rb^2]; bgr[2] = t0; + } + bgr += bgr_step/sizeof(bgr[0]) - size.width*3; + bgra += bgra_step/sizeof(bgra[0]) - size.width*4; + } +} + + void icvCvt_BGRA2RGBA_8u_C4R( const uchar* bgra, int bgra_step, uchar* rgba, int rgba_step, CvSize size ) { diff --git a/modules/highgui/src/utils.hpp b/modules/highgui/src/utils.hpp index 1e81c17..5eba19a 100644 --- a/modules/highgui/src/utils.hpp +++ b/modules/highgui/src/utils.hpp @@ -55,20 +55,28 @@ struct PaletteEntry #define descale(x,n) (((x) + (1 << ((n)-1))) >> (n)) #define saturate(x) (uchar)(((x) & ~255) == 0 ? (x) : ~((x)>>31)) -void icvCvt_BGR2Gray_16u_C3C1R( const ushort* bgr, int bgr_step, - ushort* gray, int gray_step, - CvSize size, int swap_rb=0 ); void icvCvt_BGR2Gray_8u_C3C1R( const uchar* bgr, int bgr_step, uchar* gray, int gray_step, CvSize size, int swap_rb=0 ); void icvCvt_BGRA2Gray_8u_C4C1R( const uchar* bgra, int bgra_step, uchar* gray, int gray_step, CvSize size, int swap_rb=0 ); +void icvCvt_BGRA2Gray_16u_CnC1R( const ushort* bgra, int bgra_step, + ushort* gray, int gray_step, + CvSize size, int ncn, int swap_rb=0 ); + void icvCvt_Gray2BGR_8u_C1C3R( const uchar* gray, int gray_step, uchar* bgr, int bgr_step, CvSize size ); +void icvCvt_Gray2BGR_16u_C1C3R( const ushort* gray, int gray_step, + ushort* bgr, int bgr_step, CvSize size ); + void icvCvt_BGRA2BGR_8u_C4C3R( const uchar* bgra, int bgra_step, uchar* bgr, int bgr_step, CvSize size, int swap_rb=0 ); +void icvCvt_BGRA2BGR_16u_C4C3R( const ushort* bgra, int bgra_step, + ushort* bgr, int bgr_step, + CvSize size, int _swap_rb ); + void icvCvt_BGR2RGB_8u_C3R( const uchar* bgr, int bgr_step, uchar* rgb, int rgb_step, CvSize size ); #define icvCvt_RGB2BGR_8u_C3R icvCvt_BGR2RGB_8u_C3R -- 2.7.4