910e62b5创建于 1月15日历史提交
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::simd::prelude::*;
use std::simd::Simd;

use crate::Reg;

const fn create_bayer_matrix(num: i32, denom: i32) -> [[i16; 4]; 4] {
    #[rustfmt::skip]
    let base_pattern: [[i32; 4]; 4] = [
        [ 0,  8,  2, 10],
        [12,  4, 14,  6],
        [ 3, 11,  1,  9],
        [15,  7, 13,  5],
    ];
    let mut matrix = [[0i16; 4]; 4];
    // Only while loops are possible, not for, in const fns
    let mut y = 0;
    let mut x = 0;
    while y < 4 {
        while x < 4 {
            let value = (base_pattern[y][x] - 8) * num / denom / 16;
            matrix[y][x] = value as i16;
            x += 1;
        }
        y += 1;
    }
    matrix
}

// RGB565 dither table, strengthened by 1.33x (for better masking of banding).
const BAYER_31: [[i16; 4]; 4] = create_bayer_matrix(255 * 4, 31 * 3);
const BAYER_63: [[i16; 4]; 4] = create_bayer_matrix(255 * 4, 63 * 3);

/// Bayer dithering. The purpose of the dithering is mostly to mask artifacts;
/// the strength of dithering is not really related to the quantization scheme
/// (444 or 555) nor the selector table values.
#[inline]
pub fn dither(data: &[[[Reg; 3]; 4]; 4]) -> [[[Reg; 3]; 4]; 4] {
    let mut out = [[[Reg::default(); 3]; 4]; 4];
    for y in 0..4 {
        for x in 0..4 {
            for (ch, matrix) in [(0, &BAYER_31), (1, &BAYER_63), (2, &BAYER_31)] {
                out[y][x][ch] = (data[y][x][ch] + Simd::splat(matrix[y][x]))
                    .simd_clamp(Simd::splat(0), Simd::splat(255));
            }
        }
    }
    out
}