add bmp coder/decoder

Signed-off-by: Slice <sergey.slice@gmail.com>
This commit is contained in:
Slice 2024-06-07 23:02:19 +03:00
parent e97864a4ad
commit 8359929a2e
8 changed files with 329 additions and 15 deletions

View File

@ -74,7 +74,7 @@ typedef struct {
EG_IMAGE *egDecodePNG(IN UINT8 *FileData, IN UINTN FileDataLength, IN BOOLEAN WantAlpha);
EG_IMAGE *egDecodeICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha);
EG_IMAGE * egDecodeBMP(IN UINT8 *FileData, IN UINTN FileDataLength, IN BOOLEAN WantAlpha);
EG_IMAGE *egDecodeBMP(IN UINT8 *FileData, IN UINTN FileDataLength, IN BOOLEAN WantAlpha);
VOID egFreeImage(IN EG_IMAGE *Image);
EG_IMAGE *egCreateImage(IN INTN Width, IN INTN Height, IN BOOLEAN HasAlpha);

View File

@ -70,9 +70,9 @@ then
bios_file=("$(dirname "$qemu_path")"/bios*)
diskutil umount /dev/disk3s1
diskutil umount /dev/disk3s2
diskutil eject disk3
diskutil umount /dev/disk5s1
diskutil umount /dev/disk5s2
diskutil eject disk5
"$qemu_path" \
-L "$(dirname "$qemu_path")" \
@ -94,7 +94,7 @@ diskutil eject disk3
# -hdc /JiefLand/5.Devel/Clover/CloverEfi.vmw/ElCapitan.vmdk \
hdiutil attach ./disk_image_gpt.img
diskutil mount disk3s1
diskutil mount disk5s1
fi

View File

@ -53,7 +53,7 @@ struct EFI_RES {
Num=20
1. avatar.png Offset=0x05EC (LittleEndian) Size=0x2DAF Offset+Size=0x339B
2. avatar@2x.png Offset=0x339C (!) Aligned Size=0x8432 End=0xB7CE
3. Offset=0xB7CD = 0x339B+0x8432 Not alinged(!!!) File=0xB7CE Aligned
3. Offset=0xB7CD = 0x339B+0x8432 Not aligned(!!!) File=0xB7CE Aligned
*/
XImage egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength)
@ -67,6 +67,11 @@ XImage egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength)
NewXImage.FromICNS(FileData, FileDataLength, 128);
}
if (NewXImage.isEmpty()) {
DBG(" ..png is wrong try to decode bmp\n");
NewXImage.FromBMP(FileData, FileDataLength);
}
return NewXImage;
}

View File

