File Coverage

blib/lib/Geo/GDAL/FFI/Dataset.pm
Criterion Covered Total %
statement 106 255 41.5
branch 19 86 22.0
condition 9 66 13.6
subroutine 22 39 56.4
pod 19 30 63.3
total 175 476 36.7


line stmt bran cond sub pod time code
1             package Geo::GDAL::FFI::Dataset;
2 5     5   66 use v5.10;
  5         16  
3 5     5   25 use strict;
  5         20  
  5         103  
4 5     5   23 use warnings;
  5         9  
  5         120  
5 5     5   28 use Carp;
  5         9  
  5         320  
6 5     5   41 use base 'Geo::GDAL::FFI::Object';
  5         10  
  5         579  
7 5     5   35 use Scalar::Util qw /blessed/;
  5         27  
  5         18020  
8              
9             our $VERSION = 0.0800;
10              
11             sub DESTROY {
12 15     15   2596 my $self = shift;
13 15         56 $self->FlushCache;
14             #say STDERR "DESTROY $self";
15 15         3202 Geo::GDAL::FFI::GDALClose($$self);
16             }
17              
18             sub GetName {
19 0     0 0 0 my $self = shift;
20 0         0 return $self->GetDescription;
21             }
22              
23             sub FlushCache {
24 17     17 0 1032 my $self = shift;
25 17         3272 Geo::GDAL::FFI::GDALFlushCache($$self);
26             }
27              
28             sub GetDriver {
29 1     1 1 10 my $self = shift;
30 1         5 my $dr = Geo::GDAL::FFI::GDALGetDatasetDriver($$self);
31 1         6 return bless \$dr, 'Geo::GDAL::FFI::Driver';
32             }
33              
34             sub GetWidth {
35 0     0 1 0 my $self = shift;
36 0         0 return Geo::GDAL::FFI::GDALGetRasterXSize($$self);
37             }
38              
39             sub GetHeight {
40 0     0 1 0 my $self = shift;
41 0         0 return Geo::GDAL::FFI::GDALGetRasterYSize($$self);
42             }
43              
44             sub GetSize {
45 0     0 1 0 my $self = shift;
46             return (
47 0         0 Geo::GDAL::FFI::GDALGetRasterXSize($$self),
48             Geo::GDAL::FFI::GDALGetRasterYSize($$self)
49             );
50             }
51              
52             sub GetProjectionString {
53 1     1 0 19 my ($self) = @_;
54 1         633 return Geo::GDAL::FFI::GDALGetProjectionRef($$self);
55             }
56              
57             sub SetProjectionString {
58 1     1 0 65 my ($self, $proj) = @_;
59 1         40960 my $e = Geo::GDAL::FFI::GDALSetProjection($$self, $proj);
60 1 50       39 if ($e != 0) {
61 0         0 confess Geo::GDAL::FFI::error_msg();
62             }
63             }
64              
65             sub GetGeoTransform {
66 1     1 0 7 my ($self) = @_;
67 1         4 my $t = [0,0,0,0,0,0];
68 1         7 Geo::GDAL::FFI::GDALGetGeoTransform($$self, $t);
69 1 50       4 return wantarray ? @$t : $t;
70             }
71              
72             sub SetGeoTransform {
73 1     1 0 1129 my $self = shift;
74 1 50       6 my $t = @_ > 1 ? [@_] : shift;
75 1         15 Geo::GDAL::FFI::GDALSetGeoTransform($$self, $t);
76             }
77              
78             sub GetBand {
79 3     3 1 22 my ($self, $i) = @_;
80 3   50     18 $i //= 1;
81 3         43 my $b = Geo::GDAL::FFI::GDALGetRasterBand($$self, $i);
82 3         19 Geo::GDAL::FFI::_register_parent_ref ($b, $self);
83 3         27 return bless \$b, 'Geo::GDAL::FFI::Band';
84             }
85              
86             sub GetBands {
87 0     0 1 0 my $self = shift;
88 0         0 my @bands;
89 0         0 for my $i (1..Geo::GDAL::FFI::GDALGetRasterCount($$self)) {
90 0         0 push @bands, $self->GetBand($i);
91             }
92 0         0 return @bands;
93             }
94              
95             sub GetLayerCount {
96 0     0 1 0 my ($self) = @_;
97 0         0 return Geo::GDAL::FFI::GDALDatasetGetLayerCount($$self);
98             }
99              
100              
101             sub GetLayer {
102 1     1 1 11 my ($self, $i) = @_;
103 1   50     9 $i //= 0;
104 1 50       5 my $l = Geo::GDAL::FFI::isint($i)
105             ? Geo::GDAL::FFI::GDALDatasetGetLayer($$self, $i)
106             : Geo::GDAL::FFI::GDALDatasetGetLayerByName($$self, $i);
107 1 50       5 unless ($l) {
108 0   0     0 my $msg = Geo::GDAL::FFI::error_msg()
109             // "Could not access layer $i in data set.";
110 0 0       0 confess $msg if $msg;
111             }
112 1         7 Geo::GDAL::FFI::_register_parent_ref ($l, $self);
113 1         9 return bless \$l, 'Geo::GDAL::FFI::Layer';
114             }
115              
116             sub CreateLayer {
117 3     3 1 41 my ($self, $args) = @_;
118 3   50     13 $args //= {};
119 3   100     19 my $name = $args->{Name} // '';
120 3         8 my ($gt, $sr);
121 3 50       13 if ($args->{GeometryFields}) {
122 0         0 $gt = $Geo::GDAL::FFI::geometry_types{None};
123             } else {
124 3   50     12 $gt = $args->{GeometryType} // 'Unknown';
125 3         9 $gt = $Geo::GDAL::FFI::geometry_types{$gt};
126 3 50       11 confess "Unknown geometry type: '$args->{GeometryType}'." unless defined $gt;
127 3 100       19 $sr = Geo::GDAL::FFI::OSRClone(${$args->{SpatialReference}}) if $args->{SpatialReference};
  1         104  
128             }
129 3         8 my $o = 0;
130 3 50       12 if ($args->{Options}) {
131 0         0 for my $key (keys %{$args->{Options}}) {
  0         0  
132 0         0 $o = Geo::GDAL::FFI::CSLAddString($o, "$key=$args->{Options}->{$key}");
133             }
134             }
135 3         2642 my $l = Geo::GDAL::FFI::GDALDatasetCreateLayer($$self, $name, $sr, $gt, $o);
136 3         24 Geo::GDAL::FFI::CSLDestroy($o);
137 3 100       21 Geo::GDAL::FFI::OSRRelease($sr) if $sr;
138 3         14 my $msg = Geo::GDAL::FFI::error_msg();
139 3 50       14 confess $msg if $msg;
140 3         13 Geo::GDAL::FFI::_register_parent_ref ($l, $self);
141 3         19 my $layer = bless \$l, 'Geo::GDAL::FFI::Layer';
142 3 50       12 if ($args->{Fields}) {
143 0         0 for my $f (@{$args->{Fields}}) {
  0         0  
144 0         0 $layer->CreateField($f);
145             }
146             }
147 3 50       12 if ($args->{GeometryFields}) {
148 0         0 for my $f (@{$args->{GeometryFields}}) {
  0         0  
149 0         0 $layer->CreateGeomField($f);
150             }
151             }
152 3         12 return $layer;
153             }
154              
155             sub CopyLayer {
156 1     1 1 12 my ($self, $layer, $name, $options) = @_;
157 1   50     8 $name //= '';
158 1         2 my $o = 0;
159 1         6 for my $key (keys %$options) {
160 0         0 $o = Geo::GDAL::FFI::CSLAddString($o, "$key=$options->{$key}");
161             }
162 1         126 my $l = Geo::GDAL::FFI::GDALDatasetCopyLayer($$self, $$layer, $name, $o);
163 1         1364 Geo::GDAL::FFI::CSLDestroy($o);
164 1 50       5 unless ($l) {
165 0   0     0 my $msg = Geo::GDAL::FFI::error_msg() // "GDALDatasetCopyLayer failed.";
166 0 0       0 confess $msg if $msg;
167             }
168 1         5 Geo::GDAL::FFI::_register_parent_ref ($l, $self);
169 1         7 return bless \$l, 'Geo::GDAL::FFI::Layer';
170             }
171              
172              
173             sub ExecuteSQL {
174 0     0 1 0 my ($self, $sql, $filter, $dialect) = @_;
175            
176 0         0 my $lyr = Geo::GDAL::FFI::GDALDatasetExecuteSQL(
177             $$self, $sql, $$filter, $dialect
178             );
179            
180 0 0       0 if ($lyr) {
181 0 0       0 if (defined wantarray) {
182 0         0 Geo::GDAL::FFI::_register_parent_ref ($lyr, $self);
183 0         0 return bless \$lyr, 'Geo::GDAL::FFI::Layer::ResultSet';
184             }
185             else {
186 0         0 Geo::GDAL::FFI::GDALDatasetReleaseResultSet ($lyr, $$self);
187             }
188             }
189              
190             # This is perhaps unnecessary, but ensures
191             # internal details do not leak if spatial
192             # index is built in non-void context.
193 0         0 return undef;
194             }
195              
196              
197             ## utilities
198              
199             sub new_options {
200 2     2 0 9 my ($constructor, $options) = @_;
201 2   50     12 $options //= [];
202 2 50       8 confess "The options must be a reference to an array." unless ref $options;
203 2         6 my $csl = 0;
204 2         23 for my $s (@$options) {
205 3         24 $csl = Geo::GDAL::FFI::CSLAddString($csl, $s);
206             }
207 2         57 $options = $constructor->($csl, 0);
208 2         13 Geo::GDAL::FFI::CSLDestroy($csl);
209 2         5 return $options;
210             }
211              
212             sub GetInfo {
213 1     1 0 23 my ($self, $options) = @_;
214 1         6 $options = new_options(\&Geo::GDAL::FFI::GDALInfoOptionsNew, $options);
215 1         4150 my $info = Geo::GDAL::FFI::GDALInfo($$self, $options);
216 1         10 Geo::GDAL::FFI::GDALInfoOptionsFree($options);
217 1         93 return $info;
218             }
219             *Info = *GetInfo;
220              
221             sub set_progress {
222 1     1 0 3 my ($options, $args, $setter) = @_;
223 1 50       5 return unless $args->{Progress};
224 0         0 my $ffi = FFI::Platypus->new;
225 0         0 $setter->($options, $ffi->closure($args->{Progress}), $args->{ProgressData});
226             }
227              
228             sub Translate {
229 1     1 1 49 my ($self, $path, $options, $progress, $data) = @_;
230 1         5 $options = new_options(\&Geo::GDAL::FFI::GDALTranslateOptionsNew, $options);
231 1         5 my $args = {Progress => $progress, ProgressData => $data};
232 1         6 set_progress($options, $args, \&Geo::GDAL::FFI::GDALTranslateOptionsSetProgress);
233 1         1 my $e = 0;
234 1         2879 my $ds = Geo::GDAL::FFI::GDALTranslate($path, $$self, $options, \$e);
235 1         10 Geo::GDAL::FFI::GDALTranslateOptionsFree($options);
236 1 50 33     14 return bless \$ds, 'Geo::GDAL::FFI::Dataset' if $ds && ($e == 0);
237 0   0       my $msg = Geo::GDAL::FFI::error_msg() // 'Translate failed.';
238 0           confess $msg;
239             }
240              
241             sub destination {
242 0     0 0   my ($dst) = @_;
243 0 0         confess "Destination missing." unless $dst;
244 0           my $path;
245 0 0         if (ref $dst) {
246 0           $dst = $$dst;
247             } else {
248 0           $path = $dst;
249 0           undef $dst;
250             }
251 0           return ($path, $dst);
252             }
253              
254             sub dataset_input {
255 0     0 0   my ($self, $input) = @_;
256 0   0       $input //= [];
257 0 0         confess "The input must be a reference to an array of datasets." unless ref ($input) =~ /ARRAY/;
258 0           my @datasets = ($$self);
259 0           for my $ds (@$input) {
260 0           push @datasets, $$ds;
261             }
262 0           return \@datasets;
263             }
264              
265             sub Warp {
266 0     0 1   my ($self, $args) = @_;
267            
268 0           my ($path, $dst) = destination($args->{Destination});
269 0 0 0       confess "Destination object should not be passed for non-void context"
270             if defined wantarray && blessed $dst;
271              
272 0           my $input = $self->dataset_input($args->{Input});
273              
274 0           my $options = new_options(\&Geo::GDAL::FFI::GDALWarpAppOptionsNew, $args->{Options});
275 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALWarpAppOptionsSetProgress);
276            
277 0           my $e = 0;
278 0           my $result;
279 0 0         if (blessed($dst)) {
280 0           Geo::GDAL::FFI::GDALWarp($path, $dst, scalar @$input, $input, $options, \$e);
281             } else {
282 0           $result = Geo::GDAL::FFI::GDALWarp($path, undef, scalar @$input, $input, $options, \$e);
283             }
284 0           Geo::GDAL::FFI::GDALWarpAppOptionsFree($options);
285 0 0         if (defined $result) {
286 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'Warp failed.' if !$result || $e != 0;
      0        
287 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
288             }
289             }
290              
291             sub VectorTranslate {
292 0     0 1   my ($self, $args) = @_;
293 0           my ($path, $dst) = destination($args->{Destination});
294 0 0 0       confess "Destination object should not be passed for non-void context"
295             if defined wantarray && blessed $dst;
296              
297 0           my $input = $self->dataset_input($args->{Input});
298              
299 0           my $options = new_options(\&Geo::GDAL::FFI::GDALVectorTranslateOptionsNew, $args->{Options});
300 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALVectorTranslateOptionsSetProgress);
301            
302 0           my $e = 0;
303 0           my $result;
304 0 0         if (blessed($dst)) {
305 0           Geo::GDAL::FFI::GDALVectorTranslate(undef, $$dst, scalar @$input, $input, $options, \$e);
306             }
307             else {
308 0           my $result = Geo::GDAL::FFI::GDALVectorTranslate($path, undef, scalar @$input, $input, $options, \$e);
309             }
310 0           Geo::GDAL::FFI::GDALVectorTranslateOptionsFree($options);
311 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'VectorTranslate failed.' if $e != 0;
312 0 0         if (defined $result) {
313 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
314             }
315             }
316              
317             sub DEMProcessing {
318 0     0 1   my ($self, $path, $args) = @_;
319 0   0       my $processing = $args->{Processing} // 'hillshade';
320 0           my $colorfile = $args->{ColorFilename};
321 0           my $options = new_options(\&Geo::GDAL::FFI::GDALDEMProcessingOptionsNew, $args->{Options});
322 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALDEMProcessingOptionsSetProgress);
323 0           my $e = 0;
324 0           my $result = Geo::GDAL::FFI::GDALDEMProcessing($path, $$self, $processing, $colorfile, $options, \$e);
325 0           Geo::GDAL::FFI::GDALDEMProcessingOptionsFree($options);
326 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'DEMProcessing failed.' if !$result || $e != 0;
      0        
