3 * Image handling functions
5 * Copyright (c) 2006 Christoph Pfisterer
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the
20 * * Neither the name of Christoph Pfisterer nor the names of the
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 * Modifications copyright (c) 2012-2015 Roderick W. Smith
39 * Modifications distributed under the terms of the GNU General Public
40 * License (GPL) version 3 (GPLv3), or (at your option) any later version.
44 * This program is free software: you can redistribute it and/or modify
45 * it under the terms of the GNU General Public License as published by
46 * the Free Software Foundation, either version 3 of the License, or
47 * (at your option) any later version.
49 * This program is distributed in the hope that it will be useful,
50 * but WITHOUT ANY WARRANTY; without even the implied warranty of
51 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52 * GNU General Public License for more details.
54 * You should have received a copy of the GNU General Public License
55 * along with this program. If not, see <http://www.gnu.org/licenses/>.
59 #include "../refind/global.h"
60 #include "../refind/lib.h"
61 #include "../refind/screen.h"
62 #include "../refind/mystrings.h"
63 #include "../include/refit_call_wrapper.h"
66 #define MAX_FILE_SIZE (1024*1024*1024)
68 // Multiplier for pseudo-floating-point operations in egScaleImage().
69 // A value of 4096 should keep us within limits on 32-bit systems, but I've
70 // seen some minor artifacts at this level, so give it a bit more precision
71 // on 64-bit systems....
73 #define FP_MULTIPLIER (UINTN) 65536
75 #define FP_MULTIPLIER (UINTN) 4096
78 #ifndef __MAKEWITH_GNUEFI
79 #define LibLocateHandle gBS->LocateHandleBuffer
80 #define LibOpenRoot EfiLibOpenRoot
84 // Basic image handling
87 EG_IMAGE
* egCreateImage(IN UINTN Width
, IN UINTN Height
, IN BOOLEAN HasAlpha
)
91 NewImage
= (EG_IMAGE
*) AllocatePool(sizeof(EG_IMAGE
));
94 NewImage
->PixelData
= (EG_PIXEL
*) AllocatePool(Width
* Height
* sizeof(EG_PIXEL
));
95 if (NewImage
->PixelData
== NULL
) {
96 egFreeImage(NewImage
);
100 NewImage
->Width
= Width
;
101 NewImage
->Height
= Height
;
102 NewImage
->HasAlpha
= HasAlpha
;
106 EG_IMAGE
* egCreateFilledImage(IN UINTN Width
, IN UINTN Height
, IN BOOLEAN HasAlpha
, IN EG_PIXEL
*Color
)
110 NewImage
= egCreateImage(Width
, Height
, HasAlpha
);
111 if (NewImage
== NULL
)
114 egFillImage(NewImage
, Color
);
118 EG_IMAGE
* egCopyImage(IN EG_IMAGE
*Image
)
120 EG_IMAGE
*NewImage
= NULL
;
123 NewImage
= egCreateImage(Image
->Width
, Image
->Height
, Image
->HasAlpha
);
124 if (NewImage
== NULL
)
127 CopyMem(NewImage
->PixelData
, Image
->PixelData
, Image
->Width
* Image
->Height
* sizeof(EG_PIXEL
));
131 // Returns a smaller image composed of the specified crop area from the larger area.
132 // If the specified area is larger than is in the original, returns NULL.
133 EG_IMAGE
* egCropImage(IN EG_IMAGE
*Image
, IN UINTN StartX
, IN UINTN StartY
, IN UINTN Width
, IN UINTN Height
) {
134 EG_IMAGE
*NewImage
= NULL
;
137 if (((StartX
+ Width
) > Image
->Width
) || ((StartY
+ Height
) > Image
->Height
))
140 NewImage
= egCreateImage(Width
, Height
, Image
->HasAlpha
);
141 if (NewImage
== NULL
)
144 for (y
= 0; y
< Height
; y
++) {
145 for (x
= 0; x
< Width
; x
++) {
146 NewImage
->PixelData
[y
* NewImage
->Width
+ x
] = Image
->PixelData
[(y
+ StartY
) * Image
->Width
+ x
+ StartX
];
150 } // EG_IMAGE * egCropImage()
152 // The following function implements a bilinear image scaling algorithm, based on
153 // code presented at http://tech-algorithm.com/articles/bilinear-image-scaling/.
154 // Resize an image; returns pointer to resized image if successful, NULL otherwise.
155 // Calling function is responsible for freeing allocated memory.
156 // NOTE: x_ratio, y_ratio, x_diff, and y_diff should really be float values;
157 // however, I've found that my 32-bit Mac Mini has a buggy EFI (or buggy CPU?), which
158 // causes this function to hang on float-to-UINT8 conversions on some (but not all!)
159 // float values. Therefore, this function uses integer arithmetic but multiplies
160 // all values by FP_MULTIPLIER to achieve something resembling the sort of precision
161 // needed for good results.
162 EG_IMAGE
* egScaleImage(IN EG_IMAGE
*Image
, IN UINTN NewWidth
, IN UINTN NewHeight
) {
163 EG_IMAGE
*NewImage
= NULL
;
168 UINTN x_ratio
, y_ratio
, x_diff
, y_diff
;
170 if ((Image
== NULL
) || (Image
->Height
== 0) || (Image
->Width
== 0) || (NewWidth
== 0) || (NewHeight
== 0))
173 if ((Image
->Width
== NewWidth
) && (Image
->Height
== NewHeight
))
174 return (egCopyImage(Image
));
176 NewImage
= egCreateImage(NewWidth
, NewHeight
, Image
->HasAlpha
);
177 if (NewImage
== NULL
)
180 x_ratio
= ((Image
->Width
- 1) * FP_MULTIPLIER
) / NewWidth
;
181 y_ratio
= ((Image
->Height
- 1) * FP_MULTIPLIER
) / NewHeight
;
183 for (i
= 0; i
< NewHeight
; i
++) {
184 for (j
= 0; j
< NewWidth
; j
++) {
185 x
= (j
* (Image
->Width
- 1)) / NewWidth
;
186 y
= (i
* (Image
->Height
- 1)) / NewHeight
;
187 x_diff
= (x_ratio
* j
) - x
* FP_MULTIPLIER
;
188 y_diff
= (y_ratio
* i
) - y
* FP_MULTIPLIER
;
189 Index
= ((y
* Image
->Width
) + x
);
190 a
= Image
->PixelData
[Index
];
191 b
= Image
->PixelData
[Index
+ 1];
192 c
= Image
->PixelData
[Index
+ Image
->Width
];
193 d
= Image
->PixelData
[Index
+ Image
->Width
+ 1];
196 NewImage
->PixelData
[Offset
].b
= ((a
.b
) * (FP_MULTIPLIER
- x_diff
) * (FP_MULTIPLIER
- y_diff
) +
197 (b
.b
) * (x_diff
) * (FP_MULTIPLIER
- y_diff
) +
198 (c
.b
) * (y_diff
) * (FP_MULTIPLIER
- x_diff
) +
199 (d
.b
) * (x_diff
* y_diff
)) / (FP_MULTIPLIER
* FP_MULTIPLIER
);
202 NewImage
->PixelData
[Offset
].g
= ((a
.g
) * (FP_MULTIPLIER
- x_diff
) * (FP_MULTIPLIER
- y_diff
) +
203 (b
.g
) * (x_diff
) * (FP_MULTIPLIER
- y_diff
) +
204 (c
.g
) * (y_diff
) * (FP_MULTIPLIER
- x_diff
) +
205 (d
.g
) * (x_diff
* y_diff
)) / (FP_MULTIPLIER
* FP_MULTIPLIER
);
208 NewImage
->PixelData
[Offset
].r
= ((a
.r
) * (FP_MULTIPLIER
- x_diff
) * (FP_MULTIPLIER
- y_diff
) +
209 (b
.r
) * (x_diff
) * (FP_MULTIPLIER
- y_diff
) +
210 (c
.r
) * (y_diff
) * (FP_MULTIPLIER
- x_diff
) +
211 (d
.r
) * (x_diff
* y_diff
)) / (FP_MULTIPLIER
* FP_MULTIPLIER
);
214 NewImage
->PixelData
[Offset
++].a
= ((a
.a
) * (FP_MULTIPLIER
- x_diff
) * (FP_MULTIPLIER
- y_diff
) +
215 (b
.a
) * (x_diff
) * (FP_MULTIPLIER
- y_diff
) +
216 (c
.a
) * (y_diff
) * (FP_MULTIPLIER
- x_diff
) +
217 (d
.a
) * (x_diff
* y_diff
)) / (FP_MULTIPLIER
* FP_MULTIPLIER
);
221 } // EG_IMAGE * egScaleImage()
223 VOID
egFreeImage(IN EG_IMAGE
*Image
)
226 if (Image
->PixelData
!= NULL
)
227 FreePool(Image
->PixelData
);
233 // Basic file operations
236 EFI_STATUS
egLoadFile(IN EFI_FILE
*BaseDir
, IN CHAR16
*FileName
, OUT UINT8
**FileData
, OUT UINTN
*FileDataLength
)
239 EFI_FILE_HANDLE FileHandle
;
240 EFI_FILE_INFO
*FileInfo
;
245 if ((BaseDir
== NULL
) || (FileName
== NULL
))
246 return EFI_NOT_FOUND
;
248 Status
= refit_call5_wrapper(BaseDir
->Open
, BaseDir
, &FileHandle
, FileName
, EFI_FILE_MODE_READ
, 0);
249 if (EFI_ERROR(Status
)) {
253 FileInfo
= LibFileInfo(FileHandle
);
254 if (FileInfo
== NULL
) {
255 refit_call1_wrapper(FileHandle
->Close
, FileHandle
);
256 return EFI_NOT_FOUND
;
258 ReadSize
= FileInfo
->FileSize
;
259 if (ReadSize
> MAX_FILE_SIZE
)
260 ReadSize
= MAX_FILE_SIZE
;
263 BufferSize
= (UINTN
)ReadSize
; // was limited to 1 GB above, so this is safe
264 Buffer
= (UINT8
*) AllocatePool(BufferSize
);
265 if (Buffer
== NULL
) {
266 refit_call1_wrapper(FileHandle
->Close
, FileHandle
);
267 return EFI_OUT_OF_RESOURCES
;
270 Status
= refit_call3_wrapper(FileHandle
->Read
, FileHandle
, &BufferSize
, Buffer
);
271 refit_call1_wrapper(FileHandle
->Close
, FileHandle
);
272 if (EFI_ERROR(Status
)) {
278 *FileDataLength
= BufferSize
;
282 static EFI_GUID ESPGuid
= { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
284 EFI_STATUS
egFindESP(OUT EFI_FILE_HANDLE
*RootDir
)
287 UINTN HandleCount
= 0;
290 Status
= LibLocateHandle(ByProtocol
, &ESPGuid
, NULL
, &HandleCount
, &Handles
);
291 if (!EFI_ERROR(Status
) && HandleCount
> 0) {
292 *RootDir
= LibOpenRoot(Handles
[0]);
293 if (*RootDir
== NULL
)
294 Status
= EFI_NOT_FOUND
;
300 EFI_STATUS
egSaveFile(IN EFI_FILE
* BaseDir OPTIONAL
, IN CHAR16
*FileName
,
301 IN UINT8
*FileData
, IN UINTN FileDataLength
)
304 EFI_FILE_HANDLE FileHandle
;
307 if (BaseDir
== NULL
) {
308 Status
= egFindESP(&BaseDir
);
309 if (EFI_ERROR(Status
))
313 Status
= refit_call5_wrapper(BaseDir
->Open
, BaseDir
, &FileHandle
, FileName
,
314 EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
| EFI_FILE_MODE_CREATE
, 0);
315 if (EFI_ERROR(Status
))
318 BufferSize
= FileDataLength
;
319 Status
= refit_call3_wrapper(FileHandle
->Write
, FileHandle
, &BufferSize
, FileData
);
320 refit_call1_wrapper(FileHandle
->Close
, FileHandle
);
326 // Loading images from files and embedded data
329 // Decode the specified image data. The IconSize parameter is relevant only
330 // for ICNS, for which it selects which ICNS sub-image is decoded.
331 // Returns a pointer to the resulting EG_IMAGE or NULL if decoding failed.
332 static EG_IMAGE
* egDecodeAny(IN UINT8
*FileData
, IN UINTN FileDataLength
, IN UINTN IconSize
, IN BOOLEAN WantAlpha
)
334 EG_IMAGE
*NewImage
= NULL
;
336 NewImage
= egDecodeICNS(FileData
, FileDataLength
, IconSize
, WantAlpha
);
337 if (NewImage
== NULL
)
338 NewImage
= egDecodePNG(FileData
, FileDataLength
, IconSize
, WantAlpha
);
339 if (NewImage
== NULL
)
340 NewImage
= egDecodeBMP(FileData
, FileDataLength
, IconSize
, WantAlpha
);
345 EG_IMAGE
* egLoadImage(IN EFI_FILE
* BaseDir
, IN CHAR16
*FileName
, IN BOOLEAN WantAlpha
)
349 UINTN FileDataLength
;
352 if (BaseDir
== NULL
|| FileName
== NULL
)
356 Status
= egLoadFile(BaseDir
, FileName
, &FileData
, &FileDataLength
);
357 if (EFI_ERROR(Status
))
361 NewImage
= egDecodeAny(FileData
, FileDataLength
, 128 /* arbitrary value */, WantAlpha
);
367 // Load an icon from (BaseDir)/Path, extracting the icon of size IconSize x IconSize.
368 // Returns a pointer to the image data, or NULL if the icon could not be loaded.
369 EG_IMAGE
* egLoadIcon(IN EFI_FILE
* BaseDir
, IN CHAR16
*Path
, IN UINTN IconSize
)
373 UINTN FileDataLength
;
374 EG_IMAGE
*Image
, *NewImage
;
376 if (BaseDir
== NULL
|| Path
== NULL
)
380 Status
= egLoadFile(BaseDir
, Path
, &FileData
, &FileDataLength
);
381 if (EFI_ERROR(Status
))
385 Image
= egDecodeAny(FileData
, FileDataLength
, IconSize
, TRUE
);
387 if ((Image
->Width
!= IconSize
) || (Image
->Height
!= IconSize
)) {
388 NewImage
= egScaleImage(Image
, IconSize
, IconSize
);
390 Print(L
"Warning: Unable to scale icon of the wrong size from '%s'\n", Path
);
396 } // EG_IMAGE *egLoadIcon()
398 // Returns an icon of any type from the specified subdirectory using the specified
399 // base name. All directory references are relative to BaseDir. For instance, if
400 // SubdirName is "myicons" and BaseName is "os_linux", this function will return
401 // an image based on "myicons/os_linux.icns" or "myicons/os_linux.png", in that
402 // order of preference. Returns NULL if no such file is a valid icon file.
403 EG_IMAGE
* egLoadIconAnyType(IN EFI_FILE
*BaseDir
, IN CHAR16
*SubdirName
, IN CHAR16
*BaseName
, IN UINTN IconSize
) {
404 EG_IMAGE
*Image
= NULL
;
406 CHAR16 FileName
[256];
409 while (((Extension
= FindCommaDelimited(ICON_EXTENSIONS
, i
++)) != NULL
) && (Image
== NULL
)) {
410 SPrint(FileName
, 255, L
"%s\\%s.%s", SubdirName
, BaseName
, Extension
);
411 Image
= egLoadIcon(BaseDir
, FileName
, IconSize
);
412 MyFreePool(Extension
);
416 } // EG_IMAGE *egLoadIconAnyType()
418 // Returns an icon with any extension in ICON_EXTENSIONS from either the directory
419 // specified by GlobalConfig.IconsDir or DEFAULT_ICONS_DIR. The input BaseName
420 // should be the icon name without an extension. For instance, if BaseName is
421 // os_linux, GlobalConfig.IconsDir is myicons, DEFAULT_ICONS_DIR is icons, and
422 // ICON_EXTENSIONS is "icns,png", this function will return myicons/os_linux.icns,
423 // myicons/os_linux.png, icons/os_linux.icns, or icons/os_linux.png, in that
424 // order of preference. Returns NULL if no such icon can be found. All file
425 // references are relative to SelfDir.
426 EG_IMAGE
* egFindIcon(IN CHAR16
*BaseName
, IN UINTN IconSize
) {
427 EG_IMAGE
*Image
= NULL
;
429 if (GlobalConfig
.IconsDir
!= NULL
) {
430 Image
= egLoadIconAnyType(SelfDir
, GlobalConfig
.IconsDir
, BaseName
, IconSize
);
434 Image
= egLoadIconAnyType(SelfDir
, DEFAULT_ICONS_DIR
, BaseName
, IconSize
);
438 } // EG_IMAGE * egFindIcon()
440 EG_IMAGE
* egPrepareEmbeddedImage(IN EG_EMBEDDED_IMAGE
*EmbeddedImage
, IN BOOLEAN WantAlpha
)
448 if (EmbeddedImage
->PixelMode
> EG_MAX_EIPIXELMODE
||
449 (EmbeddedImage
->CompressMode
!= EG_EICOMPMODE_NONE
&& EmbeddedImage
->CompressMode
!= EG_EICOMPMODE_RLE
))
452 // allocate image structure and pixel buffer
453 NewImage
= egCreateImage(EmbeddedImage
->Width
, EmbeddedImage
->Height
, WantAlpha
);
454 if (NewImage
== NULL
)
457 CompData
= (UINT8
*)EmbeddedImage
->Data
; // drop const
458 CompLen
= EmbeddedImage
->DataLength
;
459 PixelCount
= EmbeddedImage
->Width
* EmbeddedImage
->Height
;
461 // FUTURE: for EG_EICOMPMODE_EFICOMPRESS, decompress whole data block here
463 if (EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_GRAY
||
464 EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_GRAY_ALPHA
) {
466 // copy grayscale plane and expand
467 if (EmbeddedImage
->CompressMode
== EG_EICOMPMODE_RLE
) {
468 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, r
), PixelCount
);
470 egInsertPlane(CompData
, PLPTR(NewImage
, r
), PixelCount
);
471 CompData
+= PixelCount
;
473 egCopyPlane(PLPTR(NewImage
, r
), PLPTR(NewImage
, g
), PixelCount
);
474 egCopyPlane(PLPTR(NewImage
, r
), PLPTR(NewImage
, b
), PixelCount
);
476 } else if (EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_COLOR
||
477 EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_COLOR_ALPHA
) {
480 if (EmbeddedImage
->CompressMode
== EG_EICOMPMODE_RLE
) {
481 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, r
), PixelCount
);
482 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, g
), PixelCount
);
483 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, b
), PixelCount
);
485 egInsertPlane(CompData
, PLPTR(NewImage
, r
), PixelCount
);
486 CompData
+= PixelCount
;
487 egInsertPlane(CompData
, PLPTR(NewImage
, g
), PixelCount
);
488 CompData
+= PixelCount
;
489 egInsertPlane(CompData
, PLPTR(NewImage
, b
), PixelCount
);
490 CompData
+= PixelCount
;
495 // set color planes to black
496 egSetPlane(PLPTR(NewImage
, r
), 0, PixelCount
);
497 egSetPlane(PLPTR(NewImage
, g
), 0, PixelCount
);
498 egSetPlane(PLPTR(NewImage
, b
), 0, PixelCount
);
502 if (WantAlpha
&& (EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_GRAY_ALPHA
||
503 EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_COLOR_ALPHA
||
504 EmbeddedImage
->PixelMode
== EG_EIPIXELMODE_ALPHA
)) {
507 if (EmbeddedImage
->CompressMode
== EG_EICOMPMODE_RLE
) {
508 egDecompressIcnsRLE(&CompData
, &CompLen
, PLPTR(NewImage
, a
), PixelCount
);
510 egInsertPlane(CompData
, PLPTR(NewImage
, a
), PixelCount
);
511 CompData
+= PixelCount
;
515 egSetPlane(PLPTR(NewImage
, a
), WantAlpha
? 255 : 0, PixelCount
);
525 VOID
egRestrictImageArea(IN EG_IMAGE
*Image
,
526 IN UINTN AreaPosX
, IN UINTN AreaPosY
,
527 IN OUT UINTN
*AreaWidth
, IN OUT UINTN
*AreaHeight
)
529 if (AreaPosX
>= Image
->Width
|| AreaPosY
>= Image
->Height
) {
530 // out of bounds, operation has no effect
534 // calculate affected area
535 if (*AreaWidth
> Image
->Width
- AreaPosX
)
536 *AreaWidth
= Image
->Width
- AreaPosX
;
537 if (*AreaHeight
> Image
->Height
- AreaPosY
)
538 *AreaHeight
= Image
->Height
- AreaPosY
;
542 VOID
egFillImage(IN OUT EG_IMAGE
*CompImage
, IN EG_PIXEL
*Color
)
549 if (!CompImage
->HasAlpha
)
552 PixelPtr
= CompImage
->PixelData
;
553 for (i
= 0; i
< CompImage
->Width
* CompImage
->Height
; i
++, PixelPtr
++)
554 *PixelPtr
= FillColor
;
557 VOID
egFillImageArea(IN OUT EG_IMAGE
*CompImage
,
558 IN UINTN AreaPosX
, IN UINTN AreaPosY
,
559 IN UINTN AreaWidth
, IN UINTN AreaHeight
,
565 EG_PIXEL
*PixelBasePtr
;
567 egRestrictImageArea(CompImage
, AreaPosX
, AreaPosY
, &AreaWidth
, &AreaHeight
);
571 if (!CompImage
->HasAlpha
)
574 PixelBasePtr
= CompImage
->PixelData
+ AreaPosY
* CompImage
->Width
+ AreaPosX
;
575 for (y
= 0; y
< AreaHeight
; y
++) {
576 PixelPtr
= PixelBasePtr
;
577 for (x
= 0; x
< AreaWidth
; x
++, PixelPtr
++)
578 *PixelPtr
= FillColor
;
579 PixelBasePtr
+= CompImage
->Width
;
584 VOID
egRawCopy(IN OUT EG_PIXEL
*CompBasePtr
, IN EG_PIXEL
*TopBasePtr
,
585 IN UINTN Width
, IN UINTN Height
,
586 IN UINTN CompLineOffset
, IN UINTN TopLineOffset
)
589 EG_PIXEL
*TopPtr
, *CompPtr
;
591 for (y
= 0; y
< Height
; y
++) {
593 CompPtr
= CompBasePtr
;
594 for (x
= 0; x
< Width
; x
++) {
598 TopBasePtr
+= TopLineOffset
;
599 CompBasePtr
+= CompLineOffset
;
603 VOID
egRawCompose(IN OUT EG_PIXEL
*CompBasePtr
, IN EG_PIXEL
*TopBasePtr
,
604 IN UINTN Width
, IN UINTN Height
,
605 IN UINTN CompLineOffset
, IN UINTN TopLineOffset
)
608 EG_PIXEL
*TopPtr
, *CompPtr
;
613 for (y
= 0; y
< Height
; y
++) {
615 CompPtr
= CompBasePtr
;
616 for (x
= 0; x
< Width
; x
++) {
618 RevAlpha
= 255 - Alpha
;
619 Temp
= (UINTN
)CompPtr
->b
* RevAlpha
+ (UINTN
)TopPtr
->b
* Alpha
+ 0x80;
620 CompPtr
->b
= (Temp
+ (Temp
>> 8)) >> 8;
621 Temp
= (UINTN
)CompPtr
->g
* RevAlpha
+ (UINTN
)TopPtr
->g
* Alpha
+ 0x80;
622 CompPtr
->g
= (Temp
+ (Temp
>> 8)) >> 8;
623 Temp
= (UINTN
)CompPtr
->r
* RevAlpha
+ (UINTN
)TopPtr
->r
* Alpha
+ 0x80;
624 CompPtr
->r
= (Temp
+ (Temp
>> 8)) >> 8;
626 CompPtr->b = ((UINTN)CompPtr->b * RevAlpha + (UINTN)TopPtr->b * Alpha) / 255;
627 CompPtr->g = ((UINTN)CompPtr->g * RevAlpha + (UINTN)TopPtr->g * Alpha) / 255;
628 CompPtr->r = ((UINTN)CompPtr->r * RevAlpha + (UINTN)TopPtr->r * Alpha) / 255;
632 TopBasePtr
+= TopLineOffset
;
633 CompBasePtr
+= CompLineOffset
;
637 VOID
egComposeImage(IN OUT EG_IMAGE
*CompImage
, IN EG_IMAGE
*TopImage
, IN UINTN PosX
, IN UINTN PosY
)
639 UINTN CompWidth
, CompHeight
;
641 CompWidth
= TopImage
->Width
;
642 CompHeight
= TopImage
->Height
;
643 egRestrictImageArea(CompImage
, PosX
, PosY
, &CompWidth
, &CompHeight
);
647 if (TopImage
->HasAlpha
) {
648 egRawCompose(CompImage
->PixelData
+ PosY
* CompImage
->Width
+ PosX
, TopImage
->PixelData
,
649 CompWidth
, CompHeight
, CompImage
->Width
, TopImage
->Width
);
651 egRawCopy(CompImage
->PixelData
+ PosY
* CompImage
->Width
+ PosX
, TopImage
->PixelData
,
652 CompWidth
, CompHeight
, CompImage
->Width
, TopImage
->Width
);
655 } /* VOID egComposeImage() */
658 // misc internal functions
661 VOID
egInsertPlane(IN UINT8
*SrcDataPtr
, IN UINT8
*DestPlanePtr
, IN UINTN PixelCount
)
665 for (i
= 0; i
< PixelCount
; i
++) {
666 *DestPlanePtr
= *SrcDataPtr
++;
671 VOID
egSetPlane(IN UINT8
*DestPlanePtr
, IN UINT8 Value
, IN UINTN PixelCount
)
675 for (i
= 0; i
< PixelCount
; i
++) {
676 *DestPlanePtr
= Value
;
681 VOID
egCopyPlane(IN UINT8
*SrcPlanePtr
, IN UINT8
*DestPlanePtr
, IN UINTN PixelCount
)
685 for (i
= 0; i
< PixelCount
; i
++) {
686 *DestPlanePtr
= *SrcPlanePtr
;
687 DestPlanePtr
+= 4, SrcPlanePtr
+= 4;