X-Git-Url: https://code.delx.au/refind/blobdiff_plain/4c9f41e161bd197922912efbcf4cc676077d5c00..a3dd82017d0be4d3fdca46a722b41b5ff3777139:/libeg/image.c diff --git a/libeg/image.c b/libeg/image.c index 28d2472..e940942 100644 --- a/libeg/image.c +++ b/libeg/image.c @@ -39,6 +39,7 @@ #include "../refind/lib.h" #include "../refind/screen.h" #include "../include/refit_call_wrapper.h" +#include "lodepng.h" #define MAX_FILE_SIZE (1024*1024*1024) @@ -94,6 +95,27 @@ EG_IMAGE * egCopyImage(IN EG_IMAGE *Image) return NewImage; } +// Returns a smaller image composed of the specified crop area from the larger area. +// If the specified area is larger than is in the original, returns NULL. +EG_IMAGE * egCropImage(IN EG_IMAGE *Image, IN UINTN StartX, IN UINTN StartY, IN UINTN Width, IN UINTN Height) { + EG_IMAGE *NewImage = NULL; + UINTN x, y; + + if (((StartX + Width) > Image->Width) || ((StartY + Height) > Image->Height)) + return NULL; + + NewImage = egCreateImage(Width, Height, Image->HasAlpha); + if (NewImage == NULL) + return NULL; + + for (y = 0; y < Height; y++) { + for (x = 0; x < Width; x++) { + NewImage->PixelData[y * NewImage->Width + x] = Image->PixelData[(y + StartY) * Image->Width + x + StartX]; + } + } + return NewImage; +} // EG_IMAGE * egCropImage() + VOID egFreeImage(IN EG_IMAGE *Image) { if (Image != NULL) { @@ -211,6 +233,9 @@ static CHAR16 * egFindExtension(IN CHAR16 *FileName) return FileName + StrLen(FileName); } +// Decode the specified data as the specified format. The IconSize parameter is +// relevant only for ICNS, for which it selects which ICNS sub-image is decoded. +// Returns a pointer to the resulting EG_IMAGE or NULL if decoding failed. static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength, IN CHAR16 *Format, IN UINTN IconSize, IN BOOLEAN WantAlpha) { @@ -225,6 +250,8 @@ static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength, NewImage = egDecodeBMP(FileData, FileDataLength, IconSize, WantAlpha); } else if ((StriCmp(Format, L"ICNS") == 0) || (StriCmp(Format, L"icns") == 0)) { NewImage = egDecodeICNS(FileData, FileDataLength, IconSize, WantAlpha); + } else if ((StriCmp(Format, L"PNG") == 0) || (StriCmp(Format, L"png") == 0)) { + NewImage = egDecodePNG(FileData, FileDataLength, IconSize, WantAlpha); } // if/else return NewImage; @@ -283,6 +310,11 @@ EG_IMAGE * egLoadIcon(IN EFI_FILE* BaseDir, IN CHAR16 *Path, IN UINTN IconSize) // decode it NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(Path), IconSize, TRUE); FreePool(FileData); + if ((NewImage->Width != IconSize) || (NewImage->Height != IconSize)) { + Print(L"Warning: Attempt to load icon of the wrong size from '%s'\n", Path); + MyFreePool(NewImage); + NewImage = NULL; + } return NewImage; } // EG_IMAGE *egLoadIcon() @@ -399,11 +431,11 @@ VOID egFillImage(IN OUT EG_IMAGE *CompImage, IN EG_PIXEL *Color) UINTN i; EG_PIXEL FillColor; EG_PIXEL *PixelPtr; - + FillColor = *Color; if (!CompImage->HasAlpha) FillColor.a = 0; - + PixelPtr = CompImage->PixelData; for (i = 0; i < CompImage->Width * CompImage->Height; i++, PixelPtr++) *PixelPtr = FillColor; @@ -418,14 +450,14 @@ VOID egFillImageArea(IN OUT EG_IMAGE *CompImage, EG_PIXEL FillColor; EG_PIXEL *PixelPtr; EG_PIXEL *PixelBasePtr; - + egRestrictImageArea(CompImage, AreaPosX, AreaPosY, &AreaWidth, &AreaHeight); - + if (AreaWidth > 0) { FillColor = *Color; if (!CompImage->HasAlpha) FillColor.a = 0; - + PixelBasePtr = CompImage->PixelData + AreaPosY * CompImage->Width + AreaPosX; for (y = 0; y < AreaHeight; y++) { PixelPtr = PixelBasePtr; @@ -442,7 +474,7 @@ VOID egRawCopy(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr, { UINTN x, y; EG_PIXEL *TopPtr, *CompPtr; - + for (y = 0; y < Height; y++) { TopPtr = TopBasePtr; CompPtr = CompBasePtr; @@ -464,7 +496,7 @@ VOID egRawCompose(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr, UINTN Alpha; UINTN RevAlpha; UINTN Temp; - + for (y = 0; y < Height; y++) { TopPtr = TopBasePtr; CompPtr = CompBasePtr; @@ -492,24 +524,25 @@ VOID egRawCompose(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr, VOID egComposeImage(IN OUT EG_IMAGE *CompImage, IN EG_IMAGE *TopImage, IN UINTN PosX, IN UINTN PosY) { UINTN CompWidth, CompHeight; - + CompWidth = TopImage->Width; CompHeight = TopImage->Height; egRestrictImageArea(CompImage, PosX, PosY, &CompWidth, &CompHeight); - + // compose if (CompWidth > 0) { - if (CompImage->HasAlpha) { - CompImage->HasAlpha = FALSE; - egSetPlane(PLPTR(CompImage, a), 0, CompImage->Width * CompImage->Height); - } - - if (TopImage->HasAlpha) +// if (CompImage->HasAlpha) { +// CompImage->HasAlpha = FALSE; +// egSetPlane(PLPTR(CompImage, a), 0, CompImage->Width * CompImage->Height); +// } + + if (TopImage->HasAlpha) { egRawCompose(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData, CompWidth, CompHeight, CompImage->Width, TopImage->Width); - else + } else { egRawCopy(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData, CompWidth, CompHeight, CompImage->Width, TopImage->Width); + } } } @@ -521,7 +554,7 @@ EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height return NULL; if (Image->Width == Width && Image->Height == Height) return Image; - + NewImage = egCreateFilledImage(Width, Height, Image->HasAlpha, Color); if (NewImage == NULL) { egFreeImage(Image); @@ -529,7 +562,7 @@ EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height } egComposeImage(NewImage, Image, 0, 0); egFreeImage(Image); - + return NewImage; } @@ -540,7 +573,7 @@ EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount) { UINTN i; - + for (i = 0; i < PixelCount; i++) { *DestPlanePtr = *SrcDataPtr++; DestPlanePtr += 4; @@ -550,7 +583,7 @@ VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelC VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINTN PixelCount) { UINTN i; - + for (i = 0; i < PixelCount; i++) { *DestPlanePtr = Value; DestPlanePtr += 4; @@ -560,7 +593,7 @@ VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINTN PixelCount) VOID egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount) { UINTN i; - + for (i = 0; i < PixelCount; i++) { *DestPlanePtr = *SrcPlanePtr; DestPlanePtr += 4, SrcPlanePtr += 4;