327 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
328             }
329              
330             sub NearBlack {
331 0     0 1   my ($self, $args) = @_;
332            
333 0           my ($path, $dst) = destination($args->{Destination});
334 0 0 0       confess "Destination object should not be passed for non-void context"
335             if defined wantarray && blessed $dst;
336              
337 0           my $input = $self->dataset_input($args->{Input});
338              
339 0           my $options = new_options(\&Geo::GDAL::FFI::GDALNearblackOptionsNew, $args->{Options});
340 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALNearblackOptionsSetProgress);
341            
342 0           my $e = 0;
343 0           my $result;
344 0 0         if (blessed($dst)) {
345 0           Geo::GDAL::FFI::GDALNearblack($path, $$dst, $$self, $options, \$e);
346             } else {
347 0           $result = Geo::GDAL::FFI::GDALNearblack($path, undef, $$self, $options, \$e);
348             }
349 0           Geo::GDAL::FFI::GDALNearblackOptionsFree($options);
350              
351 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'NearBlack failed.' if $e != 0;
352 0 0         if (defined $result) {
353 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
354             }
355              
356             }
357              
358             sub Grid {
359 0     0 1   my ($self, $path, $options, $progress, $data) = @_;
360 0           $options = new_options(\&Geo::GDAL::FFI::GDALGridOptionsNew, $options);
361 0           my $args = {Progress => $progress, ProgressData => $data};
362 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALGridOptionsSetProgress);
363 0           my $e = 0;
364 0           my $result = Geo::GDAL::FFI::GDALGrid($path, $$self, $options, \$e);
365 0           Geo::GDAL::FFI::GDALGridOptionsFree($options);
366 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'Grid failed.' if !$result || $e != 0;
      0        
