kornelski / imgref

A trivial Rust struct for interchange of pixel buffers with width, height & stride
https://lib.rs/crates/imgref
Apache License 2.0
59 stars 5 forks source link

How can I build image from 3D array #14

Closed hyousefGopher closed 4 years ago

hyousefGopher commented 4 years ago

I've the content of an image extracted in a 3D array, with the dimensions of: (480, 640, 3), which can be built in Rust with one of the below ways, how can I convert this array into image? image

Image raw data:

fn main() {
   // let mut vec: Vec<Vec<Vec<i32>>> = Vec::with_capacity(j * i * k);
   // println!("Vector size = {}, {}, {}", vec.len(), vec[0].len(), vec[0][0].len()); 
    let j = 3;
    let i = 640;
    let k = 480;
    let raw_data = vec![vec![vec![0i32; j]; i]; k];
    println!("{:?}", raw_data);
}

Or as:

use ndarray::prelude::*;
use ndarray::Array;
fn main() {
  let raw_data = Array::<i32, _>::zeros((480, 640, 3).f());
  println!("{:?}", raw_data);
}

I started with below code, but not sure where to go next:

fn rust_print(vec: Vec<Vec<Vec<i32>>>) {
    println!("Vector size = {}, {}, {}", vec.len(), vec[0].len(), vec[0][0].len());    // Vector size = 480, 640, 3
    let imgvec = Img::new(vec![0; vec.len() * vec[0].len()],
                       vec.len(), vec[0].len());
    println!("New size is {}×{}", imgvec.width(), imgvec.height());   // New size is 480×640
    for px in imgvec.pixels() {
    }
}

With content:


[[[151 134 128]
  [148 131 126]
  [149 130 127]
  ...
  [225 193 182]
  [222 192 181]
  [223 193 182]]

 [[152 132 129]
  [149 130 127]
  [151 131 128]
  ...
  [222 192 181]
  [222 192 181]
  [223 193 182]]

 [[152 132 129]
  [152 132 129]
  [150 132 129]
  ...
  [220 192 181]
  [222 192 183]
  [223 193 184]]

 ...

 [[ 88  87  92]
  [ 90  89  93]
  [ 88  87  94]
  ...
  [ 70  66 105]
  [ 69  65 104]
  [ 70  66 105]]

 [[ 88  87  92]
  [ 88  87  92]
  [ 87  86  91]
  ...
  [ 68  65 109]
  [ 69  65 104]
  [ 70  66 105]]

 [[ 87  87  89]
  [ 87  87  89]
  [ 86  85  90]
  ...
  [ 67  65 104]
  [ 69  65 104]
  [ 71  67 106]]]
``
kornelski commented 4 years ago

The 3D case isn't relevant, because even your 2D case is incompatible.

The "jagged array" Vec<Vec<_>> layout is fundamentally incompatible with this crate. It's also pretty inefficient, and imgref exists to avoid it, not to support it.

ImgRef requires all rows to be laid out in memory consecutively with a predictable spacing (stride), in a single Vec. But Vec<Vec<_>> puts rows anywhere in memory, in any order the inner Vecs want.

You must get rid of the innermost Vec by merging all rows into one Vec.

In 2D case change Vec<Vec<i32>> to Vec<i32>. In the 3D case, change Vec<Vec<Vec<i32>>> to Vec<Vec<i32>>.

For 3D images it'll be Vec<ImgVec<i32>>.

hyousefGopher commented 4 years ago

Did not get your point, if the data I've is in the form of:

[
   [  
       [151 134 128]
       [148 131 126]
   ]
   [  
       [149 130 127]
       [151 134 128]
   ]
]

Do I need to make them as:

[
           [151 134 128]
           [148 131 126]
           [149 130 127]
           [151 134 128]
]

Or as:

[151 134 128 148 131 126 149 130 127 151 134 128]
kornelski commented 4 years ago

You must make that one image == one Vec.

You can't have Vec per row. All rows of one image must be concatenated together in one Vec.