zune_jpeg/
color_convert.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8
9#![allow(
10    clippy::many_single_char_names,
11    clippy::similar_names,
12    clippy::cast_possible_truncation,
13    clippy::cast_sign_loss,
14    clippy::cast_possible_wrap,
15    clippy::too_many_arguments,
16    clippy::doc_markdown
17)]
18
19//! Color space conversion routines
20//!
21//! This files exposes functions to convert one colorspace to another in a jpeg
22//! image
23//!
24//! Currently supported conversions are
25//!
26//! - `YCbCr` to `RGB,RGBA,GRAYSCALE,RGBX`.
27//!
28//!
29//! Hey there, if your reading this it means you probably need something, so let me help you.
30//!
31//! There are 3 supported cpu extensions here.
32//! 1. Scalar
33//! 2. SSE
34//! 3. AVX
35//!
36//! There are two types of the color convert functions
37//!
38//! 1. Acts on 16 pixels.
39//! 2. Acts on 8 pixels.
40//!
41//! The reason for this is because when implementing the AVX part it occurred to me that we can actually
42//! do better and process 2 MCU's if we change IDCT return type to be `i16's`, since a lot of
43//! CPU's these days support AVX extensions, it becomes nice if we optimize for that path ,
44//! therefore AVX routines can process 16 pixels directly and SSE and Scalar just compensate.
45//!
46//! By compensating, I mean I wrote the 16 pixels version operating on the 8 pixel version twice.
47//!
48//! Therefore if your looking to optimize some routines, probably start there.
49
50pub use scalar::ycbcr_to_grayscale;
51use zune_core::colorspace::ColorSpace;
52use zune_core::options::DecoderOptions;
53
54#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
55#[cfg(feature = "x86")]
56pub use crate::color_convert::avx::{ycbcr_to_rgb_avx2, ycbcr_to_rgba_avx2};
57use crate::decoder::ColorConvert16Ptr;
58
59mod avx;
60mod scalar;
61#[allow(unused_variables)]
62pub fn choose_ycbcr_to_rgb_convert_func(
63    type_need: ColorSpace, options: &DecoderOptions
64) -> Option<ColorConvert16Ptr> {
65    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
66    #[cfg(feature = "x86")]
67    {
68        use zune_core::log::debug;
69        if options.use_avx2() {
70            debug!("Using AVX optimised color conversion functions");
71
72            // I believe avx2 means sse4 is also available
73            // match colorspace
74            match type_need {
75                ColorSpace::RGB => return Some(ycbcr_to_rgb_avx2),
76                ColorSpace::RGBA => return Some(ycbcr_to_rgba_avx2),
77                _ => () // fall through to scalar, which has more types
78            };
79        }
80    }
81    // when there is no x86 or we haven't returned by here, resort to scalar
82    return match type_need {
83        ColorSpace::RGB => Some(scalar::ycbcr_to_rgb_inner_16_scalar::<false>),
84        ColorSpace::RGBA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::<false>),
85        ColorSpace::BGRA => Some(scalar::ycbcr_to_rgba_inner_16_scalar::<true>),
86        ColorSpace::BGR => Some(scalar::ycbcr_to_rgb_inner_16_scalar::<true>),
87        _ => None
88    };
89}