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