Skip to content

Commit

Permalink
chore: prevents write_xy_narray from writing incomplete blocks and ad…
Browse files Browse the repository at this point in the history
…ds more tests
  • Loading branch information
caiubi committed Nov 27, 2024
1 parent 8c6aa87 commit c87e87f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 13 deletions.
4 changes: 2 additions & 2 deletions lib/gdal/extensions/raster_band/extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def to_a
#
# @return [NArray]
def to_na(to_data_type = nil)
narray = NArray.to_na(to_a)
narray = to_nna

return narray unless to_data_type

Expand All @@ -40,7 +40,7 @@ def to_na(to_data_type = nil)
end

def to_nna
Numo::NArray[to_a]
NArray.to_na(to_a)
end

# Each pixel of the raster projected using the dataset's geo_transform.
Expand Down
23 changes: 13 additions & 10 deletions lib/gdal/extensions/raster_band/io_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,32 @@ def readlines
end
end

# Writes a 2-dimensional NArray of (x, y) pixels to the raster band using
# {GDAL::RasterBand#raster_io}. It determines +x_size+ and +y_size+ for
# the {GDAL::RasterBand#raster_io} call using the dimensions of the array.
#
# Writes a 2-dimensional NArray of (x, y) pixels to the raster band block-by-block.
# Expects the input array to have the same shape as the raster band.
# @param pixel_array [NArray] The 2d list of pixels.
def write_xy_narray(pixel_array)
data_pointer = FFI::MemoryPointer.new(:buffer_out, block_buffer_size)
read_start = 0

block_count[:y].times do |y_block_number|
block_count[:x].times do |x_block_number|
# Create a block-sized NArray of zeros. This represents the block of pixels that will be written.
block_pixels = NArray.to_na(Array.new(block_size[:y]) { Array.new(block_size[:x], 0) })

y_block_size = calculate_y_block_size(y_block_number)
x_block_size = calculate_x_block_size(x_block_number)

pixel_count_per_block = x_block_size * y_block_size
read_range = (read_start...(read_start + pixel_count_per_block))
pixels = pixel_array[read_range]
GDAL._write_pointer(data_pointer, data_type, pixels.to_a)
# Map the range of pixels corresponding to the current block.
source_x_range = x_block_number * block_size[:x]...(x_block_number * block_size[:x]) + x_block_size
source_y_range = y_block_number * block_size[:y]...(y_block_number * block_size[:y]) + y_block_size

# Copy the corresponding pixels from the input array to the block pixels.
block_pixels[0...x_block_size, 0...y_block_size] = pixel_array[source_x_range, source_y_range]

GDAL._write_pointer(data_pointer, data_type, block_pixels.to_a.flatten)

write_block(x_block_number, y_block_number, data_pointer)

data_pointer.clear
read_start = read_range.end
end
end
end
Expand Down
26 changes: 25 additions & 1 deletion spec/unit/gdal/extensions/raster_band/io_extensions_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

require "gdal/driver"
require "gdal/extensions/raster_band/io_extensions"
require "gdal/extensions/raster_band/extensions"

RSpec.describe "GDAL::RasterBand::IOExtensions" do
let(:driver) { GDAL::Driver.by_name("MEM") }
Expand Down Expand Up @@ -156,6 +156,30 @@
end

describe "#read_lines_by_block" do
context "block size is larger than the raster" do
let(:rows) { (1..4).map { |i| Array.new(15) { i } } }

let(:dataset_path) do
filename = "/tmp/#{SecureRandom.uuid}.tif"
options = { BLOCKXSIZE: 256, BLOCKYSIZE: 256, TILED: "YES" }
GDAL::Driver.by_name("GTiff").create_dataset(filename, 15, 4, **options) do |dataset|
dataset.raster_band(1).write_xy_narray(NArray.to_na(rows))
end
filename
end

after { FileUtils.rm_f(dataset_path) }

let(:dataset) { GDAL::Dataset.open(dataset_path, "r") }

subject { dataset.raster_band(1) }

it "yields all block rows with correct values" do
expect { |b| subject.read_lines_by_block(&b) }
.to yield_successive_args(*rows)
end
end

context "block is given" do
it "yields each row of pixels" do
expect { |b| subject.read_lines_by_block(&b) }
Expand Down
1 change: 1 addition & 0 deletions spec/unit/gdal/extensions/raster_band_classifier_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require "gdal/driver"
require "gdal/extensions/raster_band_classifier"
require "gdal/extensions/raster_band/extensions"

RSpec.describe GDAL::RasterBandClassifier do
let(:driver) { GDAL::Driver.by_name("MEM") }
Expand Down

0 comments on commit c87e87f

Please sign in to comment.