int ReadTile(TIFF* tiff, UINT32 col, UINT32 row, UINT32* buffer) { uint16 photometric; TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric); // To avoid dealing with YCbCr subsampling, let libtiff handle it if (photometric == PHOTOMETRIC_YCBCR) { UINT32 tile_width, tile_height, swap_line_size, i_row; UINT32* swap_line; TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_width); TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_height); swap_line_size = tile_width * sizeof(UINT32); if (tile_width != swap_line_size / sizeof(UINT32)) { return -1; } /* Read the tile into an RGBA array */ if (!TIFFReadRGBATile(tiff, col, row, buffer)) { return -1; } swap_line = (UINT32*)malloc(swap_line_size); /* * For some reason the TIFFReadRGBATile() function chooses the * lower left corner as the origin. Vertically mirror scanlines. */ for(i_row = 0; i_row < tile_height / 2; i_row++) { UINT32 *top_line, *bottom_line; top_line = buffer + tile_width * i_row; bottom_line = buffer + tile_width * (tile_height - i_row - 1); memcpy(swap_line, top_line, 4*tile_width); memcpy(top_line, bottom_line, 4*tile_width); memcpy(bottom_line, swap_line, 4*tile_width); } free(swap_line); return 0; } if (TIFFReadTile(tiff, (tdata_t)buffer, col, row, 0, 0) == -1) { TRACE(("Decode Error, Tile at %dx%d\n", col, row)); return -1; } TRACE(("Successfully read tile at %dx%d; \n\n", col, row)); return 0; }
void tiff_reader<T>::read_tiled(unsigned x0,unsigned y0,image_data_32& image) { TIFF* tif = open(stream_); if (tif) { uint32* buf = (uint32*)_TIFFmalloc(tile_width_*tile_height_*sizeof(uint32)); int width=image.width(); int height=image.height(); int start_y=(y0/tile_height_)*tile_height_; int end_y=((y0+height)/tile_height_+1)*tile_height_; int start_x=(x0/tile_width_)*tile_width_; int end_x=((x0+width)/tile_width_+1)*tile_width_; int row,tx0,tx1,ty0,ty1; for (int y=start_y;y<end_y;y+=tile_height_) { ty0 = std::max(y0,(unsigned)y) - y; ty1 = std::min(height+y0,(unsigned)(y+tile_height_)) - y; int n0=tile_height_-ty1; int n1=tile_height_-ty0-1; for (int x=start_x;x<end_x;x+=tile_width_) { if (!TIFFReadRGBATile(tif,x,y,buf)) break; tx0=std::max(x0,(unsigned)x); tx1=std::min(width+x0,(unsigned)(x+tile_width_)); row=y+ty0-y0; for (int n=n1;n>=n0;--n) { image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*tile_width_+tx0-x]); ++row; } } } _TIFFfree(buf); } }
void imb_loadtiletiff(ImBuf *ibuf, unsigned char *mem, size_t size, int tx, int ty, unsigned int *rect) { TIFF *image = NULL; uint32 width, height; ImbTIFFMemFile memFile; image = imb_tiff_client_open(&memFile, mem, size); if(image == NULL) { printf("imb_loadtiff: could not open TIFF IO layer for loading mipmap level.\n"); return; } if(TIFFSetDirectory(image, ibuf->miplevel)) { /* allocate the image buffer */ TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height); if(width == ibuf->x && height == ibuf->y) { if(rect) { /* tiff pixels are bottom to top, tiles are top to bottom */ if(TIFFReadRGBATile(image, tx*ibuf->tilex, (ibuf->ytiles - 1 - ty)*ibuf->tiley, rect) == 1) { if(ibuf->tiley > ibuf->y) memmove(rect, rect+ibuf->tilex*(ibuf->tiley - ibuf->y), sizeof(int)*ibuf->tilex*ibuf->y); if(ibuf->flags & IB_premul) IMB_premultiply_rect(rect, 32, ibuf->tilex, ibuf->tiley); } else printf("imb_loadtiff: failed to read tiff tile at mipmap level %d\n", ibuf->miplevel); } } else printf("imb_loadtiff: mipmap level %d has unexpected size %dx%d instead of %dx%d\n", ibuf->miplevel, width, height, ibuf->x, ibuf->y); } else printf("imb_loadtiff: could not find mipmap level %d\n", ibuf->miplevel); /* close the client layer interface to the in-memory file */ TIFFClose(image); }
int main(int argc, char **argv) { TIFF *tif; static const char *srcfilerel = "images/quad-tile.jpg.tiff"; char *srcdir = NULL; char srcfile[1024]; unsigned short h, v; int status; unsigned char *buffer; uint32 *rgba_buffer; tsize_t sz, szout; unsigned int pixel_status = 0; (void) argc; (void) argv; if ((srcdir = getenv("srcdir")) == NULL) { srcdir = "."; } if ((strlen(srcdir) + 1 + strlen(srcfilerel)) >= sizeof(srcfile)) { fprintf( stderr, "srcdir too long %s\n", srcdir); exit( 1 ); } strcpy(srcfile,srcdir); strcat(srcfile,"/"); strcat(srcfile,srcfilerel); tif = TIFFOpen(srcfile,"r"); if ( tif == NULL ) { fprintf( stderr, "Could not open %s\n", srcfile); exit( 1 ); } status = TIFFGetField(tif,TIFFTAG_YCBCRSUBSAMPLING, &h, &v); if ( status == 0 || h != 2 || v != 2) { fprintf( stderr, "Could not retrieve subsampling tag.\n" ); exit(1); } /* * What is the appropriate size of a YCbCr encoded tile? */ sz = TIFFTileSize(tif); if( sz != 24576) { fprintf(stderr, "tiles are %d bytes\n", (int)sz); exit(1); } buffer = (unsigned char *) malloc(sz); /* * Read a tile in decompressed form, but still YCbCr subsampled. */ szout = TIFFReadEncodedTile(tif,9,buffer,sz); if (szout != sz) { fprintf( stderr, "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n", (int) szout, (int) sz ); return 1; } if( check_cluster( 0, buffer, cluster_0 ) || check_cluster( 64, buffer, cluster_64 ) || check_cluster( 128, buffer, cluster_128 ) ) { exit(1); } free(buffer); /* * Read a tile using the built-in conversion to RGB format provided by the JPEG library. */ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); sz = TIFFTileSize(tif); if( sz != 128*128*3) { fprintf(stderr, "tiles are %d bytes\n", (int)sz); exit(1); } buffer = (unsigned char *) malloc(sz); szout = TIFFReadEncodedTile(tif,9,buffer,sz); if (szout != sz) { fprintf( stderr, "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n", (int) szout, (int) sz ); return 1; } #if JPEG_LIB_VERSION >= 70 pixel_status |= check_rgb_pixel( 0, 18, 0, 41, buffer ); pixel_status |= check_rgb_pixel( 64, 0, 0, 0, buffer ); pixel_status |= check_rgb_pixel( 512, 5, 34, 196, buffer ); #else pixel_status |= check_rgb_pixel( 0, 15, 0, 18, buffer ); pixel_status |= check_rgb_pixel( 64, 0, 0, 2, buffer ); pixel_status |= check_rgb_pixel( 512, 6, 36, 182, buffer ); #endif free( buffer ); TIFFClose(tif); /* * Reopen and test reading using the RGBA interface. */ tif = TIFFOpen(srcfile,"r"); sz = 128 * 128 * sizeof(uint32); rgba_buffer = (uint32 *) malloc(sz); if (!TIFFReadRGBATile( tif, 1*128, 2*128, rgba_buffer )) { fprintf( stderr, "TIFFReadRGBATile() returned failure code.\n" ); return 1; } /* * Currently TIFFReadRGBATile() just uses JPEGCOLORMODE_RGB so this * trivally matches the last results. Eventually we should actually * accomplish it from the YCbCr subsampled buffer ourselves in which * case the results may be subtly different but similar. */ #if JPEG_LIB_VERSION >= 70 pixel_status |= check_rgba_pixel( 0, 18, 0, 41, 255, rgba_buffer ); pixel_status |= check_rgba_pixel( 64, 0, 0, 0, 255, rgba_buffer ); pixel_status |= check_rgba_pixel( 512, 5, 34, 196, 255, rgba_buffer ); #else pixel_status |= check_rgba_pixel( 0, 15, 0, 18, 255, rgba_buffer ); pixel_status |= check_rgba_pixel( 64, 0, 0, 2, 255, rgba_buffer ); pixel_status |= check_rgba_pixel( 512, 6, 36, 182, 255, rgba_buffer ); #endif free( rgba_buffer ); TIFFClose(tif); if (pixel_status) { exit(1); } exit( 0 ); }
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; }
static int cvt_by_tile( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 tile_width, tile_height; uint32 row, col; uint32 *wrk_line; int ok = 1; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); if( !TIFFGetField(in, TIFFTAG_TILEWIDTH, &tile_width) || !TIFFGetField(in, TIFFTAG_TILELENGTH, &tile_height) ) { TIFFError(TIFFFileName(in), "Source image not tiled"); return (0); } TIFFSetField(out, TIFFTAG_TILEWIDTH, tile_width ); TIFFSetField(out, TIFFTAG_TILELENGTH, tile_height ); /* * Allocate tile buffer */ raster = (uint32*)_TIFFmalloc(tile_width * tile_height * sizeof (uint32)); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } /* * Allocate a scanline buffer for swapping during the vertical * mirroring pass. */ wrk_line = (uint32*)_TIFFmalloc(tile_width * sizeof (uint32)); if (!wrk_line) { TIFFError(TIFFFileName(in), "No space for raster scanline buffer"); ok = 0; } /* * Loop over the tiles. */ for( row = 0; ok && row < height; row += tile_height ) { for( col = 0; ok && col < width; col += tile_width ) { uint32 i_row; /* Read the tile into an RGBA array */ if (!TIFFReadRGBATile(in, col, row, raster)) { ok = 0; break; } /* * For some reason the TIFFReadRGBATile() function chooses the * lower left corner as the origin. Vertically mirror scanlines. */ for( i_row = 0; i_row < tile_height / 2; i_row++ ) { uint32 *top_line, *bottom_line; top_line = raster + tile_width * i_row; bottom_line = raster + tile_width * (tile_height-i_row-1); _TIFFmemcpy(wrk_line, top_line, 4*tile_width); _TIFFmemcpy(top_line, bottom_line, 4*tile_width); _TIFFmemcpy(bottom_line, wrk_line, 4*tile_width); } /* * Write out the result in a tile. */ if( TIFFWriteEncodedTile( out, TIFFComputeTile( out, col, row, 0, 0), raster, 4 * tile_width * tile_height ) == -1 ) { ok = 0; break; } } } _TIFFfree( raster ); _TIFFfree( wrk_line ); return ok; }
int main(int argc, char **argv) { TIFF *tif; static const char *srcfilerel = "images/quad-tile.jpg.tiff"; char *srcdir = NULL; char srcfile[1024]; unsigned short h, v; int status; unsigned char *buffer; uint32 *rgba_buffer; tsize_t sz, szout; unsigned int pixel_status = 0; (void) argc; (void) argv; if ((srcdir = getenv("srcdir")) == NULL) { srcdir = "."; } printf("XXXXXXXX %s",srcdir); if ((strlen(srcdir) + 1 + strlen(srcfilerel)) >= sizeof(srcfile)) { fprintf( stderr, "srcdir too long %s\n", srcdir); exit( 1 ); } strcpy(srcfile,srcdir); strcat(srcfile,"/"); strcat(srcfile,srcfilerel); tif = TIFFOpen(srcfile,"r"); if ( tif == NULL ) { fprintf( stderr, "Could not open %s\n", srcfile); exit( 1 ); } status = TIFFGetField(tif,TIFFTAG_YCBCRSUBSAMPLING, &h, &v); if ( status == 0 || h != 2 || v != 2) { fprintf( stderr, "Could not retrieve subsampling tag.\n" ); exit(1); } /* * What is the appropriate size of a YCbCr encoded tile? */ sz = TIFFTileSize(tif); if( sz != 24576) { fprintf(stderr, "tiles are %d bytes\n", (int)sz); exit(1); } buffer = (unsigned char *) malloc(sz); /* * Read a tile in decompressed form, but still YCbCr subsampled. */ szout = TIFFReadEncodedTile(tif,9,buffer,sz); if (szout != sz) { fprintf( stderr, "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n", (int) szout, (int) sz ); return 1; } if( check_cluster( 0, buffer, cluster_0 ) || check_cluster( 64, buffer, cluster_64 ) || check_cluster( 128, buffer, cluster_128 ) ) { exit(1); } free(buffer); /* * Read a tile using the built-in conversion to RGB format provided by the JPEG library. */ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); sz = TIFFTileSize(tif); if( sz != 128*128*3) { fprintf(stderr, "tiles are %d bytes\n", (int)sz); exit(1); } buffer = (unsigned char *) malloc(sz); szout = TIFFReadEncodedTile(tif,9,buffer,sz); if (szout != sz) { fprintf( stderr, "Did not get expected result code from TIFFReadEncodedTile()(%d instead of %d)\n", (int) szout, (int) sz ); return 1; } /* * JPEG decoding is inherently inexact, so we can't test for exact * pixel values. (Well, if we knew exactly which libjpeg version * we were using, and with what settings, we could expect specific * values ... but it's not worth the trouble to keep track of.) * Hence, use ranges of expected values. The ranges may need to be * widened over time as more versions of libjpeg appear. */ pixel_status |= check_rgb_pixel( 0, 15, 18, 0, 0, 18, 41, buffer ); pixel_status |= check_rgb_pixel( 64, 0, 0, 0, 0, 0, 2, buffer ); pixel_status |= check_rgb_pixel( 512, 5, 6, 34, 36, 182, 196, buffer ); free( buffer ); TIFFClose(tif); /* * Reopen and test reading using the RGBA interface. */ tif = TIFFOpen(srcfile,"r"); sz = 128 * 128 * sizeof(uint32); rgba_buffer = (uint32 *) malloc(sz); if (!TIFFReadRGBATile( tif, 1*128, 2*128, rgba_buffer )) { fprintf( stderr, "TIFFReadRGBATile() returned failure code.\n" ); return 1; } /* * Currently TIFFReadRGBATile() just uses JPEGCOLORMODE_RGB so this * trivally matches the last results. Eventually we should actually * accomplish it from the YCbCr subsampled buffer ourselves in which * case the results may be subtly different but similar. */ pixel_status |= check_rgba_pixel( 0, 15, 18, 0, 0, 18, 41, 255, 255, rgba_buffer ); pixel_status |= check_rgba_pixel( 64, 0, 0, 0, 0, 0, 2, 255, 255, rgba_buffer ); pixel_status |= check_rgba_pixel( 512, 5, 6, 34, 36, 182, 196, 255, 255, rgba_buffer ); free( rgba_buffer ); TIFFClose(tif); if (pixel_status) { exit(1); } exit( 0 ); }
static int cvt_by_tile( TIFF *in, TIFF *out ) { uint32* raster; /* retrieve RGBA image */ uint32 width, height; /* image width & height */ uint32 tile_width, tile_height; uint32 row, col; uint32 *wrk_line; tsize_t raster_size; int ok = 1; TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(in, TIFFTAG_IMAGELENGTH, &height); if( !TIFFGetField(in, TIFFTAG_TILEWIDTH, &tile_width) || !TIFFGetField(in, TIFFTAG_TILELENGTH, &tile_height) ) { TIFFError(TIFFFileName(in), "Source image not tiled"); return (0); } TIFFSetField(out, TIFFTAG_TILEWIDTH, tile_width ); TIFFSetField(out, TIFFTAG_TILELENGTH, tile_height ); /* * Allocate tile buffer */ raster_size = multiply(multiply(tile_width, tile_height), sizeof (uint32)); if (!raster_size) { TIFFError(TIFFFileName(in), "Can't allocate buffer for raster of size %lux%lu", (unsigned long) tile_width, (unsigned long) tile_height); return (0); } raster = (uint32*)_TIFFmalloc(raster_size); if (raster == 0) { TIFFError(TIFFFileName(in), "No space for raster buffer"); return (0); } /* * Allocate a scanline buffer for swapping during the vertical * mirroring pass. (Request can't overflow given prior checks.) */ wrk_line = (uint32*)_TIFFmalloc(tile_width * sizeof (uint32)); if (!wrk_line) { TIFFError(TIFFFileName(in), "No space for raster scanline buffer"); ok = 0; } /* * Loop over the tiles. */ for( row = 0; ok && row < height; row += tile_height ) { for( col = 0; ok && col < width; col += tile_width ) { uint32 i_row; /* Read the tile into an RGBA array */ if (!TIFFReadRGBATile(in, col, row, raster)) { ok = 0; break; } /* * XXX: raster array has 4-byte unsigned integer type, that is why * we should rearrange it here. */ #if HOST_BIGENDIAN TIFFSwabArrayOfLong(raster, tile_width * tile_height); #endif /* * For some reason the TIFFReadRGBATile() function chooses the * lower left corner as the origin. Vertically mirror scanlines. */ for( i_row = 0; i_row < tile_height / 2; i_row++ ) { uint32 *top_line, *bottom_line; top_line = raster + tile_width * i_row; bottom_line = raster + tile_width * (tile_height-i_row-1); _TIFFmemcpy(wrk_line, top_line, 4*tile_width); _TIFFmemcpy(top_line, bottom_line, 4*tile_width); _TIFFmemcpy(bottom_line, wrk_line, 4*tile_width); } /* * Write out the result in a tile. */ if( TIFFWriteEncodedTile( out, TIFFComputeTile( out, col, row, 0, 0), raster, 4 * tile_width * tile_height ) == -1 ) { ok = 0; break; } } } _TIFFfree( raster ); _TIFFfree( wrk_line ); return ok; }
void TifReader::readLine(char *buffer, int x0, int x1, int shrink) { if (this->m_info.m_bitsPerSample == 16 && this->m_info.m_samplePerPixel >= 3) { std::vector<short> app(4 * (m_info.m_lx)); readLine(&app[0], x0, x1, shrink); TPixel64 *pixin = (TPixel64 *)&app[0]; TPixel32 *pixout = (TPixel32 *)buffer; for (int j = 0; j < x0; j++) { pixout++; pixin++; } for (int i = 0; i < (x1 - x0) + 1; i++) *pixout++ = PixelConverter<TPixel32>::from(*pixin++); return; } assert(shrink > 0); const int pixelSize = 4; int stripRowSize = m_rowLength * pixelSize; if (m_row < m_info.m_y0 || m_row > m_info.m_y1) { memset(buffer, 0, (x1 - x0 + 1) * pixelSize); m_row++; return; } int stripIndex = m_row / m_rowsPerStrip; if (m_stripIndex != stripIndex) { m_stripIndex = stripIndex; if (TIFFIsTiled(m_tiff)) { uint32 tileWidth = 0, tileHeight = 0; TIFFGetField(m_tiff, TIFFTAG_TILEWIDTH, &tileWidth); TIFFGetField(m_tiff, TIFFTAG_TILELENGTH, &tileHeight); assert(tileWidth > 0 && tileHeight > 0); int tileSize = tileWidth * tileHeight; std::unique_ptr<uint32[]> tile(new uint32[tileSize]); int x = 0; int y = tileHeight * m_stripIndex; int lastTy = std::min((int)tileHeight, m_info.m_ly - y); while (x < m_info.m_lx) { int ret = TIFFReadRGBATile(m_tiff, x, y, tile.get()); assert(ret); int tileRowSize = std::min((int)tileWidth, (int)(m_info.m_lx - x)) * pixelSize; for (int ty = 0; ty < lastTy; ++ty) { memcpy( m_stripBuffer + (ty * m_rowLength + x) * pixelSize, (UCHAR *)tile.get() + ty * tileWidth * pixelSize, tileRowSize); } x += tileWidth; } } else { int y = m_rowsPerStrip * m_stripIndex; int ok = TIFFReadRGBAStrip(m_tiff, y, (uint32 *)m_stripBuffer); assert(ok); } } uint16 orient = ORIENTATION_TOPLEFT; TIFFGetField(m_tiff, TIFFTAG_ORIENTATION, &orient); int r = m_rowsPerStrip - 1 - (m_row % m_rowsPerStrip); switch (orient) // Pretty weak check for top/bottom orientation { case ORIENTATION_TOPLEFT: case ORIENTATION_TOPRIGHT: case ORIENTATION_LEFTTOP: case ORIENTATION_RIGHTTOP: // We have to invert the fixed BOTTOM-UP returned by TIFF functions - since this function is // supposed to ignore orientation issues (which are managed outside). // The last tiles row will actually start at the END OF THE IMAGE (not necessarily at // m_rowsPerStrip multiples). So, we must adjust for that. r = std::min(m_rowsPerStrip, m_info.m_ly - m_rowsPerStrip * m_stripIndex) - 1 - (m_row % m_rowsPerStrip); break; case ORIENTATION_BOTRIGHT: case ORIENTATION_BOTLEFT: case ORIENTATION_RIGHTBOT: case ORIENTATION_LEFTBOT: r = m_row % m_rowsPerStrip; break; } TPixel32 *pix = (TPixel32 *)buffer; uint32 *v = (uint32 *)(m_stripBuffer + r * stripRowSize); pix += x0; v += x0; int width = (x1 < x0) ? (m_info.m_lx - 1) / shrink + 1 : (x1 - x0) / shrink + 1; for (int i = 0; i < width; i++) { uint32 c = *v; pix->r = (UCHAR)TIFFGetR(c); pix->g = (UCHAR)TIFFGetG(c); pix->b = (UCHAR)TIFFGetB(c); pix->m = (UCHAR)TIFFGetA(c); v += shrink; pix += shrink; } m_row++; }
bool TiffDecoder::readData( Mat& img ) { bool result = false; bool color = img.channels() > 1; uchar* data = img.data; int step = img.step; 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); if( (!is_tiled && TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 )) || (is_tiled && TIFFGetField( tif, TIFFTAG_TILEWIDTH, &tile_width0 ) && TIFFGetField( tif, TIFFTAG_TILELENGTH, &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*4); uchar* buffer = _buffer; 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 ) { 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 ) { 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 ); } } result = true; } } close(); return result; }