scra_mirach_model/
data.rsuse std::{fmt::{Debug, Display}, mem::MaybeUninit};
use burn::{
prelude::Backend,
tensor::{Device, Tensor, TensorData},
};
use crate::{IMAGE_CHANNELS, IMAGE_HEIGHT, IMAGE_WIDTH};
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct CaptchaCode(u16);
impl CaptchaCode {
#[inline]
pub fn new(code: u16) -> Self {
assert!(code < 10000);
Self(code)
}
#[inline]
pub fn new_unchecked(code: u16) -> Self {
Self(code)
}
#[inline]
pub fn as_u16(&self) -> u16 {
self.0
}
#[inline]
pub fn as_digits(&self) -> [u8; 4] {
[
(self.0 / 1000) as u8,
((self.0 / 100) % 10) as u8,
((self.0 / 10) % 10) as u8,
(self.0 % 10) as u8,
]
}
#[inline]
pub fn from_digits(digits: [u8; 4]) -> Self {
Self::new_unchecked(
(digits[0] as u16 * 1000)
+ (digits[1] as u16 * 100)
+ (digits[2] as u16 * 10)
+ digits[3] as u16,
)
}
}
impl Debug for CaptchaCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("CaptchaCode({:04})", self.0))
}
}
impl Display for CaptchaCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:04}", self.0))
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct MirachImageData(Vec<u8>);
impl MirachImageData {
pub fn new(pixels: Vec<u8>) -> Self {
Self(pixels)
}
pub fn unwrap(self) -> Vec<u8> {
self.0
}
}
#[cfg(feature = "image")]
impl From<image::RgbImage> for MirachImageData {
fn from(image: image::RgbImage) -> Self {
#[allow(invalid_value)]
let mut data: Box<[u8; IMAGE_HEIGHT * IMAGE_WIDTH * IMAGE_CHANNELS]> =
unsafe { Box::new(MaybeUninit::uninit().assume_init()) };
for x in 0..IMAGE_WIDTH {
let offset = x * IMAGE_HEIGHT;
for y in 0..IMAGE_HEIGHT {
let offset = offset + y;
let pixel = image.get_pixel(x as u32, y as u32);
data[(0 * (IMAGE_WIDTH * IMAGE_HEIGHT)) + offset] = pixel[0];
data[(1 * (IMAGE_WIDTH * IMAGE_HEIGHT)) + offset] = pixel[1];
data[(2 * (IMAGE_WIDTH * IMAGE_HEIGHT)) + offset] = pixel[2];
}
}
Self(Vec::from(data as Box<[u8]>))
}
}
#[cfg(feature = "image")]
impl From<image::DynamicImage> for MirachImageData {
fn from(image: image::DynamicImage) -> Self {
image.into_rgb8().into()
}
}
impl MirachImageData {
pub fn into_tensor<B: Backend>(self, device: &Device<B>) -> Tensor<B, 4> {
let image = TensorData::new::<u8, _>(
self.unwrap(),
[1, IMAGE_CHANNELS, IMAGE_WIDTH, IMAGE_HEIGHT],
);
let image = Tensor::<B, 4>::from(image.convert::<B::FloatElem>()).to_device(device);
let image = image / 255;
debug_assert_eq!(image.dims(), [1, IMAGE_CHANNELS, IMAGE_WIDTH, IMAGE_HEIGHT]);
image
}
}