Skip to content

Commit e00372e

Browse files
Merge pull request #248 from tschaub/partial-tiles
Avoid reading tile values outside image dimensions
2 parents a3158b8 + 98c1681 commit e00372e

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

src/geotiffimage.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,16 +412,18 @@ class GeoTIFFImage {
412412
height, resampleMethod, signal) {
413413
const tileWidth = this.getTileWidth();
414414
const tileHeight = this.getTileHeight();
415+
const imageWidth = this.getWidth();
416+
const imageHeight = this.getHeight();
415417

416418
const minXTile = Math.max(Math.floor(imageWindow[0] / tileWidth), 0);
417419
const maxXTile = Math.min(
418420
Math.ceil(imageWindow[2] / tileWidth),
419-
Math.ceil(this.getWidth() / this.getTileWidth()),
421+
Math.ceil(imageWidth / tileWidth),
420422
);
421423
const minYTile = Math.max(Math.floor(imageWindow[1] / tileHeight), 0);
422424
const maxYTile = Math.min(
423425
Math.ceil(imageWindow[3] / tileHeight),
424-
Math.ceil(this.getHeight() / this.getTileHeight()),
426+
Math.ceil(imageHeight / tileHeight),
425427
);
426428
const windowWidth = imageWindow[2] - imageWindow[0];
427429

@@ -461,8 +463,8 @@ class GeoTIFFImage {
461463
const lastCol = (tile.x + 1) * tileWidth;
462464
const reader = sampleReaders[si];
463465

464-
const ymax = Math.min(blockHeight, blockHeight - (lastLine - imageWindow[3]));
465-
const xmax = Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2]));
466+
const ymax = Math.min(blockHeight, blockHeight - (lastLine - imageWindow[3]), imageHeight - firstLine);
467+
const xmax = Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2]), imageWidth - firstCol);
466468

467469
for (let y = Math.max(0, imageWindow[1] - firstLine); y < ymax; ++y) {
468470
for (let x = Math.max(0, imageWindow[0] - firstCol); x < xmax; ++x) {

test/geotiff.spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,53 @@ describe('COG tests', async () => {
549549
expect(ghostValues).to.be.null;
550550
});
551551
});
552+
553+
describe('fillValue', async () => {
554+
it('should fill pixels outside the image area (to the left and above)', async () => {
555+
const tiff = await GeoTIFF.fromSource(createSource('cog.tiff'));
556+
const image = await tiff.getImage(0);
557+
const data = await image.readRasters({ window: [-1, -1, 0, 0], fillValue: 42 });
558+
expect(data).to.have.lengthOf(15);
559+
for (const band of data) {
560+
expect(band).to.have.lengthOf(1);
561+
expect(band).to.deep.equal(new Uint16Array([42]));
562+
}
563+
});
564+
565+
it('should fill pixels outside the image area (to the right and below)', async () => {
566+
const tiff = await GeoTIFF.fromSource(createSource('cog.tiff'));
567+
const image = await tiff.getImage(0);
568+
const data = await image.readRasters({ window: [512, 512, 513, 513], fillValue: 42 });
569+
expect(data).to.have.lengthOf(15);
570+
for (const band of data) {
571+
expect(band).to.have.lengthOf(1);
572+
expect(band).to.deep.equal(new Uint16Array([42]));
573+
}
574+
});
575+
576+
it('should fill areas in overview tiles outside the image extent (left)', async () => {
577+
const tiff = await GeoTIFF.fromSource(createSource('cog.tiff'));
578+
const image = await tiff.getImage(1);
579+
const data = await image.readRasters({ window: [269, 0, 270, 1], fillValue: 42 });
580+
expect(data).to.have.lengthOf(15);
581+
for (const band of data) {
582+
expect(band).to.have.lengthOf(1);
583+
expect(band).to.deep.equal(new Uint16Array([42]));
584+
}
585+
});
586+
587+
it('should fill areas in overview tiles outside the image extent (below)', async () => {
588+
const tiff = await GeoTIFF.fromSource(createSource('cog.tiff'));
589+
const image = await tiff.getImage(1);
590+
const data = await image.readRasters({ window: [0, 224, 1, 225], fillValue: 42 });
591+
expect(data).to.have.lengthOf(15);
592+
for (const band of data) {
593+
expect(band).to.have.lengthOf(1);
594+
expect(band).to.deep.equal(new Uint16Array([42]));
595+
}
596+
});
597+
});
598+
552599
describe("64 bit tests", () => {
553600
it("DataView64 uint64 tests", () => {
554601
const littleEndianBytes = new Uint8Array([

0 commit comments

Comments
 (0)