Skip to content

Commit

Permalink
Fix out of bound segment when reading overbuffered geotiff windows
Browse files Browse the repository at this point in the history
  • Loading branch information
echeipesh committed Jan 3, 2018
1 parent 9f603fe commit 9a54b1f
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
11 changes: 10 additions & 1 deletion docs/CHANGELOG.rst
Expand Up @@ -15,7 +15,16 @@ API Changes

- **Change:** Reprojection has improved performance due to one less shuffle stage and lower memory usage.
``TileRDDReproject`` loses dependency on ``TileReprojectMethods`` in favor of ``RasterRegionReproject``


1.2.1
_____
*2018 Jan 3*

Fixes
^^^^^

- `GeoTiffSegmentLayout.getIntersectingSegments bounds checking <https://github.com/locationtech/geotrellis/pull/2534>`__


1.2.0
-----
Expand Down
Expand Up @@ -293,15 +293,29 @@ trait GeoTiffSegmentLayoutTransform {

/** Returns all segment indices which intersect given pixel grid bounds */
private [geotrellis] def getIntersectingSegments(bounds: GridBounds): Array[Int] = {
val tc = tileLayout.tileCols
val tr = tileLayout.tileRows
val ab = mutable.ArrayBuffer[Int]()
for (layoutCol <- (bounds.colMin / tc) to (bounds.colMax / tc)) {
for (layoutRow <- (bounds.rowMin / tr) to (bounds.rowMax / tr)) {
ab += (layoutRow * tileLayout.layoutCols) + layoutCol
val colMax = totalCols - 1
val rowMax = totalRows - 1
val intersects = !(colMax < bounds.colMin || bounds.colMax < 0) && !(rowMax < bounds.rowMin || bounds.rowMax < 0)

if (intersects) {
val tc = tileLayout.tileCols
val tr = tileLayout.tileRows
val colMin = math.max(0, bounds.colMin)
val rowMin = math.max(0, bounds.rowMin)
val colMax = math.min(totalCols - 1, bounds.colMax)
val rowMax = math.min(totalRows -1, bounds.rowMax)
val ab = mutable.ArrayBuilder.make[Int]

cfor(colMin / tc)(_ <= colMax / tc, _ + 1) { layoutCol =>
cfor(rowMin / tr)(_ <= rowMax / tr, _ + 1) { layoutRow =>
ab += (layoutRow * tileLayout.layoutCols) + layoutCol
}
}

ab.result
} else {
Array.empty[Int]
}
ab.toArray
}

/** Partition a list of pixel windows to localize required segment reads.
Expand Down
Expand Up @@ -18,14 +18,15 @@ package geotrellis.raster.io.geotiff

import geotrellis.raster._
import geotrellis.raster.io.geotiff.writer.GeoTiffWriter
import geotrellis.raster.io.geotiff.reader._
import geotrellis.raster.mapalgebra.local._

import geotrellis.util.{ByteReader, Filesystem}
import geotrellis.vector.Extent

import geotrellis.proj4._

import geotrellis.raster.testkit._

import java.nio.ByteBuffer
import org.scalatest._

class GeoTiffMultibandTileSpec extends FunSpec
Expand Down Expand Up @@ -697,4 +698,19 @@ class GeoTiffMultibandTileSpec extends FunSpec
}
}

describe("GeoTiffMultibandTile streaming read") {
it("reads over-buffered windows"){
val path = geoTiffPath("3bands/int32/3bands-striped-pixel.tif")
val info = GeoTiffReader.readGeoTiffInfo(ByteBuffer.wrap(Filesystem.slurp(path)),
decompress = false, streaming = true, withOverviews = false, byteReaderExternal = None)
val tiff = GeoTiffReader.geoTiffMultibandTile(info)

val windows: Array[GridBounds] = info
.segmentLayout
.listWindows(10)
.map(_.buffer(5))

val tiles = tiff.crop(windows)
}
}
}

0 comments on commit 9a54b1f

Please sign in to comment.