Skip to content

Commit

Permalink
Merge pull request #24 from jdroenner/rasterband
Browse files Browse the repository at this point in the history
Add RasterBand
  • Loading branch information
jdroenner authored Jun 30, 2016
2 parents 0f9e954 + a4037b5 commit e045a6d
Show file tree
Hide file tree
Showing 12 changed files with 297 additions and 125 deletions.
6 changes: 3 additions & 3 deletions examples/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ fn main() {
use gdal::metadata::Metadata;

let driver = gdal::raster::driver::Driver::get("mem").unwrap();
println!("driver description: {:?}", driver.get_description());
println!("driver description: {:?}", driver.description());

let path = Path::new("./fixtures/tinymarble.png");
let dataset = Dataset::open(path).unwrap();
println!("dataset description: {:?}", dataset.get_description());
println!("dataset description: {:?}", dataset.description());

let key = "INTERLEAVE";
let domain = "IMAGE_STRUCTURE";
let meta = dataset.get_metadata_item(key, domain);
let meta = dataset.metadata_item(key, domain);
println!("domain: {:?} key: {:?} -> value: {:?}", domain, key, meta);

}
25 changes: 25 additions & 0 deletions examples/rasterband.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
extern crate gdal;

use std::path::Path;
use gdal::raster::{Dataset, RasterBand};
use gdal::metadata::Metadata;

fn main() {

let path = Path::new("./fixtures/tinymarble.png");
let dataset = Dataset::open(path).unwrap();
println!("dataset description: {:?}", dataset.description());

let rasterband: RasterBand = dataset.rasterband(1).unwrap();
println!("rasterband description: {:?}", rasterband.description());
println!("rasterband no_data_value: {:?}", rasterband.no_data_value());
println!("rasterband type: {:?}", rasterband.band_type());
println!("rasterband scale: {:?}", rasterband.scale());
println!("rasterband offset: {:?}", rasterband.offset());
let rv = rasterband.read_as::<u8>(
(20, 30),
(2, 3),
(2, 3)
);
println!("{:?}", rv.data);
}
2 changes: 1 addition & 1 deletion src/gdal_major_object.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use libc::{c_void};

