Bitmap block compression

CanvasBitmap supports block compressed bitmaps. These can be loaded from a DDS file, or created with CreateFromBytes(ICanvasResourceCreator,Byte[], Int32, Int32, DirectXPixelFormat).

Block compressed bitmaps are great for bitmap heavy applications (such as games) because they take up less memory and can be drawn more efficiently. A block compressed bitmap uses up to 1/8th of the memory of an uncompressed bitmap. As a result, the GPU needs to access much less memory when drawing the bitmap, resulting in faster drawing.

About block compression

Block compression is different to the compression employed by PNG or JPG files. Compressed file formats are stored compressed but when they are loaded by Win2D they are decompressed into a bitmap with a format such as DirectXPixelFormat::B8G8R8A8UIntNormalized, which uses 32 bits (4 bytes) per pixel. So a 256x256 bitmap would take up 256 * 256 * 4 = 262,144 bytes.

A block compressed bitmap uses 8 or 16 bytes (depending on the format -- more on this later) to store a block of 4x4 pixels. So in this case a 256x256 bitmap would take up 256 * 256 / (4 * 4) * 8 = 32,768 bytes, or 256 * 256 / (4 * 4) * 16 = 65,536 bytes. That's up to 8 times smaller! Since block compression is supported directly by the GPU hardware, the bitmap can be kept compressed in memory and drawn directly from the compressed format without ever having to completely uncompress it.

Win2D supports three block compressed formats. The table below describes these formats, along with an uncompressed format for comparison.

DirectXPixelFormat Size of 4x4 bitmap Size of 256x256 bitmap Alpha
BC1Unorm 8 bytes 32,768 bytes 1 bit
BC2Unorm 16 bytes 65,536 bytes 4 bit
BC3Unorm 16 bytes 65,536 bytes ~8 bit (compressed)
B8G8R8A8UintNormalized 64 bytes 262,144 bytes 8 bit

BC1Unorm, BC2Unorm and BC3Unorm differ mostly in how they support alpha. BC1 supports only 1-bit alpha. BC2 supports each pixel in the block having a unique 4-bit alpha value. BC3 compresses the alpha values.

See Direct2D Block Compression documentation and Direct3D Block Compression documentation for more information about how block compression works.

Restrictions

  • All block compressed textures must have a width and height that is a multiple of 4. This is because block compression works on blocks of 4x4 pixels.
  • Any operation on a sub-rectangle of a block compressed texture (using GetPixelBytes(), SetPixelBytes(Byte[]), CopyPixelsFromBitmap(CanvasBitmap, Int32, Int32)) require that the sub-rectangle is 4-pixel aligned.
  • Win2D requires premultiplied alpha when using block compressed formats.

Authoring DDS files

Block compressed images can be saved in DDS files. Although these can be generated by plugins to applications such as Photoshop or Paint.NET, care must be taken to ensure that the resulting file is saved with premultiplied alpha. Win2D will load any DDS file containing a BC1Unorm, BC2Unorm or BC3Unorm image and assume that it is authored with premultiplied alpha.

If you are authoring a C++ project then you can use the Image Content Pipeline to convert the image, as described on MSDN.

Alternatively, you can use texconv.exe from https://github.com/Microsoft/DirectXTex. texconv.exe can be built using the DirectXTex_Desktop_2015.sln solution. The following command converts "smoke.png" to a BC3Unorm with premultiplied alpha:

texconv -pmalpha -m 1 -f BC3_UNORM smoke.png