diff --git a/fitsio/src/hdu.rs b/fitsio/src/hdu.rs index 5c6b1e62..b3db371c 100644 --- a/fitsio/src/hdu.rs +++ b/fitsio/src/hdu.rs @@ -4,7 +4,7 @@ use crate::errors::{check_status, Result}; use crate::fitsfile::CaseSensitivity; use crate::fitsfile::FitsFile; use crate::headers::{ReadsKey, WritesKey}; -use crate::images::{ImageType, ReadImage, WriteImage}; +use crate::images::{ImageType, ReadImage, ReadImageInto, WriteImage}; use crate::longnam::*; use crate::tables::{ ColumnIterator, ConcreteColumnDescription, DescribesColumnLocation, FitsRow, ReadsCol, @@ -124,6 +124,17 @@ impl FitsHdu { T::read_section(fits_file, self, start..end) } + /// Read a section of an image into a pre-existing buffer + pub fn read_section_into( + &self, + fits_file: &mut FitsFile, + start: usize, + buf: &mut [T], + ) -> Result<()> { + fits_file.make_current(self)?; + T::read_section_into(fits_file, self, start, buf) + } + /** # Example diff --git a/fitsio/src/images.rs b/fitsio/src/images.rs index b57b0254..d54092bf 100644 --- a/fitsio/src/images.rs +++ b/fitsio/src/images.rs @@ -46,6 +46,17 @@ pub trait ReadImage: Sized { } } +/// Reading image data into buffers +pub trait ReadImageInto: Sized { + #[doc(hidden)] + fn read_section_into( + fits_file: &mut FitsFile, + hdu: &FitsHdu, + start: usize, + buf: &mut [Self], + ) -> Result<()>; +} + /// Reading fits images pub trait WriteImage: Sized { #[doc(hidden)] @@ -287,6 +298,43 @@ macro_rules! write_image_impl { }; } +macro_rules! read_image_into_impl { + ($t:ty, $data_type:expr) => { + impl ReadImageInto for $t { + fn read_section_into( + fits_file: &mut FitsFile, + hdu: &FitsHdu, + start: usize, + buf: &mut [Self], + ) -> Result<()> { + match hdu.info { + HduInfo::ImageInfo { .. } => { + let nelements = buf.len(); + let mut status = 0; + unsafe { + fits_read_img( + fits_file.fptr.as_mut() as *mut _, + $data_type.into(), + (start + 1) as _, + nelements as i64, + ptr::null_mut(), + buf.as_mut_ptr() as *mut _, + ptr::null_mut(), + &mut status, + ); + } + check_status(status).map(|_| ()) + } + HduInfo::TableInfo { .. } => { + Err("cannot read image data from a table hdu".into()) + } + HduInfo::AnyInfo => unreachable!(), + } + } + } + }; +} + read_image_impl_vec!(i8, i8::default(), DataType::TSBYTE); read_image_impl_vec!(i16, i16::default(), DataType::TSHORT); read_image_impl_vec!(i32, i32::default(), DataType::TINT); @@ -321,6 +369,8 @@ write_image_impl!(u64, u64::default(), DataType::TLONGLONG); write_image_impl!(f32, f32::default(), DataType::TFLOAT); write_image_impl!(f64, f64::default(), DataType::TDOUBLE); +read_image_into_impl!(u32, DataType::TUINT); + /// Description of a new image #[derive(Clone)] pub struct ImageDescription<'a> { diff --git a/fitsio/tests/test_images.rs b/fitsio/tests/test_images.rs new file mode 100644 index 00000000..85180e84 --- /dev/null +++ b/fitsio/tests/test_images.rs @@ -0,0 +1,13 @@ +use fitsio::FitsFile; + +#[test] +fn test_read_into_buffer() { + let filename = "../testdata/full_example.fits"; + let mut f = FitsFile::open(filename).unwrap(); + let phdu = f.primary_hdu().unwrap(); + + let mut buf = vec![0u32; 10]; + phdu.read_section_into(&mut f, 0, &mut buf).unwrap(); + + assert_eq!(buf, vec![108, 176, 166, 177, 104, 110, 100, 193, 150, 197]); +} diff --git a/flake.nix b/flake.nix index f6125869..05254dda 100644 --- a/flake.nix +++ b/flake.nix @@ -12,8 +12,34 @@ outputs = { nixpkgs, flake-utils, rust-overlay, ... }: flake-utils.lib.eachDefaultSystem (system: let + python-overlay = self: super: { + python310 = super.python310.override { + packageOverrides = pyself: pysuper: { + fitsio = pysuper.buildPythonPackage rec { + pname = "fitsio"; + version = "1.1.8"; + src = pysuper.fetchPypi { + inherit pname version; + hash = "sha256-YfVpsmgqDK3OUsllPwybgflR0ABSLO9kXOHLSfeDAPk="; + }; + propagatedBuildInputs = [ + pyself.setuptools + pyself.ipython + ]; + buildInputs = [ + pyself.numpy + self.pkg-config + self.bzip2 + ]; + MAKEFLAGS = "-j"; + }; + }; + }; + }; + overlays = [ rust-overlay.overlays.default + python-overlay ]; pkgs = import nixpkgs { inherit overlays system; @@ -32,7 +58,11 @@ pkgs.cargo-release pkgs.rust-analyzer # for bin/test - pkgs.python3 + (pkgs.python310.withPackages + (ps: with ps; [ + numpy + fitsio + ])) ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.cargo-tarpaulin ];