Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read pixel values from image in Rust

I am using the piston Rust image library (version 0.10.3) like so:

extern crate image;

use std::f32;
use std::fs::File;
use std::path::Path;


use image::GenericImage;
use image::Pixels;
use image::Pixel;

fn init(input_path: &str) {
    let mut img = image::open(&Path::new(input_path)).unwrap();

    let img_width = img.dimensions().0;
    let img_height = img.dimensions().1;

    for p in img.pixels() { println!("pixel: {}", p.2.channel_count()); }
}

fn main() {
    init("file.png");
}

This example fails with an error message

error: no method named `channel_count` found for type `image::Rgba<u8>` in the current scope
  --> src/main.rs:20:55
   |
20 |     for p in img.pixels() { println!("pixel: {}", p.2.channel_count()); }
   |                                                       ^^^^^^^^^^^^^
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:20:29: 20:72 note: in this expansion of println! (defined in <std macros>)
   |
   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: candidate #1 is defined in the trait `image::Pixel`
  --> src/main.rs:20:55
   |
20 |     for p in img.pixels() { println!("pixel: {}", p.2.channel_count()); }
   |                                                       ^^^^^^^^^^^^^
<std macros>:2:27: 2:58 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:20:29: 20:72 note: in this expansion of println! (defined in <std macros>)

Which i understand is true, because the documentation mentions that the method I want to have is part of the Pixel trait - the documentation doesn't really make it clear how to access a single pixel in a buffer loaded from an existing image, it mostly talks about getting pixels from ImageBuffer.

How can I iterate over all pixels in an image and get rgb/other values from it?

EDIT: After reading the source code, I worked around this by calling Pixel::channels(&self) which takes &self, therefore I figured out this must be a method added via the trait to objects that implement Pixel.

So the signature of channel_count() has neither parameters nor &self. How am I supposed to call this method?

like image 541
Max Avatar asked Oct 17 '22 22:10

Max


1 Answers

The function you're trying to call, channel_count(), is a static method. It is defined for a type, not for an object of that type. You call it with

Rgba::channel_count()

or

<Rgba<u8> as Pixel>::channel_count()

as the first form will likely fail (in this instance) due to lack of type information.

However, I don't think it will give you what you want. It should just return the number 4 as that is the number of channels that Rgba has.

To get what you want, the RGB values, take a look at the documentation for the type you have, Rgba.

It has a public member, data, which is a 4-element array, and it implements Index.

If pixel is of type Rgba<u8> (corresponding to your p.2), you can get the values you seek either by calling pixel.data which will give them to you as an array, or by indexing. For example, pixel[0] will give you the red value.

like image 157
paholg Avatar answered Oct 21 '22 00:10

paholg