--- /dev/null
+/** @file\r
+ This library provides BMP image decoding capability.\r
+\r
+Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under\r
+the terms and conditions of the BSD License that accompanies this distribution.\r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php.\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <IndustryStandard/Bmp.h>\r
+#include <Protocol/GraphicsOutput.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/ImageDecoderLib.h>\r
+\r
+/**\r
+ Convert a *.BMP graphics image to a callee allocated GOP blt buffer.\r
+\r
+ @param ImageFormat Format of the image file.\r
+ @param BmpImage Pointer to BMP file\r
+ @param BmpImageSize Number of bytes in BmpImage\r
+ @param GopBlt Buffer containing GOP version of BmpImage.\r
+ @param GopBltSize Size of GopBlt in bytes.\r
+ @param PixelHeight Height of GopBlt/BmpImage in pixels\r
+ @param PixelWidth Width of GopBlt/BmpImage in pixels\r
+\r
+ @retval EFI_SUCCESS GopBlt and GopBltSize are returned.\r
+ @retval EFI_INVALID_PARAMETER GopBlt or GopBltSize is NULL.\r
+ @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BmpImageDecoderLibConvertBmpToGopBlt (\r
+ IN IMAGE_FORMAT ImageFormat,\r
+ IN UINT8 *BmpImage,\r
+ IN UINTN BmpImageSize,\r
+ OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **GopBlt,\r
+ OUT UINTN *GopBltSize,\r
+ OUT UINTN *PixelWidth,\r
+ OUT UINTN *PixelHeight\r
+ )\r
+{\r
+ UINT8 *Image;\r
+ UINT8 *ImageHeader;\r
+ BMP_IMAGE_HEADER *BmpHeader;\r
+ BMP_COLOR_MAP *BmpColorMap;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
+ UINT64 BltBufferSize;\r
+ UINTN Index;\r
+ UINTN Height;\r
+ UINTN Width;\r
+ UINTN ImageIndex;\r
+ UINT32 DataSizePerLine;\r
+ UINT32 ColorMapNum;\r
+\r
+ ASSERT ((GopBlt != NULL) && (GopBltSize != NULL));\r
+\r
+ if (ImageFormat != ImageFormatBmp) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
+\r
+ if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Doesn't support compress.\r
+ //\r
+ if (BmpHeader->CompressionType != 0) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Only support BITMAPINFOHEADER format.\r
+ // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER\r
+ //\r
+ if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // The data size in each line must be 4 byte alignment.\r
+ //\r
+ DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);\r
+ BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);\r
+ if (BltBufferSize > (UINT32) ~0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((BmpHeader->Size != BmpImageSize) || \r
+ (BmpHeader->Size < BmpHeader->ImageOffset) ||\r
+ (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Calculate Color Map offset in the image.\r
+ //\r
+ Image = BmpImage;\r
+ BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
+ if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {\r
+ switch (BmpHeader->BitPerPixel) {\r
+ case 1:\r
+ ColorMapNum = 2;\r
+ break;\r
+ case 4:\r
+ ColorMapNum = 16;\r
+ break;\r
+ case 8:\r
+ ColorMapNum = 256;\r
+ break;\r
+ default:\r
+ ColorMapNum = 0;\r
+ break;\r
+ }\r
+ //\r
+ // BMP file may has padding data between the bmp header section and the bmp data section.\r
+ //\r
+ if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Calculate graphics image data address in the image\r
+ //\r
+ Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
+ ImageHeader = Image;\r
+\r
+ //\r
+ // Calculate the BltBuffer needed size.\r
+ //\r
+ BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);\r
+ //\r
+ // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
+ //\r
+ if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
+\r
+ *GopBltSize = (UINTN) BltBufferSize;\r
+ *GopBlt = AllocatePool (*GopBltSize);\r
+ if (*GopBlt == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ *PixelWidth = BmpHeader->PixelWidth;\r
+ *PixelHeight = BmpHeader->PixelHeight;\r
+\r
+ //\r
+ // Convert image from BMP to Blt buffer format\r
+ //\r
+ BltBuffer = *GopBlt;\r
+ for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
+ Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
+ for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
+ switch (BmpHeader->BitPerPixel) {\r
+ case 1:\r
+ //\r
+ // Convert 1-bit (2 colors) BMP to 24-bit color\r
+ //\r
+ for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
+ Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
+ Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
+ Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
+ Blt++;\r
+ Width++;\r
+ }\r
+\r
+ Blt--;\r
+ Width--;\r
+ break;\r
+\r
+ case 4:\r
+ //\r
+ // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
+ //\r
+ Index = (*Image) >> 4;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ if (Width < (BmpHeader->PixelWidth - 1)) {\r
+ Blt++;\r
+ Width++;\r
+ Index = (*Image) & 0x0f;\r
+ Blt->Red = BmpColorMap[Index].Red;\r
+ Blt->Green = BmpColorMap[Index].Green;\r
+ Blt->Blue = BmpColorMap[Index].Blue;\r
+ }\r
+ break;\r
+\r
+ case 8:\r
+ //\r
+ // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
+ //\r
+ Blt->Red = BmpColorMap[*Image].Red;\r
+ Blt->Green = BmpColorMap[*Image].Green;\r
+ Blt->Blue = BmpColorMap[*Image].Blue;\r
+ break;\r
+\r
+ case 24:\r
+ //\r
+ // It is 24-bit BMP.\r
+ //\r
+ Blt->Blue = *Image++;\r
+ Blt->Green = *Image++;\r
+ Blt->Red = *Image;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Other bit format BMP is not supported.\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+ break;\r
+ };\r
+\r
+ }\r
+\r
+ ImageIndex = (UINTN) (Image - ImageHeader);\r
+ if ((ImageIndex % 4) != 0) {\r
+ //\r
+ // Bmp Image starts each row on a 32-bit boundary!\r
+ //\r
+ Image = Image + (4 - (ImageIndex % 4));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialize BmpImageDecoderLib library.\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCCESS The BmpImageDecoderLib library is initialized correctly.\r
+ @return Other value if failed to initialize the BmpImageDecoderLib library.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BmpImageDecoderLibConstructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+)\r
+{\r
+ RegisterImageDecoder (BmpImageDecoderLibConvertBmpToGopBlt);\r
+ return EFI_SUCCESS;\r
+}\r
+\r