/** Output pixels in "4 bit per pixel" format to an image. This is a internal function. @param Image Points to the image which will store the pixels. @param Data Stores the value of output pixels, 0 ~ 15. @param[in] PaletteInfo PaletteInfo which stores the color of the output pixels. Each entry corresponds to a color within [0, 15]. **/ VOID Output4bitPixel ( IN OUT EFI_IMAGE_INPUT *Image, IN UINT8 *Data, IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo ) { UINT16 Xpos; UINT16 Ypos; UINTN OffsetY; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr; EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16]; EFI_HII_IMAGE_PALETTE_INFO *Palette; UINT16 PaletteSize; UINT16 PaletteNum; UINT8 Byte; ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL); BitMapPtr = Image->Bitmap; // // The bitmap should allocate each color index starting from 0. // CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16)); PaletteSize += sizeof (UINT16); Palette = AllocateZeroPool (PaletteSize); ASSERT (Palette != NULL); CopyMem (Palette, PaletteInfo, PaletteSize); PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL)); ZeroMem (PaletteValue, sizeof (PaletteValue)); CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, PaletteNum); FreePool (Palette); // // Convert the pixel from 4 bit to corresponding color. // for (Ypos = 0; Ypos < Image->Height; Ypos++) { OffsetY = BITMAP_LEN_4_BIT (Image->Width, Ypos); // // All bits in these bytes are meaningful // for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) { Byte = *(Data + OffsetY + Xpos); BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4]; BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F]; } if (Image->Width % 2 != 0) { // // Padding bits in this byte should be ignored. // Byte = *(Data + OffsetY + Xpos); BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4]; } }
/** Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input ImageId is zero, otherwise return the address of the corresponding image block with identifier specified by ImageId. This is a internal function. @param ImageBlock Points to the beginning of a series of image blocks stored in order. @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK; else use this id to find its corresponding image block address. @return The image block address when input ImageId is not zero; otherwise return NULL. **/ UINT8* GetImageIdOrAddress ( IN UINT8 *ImageBlock, IN OUT EFI_IMAGE_ID *ImageId ) { EFI_IMAGE_ID ImageIdCurrent; UINT8 *ImageBlockHdr; UINT8 Length8; UINT16 Length16; UINT32 Length32; EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit; EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit; EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit; UINT16 Width; UINT16 Height; ASSERT (ImageBlock != NULL && ImageId != NULL); ImageBlockHdr = ImageBlock; ImageIdCurrent = 1; while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) { if (*ImageId > 0) { if (*ImageId == ImageIdCurrent) { // // If the found image block is a duplicate block, update the ImageId to // find the previous defined image block. // if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) { CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID)); ASSERT (*ImageId != ImageIdCurrent); ImageBlock = ImageBlockHdr; ImageIdCurrent = 1; continue; } return ImageBlock; } if (*ImageId < ImageIdCurrent) { // // Can not find the specified image block in this image. // return NULL; } } switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) { case EFI_HII_IIBT_EXT1: Length8 = *(UINT8*)((UINTN)ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8)); ImageBlock += Length8; break; case EFI_HII_IIBT_EXT2: CopyMem ( &Length16, (UINT8*)((UINTN)ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8)), sizeof (UINT16) ); ImageBlock += Length16; break; case EFI_HII_IIBT_EXT4: CopyMem ( &Length32, (UINT8*)((UINTN)ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8)), sizeof (UINT32) ); ImageBlock += Length32; break; case EFI_HII_IIBT_IMAGE_1BIT: case EFI_HII_IIBT_IMAGE_1BIT_TRANS: CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) + BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_4BIT: case EFI_HII_IIBT_IMAGE_4BIT_TRANS: CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) + BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_8BIT: case EFI_HII_IIBT_IMAGE_8BIT_TRANS: CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) + BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_24BIT: case EFI_HII_IIBT_IMAGE_24BIT_TRANS: CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16)); CopyMem ( &Height, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16), sizeof (UINT16) ); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) + BITMAP_LEN_24_BIT (Width, Height); ImageIdCurrent++; break; case EFI_HII_IIBT_DUPLICATE: ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_JPEG: CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32)); ImageBlock += Length32; ImageIdCurrent++; break; case EFI_HII_IIBT_SKIP1: Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK); ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8); break; case EFI_HII_IIBT_SKIP2: CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16)); ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK); ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16); break; default: // // Unknown image blocks can not be skipped, processing halts. // ASSERT (FALSE); } } // // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK. // if (*ImageId == 0) { *ImageId = ImageIdCurrent; return ImageBlock; } return NULL; }