New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

16 bits image wrongly decoded as 8 bits #78

Open
mpizenberg opened this Issue Jun 19, 2018 · 3 comments

Comments

Projects
None yet
1 participant
@mpizenberg

mpizenberg commented Jun 19, 2018

I'm trying to open a 16 bits grayscale png image as displayed by the file command here:

$ file icl-depth/0.png
icl-depth/0.png: PNG image data, 640 x 480, 16-bit grayscale, non-interlaced

The Rust code I'm using is:

fn main() {
    // Load 16 bits PNG depth image.
    let img_file = File::open("icl-depth/0.png").unwrap();
    let decoder = png::Decoder::new(img_file);
    let (info, mut reader) = decoder.read_info().unwrap();
    let mut buffer = vec![0; info.buffer_size()];
    reader.next_frame(&mut buffer).unwrap();

    // Display info.
    println!("width: {:?}", info.width);
    println!("height: {:?}", info.height);
    println!("bit depth: {:?}", info.bit_depth);
    println!("buffer size: {:?}", info.buffer_size());
}

Returns an 8 bits decoder instead of 16 bits decoder:

width: 640
height: 480
bit depth: Eight
buffer size: 307200

How can I use the png crate to read 16 bits grayscale images?

@mpizenberg

This comment has been minimized.

Show comment
Hide comment
@mpizenberg

mpizenberg Jun 19, 2018

The corresponding image in case useful:

0.png

mpizenberg commented Jun 19, 2018

The corresponding image in case useful:

0.png

@mpizenberg

This comment has been minimized.

Show comment
Hide comment
@mpizenberg

mpizenberg Jun 19, 2018

Woohoo, ok I managed to do it thanks to a hint of changing transformation from this issue of on the image crate: PistonDevelopers/image#560.

It was a bit outdated since TRANSFORM_IDENTITY is now Transformations::IDENTITY. It was also half of the solution if you need an [u16] since next_frame() still returns an [u8] anyway. To convert this [u8] of the double length into an [u16], I used the byteorder crate. Full example code below (I'm ultimately putting the values into a matix from nalgebra):

extern crate byteorder;
extern crate nalgebra as na;
extern crate png;

use byteorder::{BigEndian, ReadBytesExt};
use na::DMatrix;
use png::HasParameters;
use std::fs::File;
use std::io::Cursor;

// #[allow(dead_code)]
fn main() {
    // Load 16 bits PNG depth image.
    let img_file = File::open("icl-depth/0.png").unwrap();
    let mut decoder = png::Decoder::new(img_file);
    // Use the IDENTITY transformation because by default
    // it will use STRIP_16 which only keep 8 bits.
    decoder.set(png::Transformations::IDENTITY);
    let (info, mut reader) = decoder.read_info().unwrap();
    let mut buffer = vec![0; info.buffer_size()];
    reader.next_frame(&mut buffer).unwrap();

    // Display image metadata.
    println!("info: {:?}", info.width);
    println!("height: {:?}", info.height);
    println!("bit depth: {:?}", info.bit_depth);
    println!("buffer size: {:?}", info.buffer_size());

    // Transform buffer into 16 bits slice.
    let mut buffer_u16 = vec![0; (info.width * info.height) as usize];
    let mut buffer_cursor = Cursor::new(buffer);
    buffer_cursor
        .read_u16_into::<BigEndian>(&mut buffer_u16)
        .unwrap();

    // Transform it into a matrix.
    let img_mat: DMatrix<u16> = DMatrix::from_row_slice(
        info.height as usize,
        info.width as usize,
        buffer_u16.as_slice(),
    );
    let img_slice = img_mat.slice((0, 0), (3, 3));
    println!("Top left: {}", img_slice);
}

mpizenberg commented Jun 19, 2018

Woohoo, ok I managed to do it thanks to a hint of changing transformation from this issue of on the image crate: PistonDevelopers/image#560.

It was a bit outdated since TRANSFORM_IDENTITY is now Transformations::IDENTITY. It was also half of the solution if you need an [u16] since next_frame() still returns an [u8] anyway. To convert this [u8] of the double length into an [u16], I used the byteorder crate. Full example code below (I'm ultimately putting the values into a matix from nalgebra):

extern crate byteorder;
extern crate nalgebra as na;
extern crate png;

use byteorder::{BigEndian, ReadBytesExt};
use na::DMatrix;
use png::HasParameters;
use std::fs::File;
use std::io::Cursor;

// #[allow(dead_code)]
fn main() {
    // Load 16 bits PNG depth image.
    let img_file = File::open("icl-depth/0.png").unwrap();
    let mut decoder = png::Decoder::new(img_file);
    // Use the IDENTITY transformation because by default
    // it will use STRIP_16 which only keep 8 bits.
    decoder.set(png::Transformations::IDENTITY);
    let (info, mut reader) = decoder.read_info().unwrap();
    let mut buffer = vec![0; info.buffer_size()];
    reader.next_frame(&mut buffer).unwrap();

    // Display image metadata.
    println!("info: {:?}", info.width);
    println!("height: {:?}", info.height);
    println!("bit depth: {:?}", info.bit_depth);
    println!("buffer size: {:?}", info.buffer_size());

    // Transform buffer into 16 bits slice.
    let mut buffer_u16 = vec![0; (info.width * info.height) as usize];
    let mut buffer_cursor = Cursor::new(buffer);
    buffer_cursor
        .read_u16_into::<BigEndian>(&mut buffer_u16)
        .unwrap();

    // Transform it into a matrix.
    let img_mat: DMatrix<u16> = DMatrix::from_row_slice(
        info.height as usize,
        info.width as usize,
        buffer_u16.as_slice(),
    );
    let img_slice = img_mat.slice((0, 0), (3, 3));
    println!("Top left: {}", img_slice);
}
@mpizenberg

This comment has been minimized.

Show comment
Hide comment
@mpizenberg

mpizenberg Jun 19, 2018

It could be very useful to add some info on the home documentation page for 16 bits decoding. Thanks anyway for this crate! it's already awesome that it's available :)

mpizenberg commented Jun 19, 2018

It could be very useful to add some info on the home documentation page for 16 bits decoding. Thanks anyway for this crate! it's already awesome that it's available :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment