termimage/
util.rs

1//! Module containing various utility functions.
2
3
4use std::iter;
5use image::Rgb;
6use std::ops::Index;
7
8
9/// Magic number used for determining whether an image is a BMP.
10///
11/// Source: [Wikipedia](https://en.wikipedia.org/wiki/List_of_file_signatures).
12pub static BMP_MAGIC: &[u8] = &[0x42, 0x4D];
13
14/// Magic number used for determining whether an image is an ICO.
15///
16/// Source: [Wikipedia](https://en.wikipedia.org/wiki/List_of_file_signatures).
17pub static ICO_MAGIC: &[u8] = &[0x00, 0x00, 0x01, 0x00];
18
19/// Magic number used for determining whether an image is a GIF.
20///
21/// Source: [Wikipedia](https://en.wikipedia.org/wiki/List_of_file_signatures).
22pub static GIF_MAGIC: &[u8] = &[0x47, 0x49, 0x46, 0x38];
23
24/// Magic number used for determining whether an image is a PNG.
25///
26/// Source: [Wikipedia](https://en.wikipedia.org/wiki/List_of_file_signatures).
27pub static PNG_MAGIC: &[u8] = &[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
28
29/// Magic number used for determining whether an image is a JPEG.
30///
31/// Source: [Wikipedia](https://en.wikipedia.org/wiki/List_of_file_signatures).
32pub static JPEG_MAGIC: &[u8] = &[0xFF, 0xD8, 0xFF, 0xE0];
33
34
35/// ANSI colours for a white-background terminal, in the same order as `ANSI_COLOUR_ESCAPES`.
36///
37/// Acquired from screenshot provided by [@Ell](https://github.com/elliotpotts):
38///
39/// ![Terminal screenshot](https://cloud.githubusercontent.com/assets/6709544/18532811/e7e87a6e-7ade-11e6-868f-f6d2f9faec27.png)
40pub static ANSI_COLOURS_WHITE_BG: [Rgb<u8>; 16] = [Rgb([0xEE, 0xE8, 0xD5]),
41                                                   Rgb([0xDC, 0x32, 0x2F]),
42                                                   Rgb([0x85, 0x99, 0x00]),
43                                                   Rgb([0xB5, 0x89, 0x00]),
44                                                   Rgb([0x26, 0x8B, 0xD2]),
45                                                   Rgb([0xD3, 0x36, 0x82]),
46                                                   Rgb([0x2A, 0xA1, 0x98]),
47                                                   Rgb([0x07, 0x36, 0x42]),
48
49                                                   Rgb([0xFD, 0xF6, 0xE3]),
50                                                   Rgb([0xCB, 0x4B, 0x16]),
51                                                   Rgb([0x93, 0xA1, 0xA1]),
52                                                   Rgb([0x83, 0x94, 0x96]),
53                                                   Rgb([0x65, 0x7B, 0x83]),
54                                                   Rgb([0x6C, 0x71, 0xC4]),
55                                                   Rgb([0x58, 0x6E, 0x75]),
56                                                   Rgb([0x00, 0x2B, 0x36])];
57
58/// Linux-theme ANSI colours, in the same order as `ANSI_COLOUR_ESCAPES`.
59///
60/// Acquired from the [`colorname` table in st](https://git.suckless.org/st/file/config.def.h.html#l86),
61/// as decoded according to the [X11 colour names Wikipedia article](https://en.wikipedia.org/wiki/X11_color_names):
62///
63/// ```c
64/// static const char *colorname[] = {
65///     /* 8 normal colors */
66///     "black",
67///     "red3",
68///     "green3",
69///     "yellow3",
70///     "blue2",
71///     "magenta3",
72///     "cyan3",
73///     "gray90",
74///
75///     /* 8 bright colors */
76///     "gray50",
77///     "red",
78///     "green",
79///     "yellow",
80///     "#5c5cff",
81///     "magenta",
82///     "cyan",
83///     "white",
84///
85///     // …
86/// }
87/// ```
88pub static ANSI_COLOURS_BLACK_BG: [Rgb<u8>; 16] = [Rgb([0x00, 0x00, 0x00]),
89                                                   Rgb([0xCD, 0x00, 0x00]),
90                                                   Rgb([0x00, 0xCD, 0x00]),
91                                                   Rgb([0xCD, 0xCD, 0x00]),
92                                                   Rgb([0x00, 0x00, 0xEE]),
93                                                   Rgb([0xCD, 0x00, 0xCD]),
94                                                   Rgb([0x00, 0xCD, 0xCD]),
95                                                   Rgb([0xE6, 0xE6, 0xE6]),
96
97                                                   Rgb([0x80, 0x80, 0x80]),
98                                                   Rgb([0xFF, 0x00, 0x00]),
99                                                   Rgb([0x00, 0xFF, 0x00]),
100                                                   Rgb([0xFF, 0xFF, 0x00]),
101                                                   Rgb([0x5C, 0x5C, 0xFF]),
102                                                   Rgb([0xFF, 0x00, 0xFF]),
103                                                   Rgb([0x00, 0xFF, 0xFF]),
104                                                   Rgb([0xFF, 0xFF, 0xFF])];
105
106/// ANSI background colour escapes.
107pub static ANSI_COLOUR_ESCAPES: [&str; 16] = ["\x1B[0;30m",
108                                              "\x1B[0;31m",
109                                              "\x1B[0;32m",
110                                              "\x1B[0;33m",
111                                              "\x1B[0;34m",
112                                              "\x1B[0;35m",
113                                              "\x1B[0;36m",
114                                              "\x1B[0;37m",
115                                              "\x1B[1;30m",
116                                              "\x1B[1;31m",
117                                              "\x1B[1;32m",
118                                              "\x1B[1;33m",
119                                              "\x1B[1;34m",
120                                              "\x1B[1;35m",
121                                              "\x1B[1;36m",
122                                              "\x1B[1;37m"];
123
124/// ANSI background colour escapes.
125pub static ANSI_BG_COLOUR_ESCAPES: [&str; 8] = ["\x1B[40m", "\x1B[41m", "\x1B[42m", "\x1B[43m", "\x1B[44m", "\x1B[45m", "\x1B[46m", "\x1B[47m"];
126
127/// Reset ANSI attributes
128pub static ANSI_RESET_ATTRIBUTES: &str = "\x1B[0m";
129
130
131/// Create a string consisting of `n` repetitions of `what`.
132///
133/// # Examples
134///
135/// ```
136/// # use termimage::util::mul_str;
137/// assert_eq!(mul_str("Го! ", 3), "Го! Го! Го! ".to_string());
138/// ```
139pub fn mul_str(what: &str, n: usize) -> String {
140    iter::repeat(what).take(n).collect()
141}
142
143/// Get the closest colour to the provided one out of the specified list of colours and retirn its index.
144///
145/// The formula is the last one from the
146/// [Euclidean section in the Color difference article on Wikipedia](https://en.wikipedia.org/wiki/Color_difference#Euclidean)
147pub fn closest_colour<P: Index<usize, Output = u8>>(to: Rgb<u8>, out_of: &[P]) -> usize {
148    let mut diffs = out_of.iter()
149        .enumerate()
150        .map(|(i, rgb)| {
151            let r = (rgb[0] as f32 + to[0] as f32) / 2.0;
152            ((2.0 + (r / 256.0)) * (rgb[0] as f32 - to[0] as f32).powi(2) + 4.0 * (rgb[1] as f32 - to[1] as f32).powi(2) +
153             (2.0 + ((255.0 - r) / 256.0)) * (rgb[2] as f32 - to[2] as f32).powi(2),
154             i)
155        })
156        .collect::<Vec<_>>();
157    diffs.sort_by(|&(lhs_diff, _), &(rhs_diff, _)| lhs_diff.partial_cmp(&rhs_diff).unwrap());
158    diffs[0].1
159}
160
161/// Get the background colour set for the specified foregournd colour set
162#[inline(always)]
163pub fn bg_colours_for<C: Index<usize, Output = u8>>(foreground_colours: &[C]) -> &[C] {
164    &foreground_colours[0..8]
165}