summaryrefslogtreecommitdiffstats
path: root/third_party/rust/image/src/jpeg/entropy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/image/src/jpeg/entropy.rs')
-rw-r--r--third_party/rust/image/src/jpeg/entropy.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/third_party/rust/image/src/jpeg/entropy.rs b/third_party/rust/image/src/jpeg/entropy.rs
new file mode 100644
index 0000000000..417ebd65a7
--- /dev/null
+++ b/third_party/rust/image/src/jpeg/entropy.rs
@@ -0,0 +1,61 @@
+/// Given an array containing the number of codes of each code length,
+/// this function generates the huffman codes lengths and their respective
+/// code lengths as specified by the JPEG spec.
+fn derive_codes_and_sizes(bits: &[u8]) -> (Vec<u8>, Vec<u16>) {
+ let mut huffsize = vec![0u8; 256];
+ let mut huffcode = vec![0u16; 256];
+
+ let mut k = 0;
+ let mut j;
+
+ // Annex C.2
+ // Figure C.1
+ // Generate table of individual code lengths
+ for i in 0u8..16 {
+ j = 0;
+
+ while j < bits[usize::from(i)] {
+ huffsize[k] = i + 1;
+ k += 1;
+ j += 1;
+ }
+ }
+
+ huffsize[k] = 0;
+
+ // Annex C.2
+ // Figure C.2
+ // Generate table of huffman codes
+ k = 0;
+ let mut code = 0u16;
+ let mut size = huffsize[0];
+
+ while huffsize[k] != 0 {
+ huffcode[k] = code;
+ code += 1;
+ k += 1;
+
+ if huffsize[k] == size {
+ continue;
+ }
+
+ // FIXME there is something wrong with this code
+ let diff = huffsize[k].wrapping_sub(size);
+ code = if diff < 16 { code << diff as usize } else { 0 };
+
+ size = size.wrapping_add(diff);
+ }
+
+ (huffsize, huffcode)
+}
+
+pub(crate) fn build_huff_lut(bits: &[u8], huffval: &[u8]) -> Vec<(u8, u16)> {
+ let mut lut = vec![(17u8, 0u16); 256];
+ let (huffsize, huffcode) = derive_codes_and_sizes(bits);
+
+ for (i, &v) in huffval.iter().enumerate() {
+ lut[v as usize] = (huffsize[i], huffcode[i]);
+ }
+
+ lut
+}