녹이에 JPEG 디코더/인코더를 쓰고 있는데 RGB ↔ YCbCr 변환에 문제가 있습니다.SIMD 벡터를 사용하는 RGB에서 YCbCr로 일부 데이터가 손실됩니다.
내 코드 : (주석) 어떤 이유로 부스 테스트를위한
use std::simd::f32x4;
fn clamp<T>(val: T, min: T, max: T) -> T
where T: PartialOrd {
if val < min { min }
else if max < val { max }
else { val }
}
// in oryginal code there are 2 methods, one for processors with SSE3 and for rest
// both do the same and give the same results
pub fn sum_f32x4(f32x4(a, b, c, d): f32x4) -> f32 {
a + b + c + d
}
pub fn rgb_to_ycbcr(r: u8, g: u8, b: u8) -> (u8, u8, u8) {
let rgb = f32x4(r as f32, g as f32, b as f32, 1.0);
let y = sum_f32x4(rgb * f32x4(0.2990, 0.5870, 0.1140, 0.0));
let cb = sum_f32x4(rgb * f32x4(-0.1687, -0.3313, 0.5000, 128.0));
let cr = sum_f32x4(rgb * f32x4(0.5000, -0.4187, -0.0813, 128.0));
(y as u8, cb as u8, cr as u8)
}
pub fn ycbcr_to_rgb(y: u8, cb: u8, cr: u8) -> (u8, u8, u8) {
let ycbcr = f32x4(y as f32, cb as f32 - 128.0f32, cr as f32 - 128.0f32, 0.0);
let r = sum_f32x4(ycbcr * f32x4(1.0, 0.00000, 1.40200, 0.0));
let g = sum_f32x4(ycbcr * f32x4(1.0, -0.34414, -0.71414, 0.0));
let b = sum_f32x4(ycbcr * f32x4(1.0, 1.77200, 0.00000, 0.0));
(clamp(r, 0., 255.) as u8, clamp(g, 0., 255.) as u8, clamp(b, 0., 255.) as u8)
}
fn main() {
assert_eq!(rgb_to_ycbcr( 0, 71, 171), (61, 189, 84));
// assert_eq!(rgb_to_ycbcr( 0, 71, 169), (61, 189, 84)); // will fail
// for some reason we always lose data on blue channel
assert_eq!(ycbcr_to_rgb(61, 189, 84), ( 0, 71, 169));
}
을 전달합니다. 나는 오히려 그 중 적어도 하나가 실패 할 것이라고 기대하고있다. 내가 잘못? 적어도 어느 시점에서는 중단해야하지만, jpeg::color::utils::rgb_to_ycbcr(0, 71, 171)
을 jpeg::color::utils::rgb_to_ycbcr(0, 71, 169)
으로 변경하면 YCbCr 값이 변경되어 테스트가 실패하므로 영원히 파란색 채널이 손실됩니다.
완료. 이제 완전하고 실행 가능합니다. – Hauleth
"파란 채널을 잃어 버림"이란 무엇을 의미합니까? 그리고 왜'rgb_to_ycbcr'에 대해 동일한 출력을주기 위해 입력을 변경하려고합니까? – huon
RGB'(0, 71, 171)'에서 YCbCr'(61, 189, 84)'로 그리고 RGB'(0, 71, 169)'로 다시 변환하면 청색 채널 값이 달라지며 내가 설정 한 가치는 항상 다릅니다 (나는 "멈추지 않는"가치를 발견하지 못했습니다). – Hauleth