@ -381,6 +381,7 @@ void XImage::FlipRB()
}
}
/*
* The function converted plain array into XImage object
* Error = 0 - Success
@ -628,6 +629,7 @@ EFI_STATUS XImage::LoadXImage(const EFI_FILE *BaseDir, const wchar_t* LIconName)
{
return LoadXImage(BaseDir, XStringW().takeValueFrom(LIconName));
}
//dont call this procedure for SVG theme BaseDir == NULL?
//it can be used for other files
EFI_STATUS XImage::LoadXImage(const EFI_FILE *BaseDir, const XString8& IconName)

View File

@ -87,6 +87,8 @@ public:
EFI_STATUS ToPNG(UINT8** Data, UINTN& OutSize);
EFI_STATUS FromSVG(const CHAR8 *SVGData, float scale);
EFI_STATUS FromICNS(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize);
EFI_STATUS FromBMP(UINT8 * Data, UINTN Length);
EFI_STATUS ToBMP(UINT8** FileDataReturn, UINTN& FileDataLengthReturn);
void GetArea(const EG_RECT& Rect);
void GetArea(INTN x, INTN y, UINTN W, UINTN H);

View File

@ -0,0 +1,307 @@
/*
* libeg/load_bmp.c
* Loading function for BMP images
*
* Copyright (c) 2006 Christoph Pfisterer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Christoph Pfisterer nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "libegint.h"
#include "XImage.h"
#include <IndustryStandard/Bmp.h>
//#include "picopng.h"
#define DBG(...)
// BMP structures
//#pragma pack(1)
//
//typedef struct {
// UINT8 Blue;
// UINT8 Green;
// UINT8 Red;
// UINT8 Alpha;
//} BMP_COLOR_MAP;
//
//typedef struct {
// CHAR8 CharB;
// CHAR8 CharM;
// UINT32 Size;
// UINT16 Reserved[2];
// UINT32 ImageOffset;
// UINT32 HeaderSize;
// INT32 PixelWidth;
// INT32 PixelHeight;
// UINT16 Planes; // Must be 1
// UINT16 BitPerPixel; // 1, 4, 8, 24, or 32
// UINT32 CompressionType;
// UINT32 ImageSize; // Compressed image size in bytes
// UINT32 XPixelsPerMeter;
// UINT32 YPixelsPerMeter;
// UINT32 NumberOfColors;
// UINT32 ImportantColors;
//} BMP_IMAGE_HEADER;
//
//#pragma pack()
//
// Load BMP image
//
//EG_IMAGE * egDecodeBMP(IN UINT8 *FileData, IN UINTN FileDataLength, IN BOOLEAN WantAlpha)
EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
{
// EG_IMAGE *NewImage;
BMP_IMAGE_HEADER *BmpHeader;
BMP_COLOR_MAP *BmpColorMap;
UINT32 RealPixelHeight, RealPixelWidth;
UINT8 *ImagePtr;
UINT8 *ImagePtrBase;
UINTN ImageLineOffset;
UINT8 ImageValue = 0;
UINT8 AlphaValue;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *PixelPtr;
UINTN Index, BitIndex;
// read and check header
if (FileDataLength < sizeof(BMP_IMAGE_HEADER) || FileData == NULL) {
setEmpty(); // to be 100% sure
return EFI_NOT_FOUND;
}
BmpHeader = (BMP_IMAGE_HEADER *) FileData;
if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M')
return EFI_NOT_FOUND;
if (BmpHeader->BitPerPixel != 1 && BmpHeader->BitPerPixel != 4 &&
BmpHeader->BitPerPixel != 8 && BmpHeader->BitPerPixel != 24 &&
BmpHeader->BitPerPixel != 32)
return EFI_NOT_FOUND;
// 32-bit images are always stored uncompressed
if (BmpHeader->CompressionType > 0 && BmpHeader->BitPerPixel != 32)
return EFI_NOT_FOUND;
// calculate parameters
ImageLineOffset = BmpHeader->PixelWidth;
if (BmpHeader->BitPerPixel == 32)
ImageLineOffset *= 4;
else if (BmpHeader->BitPerPixel == 24)
ImageLineOffset *= 3;
else if (BmpHeader->BitPerPixel == 1)
ImageLineOffset = (ImageLineOffset + 7) >> 3;
else if (BmpHeader->BitPerPixel == 4)
ImageLineOffset = (ImageLineOffset + 1) >> 1;
if ((ImageLineOffset % 4) != 0)
ImageLineOffset = ImageLineOffset + (4 - (ImageLineOffset % 4));
// check bounds
RealPixelHeight = BmpHeader->PixelHeight > 0 ? BmpHeader->PixelHeight : -BmpHeader->PixelHeight;
RealPixelWidth = BmpHeader->PixelWidth > 0 ? BmpHeader->PixelWidth : -BmpHeader->PixelWidth;
if (BmpHeader->ImageOffset + ImageLineOffset * RealPixelHeight > FileDataLength)
return EFI_NOT_FOUND;
// allocate image structure and buffer
// NewImage = egCreateImage(RealPixelWidth, RealPixelHeight, WantAlpha);
// if (NewImage == NULL)
// return NULL;
// AlphaValue = WantAlpha ? 255 : 0;
AlphaValue = 255;
setSizeInPixels(RealPixelWidth, RealPixelHeight);
// PixelCount = RealPixelWidth * RealPixelHeight;
// convert image
BmpColorMap = (BMP_COLOR_MAP *)(FileData + sizeof(BMP_IMAGE_HEADER));
ImagePtrBase = FileData + BmpHeader->ImageOffset;
for (UINT32 y = 0; y < RealPixelHeight; y++) {
ImagePtr = ImagePtrBase;
ImagePtrBase += ImageLineOffset;
// vertically mirror
if (BmpHeader->PixelHeight != RealPixelHeight) {
PixelPtr = GetPixelPtr(0,0) + y * RealPixelWidth;
} else {
PixelPtr = GetPixelPtr(0,0) + (RealPixelHeight - 1 - y) * RealPixelWidth;
}
switch (BmpHeader->BitPerPixel) {
case 1:
for (UINT32 x = 0; x < RealPixelWidth; x++) {
BitIndex = x & 0x07;
if (BitIndex == 0)
ImageValue = *ImagePtr++;
Index = (ImageValue >> (7 - BitIndex)) & 0x01;
PixelPtr->Blue = BmpColorMap[Index].Blue;
PixelPtr->Green = BmpColorMap[Index].Green;
PixelPtr->Red = BmpColorMap[Index].Red;
PixelPtr->Reserved = AlphaValue;
PixelPtr++;
}
break;
case 4:
{
UINT32 x;
for (x = 0; x <= RealPixelWidth - 2; x += 2) {
ImageValue = *ImagePtr++;
Index = ImageValue >> 4;
PixelPtr->Blue = BmpColorMap[Index].Blue;
PixelPtr->Green = BmpColorMap[Index].Green;
PixelPtr->Red = BmpColorMap[Index].Red;
PixelPtr->Reserved = AlphaValue;
PixelPtr++;
Index = ImageValue & 0x0f;
PixelPtr->Blue = BmpColorMap[Index].Blue;
PixelPtr->Green = BmpColorMap[Index].Green;
PixelPtr->Red = BmpColorMap[Index].Red;
PixelPtr->Reserved = AlphaValue;
PixelPtr++;
}
if (x < RealPixelWidth) {
ImageValue = *ImagePtr++;
Index = ImageValue >> 4;
PixelPtr->Blue = BmpColorMap[Index].Blue;
PixelPtr->Green = BmpColorMap[Index].Green;
PixelPtr->Red = BmpColorMap[Index].Red;
PixelPtr->Reserved = AlphaValue;
PixelPtr++;
}
break;
}
case 8:
for (UINT32 x = 0; x < RealPixelWidth; x++) {
Index = *ImagePtr++;
PixelPtr->Blue = BmpColorMap[Index].Blue;
PixelPtr->Green = BmpColorMap[Index].Green;
PixelPtr->Red = BmpColorMap[Index].Red;
PixelPtr->Reserved = AlphaValue;
PixelPtr++;
}
break;
case 24:
for (UINT32 x = 0; x < RealPixelWidth; x++) {
PixelPtr->Blue = *ImagePtr++;
PixelPtr->Green = *ImagePtr++;
PixelPtr->Red = *ImagePtr++;
PixelPtr->Reserved = AlphaValue;
PixelPtr++;
}
break;
case 32:
for (UINT32 x = 0; x < RealPixelWidth; x++) {
PixelPtr->Blue = *ImagePtr++;
PixelPtr->Green = *ImagePtr++;
PixelPtr->Red = *ImagePtr++;
PixelPtr->Reserved = *ImagePtr++;
// if (!WantAlpha)
// PixelPtr->Reserved = 255 - PixelPtr->Reserved;
PixelPtr++;
}
}
}
return EFI_SUCCESS;
}
//
// Save BMP image
//
//VOID egEncodeBMP(IN EG_IMAGE *Image, OUT UINT8 **FileDataReturn, OUT UINTN *FileDataLengthReturn)
EFI_STATUS XImage::ToBMP(UINT8** FileDataReturn, UINTN& FileDataLengthReturn)
{
BMP_IMAGE_HEADER *BmpHeader;
UINT8 *FileData;
UINT64 FileDataLength;
UINT8 *ImagePtrBase;
UINT64 ImageLineOffset;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *PixelPtr;
UINT8 * ImagePtr = (UINT8 *)&PixelData[0];
ImageLineOffset = MultU64x32(Width, 3);
if ((ImageLineOffset & 3) != 0) {
ImageLineOffset = ImageLineOffset + (4 - (ImageLineOffset & 3));
}
// allocate buffer for file data
FileDataLength = sizeof(BMP_IMAGE_HEADER) + MultU64x64(Height, ImageLineOffset);
FileData = (UINT8*)AllocateZeroPool((UINTN)FileDataLength);
if (FileData == NULL) {
DBG("Error allocate %d bytes\n", FileDataLength);
*FileDataReturn = NULL;
FileDataLengthReturn = 0;
return EFI_NOT_FOUND;
}
// fill header
BmpHeader = (BMP_IMAGE_HEADER *)FileData;
BmpHeader->CharB = 'B';
BmpHeader->CharM = 'M';
BmpHeader->Size = (UINT32)FileDataLength;
BmpHeader->ImageOffset = sizeof(BMP_IMAGE_HEADER);
BmpHeader->HeaderSize = 40;
BmpHeader->PixelWidth = (UINT32)Width;
BmpHeader->PixelHeight = (UINT32)Height;
BmpHeader->Planes = 1;
BmpHeader->BitPerPixel = 24;
BmpHeader->CompressionType = 0;
BmpHeader->XPixelsPerMeter = 0xb13;
BmpHeader->YPixelsPerMeter = 0xb13;
// fill pixel buffer
ImagePtrBase = FileData + BmpHeader->ImageOffset;
for (size_t y = 0; y < Height; y++) {
ImagePtr = ImagePtrBase;
ImagePtrBase += ImageLineOffset;
// PixelPtr = Image->PixelData + (Image->Height - 1 - y) * Image->Width;
PixelPtr = GetPixelPtr(0,0) + (INT32)(Height - 1 - y) * (INT32)Width;
for (size_t x = 0; x < Width; x++) {
*ImagePtr++ = PixelPtr->Blue;
*ImagePtr++ = PixelPtr->Green;
*ImagePtr++ = PixelPtr->Red;
PixelPtr++;
}
}
*FileDataReturn = FileData;
FileDataLengthReturn = (UINTN)FileDataLength;
return EFI_SUCCESS;
}
/* EOF */

