gpt4 book ai didi

rust - 在泛型的特征实现中转换为 f32

转载 作者:行者123 更新时间:2023-11-29 08:30:48 27 4
gpt4 key购买 nike

为了学习 Rust,我尝试实现一个通用图像类/对象。

我对 Image::save(...) 函数和 RgbaGeneric 的 Pixel::gray() 的实现有疑问。

编译器说我必须使用 From 或 Into 特性。但我不知道语法看起来如何。所有让它工作的尝试都失败了。

mod image {
use std::fmt;

use std::path::Path;
use std::io::Write;
use std::fs::File;

#[derive(Clone, Debug)]
pub struct RgbaGeneric<T> {
r: T, g: T, b: T, a: T,
}

trait Pixel<T> {
fn red(&self) -> T;
fn green(&self) -> T;
fn blue(&self) -> T;
fn alpha(&self) -> T;
fn gray(&self) -> T;
}

impl<T> Pixel<T> for RgbaGeneric<T> {
fn red(&self) -> T { return self.r;}
fn green(&self) -> T { return self.g; }
fn blue(&self) -> T { return self.b; }
fn alpha(&self) -> T { return self.a; }
fn gray(&self) -> T {
return (self.r as f32 * 0.21 +
self.g as f32 * 0.72 +
self.b as f32 * 0.07) as T;
}
}

impl<T> RgbaGeneric<T> {
pub fn new(r: T, g: T, b: T, a: T) -> RgbaGeneric<T> {
RgbaGeneric { r, g, b, a }
}
}

pub type RgbaU8 = RgbaGeneric<u8>;

pub struct Image<T> {
width: usize, height: usize, data: Vec<T>,
}

pub type ImageRgbaU8 = Image<RgbaU8>;

impl<T> Image<T>
where
T: Clone + Pixel<T>
{
pub fn new(width: usize, height: usize, val: T) -> Image<T> {
Image {
width,
height,
data: vec![val; width * height],
}
}

pub fn width(&self) -> usize { return self.width; }
pub fn height(&self) -> usize { return self.height; }
pub fn pixel_count(&self) -> usize {
return self.width * self.height;
}

pub fn pixels(&self) -> &[T] { return self.data.as_slice(); }

pub fn pixel(&self, x: usize, y: usize) -> &T {
return &self.data[self.index(x, y)];
}

pub fn set_pixel(&mut self, x: usize, y: usize, pixel: T) {
let idx = self.index(x, y);
self.data[idx] = pixel;
}

pub fn save(&self, filename: &str) -> std::io::Result<()> {
let path = Path::new(filename);
let mut file = try!(File::create(&path));
let header = format!("P6 {} {} 255\n", self.width, self.height);
try!(file.write(header.as_bytes()));
for y in 0..self.height() {
for x in 0..self.width() {
let pix = self.pixel(x,y);
try!(file.write(pix.red()));
try!(file.write(pix.green()));
try!(file.write(pix.blue()));
}
}
return Ok(());
}

fn index(&self, x: usize, y: usize) -> usize {
return y * &self.width + x;
}
}
}

最佳答案

gray 方法的实现应该是这样的:

impl<T> Pixel<T> for RgbaGeneric<T> where
f32: std::convert::From<T>,
T: std::convert::From<f32>{
fn red(&self) -> T { return self.r;}
fn green(&self) -> T { return self.g; }
fn blue(&self) -> T { return self.b; }
fn alpha(&self) -> T { return self.a; }
fn gray(&self) -> T {
return (Into::<f32>::into(self.r) * 0.21 +
Into::<f32>::into(self.g) * 0.72 +
Into::<f32>::into(self.b) * 0.07).into();
}
}

在 block 的头部,我们说我们的T可以与f32类型相互转换,然后我们使用into()方法因为 as 表达式只能用于基本类型之间的转换(编译器暗示 T 可以是任何类型)。

关于rust - 在泛型的特征实现中转换为 f32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58428847/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com