summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-06-30 10:17:17 +0200
committerLuboš Luňák <l.lunak@collabora.com>2020-06-30 17:10:29 +0200
commita0710ac169953aeff7c9505fb48a55c390bf3206 (patch)
tree3f777ca2bfeadc7871406d20e49b960920341ff7
parent189086209113a20a36ad43d19e53af6678ff772c (diff)
faster conversions from 1bpp mask bitmaps for Skia/GL
Tdf#134363 leads to creating a large 1bpp bitmap, and this conversion takes ages. Change-Id: If596d55829698df54f1b205a5f9a5d68cbea40fe Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97489 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r--vcl/source/bitmap/salbmp.cxx87
1 files changed, 87 insertions, 0 deletions
diff --git a/vcl/source/bitmap/salbmp.cxx b/vcl/source/bitmap/salbmp.cxx
index f731a5690948..3932c12b8ce7 100644
--- a/vcl/source/bitmap/salbmp.cxx
+++ b/vcl/source/bitmap/salbmp.cxx
@@ -141,6 +141,70 @@ ImplPixelFormat* ImplPixelFormat::GetFormat( sal_uInt16 nBits, const BitmapPalet
return nullptr;
}
+// Optimized conversion from 1bpp. Currently LO uses 1bpp bitmaps for masks, which is nowadays
+// a lousy obsolete format, as the memory saved is just not worth the cost of fiddling with the bits.
+// Ideally LO should move to RGBA bitmaps. Until then, try to be faster with 1bpp bitmaps.
+typedef void(*WriteColorFunction)( sal_uInt8 color8Bit, sal_uInt8*& dst );
+void writeColorA8(sal_uInt8 color8Bit, sal_uInt8*& dst ) { *dst++ = color8Bit; };
+void writeColorRGB(sal_uInt8 color8Bit, sal_uInt8*& dst ) { *dst++ = color8Bit; *dst++ = color8Bit; *dst++ = color8Bit; };
+void writeColorRGBA(sal_uInt8 color8Bit, sal_uInt8*& dst ) { *dst++ = color8Bit; *dst++ = color8Bit; *dst++ = color8Bit; *dst++ = 0xff; };
+typedef void(*WriteBlackWhiteFunction)( sal_uInt8*& dst, int count );
+void writeBlackA8(sal_uInt8*& dst, int count ) { memset( dst, 0, count ); dst += count; };
+void writeWhiteA8(sal_uInt8*& dst, int count ) { memset( dst, 0xff, count ); dst += count; };
+void writeBlackRGB(sal_uInt8*& dst, int count ) { memset( dst, 0, count * 3 ); dst += count * 3; };
+void writeWhiteRGB(sal_uInt8*& dst, int count ) { memset( dst, 0xff, count * 3 ); dst += count * 3; };
+void writeWhiteRGBA(sal_uInt8*& dst, int count ) { memset( dst, 0xff, count * 4 ); dst += count * 4; };
+void writeBlackRGBA(sal_uInt8*& dst, int count )
+{
+ for( int i = 0; i < count; ++i )
+ {
+ dst[0] = 0x00;
+ dst[1] = 0x00;
+ dst[2] = 0x00;
+ dst[3] = 0xff;
+ dst += 4;
+ }
+};
+
+template< WriteColorFunction func, WriteBlackWhiteFunction funcBlack, WriteBlackWhiteFunction funcWhite >
+void writeBlackWhiteData( const sal_uInt8* src, sal_uInt8* dst, int width, int height, int bytesPerRow )
+{
+ for( int y = 0; y < height; ++y )
+ {
+ const sal_uInt8* srcLine = src;
+ int xsize = width;
+ while( xsize >= 64 )
+ {
+ // TODO alignment?
+ const sal_uInt64* src64 = reinterpret_cast< const sal_uInt64* >( src );
+ if( *src64 == 0x00 )
+ funcBlack( dst, 64 );
+ else if( *src64 == static_cast< sal_uInt64 >( -1 ))
+ funcWhite( dst, 64 );
+ else
+ break;
+ src += sizeof( sal_uInt64 );
+ xsize -= 64;
+ }
+ while( xsize >= 8 )
+ {
+ if( *src == 0x00 ) // => eight black pixels
+ funcBlack( dst, 8 );
+ else if( *src == 0xff ) // => eight white pixels
+ funcWhite( dst, 8 );
+ else
+ for( int bit = 7; bit >= 0; --bit )
+ func(( *src >> bit ) & 1 ? 0xff : 0, dst );
+ ++src;
+ xsize -= 8;
+ }
+ for( int bit = 7; bit > 7 - xsize; --bit )
+ func(( *src >> bit ) & 1 ? 0xff : 0, dst );
+ ++src;
+ src = srcLine + bytesPerRow;
+ }
+}
+
} // namespace
std::unique_ptr< sal_uInt8[] > SalBitmap::convertDataBitCount( const sal_uInt8* src,
@@ -157,6 +221,29 @@ std::unique_ptr< sal_uInt8[] > SalBitmap::convertDataBitCount( const sal_uInt8*
return data;
}
+ if(bitCount == 1 && palette.GetEntryCount() == 2 && palette[ 0 ] == COL_BLACK && palette[ 1 ] == COL_WHITE)
+ {
+ switch( type )
+ {
+ case BitConvert::A8 :
+ writeBlackWhiteData< writeColorA8, writeBlackA8, writeWhiteA8 >
+ ( src, data.get(), width, height, bytesPerRow );
+ return data;
+ case BitConvert::BGR :
+ case BitConvert::RGB :
+ // BGR/RGB is the same, all 3 values get the same value
+ writeBlackWhiteData< writeColorRGB, writeBlackRGB, writeWhiteRGB >
+ ( src, data.get(), width, height, bytesPerRow );
+ return data;
+ case BitConvert::BGRA :
+ case BitConvert::RGBA :
+ // BGRA/RGBA is the same, all 3 values get the same value
+ writeBlackWhiteData< writeColorRGBA, writeBlackRGBA, writeWhiteRGBA >
+ ( src, data.get(), width, height, bytesPerRow );
+ return data;
+ }
+ }
+
std::unique_ptr<ImplPixelFormat> pSrcFormat(ImplPixelFormat::GetFormat(bitCount, palette));
const sal_uInt8* pSrcData = src;