public bool ReadRGBATile(int col, int row, int[] raster)
{
// Verify that our request is legal - on a tile file, and on a tile boundary.
if (!IsTiled())
{
ErrorExt(this, m_clientdata, FileName(), "Can't use ReadRGBATile() with stripped file.");
return false;
}
FieldValue[] result = GetFieldDefaulted(TiffTag.TILEWIDTH);
int tile_xsize = result[0].ToInt();
result = GetFieldDefaulted(TiffTag.TILELENGTH);
int tile_ysize = result[0].ToInt();
if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0)
{
ErrorExt(this, m_clientdata, FileName(), "Row/col passed to ReadRGBATile() must be topleft corner of a tile.");
return false;
}
// Setup the RGBA reader.
string emsg;
TiffRgbaImage img = TiffRgbaImage.Create(this, false, out emsg);
if (!RGBAImageOK(out emsg) || img == null)
{
ErrorExt(this, m_clientdata, FileName(), "{0}", emsg);
return false;
}
// The TiffRgbaImage.Get() function doesn't allow us to get off the edge of the
// image, even to fill an otherwise valid tile. So we figure out how much we can read,
// and fix up the tile buffer to a full tile configuration afterwards.
int read_ysize;
if (row + tile_ysize > img.Height)
read_ysize = img.Height - row;
else
read_ysize = tile_ysize;
int read_xsize;
if (col + tile_xsize > img.Width)
read_xsize = img.Width - col;
else
read_xsize = tile_xsize;
// Read the chunk of imagery.
img.row_offset = row;
img.col_offset = col;
bool ok = img.GetRaster(raster, 0, read_xsize, read_ysize);
// If our read was incomplete we will need to fix up the tile by shifting the data
// around as if a full tile of data is being returned. This is all the more
// complicated because the image is organized in bottom to top format.
if (read_xsize == tile_xsize && read_ysize == tile_ysize)
return ok;
for (int i_row = 0; i_row < read_ysize; i_row++)
{
Buffer.BlockCopy(raster, (read_ysize - i_row - 1) * read_xsize * sizeof(int),
raster, (tile_ysize - i_row - 1) * tile_xsize * sizeof(int), read_xsize * sizeof(int));
Array.Clear(raster, (tile_ysize - i_row - 1) * tile_xsize + read_xsize, tile_xsize - read_xsize);
}
for (int i_row = read_ysize; i_row < tile_ysize; i_row++)
Array.Clear(raster, (tile_ysize - i_row - 1) * tile_xsize, tile_xsize);
return ok;
}