@@ -3,7 +3,7 @@ import { Projection, ProjectionLoader, TileId, TileMatrixSet, TileMatrixSets } f
3
3
import { fsa , LogType , stringToUrlFolder , Tiff } from '@basemaps/shared' ;
4
4
import { CliId , CliInfo } from '@basemaps/shared/build/cli/info.js' ;
5
5
import { Metrics } from '@linzjs/metrics' ;
6
- import { command , flag , number , option , optional , restPositionals } from 'cmd-ts' ;
6
+ import { command , flag , number , option , optional , restPositionals , string } from 'cmd-ts' ;
7
7
import { mkdir , rm } from 'fs/promises' ;
8
8
import { tmpdir } from 'os' ;
9
9
import pLimit from 'p-limit' ;
@@ -18,12 +18,22 @@ import { getLogger, logArguments } from '../../log.js';
18
18
import { gdalBuildCog , gdalBuildVrt , gdalBuildVrtWarp , gdalCreate } from '../gdal.command.js' ;
19
19
import { GdalRunner } from '../gdal.runner.js' ;
20
20
import { Url , UrlArrayJsonFile } from '../parsers.js' ;
21
- import { CogifyCreationOptions , CogifyStacItem , getCutline , getSources } from '../stac.js' ;
21
+ import { Background , CogifyCreationOptions , CogifyStacItem , getCutline , getSources } from '../stac.js' ;
22
22
23
23
function extractSourceFiles ( item : CogifyStacItem , baseUrl : URL ) : URL [ ] {
24
24
return item . links . filter ( ( link ) => link . rel === 'linz_basemaps:source' ) . map ( ( link ) => new URL ( link . href , baseUrl ) ) ;
25
25
}
26
26
27
+ function parseBackgroud ( background : string ) : Background {
28
+ const parts = background . split ( ',' ) . map ( ( f ) => {
29
+ const value = parseInt ( f ) ;
30
+ if ( value < 0 || value > 255 ) throw new Error ( 'Invalid rgba number' ) ;
31
+ return value ;
32
+ } ) ;
33
+ if ( parts . length !== 4 ) throw new Error ( 'Invalid background format' ) ;
34
+ return { r : parts [ 0 ] , g : parts [ 1 ] , b : parts [ 2 ] , alpha : parts [ 3 ] } ;
35
+ }
36
+
27
37
const Collections = new Map < string , Promise < StacCollection > > ( ) ;
28
38
29
39
export interface CogItem {
@@ -72,6 +82,11 @@ export const BasemapsCogifyCreateCommand = command({
72
82
defaultValue : ( ) => 4 ,
73
83
defaultValueIsSerializable : true ,
74
84
} ) ,
85
+ background : option ( {
86
+ type : optional ( string ) ,
87
+ long : 'background' ,
88
+ description : 'Background rbga color to fill empty space in the COG' + 'Format: "r,g,b,a" eg "255,0,0,0.5"' ,
89
+ } ) ,
75
90
docker : flag ( { long : 'docker' , description : 'Run GDAL inside docker container' } ) ,
76
91
fromFile : option ( {
77
92
type : optional ( UrlArrayJsonFile ) ,
@@ -87,7 +102,7 @@ export const BasemapsCogifyCreateCommand = command({
87
102
const logger = getLogger ( this , args ) ;
88
103
89
104
if ( args . docker ) process . env [ 'GDAL_DOCKER' ] = '1' ;
90
-
105
+ const background = args . background ? parseBackgroud ( args . background ) : undefined ;
91
106
const paths = args . fromFile != null ? args . path . concat ( args . fromFile ) : args . path ;
92
107
93
108
const toCreate = await Promise . all ( paths . map ( async ( p ) => loadItem ( p , logger ) ) ) ;
@@ -158,6 +173,9 @@ export const BasemapsCogifyCreateCommand = command({
158
173
const options = item . properties [ 'linz_basemaps:options' ] ;
159
174
const tileId = TileId . fromTile ( options . tile ) ;
160
175
176
+ // Forces background if defined.
177
+ if ( background ) options . background = background ;
178
+
161
179
// Location to where the tiff should be stored
162
180
const tiffPath = new URL ( tileId + '.tiff' , url ) ;
163
181
const itemStacPath = new URL ( tileId + '.json' , url ) ;
@@ -332,22 +350,28 @@ async function createCog(ctx: CogCreationContext): Promise<URL> {
332
350
) ;
333
351
await new GdalRunner ( vrtWarpCommand ) . run ( logger ) ;
334
352
335
- // Create a tiff file covering the whole world in sea blue
336
- const gdalCreateCommand = gdalCreate ( new URL ( `${ tileId } -bg.tiff` , ctx . tempFolder ) , options ) ;
337
- await new GdalRunner ( gdalCreateCommand ) . run ( logger ) ;
338
-
339
- // Create a vrt layering with the sea blue behind the warp VRT
340
- const vrtMergeCommand = gdalBuildVrt ( new URL ( `${ tileId } -merged.vrt` , ctx . tempFolder ) , [
341
- gdalCreateCommand . output ,
342
- vrtWarpCommand . output ,
343
- ] ) ;
344
- await new GdalRunner ( vrtMergeCommand ) . run ( logger ) ;
345
-
346
- // Create the COG from the warped vrt
347
- const cogCreateCommand = gdalBuildCog ( new URL ( `${ tileId } .tiff` , ctx . tempFolder ) , vrtMergeCommand . output , options ) ;
348
- await new GdalRunner ( cogCreateCommand ) . run ( logger ) ;
349
-
350
- return cogCreateCommand . output ;
353
+ if ( options . background ) {
354
+ // Create a tiff with background to fill the empty space in the target cog
355
+ const gdalCreateCommand = gdalCreate ( new URL ( `${ tileId } -bg.tiff` , ctx . tempFolder ) , options ) ;
356
+ await new GdalRunner ( gdalCreateCommand ) . run ( logger ) ;
357
+
358
+ // Create a vrt layering with the backgroud tiff
359
+ const vrtMergeCommand = gdalBuildVrt ( new URL ( `${ tileId } -merged.vrt` , ctx . tempFolder ) , [
360
+ gdalCreateCommand . output ,
361
+ vrtWarpCommand . output ,
362
+ ] ) ;
363
+ await new GdalRunner ( vrtMergeCommand ) . run ( logger ) ;
364
+
365
+ // Create the COG from the merged Vrt with background
366
+ const cogCreateCommand = gdalBuildCog ( new URL ( `${ tileId } .tiff` , ctx . tempFolder ) , vrtMergeCommand . output , options ) ;
367
+ await new GdalRunner ( cogCreateCommand ) . run ( logger ) ;
368
+ return cogCreateCommand . output ;
369
+ } else {
370
+ // Create the COG from the warped vrt without background
371
+ const cogCreateCommand = gdalBuildCog ( new URL ( `${ tileId } .tiff` , ctx . tempFolder ) , vrtWarpCommand . output , options ) ;
372
+ await new GdalRunner ( cogCreateCommand ) . run ( logger ) ;
373
+ return cogCreateCommand . output ;
374
+ }
351
375
}
352
376
353
377
/**
0 commit comments