@@ -14,6 +14,7 @@ pub fn convert_image(in_path: &Path, out_path: &Path, sys_pal: &Palette) -> Resu
1414 }
1515 let mut img_pal = make_palette ( & img, sys_pal) . context ( "detect colors used in the image" ) ?;
1616 let mut out = File :: create ( out_path) . context ( "create output path" ) ?;
17+ // The magic number. "2"=image, "1"=v1.
1718 write_u8 ( & mut out, 0x21 ) ?;
1819 let n_colors = img_pal. len ( ) ;
1920 if n_colors <= 2 {
@@ -101,42 +102,47 @@ fn make_palette(img: &RgbaImage, sys_pal: &Palette) -> Result<Vec<Color>> {
101102}
102103
103104/// Add empty colors at the end of the palette to match the BPP size.
105+ ///
106+ /// If the given image palette is fully contained within the system palette
107+ /// (after being cut to the expected swaps size), place the colors in the
108+ /// image palette in the same positions as they are in the system palette.
109+ /// This will make it possible to read such images without worrying about
110+ /// applying color swaps.
104111fn extend_palette ( img_pal : & mut Vec < Color > , sys_pal : & Palette , size : usize ) {
105112 if img_pal. len ( ) > size {
106113 return ;
107114 }
108- // If the given image palette is fully contained within the system palette,
109- // place the colors in the image palette in the same positions as they are
110- // in the system palette. This will make it possible to read such images
111- // without worrying about applying color swaps.
112- if size == sys_pal. len ( ) && is_subpalette ( img_pal, sys_pal) {
113- let has_transp = img_pal. iter ( ) . any ( Option :: is_none) ;
114- if !has_transp {
115- img_pal. copy_from_slice ( sys_pal) ;
116- return ;
117- }
118115
119- let mut new_pal: Vec < Color > = Vec :: new ( ) ;
120- let mut found_transp = false ;
121- for c in sys_pal {
122- if found_transp || img_pal. contains ( c) {
123- new_pal. push ( * c) ;
124- } else {
125- new_pal. push ( None ) ;
126- found_transp = true ;
127- }
128- }
129- img_pal. copy_from_slice ( & new_pal[ ..] ) ;
116+ let sys_pal_prefix = & sys_pal[ ..size] ;
117+ if !is_subpalette ( img_pal, sys_pal_prefix) {
118+ img_pal. extend_from_slice ( & sys_pal[ img_pal. len ( ) ..size] ) ;
130119 return ;
131120 }
132- let n = size - img_pal. len ( ) ;
133- for _ in 0 ..n {
134- img_pal. push ( sys_pal[ 0 ] ) ;
121+
122+ // No transparency? Just use the system palette.
123+ let has_transp = img_pal. iter ( ) . any ( Option :: is_none) ;
124+ if !has_transp {
125+ img_pal. clear ( ) ;
126+ img_pal. extend ( sys_pal_prefix) ;
127+ return ;
135128 }
129+
130+ // Has transparency? Then copy the system palette and poke one hole in it.
131+ let mut new_pal: Vec < Color > = Vec :: new ( ) ;
132+ let mut found_transp = false ;
133+ for c in sys_pal_prefix {
134+ if found_transp || img_pal. contains ( c) {
135+ new_pal. push ( * c) ;
136+ } else {
137+ new_pal. push ( None ) ;
138+ found_transp = true ;
139+ }
140+ }
141+ img_pal. copy_from_slice ( & new_pal[ ..] ) ;
136142}
137143
138144/// Check if the image palette is fully contained within the given system palette.
139- fn is_subpalette ( img_pal : & Vec < Color > , sys_pal : & Palette ) -> bool {
145+ fn is_subpalette ( img_pal : & [ Color ] , sys_pal : & [ Color ] ) -> bool {
140146 for c in img_pal {
141147 if c. is_some ( ) && !sys_pal. contains ( c) {
142148 return false ;
@@ -231,4 +237,44 @@ mod tests {
231237 assert_eq ! ( pick_transparent( & [ c1, c0, None ] , pal) . unwrap( ) , 2 ) ;
232238 assert_eq ! ( pick_transparent( & [ c0, c1, c2, c3, None ] , pal) . unwrap( ) , 4 ) ;
233239 }
240+
241+ #[ test]
242+ fn test_extend_palette ( ) {
243+ let pal = SWEETIE16 ;
244+ let c0 = pal[ 0 ] ;
245+ let c1 = pal[ 1 ] ;
246+ let c2 = pal[ 2 ] ;
247+ let c3 = pal[ 3 ] ;
248+ let c4 = pal[ 4 ] ;
249+
250+ // Already the palette prefix, do nothing.
251+ let mut img_pal = vec ! [ c0, c1] ;
252+ extend_palette ( & mut img_pal, pal, 2 ) ;
253+ assert_eq ! ( img_pal, vec![ c0, c1] ) ;
254+
255+ // A prefix but in a wrong order. Fix the order.
256+ let mut img_pal = vec ! [ c1, c0] ;
257+ extend_palette ( & mut img_pal, pal, 2 ) ;
258+ assert_eq ! ( img_pal, vec![ c0, c1] ) ;
259+
260+ // Not a prefix and already full. Keep the given palette.
261+ let mut img_pal = vec ! [ c2, c1] ;
262+ extend_palette ( & mut img_pal, pal, 2 ) ;
263+ assert_eq ! ( img_pal, vec![ c2, c1] ) ;
264+
265+ // A prefix but too short. Fill the rest.
266+ let mut img_pal = vec ! [ c0, c1] ;
267+ extend_palette ( & mut img_pal, pal, 4 ) ;
268+ assert_eq ! ( img_pal, vec![ c0, c1, c2, c3] ) ;
269+
270+ // Within the palette prefix.
271+ let mut img_pal = vec ! [ c2, c1] ;
272+ extend_palette ( & mut img_pal, pal, 4 ) ;
273+ assert_eq ! ( img_pal, vec![ c0, c1, c2, c3] ) ;
274+
275+ // Not a prefix but too short. Don't touch the given, fill the rest.
276+ let mut img_pal = vec ! [ c4, c2] ;
277+ extend_palette ( & mut img_pal, pal, 4 ) ;
278+ assert_eq ! ( img_pal, vec![ c4, c2, c2, c3] ) ;
279+ }
234280}
0 commit comments