pub trait MajorObject {
unsafe fn get_gdal_object_ptr(&self) -> *const c_void;
unsafe fn gdal_object_ptr(&self) -> *const c_void;
}
10 changes: 5 additions & 5 deletions src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ extern {

pub trait Metadata: MajorObject {

fn get_description(&self) -> Option<String>{
let c_res = unsafe { GDALGetDescription(self.get_gdal_object_ptr())};
fn description(&self) -> Option<String>{
let c_res = unsafe { GDALGetDescription(self.gdal_object_ptr())};
if c_res.is_null() {
None
} else {
Some(_string(c_res))
}
}

fn get_metadata_item(&self, key: &str, domain: &str) -> Option<String> {
fn metadata_item(&self, key: &str, domain: &str) -> Option<String> {
if let Ok(c_key) = CString::new(key.to_owned()) {
if let Ok(c_domain) = CString::new(domain.to_owned()){
let c_res = unsafe { GDALGetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_domain.as_ptr())};
let c_res = unsafe { GDALGetMetadataItem(self.gdal_object_ptr(), c_key.as_ptr(), c_domain.as_ptr())};
if !c_res.is_null() {
return Some(_string(c_res));
}
Expand All @@ -37,7 +37,7 @@ pub trait Metadata: MajorObject {
if let Ok(c_key) = CString::new(key.to_owned()){
if let Ok(c_domain) = CString::new(domain.to_owned()){
if let Ok(c_value) = CString::new(value.to_owned()){
let c_res = unsafe { GDALSetMetadataItem(self.get_gdal_object_ptr(), c_key.as_ptr(), c_value.as_ptr(), c_domain.as_ptr())};
let c_res = unsafe { GDALSetMetadataItem(self.gdal_object_ptr(), c_key.as_ptr(), c_value.as_ptr(), c_domain.as_ptr())};
if c_res == 0 {
return Ok(());
}
Expand Down
124 changes: 34 additions & 90 deletions src/raster/dataset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use libc::{c_int, c_double, c_void};
use std::ffi::CString;
use std::path::Path;
use utils::_string;
use raster::{gdal, Driver};
use raster::{gdal, Driver, RasterBand};
use raster::driver::_register_drivers;
use raster::gdal_enums::{GDALRWFlag, GDALAccess, GDALDataType};
use raster::gdal_enums::{GDALAccess, GDALDataType};
use raster::types::GdalType;
use gdal_major_object::MajorObject;
use metadata::Metadata;
Expand All @@ -16,14 +16,13 @@ pub struct Dataset {
}

impl MajorObject for Dataset {
unsafe fn get_gdal_object_ptr(&self) -> *const c_void {
unsafe fn gdal_object_ptr(&self) -> *const c_void {
self.c_dataset
}
}

impl Metadata for Dataset {}



impl Drop for Dataset {
fn drop(&mut self) {
unsafe { gdal::GDALClose(self.c_dataset); }
Expand All @@ -49,11 +48,22 @@ impl Dataset {

pub unsafe fn _c_ptr(&self) -> *const c_void {
return self.c_dataset;
}

pub fn size(&self) -> (isize, isize) {
let size_x = unsafe { gdal::GDALGetRasterXSize(self.c_dataset) } as isize;
let size_y = unsafe { gdal::GDALGetRasterYSize(self.c_dataset) } as isize;
}


pub fn rasterband<'a>(&'a self, band_index: isize) -> Option<RasterBand<'a>> {
unsafe {
let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
if c_band.is_null() {
return None;
}
Some(RasterBand::_with_c_ptr(c_band, self))
}
}

pub fn size(&self) -> (usize, usize) {
let size_x = unsafe { gdal::GDALGetRasterXSize(self.c_dataset) } as usize;
let size_y = unsafe { gdal::GDALGetRasterYSize(self.c_dataset) } as usize;
return (size_x, size_y);
}

Expand Down Expand Up @@ -122,7 +132,11 @@ impl Dataset {
true => None,
false => Some(Dataset{c_dataset: c_dataset}),
};
}
}

pub fn band_type(&self, band_index: isize) -> Option<GDALDataType> {
self.rasterband(band_index).map(|band| band.band_type())
}

/// Read a 'Buffer<u8>' from a 'Dataset'.
/// # Arguments
Expand All @@ -135,7 +149,7 @@ impl Dataset {
window: (isize, isize),
window_size: (usize, usize),
size: (usize, usize)
) -> ByteBuffer
) -> Option<ByteBuffer>
{
self.read_raster_as::<u8>(
band_index,
Expand All @@ -151,23 +165,10 @@ impl Dataset {
pub fn read_full_raster_as<T: Copy + GdalType>(
&self,
band_index: isize,
) -> Buffer<T>
) -> Option<Buffer<T>>
{
let size_x;
let size_y;

unsafe{
size_x = gdal::GDALGetRasterXSize(self.c_dataset) as usize;
size_y = gdal::GDALGetRasterYSize(self.c_dataset) as usize;
}

self.read_raster_as::<T>(
band_index,
(0, 0),
(size_x, size_y),
(size_y, size_y)
)
}
self.rasterband(band_index).map(|band| band.read_band_as())
}

/// Read a 'Buffer<T>' from a 'Dataset'. T implements 'GdalType'
/// # Arguments
Expand All @@ -181,34 +182,9 @@ impl Dataset {
window: (isize, isize),
window_size: (usize, usize),
size: (usize, usize),
) -> Buffer<T>
) -> Option<Buffer<T>>
{
let pixels = (size.0 * size.1) as usize;
let mut data: Vec<T> = Vec::with_capacity(pixels);
//let no_data:
unsafe {
let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
let rv = gdal::GDALRasterIO(
c_band,
GDALRWFlag::GF_Read,
window.0 as c_int,
window.1 as c_int,
window_size.0 as c_int,
window_size.1 as c_int,
data.as_mut_ptr() as *const c_void,
size.0 as c_int,
size.1 as c_int,
T::gdal_type(),
0,
0
) as isize;
assert!(rv == 0);
data.set_len(pixels);
};
Buffer{
size: size,
data: data,
}
self.rasterband(band_index).map(|band| band.read_as(window, window_size, size))
}

/// Write a 'Buffer<T>' into a 'Dataset'.
Expand All @@ -223,41 +199,9 @@ impl Dataset {
window_size: (usize, usize),
buffer: Buffer<T>
) {
assert_eq!(buffer.data.len(), buffer.size.0 * buffer.size.1);
unsafe {
let c_band = gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int);
let rv = gdal::GDALRasterIO(
c_band,
GDALRWFlag::GF_Write,
window.0 as c_int,
window.1 as c_int,
window_size.0 as c_int,
window_size.1 as c_int,
buffer.data.as_ptr() as *const c_void,
buffer.size.0 as c_int,
buffer.size.1 as c_int,
T::gdal_type(),
0,
0
) as isize;
assert!(rv == 0);
};
}


pub fn get_band_type(&self, band_index: isize) -> Option<GDALDataType> {

let band_count = self.count();
if band_index < 1 || band_count < band_index {
return None
}

let gdal_type: c_int;
unsafe{
gdal_type = gdal::GDALGetRasterDataType(gdal::GDALGetRasterBand(self.c_dataset, band_index as c_int));
}
Some(GDALDataType::from_c_int(gdal_type))
self.rasterband(band_index).expect("Invalid RasterBand").write(window, window_size, buffer)
}

}

pub struct Buffer<T: GdalType> {
Expand All @@ -271,4 +215,4 @@ impl<T: GdalType> Buffer<T> {
}
}

pub type ByteBuffer = Buffer<u8>;
pub type ByteBuffer = Buffer<u8>;
2 changes: 1 addition & 1 deletion src/raster/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl Driver {
}

impl MajorObject for Driver {
unsafe fn get_gdal_object_ptr(&self) -> *const c_void {
unsafe fn gdal_object_ptr(&self) -> *const c_void {
return self.c_driver;
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/raster/gdal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::gdal_enums::*;

#[link(name="gdal")]
extern {
// driver
pub fn GDALAllRegister();
pub fn GDALGetDriverByName(pszName: *const c_char) -> *const c_void;
pub fn GDALGetDriverShortName(hDriver: *const c_void) -> *const c_char;
Expand All @@ -26,17 +27,22 @@ extern {
pProgressData: *const c_void
) -> *const c_void;
pub fn GDALOpen(pszFilename: *const c_char, eAccess: GDALAccess) -> *const c_void;
// dataset
pub fn GDALClose(hDS: *const c_void);
pub fn GDALGetDatasetDriver(hDataset: *const c_void) -> *const c_void;
pub fn GDALGetRasterXSize(hDataset: *const c_void) -> c_int;
pub fn GDALGetRasterYSize(hDataset: *const c_void) -> c_int;
pub fn GDALGetRasterCount(hDataset: *const c_void) -> c_int;
pub fn GDALGetProjectionRef(hDataset: *const c_void) -> *const c_char;
pub fn GDALSetProjection(hDataset: *const c_void, pszProjection: *const c_char) -> c_int;
pub fn GDALSetGeoTransform(hDataset: *const c_void, padfTransform: *const c_double) -> c_int;
pub fn GDALGetGeoTransform(hDataset: *const c_void, padfTransform: *mut c_double) -> c_int;
pub fn GDALGetRasterBand(hDataset: *const c_void, nBandId: c_int) -> *const c_void;
// band
pub fn GDALGetRasterDataType(hBand: *const c_void) -> c_int;
pub fn GDALGetProjectionRef(hDS: *const c_void) -> *const c_char;
pub fn GDALSetProjection(hDS: *const c_void, pszProjection: *const c_char) -> c_int;
pub fn GDALSetGeoTransform(hDS: *const c_void, padfTransform: *const c_double) -> c_int;
pub fn GDALGetGeoTransform(hDS: *const c_void, padfTransform: *mut c_double) -> c_int;
pub fn GDALGetRasterBand(hDS: *const c_void, nBandId: c_int) -> *const c_void;
pub fn GDALGetRasterNoDataValue(hBand: *const c_void, pbSuccess: *mut c_int) -> c_double;
pub fn GDALGetRasterOffset(hBand: *const c_void, pbSuccess: *mut c_int) -> c_double;
pub fn GDALGetRasterScale(hBand: *const c_void, pbSuccess: *mut c_int) -> c_double;
pub fn GDALRasterIO(
hBand: *const c_void,
eRWFlag: GDALRWFlag,
Expand Down
6 changes: 4 additions & 2 deletions src/raster/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
pub use raster::dataset::{Dataset, Buffer, ByteBuffer};
pub use raster::driver::Driver;
pub use raster::warp::reproject;
pub use raster::warp::reproject;
pub use raster::rasterband::{RasterBand};

mod gdal;
mod types;
mod gdal_enums;
pub mod dataset;
pub mod driver;
pub mod warp;
pub mod warp;
pub mod rasterband;

#[cfg(test)]
mod tests;
Loading

0 comments on commit e045a6d

Please sign in to comment.