View File

@ -55,12 +55,11 @@
//these functions used for icns, not with png
void egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
{
UINTN i;
if (!SrcDataPtr || !DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
for (UINTN i = 0; i < PixelCount; i++) {
*DestPlanePtr = *SrcDataPtr++;
DestPlanePtr += 4;
}
@ -68,12 +67,11 @@ void egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelC
void egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINT64 PixelCount)
{
UINT64 i;
if (!DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
for (UINT64 i = 0; i < PixelCount; i++) {
*DestPlanePtr = Value;
DestPlanePtr += 4;
}
@ -81,12 +79,11 @@ void egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINT64 PixelCount)
void egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
{
UINTN i;
if (!SrcPlanePtr || !DestPlanePtr) {
return;
}
for (i = 0; i < PixelCount; i++) {
for (UINTN i = 0; i < PixelCount; i++) {
*DestPlanePtr = *SrcPlanePtr;
DestPlanePtr += 4; SrcPlanePtr += 4;
}
@ -103,7 +100,7 @@ void egDecompressIcnsRLE(IN OUT UINT8 **CompData, IN OUT UINTN *CompLen, IN UINT
UINT8 *cp_end;
UINT8 *pp;
UINTN pp_left;
UINTN len, i;
UINTN len;
UINT8 value;
// setup variables
@ -120,7 +117,7 @@ void egDecompressIcnsRLE(IN OUT UINT8 **CompData, IN OUT UINTN *CompLen, IN UINT
if (len > pp_left)
break;
value = *cp++;
for (i = 0; i < len; i++) {
for (UINTN i = 0; i < len; i++) {
*pp = value;
pp += 4;
}
@ -128,7 +125,7 @@ void egDecompressIcnsRLE(IN OUT UINT8 **CompData, IN OUT UINTN *CompLen, IN UINT
len++;
if (len > pp_left || cp + len > cp_end)
break;
for (i = 0; i < len; i++) {
for (UINTN i = 0; i < len; i++) {
*pp = *cp++;
pp += 4;
}

View File

@ -181,6 +181,7 @@
libeg/load_icns.cpp
libeg/lodepng.cpp
libeg/lodepng.h
libeg/load_bmp.cpp
libeg/nanosvg.cpp
libeg/nanosvg.h
libeg/nanosvgrast.cpp