Improve hashing algorithm slightly (see credits)
This commit is contained in:
parent
52cc56381e
commit
c062c6b79b
2 changed files with 16 additions and 6 deletions
|
@ -4,6 +4,8 @@ use core::convert::TryFrom;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
|
use bytemuck::Pod;
|
||||||
|
|
||||||
use crate::consts::{QOI_HEADER_SIZE, QOI_OP_INDEX, QOI_OP_RUN, QOI_PADDING, QOI_PADDING_SIZE};
|
use crate::consts::{QOI_HEADER_SIZE, QOI_OP_INDEX, QOI_OP_RUN, QOI_PADDING, QOI_PADDING_SIZE};
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::header::Header;
|
use crate::header::Header;
|
||||||
|
@ -17,6 +19,7 @@ use crate::utils::{unlikely, BytesMut, Writer};
|
||||||
fn encode_impl<W: Writer, const N: usize>(mut buf: W, data: &[u8]) -> Result<usize>
|
fn encode_impl<W: Writer, const N: usize>(mut buf: W, data: &[u8]) -> Result<usize>
|
||||||
where
|
where
|
||||||
Pixel<N>: SupportedChannels,
|
Pixel<N>: SupportedChannels,
|
||||||
|
[u8; N]: Pod,
|
||||||
{
|
{
|
||||||
let cap = buf.capacity();
|
let cap = buf.capacity();
|
||||||
|
|
||||||
|
|
19
src/pixel.rs
19
src/pixel.rs
|
@ -1,6 +1,7 @@
|
||||||
use crate::consts::{QOI_OP_DIFF, QOI_OP_LUMA, QOI_OP_RGB, QOI_OP_RGBA};
|
use crate::consts::{QOI_OP_DIFF, QOI_OP_LUMA, QOI_OP_RGB, QOI_OP_RGBA};
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::utils::Writer;
|
use crate::utils::Writer;
|
||||||
|
use bytemuck::{cast, Pod};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -107,12 +108,18 @@ impl<const N: usize> Pixel<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn hash_index(self) -> u8 {
|
pub fn hash_index(self) -> u8
|
||||||
let r = self.r().wrapping_mul(3);
|
where
|
||||||
let g = self.g().wrapping_mul(5);
|
[u8; N]: Pod,
|
||||||
let b = self.b().wrapping_mul(7);
|
{
|
||||||
let a = self.a_or(0xff).wrapping_mul(11);
|
// credits for the initial idea: @zakarumych
|
||||||
r.wrapping_add(g).wrapping_add(b).wrapping_add(a) % 64
|
let v = if N == 4 {
|
||||||
|
u32::from_ne_bytes(cast(self.0))
|
||||||
|
} else {
|
||||||
|
u32::from_ne_bytes([self.0[0], self.0[1], self.0[2], 0xff])
|
||||||
|
} as u64;
|
||||||
|
let s = ((v & 0xff00_ff00) << 32) | (v & 0x00ff_00ff);
|
||||||
|
s.wrapping_mul(0x0300_0700_0005_000b_u64).to_le().swap_bytes() as u8 & 63
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Reference in a new issue