@@ -209,6 +209,7 @@ pub use raw_iter::{RawPixel, RawPixels};
209209pub struct Bmp < ' a , C > {
210210 raw_bmp : RawBmp < ' a > ,
211211 color_type : PhantomData < C > ,
212+ alpha_bg : Rgb888 ,
212213}
213214
214215impl < ' a , C > Bmp < ' a , C >
@@ -225,9 +226,18 @@ where
225226 Ok ( Self {
226227 raw_bmp,
227228 color_type : PhantomData ,
229+ alpha_bg : Rgb888 :: BLACK ,
228230 } )
229231 }
230232
233+ /// If this image contains transparent pixels (pixels with an alpha channel), then blend these
234+ /// pixels with the provided color. Note that this will only be used when drawing to a target.
235+ /// It will not be applied when querying pixels from the image.
236+ pub fn with_alpha_bg < BG : Into < Rgb888 > > ( mut self , alpha_bg : BG ) -> Self {
237+ self . alpha_bg = alpha_bg. into ( ) ;
238+ self
239+ }
240+
231241 /// Returns an iterator over the pixels in this image.
232242 ///
233243 /// The iterator always starts at the top left corner of the image, regardless of the row order
@@ -362,11 +372,37 @@ where
362372 RawColors :: < RawU32 > :: new ( & self . raw_bmp )
363373 . map ( |raw| Rgb888 :: from ( RawU24 :: new ( raw. into_inner ( ) ) ) . into ( ) ) ,
364374 ) ,
365- ColorType :: Argb8888 => target. fill_contiguous (
366- & area,
367- RawColors :: < RawU32 > :: new ( & self . raw_bmp )
368- . map ( |raw| Rgb888 :: from ( RawU24 :: new ( raw. into_inner ( ) >> 8 ) ) . into ( ) ) ,
369- ) ,
375+ ColorType :: Argb8888 => {
376+ target. fill_contiguous (
377+ & area,
378+ RawColors :: < RawU32 > :: new ( & self . raw_bmp ) . map ( |raw| {
379+ // integer blending approach from https://stackoverflow.com/a/12016968
380+ let v = raw. into_inner ( ) ;
381+ let mut alpha = v & 0xFF ;
382+ let inv_alpha = 256 - alpha;
383+ alpha += 1 ;
384+ if alpha == 0 {
385+ // pixel is completely transparent, use bg color
386+ self . alpha_bg
387+ } else if alpha == 255 {
388+ // pixel is completely opaque, just use its color
389+ Rgb888 :: from ( RawU24 :: new ( v >> 8 ) )
390+ } else {
391+ // pixel has transparency, blend with BG color
392+ let col = Rgb888 :: from ( RawU24 :: new ( v >> 8 ) ) ;
393+ Rgb888 :: new (
394+ ( ( alpha * col. r ( ) as u32 + inv_alpha * self . alpha_bg . r ( ) as u32 )
395+ >> 8 ) as u8 ,
396+ ( ( alpha * col. g ( ) as u32 + inv_alpha * self . alpha_bg . g ( ) as u32 )
397+ >> 8 ) as u8 ,
398+ ( ( alpha * col. b ( ) as u32 + inv_alpha * self . alpha_bg . b ( ) as u32 )
399+ >> 8 ) as u8 ,
400+ )
401+ }
402+ . into ( )
403+ } ) ,
404+ )
405+ }
370406 }
371407 }
372408
0 commit comments