@@ -25,7 +25,8 @@ import astraea.spark.rasterframes.datasource._
2525import astraea .spark .rasterframes .util ._
2626import com .typesafe .scalalogging .LazyLogging
2727import org .apache .spark .sql .sources .{BaseRelation , CreatableRelationProvider , DataSourceRegister , RelationProvider }
28- import org .apache .spark .sql .{DataFrame , SQLContext , SaveMode }
28+ import org .apache .spark .sql .types .LongType
29+ import org .apache .spark .sql .{DataFrame , SQLContext , SaveMode , functions ⇒ F }
2930
3031/**
3132 * Spark SQL data source over GeoTIFF files.
@@ -50,22 +51,44 @@ class DefaultSource extends DataSourceRegister with RelationProvider with Creata
5051 require(pathO.get.getScheme == " file" || pathO.get.getScheme == null , " Currently only 'file://' destinations are supported" )
5152 sqlContext.withRasterFrames
5253
53-
5454 require(data.isRF, " GeoTIFF can only be constructed from a RasterFrame" )
5555 val rf = data.certify
5656
57- val tl = rf.tileLayerMetadata.merge.layout.tileLayout
57+ // If no desired image size is given, write at full size.
58+ lazy val (fullResCols, fullResRows) = {
59+ // get the layout size given that the tiles may be heterogenously sized
60+ // first get any valid row and column in the spatial key structure
61+ val sk = rf.select(SPATIAL_KEY_COLUMN ).first()
62+
63+ val tc = rf.tileColumns.head
64+
65+ val c = rf
66+ .where(SPATIAL_KEY_COLUMN (" row" ) === sk.row)
67+ .agg(
68+ F .sum(tileDimensions(tc)(" cols" ) cast(LongType ))
69+ ).first()
70+ .getLong(0 )
71+
72+ val r = rf
73+ .where(SPATIAL_KEY_COLUMN (" col" ) === sk.col)
74+ .agg(
75+ F .sum(tileDimensions(tc)(" rows" ) cast(LongType ))
76+ ).first()
77+ .getLong(0 )
78+
79+ (c, r)
80+ }
5881
59- val cols = numParam(DefaultSource .IMAGE_WIDTH_PARAM , parameters).getOrElse(tl.totalCols )
60- val rows = numParam(DefaultSource .IMAGE_HEIGHT_PARAM , parameters).getOrElse(tl.totalRows )
82+ val cols = numParam(DefaultSource .IMAGE_WIDTH_PARAM , parameters).getOrElse(fullResCols )
83+ val rows = numParam(DefaultSource .IMAGE_HEIGHT_PARAM , parameters).getOrElse(fullResRows )
6184
6285 require(cols <= Int .MaxValue && rows <= Int .MaxValue , s " Can't construct a GeoTIFF of size $cols x $rows. (Too big!) " )
6386
6487 // Should we really play traffic cop here?
6588 if (cols.toDouble * rows * 64.0 > Runtime .getRuntime.totalMemory() * 0.5 )
6689 logger.warn(s " You've asked for the construction of a very large image ( $cols x $rows), destined for ${pathO.get}. Out of memory error likely. " )
6790
68- println( )
91+ logger.debug( s " Writing DataFrame to GeoTIFF ( $cols by $rows ) at ${pathO.get} " )
6992 val raster = rf.toMultibandRaster(rf.tileColumns, cols.toInt, rows.toInt)
7093
7194 GeoTiff (raster).write(pathO.get.getPath)
0 commit comments