bool TiffDecoder::readData( Mat& img ) { bool result = false; bool color = img.channels() > 1; uchar* data = img.data; int step = (int)img.step; if( img.depth() != CV_8U && img.depth() != CV_16U && img.depth() != CV_32F && img.depth() != CV_64F ) return false; if( m_tif && m_width && m_height ) { TIFF* tif = (TIFF*)m_tif; 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 ); const int bitsPerByte = 8; int dst_bpp = (int)(img.elemSize1() * bitsPerByte); if(dst_bpp == 8) { char errmsg[1024]; if(!TIFFRGBAImageOK( tif, errmsg )) { close(); return false; } } if( (!is_tiled) || (is_tiled && TIFFGetField( tif, TIFFTAG_TILEWIDTH, &tile_width0 ) && TIFFGetField( tif, TIFFTAG_TILELENGTH, &tile_height0 ))) { if(!is_tiled) TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 ); if( tile_width0 <= 0 ) tile_width0 = m_width; if( tile_height0 <= 0 ) tile_height0 = m_height; AutoBuffer<uchar> _buffer(tile_height0*tile_width0*8); uchar* buffer = _buffer; ushort* buffer16 = (ushort*)buffer; float* buffer32 = (float*)buffer; double* buffer64 = (double*)buffer; int tileidx = 0; for( y = 0; y < m_height; y += tile_height0, data += step*tile_height0 ) { int tile_height = tile_height0; if( y + tile_height > m_height ) tile_height = m_height - y; 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; switch(dst_bpp) { case 8: { 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 ); break; } case 16: { if( !is_tiled ) ok = (int)TIFFReadEncodedStrip( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0; else ok = (int)TIFFReadEncodedTile( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0; 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 ); } } } break; } case 32: case 64: { if( !is_tiled ) ok = (int)TIFFReadEncodedStrip( tif, tileidx, buffer, (tsize_t)-1 ) >= 0; else ok = (int)TIFFReadEncodedTile( tif, tileidx, buffer, (tsize_t)-1 ) >= 0; if( !ok || ncn != 1 ) { close(); return false; } for( i = 0; i < tile_height; i++ ) { if(dst_bpp == 32) { memcpy((float*)(data + step*i)+x, buffer32 + i*tile_width*ncn, tile_width*sizeof(buffer32[0])); } else { memcpy((double*)(data + step*i)+x, buffer64 + i*tile_width*ncn, tile_width*sizeof(buffer64[0])); } } break; } default: { close(); return false; } } } } result = true; } } close(); return result; }
bool PxMDecoder::readData( Mat& img ) { int color = img.channels() > 1; uchar* data = img.data; int step = (int)img.step; PaletteEntry palette[256]; bool result = false; int bit_depth = CV_ELEM_SIZE1(m_type)*8; int src_pitch = (m_width*m_bpp*bit_depth/8 + 7)/8; int nch = CV_MAT_CN(m_type); int width3 = m_width*nch; int i, x, y; if( m_offset < 0 || !m_strm.isOpened()) return false; AutoBuffer<uchar> _src(src_pitch + 32); uchar* src = _src; AutoBuffer<uchar> _gray_palette; uchar* gray_palette = _gray_palette; // create LUT for converting colors if( bit_depth == 8 ) { _gray_palette.allocate(m_maxval + 1); gray_palette = _gray_palette; for( i = 0; i <= m_maxval; i++ ) gray_palette[i] = (uchar)((i*255/m_maxval)^(m_bpp == 1 ? 255 : 0)); FillGrayPalette( palette, m_bpp==1 ? 1 : 8 , m_bpp == 1 ); } try { m_strm.setPos( m_offset ); switch( m_bpp ) { ////////////////////////// 1 BPP ///////////////////////// case 1: if( !m_binary ) { for( y = 0; y < m_height; y++, data += step ) { for( x = 0; x < m_width; x++ ) src[x] = ReadNumber( m_strm, 1 ) != 0; if( color ) FillColorRow8( data, src, m_width, palette ); else FillGrayRow8( data, src, m_width, gray_palette ); } } else { for( y = 0; y < m_height; y++, data += step ) { m_strm.getBytes( src, src_pitch ); if( color ) FillColorRow1( data, src, m_width, palette ); else FillGrayRow1( data, src, m_width, gray_palette ); } } result = true; break; ////////////////////////// 8 BPP ///////////////////////// case 8: case 24: for( y = 0; y < m_height; y++, data += step ) { if( !m_binary ) { for( x = 0; x < width3; x++ ) { int code = ReadNumber( m_strm, INT_MAX ); if( (unsigned)code > (unsigned)m_maxval ) code = m_maxval; if( bit_depth == 8 ) src[x] = gray_palette[code]; else ((ushort *)src)[x] = (ushort)code; } } else { m_strm.getBytes( src, src_pitch ); if( bit_depth == 16 && !isBigEndian() ) { for( x = 0; x < width3; x++ ) { uchar v = src[x * 2]; src[x * 2] = src[x * 2 + 1]; src[x * 2 + 1] = v; } } } if( img.depth() == CV_8U && bit_depth == 16 ) { for( x = 0; x < width3; x++ ) { int v = ((ushort *)src)[x]; src[x] = (uchar)(v >> 8); } } if( m_bpp == 8 ) // image has one channel { if( color ) { if( img.depth() == CV_8U ) { uchar *d = data, *s = src, *end = src + m_width; for( ; s < end; d += 3, s++) d[0] = d[1] = d[2] = *s; } else { ushort *d = (ushort *)data, *s = (ushort *)src, *end = ((ushort *)src) + m_width; for( ; s < end; s++, d += 3) d[0] = d[1] = d[2] = *s; } } else memcpy( data, src, m_width*(bit_depth/8) ); } else { if( color ) { if( img.depth() == CV_8U ) icvCvt_RGB2BGR_8u_C3R( src, 0, data, 0, cvSize(m_width,1) ); else icvCvt_RGB2BGR_16u_C3R( (ushort *)src, 0, (ushort *)data, 0, cvSize(m_width,1) ); } else if( img.depth() == CV_8U ) icvCvt_BGR2Gray_8u_C3C1R( src, 0, data, 0, cvSize(m_width,1), 2 ); else icvCvt_BGRA2Gray_16u_CnC1R( (ushort *)src, 0, (ushort *)data, 0, cvSize(m_width,1), 3, 2 ); } } result = true; break; default: assert(0); } } catch(...) { } return result; }