367 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
368             }
369              
370             sub Rasterize {
371 0     0 1   my ($self, $args) = @_;
372            
373 0           my $dst = $args->{Destination};
374 0 0 0       confess "Destination argument should not be passed for non-void context"
375             if defined wantarray && blessed $dst;
376              
377 0           my $options = new_options(\&Geo::GDAL::FFI::GDALRasterizeOptionsNew, $args->{Options});
378 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALRasterizeOptionsSetProgress);
379            
380 0           my $e = 0;
381 0           my $result;
382 0 0         if (blessed($dst)) {
383 0           Geo::GDAL::FFI::GDALRasterize(undef, $$dst, $$self, $options, \$e);
384             } else {
385 0           $result = Geo::GDAL::FFI::GDALRasterize($dst, undef, $$self, $options, \$e);
386             }
387 0           Geo::GDAL::FFI::GDALRasterizeOptionsFree($options);
388            
389 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'Rasterize failed.' if $e != 0;
390 0 0         if (defined $result) {
391 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
392             }
393             }
394              
395             sub BuildVRT {
396 0     0 1   my ($self, $path, $args) = @_;
397 0           my $input = $self->dataset_input($args->{Input});
398 0           my $options = new_options(\&Geo::GDAL::FFI::GDALBuildVRTOptionsNew, $args->{Options});
399 0           set_progress($options, $args, \&Geo::GDAL::FFI::GDALBuildVRTOptionsSetProgress);
400 0           my $e = 0;
401 0           my $result = Geo::GDAL::FFI::GDALBuildVRT($path, scalar @$input, $input, 0, $options, \$e);
402 0           Geo::GDAL::FFI::GDALBuildVRTOptionsFree($options);
403 0 0 0       confess Geo::GDAL::FFI::error_msg() // 'BuildVRT failed.' if !$result || $e != 0;
      0        
404 0           return bless \$result, 'Geo::GDAL::FFI::Dataset';
405             }
406              
407             1;
408              
409             {
410             # dummy class for result sets from ExecuteSQL
411             # allows specialised destroy method
412             package Geo::GDAL::FFI::Layer::ResultSet;
413 5     5   54 use base qw /Geo::GDAL::FFI::Layer/;
  5         10  
  5         2437  
414            
415             sub DESTROY {
416 0     0     my ($self) = @_;
417 0           my $parent = Geo::GDAL::FFI::_get_parent_ref ($$self);
418 0           Geo::GDAL::FFI::GDALDatasetReleaseResultSet ($$parent, $$self);
419 0           Geo::GDAL::FFI::_deregister_parent_ref ($$self);
420             }
421            
422             1;
423             }
424              
425              
426              
427             =pod
428              
429             =encoding UTF-8
430              
431             =head1 NAME
432              
433             Geo::GDAL::FFI::Dataset - A GDAL dataset
434              
435             =head1 SYNOPSIS
436              
437             =head1 DESCRIPTION
438              
439             A collection of raster bands or vector layers. Obtain a dataset object
440             by opening it with the Open method of Geo::GDAL::FFI object or by
441             creating it with the Create method of a Driver object.
442              
443             =head1 METHODS
444              
445             =head2 GetDriver
446              
447             my $driver = $dataset->GetDriver;
448              
449             =head2 GetWidth
450              
451             my $w = $dataset->GetWidth;
452              
453             =head2 GetHeight
454              
455             my $h = $dataset->GetHeight;
456              
457             =head2 GetSize
458              
459             my @size = $dataset->GetSize;
460              
461             Returns the size (width, height) of the bands of this raster dataset.
462              
463             =head2 GetBand
464              
465             my $band = $dataset->GetBand($i);
466              
467             Get the ith (by default the first) band of a raster dataset.
468              
469             =head2 GetBands
470              
471             my @bands = $dataset->GetBands;
472              
473             Returns a list of Band objects representing the bands of this raster
474             dataset.
475              
476             =head2 CreateLayer
477              
478             my $layer = $dataset->CreateLayer({Name => 'layer', ...});
479              
480             Create a new vector layer into this vector dataset.
481              
482             Named arguments are the following.
483              
484             =over 4
485              
486             =item C
487              
488             Optional, string, default is ''.
489              
490             =item C
491              
492             Optional, default is 'Unknown', the type of the first geometry field;
493             note: if type is 'None', the layer schema does not initially contain
494             any geometry fields.
495              
496             =item C
497              
498             Optional, a SpatialReference object, the spatial reference for the
499             first geometry field.
500              
501             =item C
502              
503             Optional, driver specific options in an anonymous hash.
504              
505             =item C
506              
507             Optional, a reference to an array of Field objects or schemas, the
508             fields to create into the layer.
509              
510             =item C
511              
512             Optional, a reference to an array of GeometryField objects or schemas,
513             the geometry fields to create into the layer; note that if this
514             argument is defined then the arguments GeometryType and
515             SpatialReference are ignored.
516              
517             =back
518              
519             =head2 GetLayerCount
520             my $count = $dataset->GetLayerCount();
521              
522              
523             =head2 GetLayer
524              
525             my $layer = $dataset->GetLayer($name);
526              
527             If $name is strictly an integer, then returns the (name-1)th layer in
528             the dataset, otherwise returns the layer whose name is $name. Without
529             arguments returns the first layer.
530              
531             =head2 CopyLayer
532              
533             my $copy = $dataset->CopyLayer($layer, $name, {DST_SRSWKT => 'WKT of a SRS', ...});
534              
535             Copies the given layer into this dataset using the name $name and
536             returns the new layer. The options hash is mostly driver specific.
537              
538             =head2 ExecuteSQL
539             $dataset->ExecuteSQL ($sql, $filter, $dialect);
540              
541             # build a spatial index
542             $dataset->ExecuteSQL (qq{CREATE SPATIAL INDEX ON "$some_layer_name"});
543            
544             # filter a data set using the SQLite dialect and a second geometry
545             my $filtered = $dataset->ExecuteSQL (
546             qq{SELECT "$fld1", "$fld2" FROM "$some_layer_name"},
547             $some_geometry,
548             'SQLite',
549             );
550            
551             =head2 Info
552              
553             my $info = $dataset->Info($options);
554             my $info = $dataset->Info(['-json', '-stats']);
555              
556             This is the same as gdalinfo utility. $options is a reference to an
557             array. Valid options are as per the L utility.
558              
559             =head2 Translate
560              
561             my $target = $source->Translate($path, $options, $progress, $progress_data);
562              
563             Convert a raster dataset into another raster dataset. This is the same
564             as the L utility. $name is the name of the target
565             dataset. $options is a reference to an array of switches.
566              
567             =head2 Warp
568              
569             my $result = $dataset->Warp($args);
570              
571             $args is a hashref, keys may be Destination, Input, Options, Progress,
572             ProgressData.
573              
574             Valid options are as per the L utility.
575              
576             =head2 VectorTranslate
577              
578             my $result = $dataset->VectorTranslate($args);
579              
580             $args is a hashref, keys may be Destination, Input, Options, Progress,
581             ProgressData.
582              
583             Valid options are as per the L utility.
584              
585             =head2 DEMProcessing
586              
587             my $result = $dataset->DEMProcessing($path, $args);
588              
589             $args is a hashref, keys may be Processing, ColorFilename, Options,
590             Progress, ProgressData.
591              
592             See also L.
593              
594             =head2 NearBlack
595              
596             my $result = $dataset->NearBlack($args);
597              
598             $args is a hashref, keys may be Destination, Options, Progress,
599             ProgressData.
600              
601             Valid options are as per the L utility.
602              
603             =head2 Grid
604              
605             my $result = $dataset->Grid($path, $options, $progress, $progress_data);
606            
607             Valid options are as per the L utility.
608              
609             =head2 Rasterize
610              
611             my $result = $dataset->Rasterize($args);
612             my $result = $dataset->Rasterize({Options => [-b => 1, -at]});
613              
614             $args is a hashref, keys may be Destination, Options, Progress,
615             ProgressData.
616              
617             Valid options are as per the L utility.
618              
619             =head2 BuildVRT
620              
621             my $result = $dataset->BuildVRT($path, $args);
622              
623             $args is a hashref, keys may be Input, Options, Progress,
624             ProgressData.
625              
626             =head1 LICENSE
627              
628             This software is released under the Artistic License. See
629             L.
630              
631             =head1 AUTHOR
632              
633             Ari Jolma - Ari.Jolma at gmail.com
634              
635             =head1 SEE ALSO
636              
637             L
638              
639             L, L, L
640              
641             =cut
642              
643             __END__;