mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-09-21 02:51:04 +02:00
fix bmp decoder error
Signed-off-by: Slice <sergey.slice@gmail.com>
This commit is contained in:
parent
8359929a2e
commit
cd78a41c5e
@ -19,19 +19,19 @@ typedef struct {
|
||||
} BMP_COLOR_MAP;
|
||||
|
||||
typedef struct {
|
||||
CHAR8 CharB;
|
||||
CHAR8 CharM;
|
||||
UINT32 Size;
|
||||
UINT16 Reserved[2];
|
||||
UINT32 ImageOffset;
|
||||
UINT32 HeaderSize;
|
||||
UINT32 PixelWidth;
|
||||
UINT32 PixelHeight;
|
||||
UINT16 Planes; ///< Must be 1
|
||||
UINT16 BitPerPixel; ///< 1, 4, 8, or 24
|
||||
UINT32 CompressionType;
|
||||
UINT32 ImageSize; ///< Compressed image size in bytes
|
||||
UINT32 XPixelsPerMeter;
|
||||
CHAR8 CharB; //B
|
||||
CHAR8 CharM; //M
|
||||
UINT32 Size; // 8A 44 01 00
|
||||
UINT16 Reserved[2]; // 00 00 00 00
|
||||
UINT32 ImageOffset; // 8A 00 00 00
|
||||
UINT32 HeaderSize; // 7C 00 00 00
|
||||
INT32 PixelWidth; // 90 00 00 00
|
||||
INT32 PixelHeight; // 70 FF FF FF
|
||||
UINT16 Planes; // 01 00 //< Must be 1
|
||||
UINT16 BitPerPixel; // 20 00 //< 1, 4, 8, or 24
|
||||
UINT32 CompressionType; // 03 00 0000
|
||||
UINT32 ImageSize; // 00 44 01 00 //< Compressed image size in bytes
|
||||
UINT32 XPixelsPerMeter; //
|
||||
UINT32 YPixelsPerMeter;
|
||||
UINT32 NumberOfColors;
|
||||
UINT32 ImportantColors;
|
||||
|
@ -690,6 +690,30 @@ EFI_STATUS REFIT_MENU_SCREEN::WaitForInputEventPoll(UINTN TimeoutDefault)
|
||||
return Status;
|
||||
}
|
||||
|
||||
void testBMP()
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *FileData = NULL;
|
||||
UINTN FileDataLength = 0;
|
||||
INTN Width = 256, Height = 256;
|
||||
|
||||
// load file
|
||||
Status = egLoadFile(&self.getSelfVolumeRootDir(), L"Sample.bmp", &FileData, &FileDataLength);
|
||||
|
||||
if (!EFI_ERROR(Status)) {
|
||||
DBG("read file size=%llu\n", FileDataLength);
|
||||
XImage NewImage(Width, Height);
|
||||
NewImage.FromBMP(FileData, FileDataLength);
|
||||
Width = NewImage.GetWidth();
|
||||
Height = NewImage.GetHeight();
|
||||
DBG("new image sizes w=%llu h=%llu\n", Width, Height);
|
||||
NewImage.Draw((UGAWidth - Width) / 2, (UGAHeight - Height) / 2);
|
||||
FreePool(FileData);
|
||||
FileData = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
UINTN REFIT_MENU_SCREEN::RunGenericMenu(IN OUT INTN *DefaultEntryIndex, OUT REFIT_ABSTRACT_MENU_ENTRY **ChosenEntry)
|
||||
{
|
||||
@ -975,7 +999,8 @@ UINTN REFIT_MENU_SCREEN::RunGenericMenu(IN OUT INTN *DefaultEntryIndex, OUT REFI
|
||||
|
||||
break;
|
||||
case SCAN_F8:
|
||||
testSVG();
|
||||
// testSVG();
|
||||
testBMP();
|
||||
// SaveHdaDumpBin();
|
||||
// SaveHdaDumpTxt();
|
||||
break;
|
||||
@ -1014,6 +1039,9 @@ UINTN REFIT_MENU_SCREEN::RunGenericMenu(IN OUT INTN *DefaultEntryIndex, OUT REFI
|
||||
MenuExit = MENU_EXIT_ENTER;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
testBMP();
|
||||
break;
|
||||
case ' ': //CHAR_SPACE
|
||||
if ((Entries[ScrollState.CurrentSelection].getREFIT_INPUT_DIALOG()) ||
|
||||
(Entries[ScrollState.CurrentSelection].getREFIT_MENU_CHECKBIT())) {
|
||||
|
@ -579,8 +579,10 @@ void XImage::Draw(INTN x, INTN y, float scale) const
|
||||
|
||||
void XImage::Draw(INTN x, INTN y, float scale, XBool Opaque) const
|
||||
{
|
||||
DBG("draw at %lld %lld\n", x, y);
|
||||
//prepare images
|
||||
if (isEmpty()) {
|
||||
DBG("emptyimage\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -34,11 +34,13 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "libegint.h"
|
||||
#include "../Platform/Utils.h"
|
||||
#include "XImage.h"
|
||||
|
||||
#include <IndustryStandard/Bmp.h>
|
||||
//#include "picopng.h"
|
||||
|
||||
//#define DBG(...) DebugLog(1, __VA_ARGS__)
|
||||
#define DBG(...)
|
||||
|
||||
// BMP structures
|
||||
@ -83,7 +85,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
// EG_IMAGE *NewImage;
|
||||
BMP_IMAGE_HEADER *BmpHeader;
|
||||
BMP_COLOR_MAP *BmpColorMap;
|
||||
UINT32 RealPixelHeight, RealPixelWidth;
|
||||
INT32 RealPixelHeight, RealPixelWidth;
|
||||
UINT8 *ImagePtr;
|
||||
UINT8 *ImagePtrBase;
|
||||
UINTN ImageLineOffset;
|
||||
@ -95,18 +97,25 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
// read and check header
|
||||
if (FileDataLength < sizeof(BMP_IMAGE_HEADER) || FileData == NULL) {
|
||||
setEmpty(); // to be 100% sure
|
||||
DBG("1\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
BmpHeader = (BMP_IMAGE_HEADER *) FileData;
|
||||
if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M')
|
||||
if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {
|
||||
DBG("2\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
if (BmpHeader->BitPerPixel != 1 && BmpHeader->BitPerPixel != 4 &&
|
||||
BmpHeader->BitPerPixel != 8 && BmpHeader->BitPerPixel != 24 &&
|
||||
BmpHeader->BitPerPixel != 32)
|
||||
BmpHeader->BitPerPixel != 32) {
|
||||
DBG("3\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
// 32-bit images are always stored uncompressed
|
||||
if (BmpHeader->CompressionType > 0 && BmpHeader->BitPerPixel != 32)
|
||||
if (BmpHeader->CompressionType > 0 && BmpHeader->BitPerPixel != 32) {
|
||||
DBG("4\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// calculate parameters
|
||||
ImageLineOffset = BmpHeader->PixelWidth;
|
||||
@ -121,11 +130,16 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
if ((ImageLineOffset % 4) != 0)
|
||||
ImageLineOffset = ImageLineOffset + (4 - (ImageLineOffset % 4));
|
||||
|
||||
DBG("ImageOffset=%d ImageLineOffset=%lld FileDataLength=%lld\n",
|
||||
BmpHeader->ImageOffset, ImageLineOffset, FileDataLength);
|
||||
|
||||
// check bounds
|
||||
RealPixelHeight = BmpHeader->PixelHeight > 0 ? BmpHeader->PixelHeight : -BmpHeader->PixelHeight;
|
||||
RealPixelWidth = BmpHeader->PixelWidth > 0 ? BmpHeader->PixelWidth : -BmpHeader->PixelWidth;
|
||||
if (BmpHeader->ImageOffset + ImageLineOffset * RealPixelHeight > FileDataLength)
|
||||
RealPixelHeight = (BmpHeader->PixelHeight > 0 ? BmpHeader->PixelHeight : -BmpHeader->PixelHeight);
|
||||
RealPixelWidth = (BmpHeader->PixelWidth > 0 ? BmpHeader->PixelWidth : -BmpHeader->PixelWidth);
|
||||
if (BmpHeader->ImageOffset + ImageLineOffset * RealPixelHeight > FileDataLength) {
|
||||
DBG("5 H=%d W=%d\n", RealPixelHeight, RealPixelWidth);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// allocate image structure and buffer
|
||||
// NewImage = egCreateImage(RealPixelWidth, RealPixelHeight, WantAlpha);
|
||||
@ -135,12 +149,13 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
|
||||
AlphaValue = 255;
|
||||
setSizeInPixels(RealPixelWidth, RealPixelHeight);
|
||||
DBG("set sizes %u,%u\n", 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++) {
|
||||
for (INT32 y = 0; y < RealPixelHeight; y++) {
|
||||
ImagePtr = ImagePtrBase;
|
||||
ImagePtrBase += ImageLineOffset;
|
||||
// vertically mirror
|
||||
@ -150,11 +165,11 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
} else {
|
||||
PixelPtr = GetPixelPtr(0,0) + (RealPixelHeight - 1 - y) * RealPixelWidth;
|
||||
}
|
||||
|
||||
DBG("6 BitPerPixel=%d\n", BmpHeader->BitPerPixel);
|
||||
switch (BmpHeader->BitPerPixel) {
|
||||
|
||||
case 1:
|
||||
for (UINT32 x = 0; x < RealPixelWidth; x++) {
|
||||
for (INT32 x = 0; x < RealPixelWidth; x++) {
|
||||
BitIndex = x & 0x07;
|
||||
if (BitIndex == 0)
|
||||
ImageValue = *ImagePtr++;
|
||||
@ -170,8 +185,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
|
||||
case 4:
|
||||
{
|
||||
UINT32 x;
|
||||
for (x = 0; x <= RealPixelWidth - 2; x += 2) {
|
||||
for (INT32 x = 0; x <= RealPixelWidth - 2; x += 2) {
|
||||
ImageValue = *ImagePtr++;
|
||||
|
||||
Index = ImageValue >> 4;
|
||||
@ -188,7 +202,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
PixelPtr->Reserved = AlphaValue;
|
||||
PixelPtr++;
|
||||
}
|
||||
if (x < RealPixelWidth) {
|
||||
if ((RealPixelWidth & 1) == 1) { // для нечетных
|
||||
ImageValue = *ImagePtr++;
|
||||
|
||||
Index = ImageValue >> 4;
|
||||
@ -201,7 +215,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
for (UINT32 x = 0; x < RealPixelWidth; x++) {
|
||||
for (INT32 x = 0; x < RealPixelWidth; x++) {
|
||||
Index = *ImagePtr++;
|
||||
PixelPtr->Blue = BmpColorMap[Index].Blue;
|
||||
PixelPtr->Green = BmpColorMap[Index].Green;
|
||||
@ -212,7 +226,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
break;
|
||||
|
||||
case 24:
|
||||
for (UINT32 x = 0; x < RealPixelWidth; x++) {
|
||||
for (INT32 x = 0; x < RealPixelWidth; x++) {
|
||||
PixelPtr->Blue = *ImagePtr++;
|
||||
PixelPtr->Green = *ImagePtr++;
|
||||
PixelPtr->Red = *ImagePtr++;
|
||||
@ -221,7 +235,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
for (UINT32 x = 0; x < RealPixelWidth; x++) {
|
||||
for (INT32 x = 0; x < RealPixelWidth; x++) {
|
||||
PixelPtr->Blue = *ImagePtr++;
|
||||
PixelPtr->Green = *ImagePtr++;
|
||||
PixelPtr->Red = *ImagePtr++;
|
||||
@ -233,6 +247,7 @@ EFI_STATUS XImage::FromBMP(UINT8 *FileData, IN UINTN FileDataLength)
|
||||
|
||||
}
|
||||
}
|
||||
DBG("sucсess\n");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -263,7 +278,7 @@ EFI_STATUS XImage::ToBMP(UINT8** FileDataReturn, UINTN& FileDataLengthReturn)
|
||||
FileDataLength = sizeof(BMP_IMAGE_HEADER) + MultU64x64(Height, ImageLineOffset);
|
||||
FileData = (UINT8*)AllocateZeroPool((UINTN)FileDataLength);
|
||||
if (FileData == NULL) {
|
||||
DBG("Error allocate %d bytes\n", FileDataLength);
|
||||
DBG("Error allocate %lld bytes\n", FileDataLength);
|
||||
*FileDataReturn = NULL;
|
||||
FileDataLengthReturn = 0;
|
||||
return EFI_NOT_FOUND;
|
||||
|
Loading…
Reference in New Issue
Block a user