@@ -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,34 @@ 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 )
379+ . map ( |raw| {
380+ // integer blending approach from https://stackoverflow.com/a/12016968
381+ let v = raw. into_inner ( ) ;
382+ let mut alpha = v & 0xFF ;
383+ let inv_alpha = 256 - alpha;
384+ alpha += 1 ;
385+ if alpha == 0 {
386+ // pixel is completely transparent, use bg color
387+ self . alpha_bg
388+ } else if alpha == 255 {
389+ // pixel is completely opaque, just use its color
390+ Rgb888 :: from ( RawU24 :: new ( v >> 8 ) )
391+ } else {
392+ // pixel has transparency, blend with BG color
393+ let col = Rgb888 :: from ( RawU24 :: new ( v >> 8 ) ) ;
394+ Rgb888 :: new (
395+ ( ( alpha * col. r ( ) as u32 + inv_alpha * self . alpha_bg . r ( ) as u32 ) >> 8 ) as u8 ,
396+ ( ( alpha * col. g ( ) as u32 + inv_alpha * self . alpha_bg . g ( ) as u32 ) >> 8 ) as u8 ,
397+ ( ( alpha * col. b ( ) as u32 + inv_alpha * self . alpha_bg . b ( ) as u32 ) >> 8 ) as u8 ,
398+ )
399+ } . into ( )
400+ } ) ,
401+ )
402+ } ,
370403 }
371404 }
372405
0 commit comments