@@ -325,6 +325,23 @@ impl<P, S: ImageSizeLike> Image<P, S> {
325325 ) ;
326326 row * self . width ( ) + col
327327 }
328+
329+ /// Builds an image from its components
330+ ///
331+ /// Returns an error if `data` does not match the number of pixels in `size`
332+ pub fn build ( data : Vec < P > , size : S ) -> Result < Self , BadPixelCount > {
333+ let expected = u64:: from ( size. width ( ) ) * u64:: from ( size. height ( ) ) ;
334+ let actual = data. len ( ) ;
335+ if expected != actual as u64 {
336+ return Err ( BadPixelCount {
337+ expected,
338+ actual,
339+ width : size. width ( ) ,
340+ height : size. height ( ) ,
341+ } ) ;
342+ }
343+ Ok ( Self { data, size } )
344+ }
328345}
329346
330347impl < P , S > Image < P , S > {
@@ -458,3 +475,47 @@ impl<P: Default + Copy + Clone> Image<P, VoxelSize> {
458475
459476/// Three-channel color image
460477pub type ColorImage = Image < [ u8 ; 3 ] > ;
478+
479+ /// Error type for image builder
480+ #[ derive( thiserror:: Error , Debug , PartialEq ) ]
481+ #[ error(
482+ "bad pixel count: expected {expected} ({width} × {height}), got {actual}"
483+ ) ]
484+ pub struct BadPixelCount {
485+ /// Expected pixel count from size
486+ pub expected : u64 ,
487+ /// Actual pixel count in data
488+ pub actual : usize ,
489+ /// Expected width
490+ pub width : u32 ,
491+ /// Expected height
492+ pub height : u32 ,
493+ }
494+
495+ #[ cfg( test) ]
496+ mod test {
497+ use super :: * ;
498+
499+ #[ test]
500+ fn image_construction ( ) {
501+ let i = Image :: build ( vec ! [ 1 , 2 , 3 , 4 , 5 , 6 ] , ImageSize :: new ( 2 , 3 ) ) ;
502+ assert ! ( i. is_ok( ) ) ;
503+
504+ let i = Image :: build ( vec ! [ 1 , 2 , 3 , 4 , 5 , 6 ] , ImageSize :: new ( 3 , 2 ) ) ;
505+ assert ! ( i. is_ok( ) ) ;
506+
507+ let i = Image :: build ( vec ! [ 1 , 2 , 3 , 4 , 5 ] , ImageSize :: new ( 2 , 3 ) ) ;
508+ let Err ( e) = i else {
509+ panic ! ( "expected error, got valid image" ) ;
510+ } ;
511+ assert_eq ! (
512+ e,
513+ BadPixelCount {
514+ expected: 6 ,
515+ actual: 5 ,
516+ width: 2 ,
517+ height: 3 ,
518+ }
519+ ) ;
520+ }
521+ }
0 commit comments