1+ use std:: { io:: Cursor , path:: PathBuf , sync:: Arc } ;
2+
3+ use bytes:: Bytes ;
4+ use image:: { GenericImageView , ImageReader } ;
5+ use log:: { error, warn} ;
6+ use rgb:: FromSlice ;
7+ use tokio:: sync:: { Semaphore , mpsc:: { self , Sender } } ;
8+
9+ use crate :: util:: { r#macro:: unwrap_helper, stream:: { BoundedFrameDecoder , LengthPrefixedDataDecoder } } ;
10+
11+ pub struct ImageState {
12+ pub transmit : Arc < Sender < ( String , Vec < u8 > ) > >
13+ }
14+
15+ pub fn image_queue_processor (
16+ base_path : Arc < PathBuf > , transcode : bool , image_guard : Arc < Semaphore >
17+ ) -> mpsc:: Sender < ( String , Vec < u8 > ) > {
18+ let ( tx, mut rx) = mpsc:: channel :: < ( String , Vec < u8 > ) > (
19+ 128
20+ ) ;
21+ tokio:: spawn ( async move {
22+ while let Some ( data) = rx. recv ( ) . await {
23+ submit_image ( base_path. clone ( ) , transcode, image_guard. clone ( ) , data) . await ;
24+ }
25+ } ) ;
26+ tx
27+ }
28+
29+ async fn submit_image ( base_path : Arc < PathBuf > , transcode : bool , image_guard : Arc < Semaphore > , data : ( String , Vec < u8 > ) ) {
30+ let permit = image_guard. clone ( ) . acquire_owned ( ) . await . unwrap ( ) ;
31+ tokio:: task:: spawn_blocking ( move || {
32+ let _permit_use = permit;
33+ store_map_image ( base_path, transcode, data) ;
34+ } ) ;
35+ }
36+
37+ fn store_map_image (
38+ base_path : Arc < PathBuf > ,
39+ transcode : bool ,
40+ image_and_name : ( String , Vec < u8 > )
41+ ) {
42+ let ( file_name, image) = image_and_name;
43+ if !transcode {
44+ let destination = base_path. join ( format ! ( "{}.png" , file_name) ) ;
45+ std:: fs:: write ( destination, image) ;
46+ } else {
47+ let destination = base_path. join ( format ! ( "{}.avif" , file_name) ) ;
48+ let data = image;
49+
50+ let mut image_reader = ImageReader :: new ( Cursor :: new ( data) ) ;
51+ image_reader. set_format ( image:: ImageFormat :: Png ) ;
52+ let image = match image_reader. decode ( ) {
53+ Ok ( image) => image,
54+ Err ( e) => {
55+ error ! ( "Could not save {} due to {:?}" , file_name, e) ;
56+ return ;
57+ } ,
58+ } ;
59+ let ( width, height) = image. dimensions ( ) ;
60+ let rgb_image = image. into_rgba8 ( ) ;
61+ let rgb_data = rgb_image. into_raw ( ) ;
62+ let encoder = ravif:: Encoder :: new ( ) ;
63+ let img = imgref:: Img :: new ( rgb_data. as_rgba ( ) , width as usize , height as usize ) ;
64+ let avif_data = unwrap_helper:: result_return_default!( encoder. encode_rgba( img) , ( ) ) ;
65+ std:: fs:: write ( destination, avif_data. avif_file ) ;
66+ }
67+ }
68+
69+ pub fn create_image_decoder ( ) -> BoundedFrameDecoder {
70+ BoundedFrameDecoder :: new (
71+ 1024 ,
72+ Box :: new (
73+ LengthPrefixedDataDecoder :: new ( )
74+ )
75+ )
76+ }
77+
78+ pub fn parse_image_data ( mut bytes : Bytes ) -> ( String , Vec < u8 > ) {
79+ let image_name = read_length_prefixed_string ( & mut bytes) ;
80+ ( image_name, Vec :: from ( bytes) )
81+ }
82+
83+ fn read_length_prefixed_string ( bytes : & mut Bytes ) -> String {
84+ String :: from_utf8 ( Vec :: from ( read_length_prefixed_data ( bytes) ) ) . unwrap ( )
85+ }
86+
87+ fn read_length_prefixed_data ( bytes : & mut Bytes ) -> Bytes {
88+ let arr = <[ u8 ; 4 ] >:: try_from ( bytes. split_to ( 4 ) . as_ref ( ) ) . unwrap ( ) ;
89+ let size = u32:: from_be_bytes ( arr) ;
90+ bytes. split_to ( size as usize )
91+ }
0 commit comments