From: srs5694 Date: Tue, 15 Jan 2013 03:16:46 +0000 (-0500) Subject: Added PNG support for icons, selection images, & banners. X-Git-Url: https://code.delx.au/refind/commitdiff_plain/82a7c4ececec4d1db39fb7996b1c3689ea125f4c Added PNG support for icons, selection images, & banners. --- diff --git a/CREDITS.txt b/CREDITS.txt index be34553..2870038 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -53,6 +53,10 @@ Program (C source code) files: functionality in rEFInd. Most of the files in the mok subdirectory are based on Bottomley's PreBootloader code. +* The PNG support, in the files libeg/lodepng.c and libeg/lodepng.h, is a + slightly modified version of LodePNG (http://lodev.org/lodepng/) by Lode + Vandevenne. + Icons and graphics: ------------------- diff --git a/NEWS.txt b/NEWS.txt index 5a335cd..6b940ff 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,6 +1,8 @@ 0.6.5 (1/??/2013): ------------------ +- Added support for PNGs as banners, icons, and selectors. + - Added icon for ALT Linux. - Added "safemode" option to "hideui" token, to hide option to boot into diff --git a/libeg/Make.tiano b/libeg/Make.tiano index 9b196c7..647c3d0 100644 --- a/libeg/Make.tiano +++ b/libeg/Make.tiano @@ -5,7 +5,7 @@ include ../Make.tiano -SOURCE_NAMES = image load_bmp load_icns screen text +SOURCE_NAMES = image load_bmp load_icns lodepng screen text OBJS = $(SOURCE_NAMES:=.obj) #DRIVERNAME = ext2 #BUILDME = $(DRIVERNAME)_$(FILENAME_CODE).efi diff --git a/libeg/Makefile b/libeg/Makefile index 73c46db..7766472 100644 --- a/libeg/Makefile +++ b/libeg/Makefile @@ -9,7 +9,7 @@ VPATH = $(SRCDIR) LOCAL_CPPFLAGS = -I$(SRCDIR) -I$(SRCDIR)/../include -OBJS = screen.o image.o text.o load_bmp.o load_icns.o +OBJS = screen.o image.o text.o load_bmp.o load_icns.o lodepng.o TARGET = libeg.a all: $(TARGET) diff --git a/libeg/image.c b/libeg/image.c index cd25312..4cf282e 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) @@ -246,6 +247,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; @@ -304,6 +307,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() diff --git a/refind/icns.c b/refind/icns.c index a9b3f01..5cd9fcd 100644 --- a/refind/icns.c +++ b/refind/icns.c @@ -81,49 +81,65 @@ EG_IMAGE * BuiltinIcon(IN UINTN Id) return BuiltinIconTable[Id].Image; } +// Construct filename for all valid icon extensions and try to load it. +// Returns image data or NULL if it can't be found. +static EG_IMAGE * LoadIconAnyFormat(IN CHAR16 *IconsDir, IN CHAR16 *BaseName, IN CHAR16 *OsName) { + CHAR16 FileName[256]; + CHAR16 *Extension; + EG_IMAGE *Image = NULL; + UINTN Index = 0; + + while (((Extension = FindCommaDelimited(ICON_EXTENSIONS, Index++)) != NULL) && (Image == NULL)) { + SPrint(FileName, 255, L"%s\\%s_%s.%s", IconsDir, BaseName, OsName, Extension); + + // try to load it + Image = egLoadIcon(SelfDir, FileName, 128); + MyFreePool(Extension); + } // while() + return Image; +} // EG_IMAGE * LoadIconAnyFormat() + // // Load an icon for an operating system // // Load an OS icon from among the comma-delimited list provided in OSIconName. +// Searches for icons with extensions in the ICON_EXTENSIONS list (via +// LoadIconAnyFormat()). +// Returns image data. On failure, returns an ugly "dummy" icon. EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo) { - EG_IMAGE *Image; + EG_IMAGE *Image = NULL; CHAR16 *CutoutName; - CHAR16 FileName[256]; UINTN Index = 0; if (GlobalConfig.TextOnly) // skip loading if it's not used anyway return NULL; // try the names from OSIconName - while ((CutoutName = FindCommaDelimited(OSIconName, Index++)) != NULL) { - SPrint(FileName, 255, L"%s\\%s_%s.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR, - BootLogo ? L"boot" : L"os", CutoutName); - - // try to load it - Image = egLoadIcon(SelfDir, FileName, 128); - if (Image != NULL) { - MyFreePool(CutoutName); - return Image; - } - MyFreePool(CutoutName); - } // while + while (((CutoutName = FindCommaDelimited(OSIconName, Index++)) != NULL) && (Image == NULL)) { + Image = LoadIconAnyFormat(GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR, + BootLogo ? L"boot" : L"os", CutoutName); + MyFreePool(CutoutName); + } // while() // try the fallback name - SPrint(FileName, 255, L"%s\\%s_%s.icns", GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR, - BootLogo ? L"boot" : L"os", FallbackIconName); - Image = egLoadIcon(SelfDir, FileName, 128); - if (Image != NULL) - return Image; + if (Image == NULL) + Image = LoadIconAnyFormat(GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR, + BootLogo ? L"boot" : L"os", FallbackIconName); // try the fallback name with os_ instead of boot_ - if (BootLogo) - return LoadOSIcon(NULL, FallbackIconName, FALSE); + if (BootLogo && (Image == NULL)) + Image = LoadIconAnyFormat(GlobalConfig.IconsDir ? GlobalConfig.IconsDir : DEFAULT_ICONS_DIR, + L"os", FallbackIconName); - return DummyImage(128); + if (Image != NULL) + return Image; + else + return DummyImage(128); } /* EG_IMAGE * LoadOSIcon() */ + // // Load an image from a .icns file // @@ -143,11 +159,11 @@ EG_IMAGE * DummyImage(IN UINTN PixelSize) EG_IMAGE *Image; UINTN x, y, LineOffset; CHAR8 *Ptr, *YPtr; - + Image = egCreateFilledImage(PixelSize, PixelSize, TRUE, &BlackPixel); - + LineOffset = PixelSize * 4; - + YPtr = (CHAR8 *)Image->PixelData + ((PixelSize - 32) >> 1) * (LineOffset + 4); for (y = 0; y < 32; y++) { Ptr = YPtr; diff --git a/refind/icns.h b/refind/icns.h index bf8db1f..6035ee4 100644 --- a/refind/icns.h +++ b/refind/icns.h @@ -49,6 +49,8 @@ // icns loader module // +#define ICON_EXTENSIONS L"icns,png" + EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo); EG_IMAGE * LoadIcns(IN EFI_FILE_HANDLE BaseDir, IN CHAR16 *FileName, IN UINTN PixelSize); diff --git a/refind/main.c b/refind/main.c index ba1c694..6459939 100644 --- a/refind/main.c +++ b/refind/main.c @@ -128,7 +128,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.4.3"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.4.4"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");