ffi-gdal 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +9 -0
  3. data/.devcontainer/devcontainer.json +98 -0
  4. data/.github/CODEOWNERS +1 -0
  5. data/.github/workflows/codacy.yml +3 -3
  6. data/.github/workflows/codeql.yml +4 -4
  7. data/.github/workflows/continuous-integration.yml +30 -19
  8. data/.github/workflows/dependency-review.yml +2 -2
  9. data/.github/workflows/specs-in-docker.yml +12 -6
  10. data/.gitignore +4 -1
  11. data/Changelog.md +40 -5
  12. data/Gemfile +4 -2
  13. data/README.md +35 -0
  14. data/lib/ext/numeric_as_data_type.rb +1 -1
  15. data/lib/ffi/cpl/vsi.rb +10 -0
  16. data/lib/ffi/gdal/gdal.rb +9 -2
  17. data/lib/ffi/gdal/grid_data_metrics_options.rb +27 -5
  18. data/lib/ffi/gdal/grid_inverse_distance_to_a_power_options.rb +30 -10
  19. data/lib/ffi/gdal/grid_moving_average_options.rb +30 -5
  20. data/lib/ffi/gdal/grid_nearest_neighbor_options.rb +24 -4
  21. data/lib/ffi/gdal/internal_helpers/gdal_version.rb +15 -0
  22. data/lib/ffi/gdal/internal_helpers/layout_version.rb +9 -0
  23. data/lib/ffi/gdal/internal_helpers/layout_version_resolver.rb +24 -0
  24. data/lib/ffi/gdal/internal_helpers.rb +11 -0
  25. data/lib/ffi/gdal/utils.rb +984 -0
  26. data/lib/ffi/gdal/version.rb +1 -1
  27. data/lib/ffi/gdal.rb +3 -1
  28. data/lib/ffi/ogr/core.rb +1 -1
  29. data/lib/ffi/ogr/srs_api.rb +17 -0
  30. data/lib/gdal/cpl_error_handler.rb +30 -15
  31. data/lib/gdal/exceptions.rb +35 -16
  32. data/lib/gdal/extensions/color_table/extensions.rb +1 -1
  33. data/lib/gdal/extensions/gridder.rb +4 -0
  34. data/lib/gdal/geo_transform.rb +13 -0
  35. data/lib/gdal/grid_algorithms/algorithm_base.rb +35 -0
  36. data/lib/gdal/grid_algorithms/inverse_distance_to_a_power.rb +3 -7
  37. data/lib/gdal/grid_algorithms/metric_average_distance.rb +5 -4
  38. data/lib/gdal/grid_algorithms/metric_average_distance_pts.rb +5 -4
  39. data/lib/gdal/grid_algorithms/metric_count.rb +5 -4
  40. data/lib/gdal/grid_algorithms/metric_maximum.rb +5 -4
  41. data/lib/gdal/grid_algorithms/metric_minimum.rb +5 -4
  42. data/lib/gdal/grid_algorithms/metric_range.rb +5 -4
  43. data/lib/gdal/grid_algorithms/moving_average.rb +3 -7
  44. data/lib/gdal/grid_algorithms/nearest_neighbor.rb +3 -7
  45. data/lib/gdal/grid_algorithms.rb +2 -0
  46. data/lib/gdal/internal_helpers.rb +8 -5
  47. data/lib/gdal/major_object.rb +6 -0
  48. data/lib/gdal/raster_band.rb +16 -12
  49. data/lib/gdal/utils/dem/options.rb +52 -0
  50. data/lib/gdal/utils/dem.rb +108 -0
  51. data/lib/gdal/utils/grid/options.rb +52 -0
  52. data/lib/gdal/utils/grid.rb +72 -0
  53. data/lib/gdal/utils/helpers/dataset_list.rb +43 -0
  54. data/lib/gdal/utils/helpers/string_list.rb +47 -0
  55. data/lib/gdal/utils/helpers.rb +11 -0
  56. data/lib/gdal/utils/info/options.rb +52 -0
  57. data/lib/gdal/utils/info.rb +40 -0
  58. data/lib/gdal/utils/nearblack/options.rb +52 -0
  59. data/lib/gdal/utils/nearblack.rb +119 -0
  60. data/lib/gdal/utils/rasterize/options.rb +52 -0
  61. data/lib/gdal/utils/rasterize.rb +108 -0
  62. data/lib/gdal/utils/translate/options.rb +52 -0
  63. data/lib/gdal/utils/translate.rb +72 -0
  64. data/lib/gdal/utils/vector_translate/options.rb +52 -0
  65. data/lib/gdal/utils/vector_translate.rb +132 -0
  66. data/lib/gdal/utils/warp/options.rb +52 -0
  67. data/lib/gdal/utils/warp.rb +118 -0
  68. data/lib/gdal/utils.rb +22 -0
  69. data/lib/gdal/warp_options.rb +11 -2
  70. data/lib/gdal.rb +1 -0
  71. data/lib/ogr/extensions/layer/extensions.rb +1 -1
  72. data/lib/ogr/extensions/spatial_reference/extensions.rb +4 -4
  73. data/lib/ogr/geometry.rb +1 -6
  74. data/lib/ogr/layer.rb +1 -1
  75. data/lib/ogr/spatial_reference.rb +27 -2
  76. metadata +32 -5
  77. data/.ruby-version +0 -1
  78. data/lib/gdal/grid_algorithms/data_metrics_base.rb +0 -14
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "dem/options"
4
+
5
+ module GDAL
6
+ module Utils
7
+ # Wrapper for gdaldem using GDALDEMProcessing C API.
8
+ #
9
+ # @see https://gdal.org/programs/gdaldem.html gdaldem utility documentation.
10
+ # @see https://gdal.org/api/gdal_utils.html#_CPPv417GDALDEMProcessingPKc12GDALDatasetHPKcPKcPK24GDALDEMProcessingOptionsPi
11
+ # GDALDEMProcessing C API.
12
+ class DEM
13
+ # Perform the gdaldem (GDALDEMProcessing) operation.
14
+ #
15
+ # @example Create a raster dataset.
16
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
17
+ #
18
+ # dataset = GDAL::Utils::DEM.perform(
19
+ # dst_dataset_path: "destination.tif",
20
+ # src_dataset: src_dataset,
21
+ # processing: "hillshade"
22
+ # )
23
+ #
24
+ # # Do something with the dataset.
25
+ # puts dataset.raster_x_size
26
+ #
27
+ # # You must close the dataset when you are done with it.
28
+ # dataset.close
29
+ # src_dataset.close
30
+ #
31
+ # @example Create a raster dataset for color-relief.
32
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
33
+ #
34
+ # dataset = GDAL::Utils::DEM.perform(
35
+ # dst_dataset_path: "destination.tif",
36
+ # src_dataset: src_dataset,
37
+ # processing: "color-relief",
38
+ # color_filename: "color.txt"
39
+ # )
40
+ #
41
+ # # Do something with the dataset.
42
+ # puts dataset.raster_x_size
43
+ #
44
+ # # You must close the dataset when you are done with it.
45
+ # dataset.close
46
+ # src_dataset.close
47
+ #
48
+ # @example Create a raster dataset with options.
49
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
50
+ # options = GDAL::Utils::DEM::Options.new(options: ["-of", "GTiff", "-co", "TILED=YES"])
51
+ #
52
+ # dataset = GDAL::Utils::DEM.perform(
53
+ # dst_dataset_path: "destination.tif",
54
+ # src_dataset: src_dataset,
55
+ # processing: "hillshade",
56
+ # options: options
57
+ # )
58
+ #
59
+ # # Do something with the dataset.
60
+ # puts dataset.raster_x_size
61
+ #
62
+ # # You must close the dataset when you are done with it.
63
+ # dataset.close
64
+ # src_dataset.close
65
+ #
66
+ # @example Create a raster dataset using block syntax.
67
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
68
+ #
69
+ # GDAL::Utils::DEM.perform(
70
+ # dst_dataset_path: "destination.tif",
71
+ # src_dataset: src_dataset,
72
+ # processing: "hillshade"
73
+ # ) do |dataset|
74
+ # # Do something with the dataset.
75
+ # puts dataset.raster_x_size
76
+ #
77
+ # # Dataset will be closed automatically.
78
+ # end
79
+ # src_dataset.close
80
+ #
81
+ # @param dst_dataset_path [String] The path to the destination dataset.
82
+ # @param src_dataset [OGR::DataSource] The source dataset.
83
+ # @param processing [String] The processing type
84
+ # (one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", "Roughness").
85
+ # @param color_filename [String] color file (mandatory for "color-relief" processing, should be NULL otherwise).
86
+ # @param options [GDAL::Utils::DEM::Options] Options.
87
+ # @yield [GDAL::Dataset] The destination dataset.
88
+ # @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
89
+ # @raise [GDAL::Error] If the operation fails.
90
+ def self.perform(dst_dataset_path:, src_dataset:, processing:, color_filename: nil, options: Options.new, &block)
91
+ result_code_ptr = ::FFI::MemoryPointer.new(:int)
92
+ dst_dataset_ptr = ::FFI::GDAL::Utils.GDALDEMProcessing(
93
+ dst_dataset_path,
94
+ src_dataset.c_pointer,
95
+ processing,
96
+ color_filename,
97
+ options.c_pointer,
98
+ result_code_ptr
99
+ )
100
+ success = result_code_ptr.read_int.zero?
101
+
102
+ raise ::GDAL::Error, "GDALDEMProcessing failed." if dst_dataset_ptr.null? || !success
103
+
104
+ ::GDAL::Dataset.open(dst_dataset_ptr, "w", &block)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ class Grid
6
+ # Ruby wrapper for GDALGridOptions C API (options for gdal_grid utility).
7
+ #
8
+ # @see GDAL::Utils::Grid
9
+ # @see https://gdal.org/programs/gdal_grid.html gdal_grid utility documentation.
10
+ class Options
11
+ # @private
12
+ class AutoPointer < ::FFI::AutoPointer
13
+ # @param pointer [FFI::Pointer]
14
+ def self.release(pointer)
15
+ return unless pointer && !pointer.null?
16
+
17
+ ::FFI::GDAL::Utils.GDALGridOptionsFree(pointer)
18
+ end
19
+ end
20
+
21
+ # @return [AutoPointer] C pointer to the GDALGridOptions.
22
+ attr_reader :c_pointer
23
+
24
+ # @return [Array<String>] The options.
25
+ attr_reader :options
26
+
27
+ # Create a new instance.
28
+ #
29
+ # @see https://gdal.org/programs/gdal_grid.html
30
+ # List of available options could be found in gdal_grid utility documentation.
31
+ #
32
+ # @example Create a new instance.
33
+ # options = GDAL::Utils::Grid::Options.new(options: ["-of", "GTiff", "-outsize", "10", "10"])
34
+ #
35
+ # @param options [Array<String>] The options list.
36
+ def initialize(options: [])
37
+ @options = options
38
+ @string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
39
+ @c_pointer = AutoPointer.new(options_pointer)
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :string_list
45
+
46
+ def options_pointer
47
+ ::FFI::GDAL::Utils.GDALGridOptionsNew(string_list.c_pointer, nil)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "grid/options"
4
+
5
+ module GDAL
6
+ module Utils
7
+ # Wrapper for gdal_grid using GDALGrid C API.
8
+ #
9
+ # @see https://gdal.org/programs/gdal_grid.html gdal_grid utility documentation.
10
+ # @see https://gdal.org/api/gdal_utils.html#_CPPv48GDALGridPKc12GDALDatasetHPK15GDALGridOptionsPi GDALGrid C API.
11
+ class Grid
12
+ # Perform the gdal_grid (GDALGrid) operation.
13
+ #
14
+ # @example Create a raster dataset.
15
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
16
+ # dataset = GDAL::Utils::Grid.perform(dst_dataset_path: "destination.tif", src_dataset: src_dataset)
17
+ #
18
+ # # Do something with the dataset.
19
+ # puts dataset.raster_x_size
20
+ #
21
+ # # You must close the dataset when you are done with it.
22
+ # dataset.close
23
+ # src_dataset.close
24
+ #
25
+ # @example Create a raster dataset with options.
26
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
27
+ # dataset = GDAL::Utils::Grid.perform(
28
+ # dst_dataset_path: "destination.tif",
29
+ # src_dataset: src_dataset,
30
+ # options: GDAL::Utils::Grid::Options.new(options: ["-of", "GTiff", "-co", "COMPRESS=DEFLATE"])
31
+ # )
32
+ #
33
+ # # Do something with the dataset.
34
+ # puts dataset.raster_x_size
35
+ #
36
+ # # You must close the dataset when you are done with it.
37
+ # dataset.close
38
+ # src_dataset.close
39
+ #
40
+ # @example Create a raster dataset using block syntax.
41
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
42
+ # GDAL::Utils::Grid.perform(dst_dataset_path: "destination.tif", src_dataset: src_dataset) do |dataset|
43
+ # # Do something with the dataset.
44
+ # puts dataset.raster_x_size
45
+ #
46
+ # # Dataset will be closed automatically.
47
+ # end
48
+ # src_dataset.close
49
+ #
50
+ # @param dst_dataset_path [String] The path to the destination dataset.
51
+ # @param src_dataset [OGR::DataSource] The source dataset.
52
+ # @param options [GDAL::Utils::Grid::Options] Options.
53
+ # @yield [GDAL::Dataset] The destination dataset.
54
+ # @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
55
+ # @raise [GDAL::Error] If the operation fails.
56
+ def self.perform(dst_dataset_path:, src_dataset:, options: Options.new, &block)
57
+ result_code_ptr = ::FFI::MemoryPointer.new(:int)
58
+ dst_dataset_ptr = ::FFI::GDAL::Utils.GDALGrid(
59
+ dst_dataset_path,
60
+ src_dataset.c_pointer,
61
+ options.c_pointer,
62
+ result_code_ptr
63
+ )
64
+ success = result_code_ptr.read_int.zero?
65
+
66
+ raise ::GDAL::Error, "GDALGrid failed." if dst_dataset_ptr.null? || !success
67
+
68
+ ::GDAL::Dataset.open(dst_dataset_ptr, "w", &block)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ module Helpers
6
+ # A basic wrapper for C Array of dataset handlers (e.g. GDALDatasetH *pahSrcDS).
7
+ #
8
+ # @private
9
+ # @note This class is intended only to be used internally in ffi-gdal. It's API may change.
10
+ # Do not use this class directly.
11
+ class DatasetList
12
+ # @return [FFI::Pointer] C pointer to the Array of dataset handlers (e.g. GDALDatasetH *pahSrcDS).
13
+ attr_reader :c_pointer
14
+
15
+ # @return [Array<GDAL::Dataset>] List of datasets.
16
+ attr_reader :datasets
17
+
18
+ # @param datasets [Array<GDAL::Dataset>] List of datasets.
19
+ def initialize(datasets: [])
20
+ @datasets = datasets
21
+ @c_pointer = datasets_pointer
22
+ end
23
+
24
+ # @return [Integer] The number of datasets in the list.
25
+ def count
26
+ dataset_pointers.count
27
+ end
28
+
29
+ private
30
+
31
+ def dataset_pointers
32
+ @dataset_pointers ||= datasets.map(&:c_pointer)
33
+ end
34
+
35
+ def datasets_pointer
36
+ ::FFI::MemoryPointer
37
+ .new(:pointer, count)
38
+ .write_array_of_pointer(dataset_pointers)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ module Helpers
6
+ # A basic wrapper for CPLStringList (e.g. char **papszArgv).
7
+ #
8
+ # @private
9
+ # @note This class is intended only to be used internally in ffi-gdal. It's API may change.
10
+ # Do not use this class directly.
11
+ class StringList
12
+ class AutoPointer < ::FFI::AutoPointer
13
+ # @param pointer [FFI::Pointer]
14
+ def self.release(pointer)
15
+ return unless pointer && !pointer.null?
16
+
17
+ ::FFI::CPL::String.CSLDestroy(pointer)
18
+ end
19
+ end
20
+
21
+ # @return [FFI::Pointer] C pointer to CPLStringList (e.g. char **papszArgv).
22
+ attr_reader :c_pointer
23
+
24
+ # @return [Array<String>] Strings in the list.
25
+ attr_reader :strings
26
+
27
+ # @param strings [Array<String>] Strings to build the list.
28
+ def initialize(strings: [])
29
+ @strings = strings
30
+ @c_pointer = AutoPointer.new(string_list_pointer)
31
+ end
32
+
33
+ private
34
+
35
+ def string_list_pointer
36
+ pointer = ::FFI::Pointer.new(FFI::Pointer::NULL)
37
+
38
+ strings.each do |string|
39
+ pointer = ::FFI::CPL::String.CSLAddString(pointer, string.to_s)
40
+ end
41
+
42
+ pointer
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ # Internal helpers for GDAL Utils.
6
+ module Helpers
7
+ autoload :DatasetList, File.expand_path("helpers/dataset_list", __dir__)
8
+ autoload :StringList, File.expand_path("helpers/string_list", __dir__)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ class Info
6
+ # Ruby wrapper for GDALInfoOptions C API (options for gdalinfo utility).
7
+ #
8
+ # @see GDAL::Utils::Info
9
+ # @see https://gdal.org/programs/gdalinfo.html gdalinfo utility documentation.
10
+ class Options
11
+ # @private
12
+ class AutoPointer < ::FFI::AutoPointer
13
+ # @param pointer [FFI::Pointer]
14
+ def self.release(pointer)
15
+ return unless pointer && !pointer.null?
16
+
17
+ ::FFI::GDAL::Utils.GDALInfoOptionsFree(pointer)
18
+ end
19
+ end
20
+
21
+ # @return [AutoPointer] C pointer to the GDALInfoOptions.
22
+ attr_reader :c_pointer
23
+
24
+ # @return [Array<String>] The options.
25
+ attr_reader :options
26
+
27
+ # Create a new instance.
28
+ #
29
+ # @see https://gdal.org/programs/gdalinfo.html
30
+ # List of available options could be found in gdalinfo utility documentation.
31
+ #
32
+ # @example Create a new instance.
33
+ # options = GDAL::Utils::Info::Options.new(options: ["-json", "-mdd", "all"])
34
+ #
35
+ # @param options [Array<String>] The options list.
36
+ def initialize(options: [])
37
+ @options = options
38
+ @string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
39
+ @c_pointer = AutoPointer.new(options_pointer)
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :string_list
45
+
46
+ def options_pointer
47
+ ::FFI::GDAL::Utils.GDALInfoOptionsNew(string_list.c_pointer, nil)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "info/options"
4
+
5
+ module GDAL
6
+ module Utils
7
+ # Wrapper for gdalinfo using GDALInfo C API.
8
+ #
9
+ # @see https://gdal.org/programs/gdalinfo.html gdalinfo utility documentation.
10
+ # @see https://gdal.org/api/gdal_utils.html#_CPPv48GDALInfo12GDALDatasetHPK15GDALInfoOptions GDALInfo C API.
11
+ class Info
12
+ # Perform the gdalinfo (GDALInfo) operation.
13
+ #
14
+ # @example Get info for a dataset.
15
+ # dataset = GDAL::Dataset.open("my.tif", "r")
16
+ # info = GDAL::Utils::Info.perform(dataset: dataset)
17
+ # dataset.close
18
+ #
19
+ # @example Get info for a dataset with options.
20
+ # dataset = GDAL::Dataset.open("my.tif", "r")
21
+ # info = GDAL::Utils::Info.perform(
22
+ # dataset: dataset,
23
+ # options: GDAL::Utils::Info::Options.new(options: ["-json", "-mdd", "all"])
24
+ # )
25
+ # dataset.close
26
+ #
27
+ # @param dataset [GDAL::Dataset] The dataset to get info for.
28
+ # @param options [GDAL::Utils::Info::Options] Options.
29
+ # @return [String] The info string.
30
+ def self.perform(dataset:, options: Options.new)
31
+ string, str_pointer = ::FFI::GDAL::Utils.GDALInfo(dataset.c_pointer, options.c_pointer)
32
+
33
+ string
34
+ ensure
35
+ # Returned string pointer must be freed with CPLFree().
36
+ ::FFI::CPL::VSI.VSIFree(str_pointer)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ class Nearblack
6
+ # Ruby wrapper for GDALNearblackOptions C API (options for nearblack utility).
7
+ #
8
+ # @see GDAL::Utils::Nearblack
9
+ # @see https://gdal.org/programs/nearblack.html nearblack utility documentation.
10
+ class Options
11
+ # @private
12
+ class AutoPointer < ::FFI::AutoPointer
13
+ # @param pointer [FFI::Pointer]
14
+ def self.release(pointer)
15
+ return unless pointer && !pointer.null?
16
+
17
+ ::FFI::GDAL::Utils.GDALNearblackOptionsFree(pointer)
18
+ end
19
+ end
20
+
21
+ # @return [AutoPointer] C pointer to the GDALNearblackOptions.
22
+ attr_reader :c_pointer
23
+
24
+ # @return [Array<String>] The options.
25
+ attr_reader :options
26
+
27
+ # Create a new instance.
28
+ #
29
+ # @see https://gdal.org/programs/nearblack.html
30
+ # List of available options could be found in nearblack utility documentation.
31
+ #
32
+ # @example Create a new instance.
33
+ # options = GDAL::Utils::Nearblack::Options.new(options: ["-of", "GTiff", "-near", "10"])
34
+ #
35
+ # @param options [Array<String>] The options list.
36
+ def initialize(options: [])
37
+ @options = options
38
+ @string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
39
+ @c_pointer = AutoPointer.new(options_pointer)
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :string_list
45
+
46
+ def options_pointer
47
+ ::FFI::GDAL::Utils.GDALNearblackOptionsNew(string_list.c_pointer, nil)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "nearblack/options"
4
+
5
+ module GDAL
6
+ module Utils
7
+ # Wrapper for nearblack using GDALNearblack C API.
8
+ #
9
+ # @see https://gdal.org/programs/nearblack.html nearblack utility documentation.
10
+ # @see https://gdal.org/api/gdal_utils.html#_CPPv413GDALNearblackPKc12GDALDatasetH12GDALDatasetHPK20GDALNearblackOptionsPi
11
+ # GDALNearblack C API.
12
+ class Nearblack
13
+ # Perform the nearblack (GDALNearblack) operation.
14
+ #
15
+ # @example Perform nearblack on dataset (for dst_dataset_path).
16
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
17
+ #
18
+ # dataset = GDAL::Utils::Nearblack.perform(dst_dataset_path: "destination.tif", src_dataset: src_dataset)
19
+ #
20
+ # # Do something with the dataset.
21
+ # puts dataset.raster_x_size
22
+ #
23
+ # # You must close the dataset when you are done with it.
24
+ # dataset.close
25
+ # src_dataset.close
26
+ #
27
+ # @example Perform nearblack on dataset with options (for dst_dataset_path).
28
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
29
+ # options = GDAL::Utils::Nearblack::Options.new(options: ["-near", "10"])
30
+ #
31
+ # dataset = GDAL::Utils::Nearblack.perform(
32
+ # dst_dataset_path: "destination.tif",
33
+ # src_dataset: src_dataset,
34
+ # options: options
35
+ # )
36
+ #
37
+ # # Do something with the dataset.
38
+ # puts dataset.raster_x_size
39
+ #
40
+ # # You must close the dataset when you are done with it.
41
+ # dataset.close
42
+ # src_dataset.close
43
+ #
44
+ # @example Perform nearblack on dataset (for dst_dataset_path) using block syntax.
45
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
46
+ # options = GDAL::Utils::Nearblack::Options.new(options: ["-near", "10"])
47
+ #
48
+ # GDAL::Utils::Nearblack.perform(
49
+ # dst_dataset_path: "destination.tif",
50
+ # src_dataset: src_dataset,
51
+ # options: options
52
+ # ) do |dataset|
53
+ # # Do something with the dataset.
54
+ # puts dataset.raster_x_size
55
+ #
56
+ # # Dataset will be closed automatically.
57
+ # end
58
+ # src_dataset.close
59
+ #
60
+ # @example Perform nearblack on dataset (for dst_dataset).
61
+ # src_dataset = GDAL::Dataset.open("source.tif", "r")
62
+ # dst_dataset = GDAL::Dataset.open("destination.tif", "w")
63
+ #
64
+ # GDAL::Utils::Nearblack.perform(dst_dataset: dst_dataset, src_dataset: src_dataset)
65
+ #
66
+ # # You must close the dataset when you are done with it.
67
+ # dst_dataset.close
68
+ # src_dataset.close
69
+ #
70
+ # @param dst_dataset_path [String] The path to the destination dataset.
71
+ # @param dst_dataset [GDAL::Dataset] The destination dataset.
72
+ # @param src_dataset [GDAL::Dataset] The source dataset.
73
+ # @param options [GDAL::Utils::Nearblack::Options] Options.
74
+ # @yield [GDAL::Dataset] The destination dataset.
75
+ # @return [GDAL::Dataset] The destination dataset (only if block is not specified; dataset must be closed).
76
+ def self.perform(src_dataset:, dst_dataset: nil, dst_dataset_path: nil, options: Options.new, &block)
77
+ if dst_dataset
78
+ for_dataset(dst_dataset: dst_dataset, src_dataset: src_dataset, options: options)
79
+ else
80
+ for_dataset_path(dst_dataset_path: dst_dataset_path, src_dataset: src_dataset, options: options, &block)
81
+ end
82
+ end
83
+
84
+ def self.for_dataset(dst_dataset:, src_dataset:, options: Options.new)
85
+ result_dataset_ptr(dst_dataset: dst_dataset, src_dataset: src_dataset, options: options)
86
+
87
+ # Return the input dataset as the output dataset (dataset is modified in place).
88
+ dst_dataset
89
+ end
90
+ private_class_method :for_dataset
91
+
92
+ def self.for_dataset_path(dst_dataset_path:, src_dataset:, options: Options.new, &block)
93
+ dst_dataset_ptr = result_dataset_ptr(
94
+ dst_dataset_path: dst_dataset_path, src_dataset: src_dataset, options: options
95
+ )
96
+
97
+ ::GDAL::Dataset.open(dst_dataset_ptr, "w", &block)
98
+ end
99
+ private_class_method :for_dataset_path
100
+
101
+ def self.result_dataset_ptr(src_dataset:, dst_dataset_path: nil, dst_dataset: nil, options: Options.new)
102
+ result_code_ptr = ::FFI::MemoryPointer.new(:int)
103
+ dst_dataset_ptr = ::FFI::GDAL::Utils.GDALNearblack(
104
+ dst_dataset_path,
105
+ dst_dataset&.c_pointer,
106
+ src_dataset.c_pointer,
107
+ options.c_pointer,
108
+ result_code_ptr
109
+ )
110
+ success = result_code_ptr.read_int.zero?
111
+
112
+ raise ::GDAL::Error, "GDALNearblack failed." if dst_dataset_ptr.null? || !success
113
+
114
+ dst_dataset_ptr
115
+ end
116
+ private_class_method :result_dataset_ptr
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GDAL
4
+ module Utils
5
+ class Rasterize
6
+ # Ruby wrapper for GDALRasterizeOptions C API (options for gdal_rasterize utility).
7
+ #
8
+ # @see GDAL::Utils::Rasterize
9
+ # @see https://gdal.org/programs/gdal_rasterize.html gdal_rasterize utility documentation.
10
+ class Options
11
+ # @private
12
+ class AutoPointer < ::FFI::AutoPointer
13
+ # @param pointer [FFI::Pointer]
14
+ def self.release(pointer)
15
+ return unless pointer && !pointer.null?
16
+
17
+ ::FFI::GDAL::Utils.GDALRasterizeOptionsFree(pointer)
18
+ end
19
+ end
20
+
21
+ # @return [AutoPointer] C pointer to the GDALRasterizeOptions.
22
+ attr_reader :c_pointer
23
+
24
+ # @return [Array<String>] The options.
25
+ attr_reader :options
26
+
27
+ # Create a new instance.
28
+ #
29
+ # @see https://gdal.org/programs/gdal_rasterize.html
30
+ # List of available options could be found in gdal_rasterize utility documentation.
31
+ #
32
+ # @example Create a new instance.
33
+ # options = GDAL::Utils::Rasterize::Options.new(options: ["-of", "GTiff", "-ts", "10", "10"])
34
+ #
35
+ # @param options [Array<String>] The options list.
36
+ def initialize(options: [])
37
+ @options = options
38
+ @string_list = ::GDAL::Utils::Helpers::StringList.new(strings: options)
39
+ @c_pointer = AutoPointer.new(options_pointer)
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :string_list
45
+
46
+ def options_pointer
47
+ ::FFI::GDAL::Utils.GDALRasterizeOptionsNew(string_list.c_pointer, nil)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end