1- use crate :: cache:: { Cache , ItemType } ;
2- use crate :: options:: { Compression , Options } ;
3- use crate :: png :: { crc , recoverer } ;
1+ use crate :: cache:: Cache ;
2+ use crate :: options:: Options ;
3+ use crate :: resource_pack :: files :: unknowntexture :: UnknownTexture ;
44use crate :: resource_pack:: identifier:: Identifier ;
5- use crate :: LogLevel :: { Info , Warning } ;
6- use crate :: { options, profile_scope, LogMessage } ;
7- use once_cell:: sync:: Lazy ;
8- use oxipng:: { indexset, optimize_from_memory, Deflater , FilterStrategy , StripChunks } ;
9- use sha2:: { Digest , Sha256 } ;
10- use std:: time:: Duration ;
5+ use crate :: LogMessage ;
116
127// textures are referenced in `models`, `items` and `font`
138#[ derive( Clone , Debug ) ]
149pub struct Texture {
1510 pub overlay : String ,
1611 pub identifier : Identifier ,
17- pub bytes : Vec < u8 > ,
12+ pub unknown_texture : UnknownTexture
1813}
1914
2015impl Texture {
@@ -23,10 +18,22 @@ impl Texture {
2318 identifier : impl Into < Identifier > ,
2419 bytes : Vec < u8 > ,
2520 ) -> Self {
21+ let overlay = overlay. into ( ) ;
22+ let prefix = if overlay. is_empty ( ) {
23+ "" . to_string ( )
24+ } else {
25+ format ! ( "{}/" , overlay)
26+ } ;
27+ let identifier = identifier. into ( ) ;
28+ let path = format ! (
29+ "{}assets/{}/textures/{}.png" ,
30+ prefix, identifier. namespace, identifier. path
31+ ) ;
32+ let unknown_texture = UnknownTexture :: new ( path, bytes) ;
2633 Self {
2734 overlay : overlay. into ( ) ,
2835 identifier : identifier. into ( ) ,
29- bytes ,
36+ unknown_texture ,
3037 }
3138 }
3239
@@ -36,232 +43,11 @@ impl Texture {
3643 logger : & tokio:: sync:: mpsc:: UnboundedSender < LogMessage > ,
3744 cache : & Option < Cache > ,
3845 ) {
39- self . bytes = Self :: cache_or_optimize ( & self . bytes , options, logger, cache, & self . path ( ) ) ;
40- if options. corrupt_png_files {
41- match crc:: modify_png_crcs ( & self . bytes ) {
42- Ok ( bytes) => {
43- self . bytes = bytes;
44- }
45- Err ( e) => {
46- let _ = logger. send ( LogMessage {
47- level : Warning ,
48- message : format ! ( "Could not corrupt image '{}'. Error: {}" , self . path( ) , e) ,
49- } ) ;
50- }
51- }
52- }
53- }
54-
55- fn cache_or_optimize (
56- bytes : & [ u8 ] ,
57- options : & Options ,
58- logger : & tokio:: sync:: mpsc:: UnboundedSender < LogMessage > ,
59- cache : & Option < Cache > ,
60- path : & str ,
61- ) -> Vec < u8 > {
62- profile_scope ! ( "cache_or_optimize::texture" ) ;
63- if let Some ( cache) = cache {
64- let mut sha256 = Sha256 :: new ( ) ;
65- sha256. update ( bytes) ;
66- let hash: [ u8 ; 32 ] = sha256. finalize ( ) . into ( ) ;
67-
68- if let Some ( bytes) = cache
69- . with_item ( & hash, ItemType :: Image , |it| {
70- ( it. compression as u8 >= options. compression . clone ( ) as u8 )
71- . then ( || it. data . clone ( ) )
72- } )
73- . flatten ( )
74- {
75- let _ = logger. send ( LogMessage {
76- level : Info ,
77- message : format ! ( "Image '{}' was loaded from cache." , path) ,
78- } ) ;
79- return bytes;
80- }
81- }
82- let oxipng_options = match options. compression {
83- Compression :: Simplest => & DEFAULT_OPTIONS ,
84- Compression :: Normal => & NORMAL_OPTIONS ,
85- Compression :: Max => & MAX_OPTIONS ,
86- } ;
87- match optimize_from_memory ( bytes, oxipng_options) {
88- Ok ( value) => {
89- if let Some ( cache) = cache {
90- cache. add_item (
91- bytes,
92- & * value,
93- options. compression . clone ( ) as u8 ,
94- ItemType :: Image ,
95- )
96- }
97- value
98- }
99- Err ( e) => {
100- let _ = logger. send ( LogMessage {
101- level : Info ,
102- message : format ! (
103- "Could not optimize image '{}'. Trying to recover it. Error: {}" ,
104- path, e
105- ) ,
106- } ) ;
107- match recoverer:: recover_png ( bytes) {
108- Ok ( value) => {
109- let _ = logger. send ( LogMessage {
110- level : Info ,
111- message : format ! ( "Image '{}' was recovered successfully." , path) ,
112- } ) ;
113- match optimize_from_memory ( value. as_slice ( ) , oxipng_options) {
114- Ok ( value) => {
115- if let Some ( cache) = cache {
116- cache. add_item (
117- bytes,
118- & * value,
119- options. compression . clone ( ) as u8 ,
120- ItemType :: Image ,
121- )
122- }
123- value
124- }
125- Err ( e) => {
126- let _ = logger. send ( LogMessage {
127- level : Warning ,
128- message : format ! (
129- "Could not optimize image '{}'. Skipping optimization. Error: {}" ,
130- path,
131- e) ,
132- } ) ;
133- value
134- }
135- }
136- }
137- Err ( e) => {
138- let _ = logger. send ( LogMessage {
139- level : Warning ,
140- message : format ! (
141- "Could not recover image '{}'. Skipping optimization. Error: {}" ,
142- path, e
143- ) ,
144- } ) ;
145- bytes. to_owned ( )
146- }
147- }
148- }
149- }
46+ self . unknown_texture . optimize ( options, logger, cache) ;
15047 }
15148
15249 pub fn path ( & self ) -> String {
153- let prefix = if self . overlay . is_empty ( ) {
154- "" . to_string ( )
155- } else {
156- format ! ( "{}/" , self . overlay)
157- } ;
158- format ! (
159- "{}assets/{}/textures/{}.png" ,
160- prefix, self . identifier. namespace, self . identifier. path
161- )
50+ self . unknown_texture . path . clone ( )
16251 }
16352}
16453
165- /**
166- Currently, only the `deflater` option changes, but some other options could be modified based on the compression wanted.
167- */
168- //<editor-fold desc="Oxipng options" defaultstate="collapsed">
169- static DEFAULT_OPTIONS : Lazy < oxipng:: Options > = Lazy :: new ( || oxipng:: Options {
170- fix_errors : true ,
171- force : false ,
172- filters : indexset ! {
173- FilterStrategy :: NONE ,
174- FilterStrategy :: SUB ,
175- FilterStrategy :: UP ,
176- FilterStrategy :: AVERAGE ,
177- FilterStrategy :: PAETH ,
178- FilterStrategy :: MinSum ,
179- FilterStrategy :: Entropy ,
180- FilterStrategy :: Bigrams ,
181- FilterStrategy :: BigEnt ,
182- FilterStrategy :: Brute {
183- num_lines: 8 ,
184- level: 12 ,
185- } ,
186- } ,
187- interlace : Some ( false ) ,
188- optimize_alpha : true ,
189- bit_depth_reduction : true ,
190- color_type_reduction : true ,
191- palette_reduction : true ,
192- grayscale_reduction : true ,
193- idat_recoding : true ,
194- scale_16 : false ,
195- strip : StripChunks :: All ,
196- deflater : Deflater :: Libdeflater { compression : 6 } , // 6: default compression level
197- fast_evaluation : false ,
198- timeout : Some ( Duration :: from_secs ( 3 ) ) ,
199- max_decompressed_size : None ,
200- } ) ;
201-
202- static NORMAL_OPTIONS : Lazy < oxipng:: Options > = Lazy :: new ( || oxipng:: Options {
203- fix_errors : true ,
204- force : false ,
205- filters : indexset ! {
206- FilterStrategy :: NONE ,
207- FilterStrategy :: SUB ,
208- FilterStrategy :: UP ,
209- FilterStrategy :: AVERAGE ,
210- FilterStrategy :: PAETH ,
211- FilterStrategy :: MinSum ,
212- FilterStrategy :: Entropy ,
213- FilterStrategy :: Bigrams ,
214- FilterStrategy :: BigEnt ,
215- FilterStrategy :: Brute {
216- num_lines: 8 ,
217- level: 12 ,
218- } ,
219- } ,
220- interlace : Some ( false ) ,
221- optimize_alpha : true ,
222- bit_depth_reduction : true ,
223- color_type_reduction : true ,
224- palette_reduction : true ,
225- grayscale_reduction : true ,
226- idat_recoding : true ,
227- scale_16 : false ,
228- strip : StripChunks :: All ,
229- deflater : Deflater :: Libdeflater { compression : 12 } , // 12: max compression level for libdeflater
230- fast_evaluation : false ,
231- timeout : Some ( Duration :: from_secs ( 3 ) ) ,
232- max_decompressed_size : None ,
233- } ) ;
234-
235- static MAX_OPTIONS : Lazy < oxipng:: Options > = Lazy :: new ( || oxipng:: Options {
236- fix_errors : true ,
237- force : false ,
238- filters : indexset ! {
239- FilterStrategy :: NONE ,
240- FilterStrategy :: SUB ,
241- FilterStrategy :: UP ,
242- FilterStrategy :: AVERAGE ,
243- FilterStrategy :: PAETH ,
244- FilterStrategy :: MinSum ,
245- FilterStrategy :: Entropy ,
246- FilterStrategy :: Bigrams ,
247- FilterStrategy :: BigEnt ,
248- FilterStrategy :: Brute {
249- num_lines: 8 ,
250- level: 12 ,
251- } ,
252- } ,
253- interlace : Some ( false ) ,
254- optimize_alpha : true ,
255- bit_depth_reduction : true ,
256- color_type_reduction : true ,
257- palette_reduction : true ,
258- grayscale_reduction : true ,
259- idat_recoding : true ,
260- scale_16 : false ,
261- strip : StripChunks :: All ,
262- deflater : Deflater :: Zopfli ( options:: ZOPFLI_OPTIONS . to_owned ( ) ) , // zopfli: best compression
263- fast_evaluation : false ,
264- timeout : Some ( Duration :: from_secs ( 3 ) ) ,
265- max_decompressed_size : None ,
266- } ) ;
267- //</editor-fold>
0 commit comments