File: dither.rs

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (52 lines) | stat: -rw-r--r-- 1,664 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 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
}