source.seek(source.getFlushedPosition() + size);
source.flush();
}
Box2i dw = getDataWindow();
CompressionMethod cm = getCompressionMethod();
source.flush();
if (tiled) {
TileDescription td = getTiles();
int numTiles;
switch (td.getLevelMode()) {
case ONE_LEVEL:
numTiles = (1 + (dw.getYSize() - 1) / td.getYSize())
* (1 + (dw.getXSize() - 1) / td.getXSize());
break;
case MIPMAP_LEVELS:
{
int w = dw.getXSize();
int h = dw.getYSize();
int tw = td.getXSize();
int th = td.getYSize();
RoundingMode rm = td.getRoundingMode();
int n = 1 + round(Math.log(Math.max(w, h)) / Math.log(2.0), rm);
numTiles = 0;
for (int i = 0; i < n; i++) {
int lx = round(w / Math.pow(2.0, i), rm);
int ly = round(h / Math.pow(2.0, i), rm);
int tx = 1 + (lx - 1) / tw;
int ty = 1 + (ly - 1) / th;
numTiles += tx * ty;
}
break;
}
case RIPMAP_LEVELS:
{
int w = dw.getXSize();
int h = dw.getYSize();
int tw = td.getXSize();
int th = td.getYSize();
RoundingMode rm = td.getRoundingMode();
int nx = 1 + round(Math.log(w) / Math.log(2.0), rm);
int ny = 1 + round(Math.log(h) / Math.log(2.0), rm);
numTiles = 0;
for (int j = 0; j < ny; j++) {
int ly = round(h / Math.pow(2.0, j), rm);
int ty = 1 + (ly - 1) / th;
for (int i = 0; i < nx; i++) {
int lx = round(w / Math.pow(2.0, i), rm);
int tx = 1 + (lx - 1) / tw;
numTiles += tx * ty;
}
}
break;
}
default:
throw new UnexpectedException("Invalid level mode.");
}
source.seek(source.getFlushedPosition() + 8 * numTiles);
source.flush();
throw new UnimplementedException();
} else { // scan lines
int w = dw.getXSize();
int h = dw.getYSize();
int ymin = dw.getYMin();
int ymax = dw.getYMax();
int blockHeight = cm.getScanLinesPerBlock();
int numBlocks = 1 + (h - 1) / blockHeight;
ChannelList chlist = getChannelList();
source.seek(source.getFlushedPosition() + 8 * numBlocks);
for (int i = 0; i < numBlocks; i++) {
source.flush();
int x0 = dw.getXMin();
int x1 = dw.getXMax();
int y0 = source.readInt();
int y1 = Math.min(y0 + blockHeight - 1, ymax);
Box2i block = new Box2i(x0, y0, x1, y1);
int size = source.readInt();
int blockSize = computeTileSize(block);
IIOByteBuffer buf = new IIOByteBuffer(null, 0, 0);
source.readBytes(buf, size);
if (size < blockSize) {
cm.decompress(buf, block);
if (buf.getLength() < blockSize) {
throw new RuntimeException("Undersized block");
}
}
f.write(buf.getData(), buf.getOffset(), buf.getLength());