]> code.delx.au - refind/blob - libeg/image.c
Code cleanup & consolidation of icon code; minor patch to ext4fs driver
[refind] / libeg / image.c
1 /*
2 * libeg/image.c
3 * Image handling functions
4 *
5 * Copyright (c) 2006 Christoph Pfisterer
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
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
18 * distribution.
19 *
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.
23 *
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.
35 */
36
37 #include "libegint.h"
38 #include "../refind/global.h"
39 #include "../refind/lib.h"
40 #include "../refind/screen.h"
41 #include "../include/refit_call_wrapper.h"
42 #include "lodepng.h"
43
44 #define MAX_FILE_SIZE (1024*1024*1024)
45
46 #ifndef __MAKEWITH_GNUEFI
47 #define LibLocateHandle gBS->LocateHandleBuffer
48 #define LibOpenRoot EfiLibOpenRoot
49 #endif
50
51 //
52 // Basic image handling
53 //
54
55 EG_IMAGE * egCreateImage(IN UINTN Width, IN UINTN Height, IN BOOLEAN HasAlpha)
56 {
57 EG_IMAGE *NewImage;
58
59 NewImage = (EG_IMAGE *) AllocatePool(sizeof(EG_IMAGE));
60 if (NewImage == NULL)
61 return NULL;
62 NewImage->PixelData = (EG_PIXEL *) AllocatePool(Width * Height * sizeof(EG_PIXEL));
63 if (NewImage->PixelData == NULL) {
64 FreePool(NewImage);
65 return NULL;
66 }
67
68 NewImage->Width = Width;
69 NewImage->Height = Height;
70 NewImage->HasAlpha = HasAlpha;
71 return NewImage;
72 }
73
74 EG_IMAGE * egCreateFilledImage(IN UINTN Width, IN UINTN Height, IN BOOLEAN HasAlpha, IN EG_PIXEL *Color)
75 {
76 EG_IMAGE *NewImage;
77
78 NewImage = egCreateImage(Width, Height, HasAlpha);
79 if (NewImage == NULL)
80 return NULL;
81
82 egFillImage(NewImage, Color);
83 return NewImage;
84 }
85
86 EG_IMAGE * egCopyImage(IN EG_IMAGE *Image)
87 {
88 EG_IMAGE *NewImage;
89
90 NewImage = egCreateImage(Image->Width, Image->Height, Image->HasAlpha);
91 if (NewImage == NULL)
92 return NULL;
93
94 CopyMem(NewImage->PixelData, Image->PixelData, Image->Width * Image->Height * sizeof(EG_PIXEL));
95 return NewImage;
96 }
97
98 // Returns a smaller image composed of the specified crop area from the larger area.
99 // If the specified area is larger than is in the original, returns NULL.
100 EG_IMAGE * egCropImage(IN EG_IMAGE *Image, IN UINTN StartX, IN UINTN StartY, IN UINTN Width, IN UINTN Height) {
101 EG_IMAGE *NewImage = NULL;
102 UINTN x, y;
103
104 if (((StartX + Width) > Image->Width) || ((StartY + Height) > Image->Height))
105 return NULL;
106
107 NewImage = egCreateImage(Width, Height, Image->HasAlpha);
108 if (NewImage == NULL)
109 return NULL;
110
111 for (y = 0; y < Height; y++) {
112 for (x = 0; x < Width; x++) {
113 NewImage->PixelData[y * NewImage->Width + x] = Image->PixelData[(y + StartY) * Image->Width + x + StartX];
114 }
115 }
116 return NewImage;
117 } // EG_IMAGE * egCropImage()
118
119 VOID egFreeImage(IN EG_IMAGE *Image)
120 {
121 if (Image != NULL) {
122 if (Image->PixelData != NULL)
123 FreePool(Image->PixelData);
124 FreePool(Image);
125 }
126 }
127
128 //
129 // Basic file operations
130 //
131
132 EFI_STATUS egLoadFile(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileDataLength)
133 {
134 EFI_STATUS Status;
135 EFI_FILE_HANDLE FileHandle;
136 EFI_FILE_INFO *FileInfo;
137 UINT64 ReadSize;
138 UINTN BufferSize;
139 UINT8 *Buffer;
140
141 Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
142 if (EFI_ERROR(Status)) {
143 return Status;
144 }
145
146 FileInfo = LibFileInfo(FileHandle);
147 if (FileInfo == NULL) {
148 refit_call1_wrapper(FileHandle->Close, FileHandle);
149 return EFI_NOT_FOUND;
150 }
151 ReadSize = FileInfo->FileSize;
152 if (ReadSize > MAX_FILE_SIZE)
153 ReadSize = MAX_FILE_SIZE;
154 FreePool(FileInfo);
155
156 BufferSize = (UINTN)ReadSize; // was limited to 1 GB above, so this is safe
157 Buffer = (UINT8 *) AllocatePool(BufferSize);
158 if (Buffer == NULL) {
159 refit_call1_wrapper(FileHandle->Close, FileHandle);
160 return EFI_OUT_OF_RESOURCES;
161 }
162
163 Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &BufferSize, Buffer);
164 refit_call1_wrapper(FileHandle->Close, FileHandle);
165 if (EFI_ERROR(Status)) {
166 FreePool(Buffer);
167 return Status;
168 }
169
170 *FileData = Buffer;
171 *FileDataLength = BufferSize;
172 return EFI_SUCCESS;
173 }
174
175 static EFI_GUID ESPGuid = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
176
177 static EFI_STATUS egFindESP(OUT EFI_FILE_HANDLE *RootDir)
178 {
179 EFI_STATUS Status;
180 UINTN HandleCount = 0;
181 EFI_HANDLE *Handles;
182
183 Status = LibLocateHandle(ByProtocol, &ESPGuid, NULL, &HandleCount, &Handles);
184 if (!EFI_ERROR(Status) && HandleCount > 0) {
185 *RootDir = LibOpenRoot(Handles[0]);
186 if (*RootDir == NULL)
187 Status = EFI_NOT_FOUND;
188 FreePool(Handles);
189 }
190 return Status;
191 }
192
193 EFI_STATUS egSaveFile(IN EFI_FILE* BaseDir OPTIONAL, IN CHAR16 *FileName,
194 IN UINT8 *FileData, IN UINTN FileDataLength)
195 {
196 EFI_STATUS Status;
197 EFI_FILE_HANDLE FileHandle;
198 UINTN BufferSize;
199
200 if (BaseDir == NULL) {
201 Status = egFindESP(&BaseDir);
202 if (EFI_ERROR(Status))
203 return Status;
204 }
205
206 Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName,
207 EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
208 if (EFI_ERROR(Status))
209 return Status;
210
211 BufferSize = FileDataLength;
212 Status = refit_call3_wrapper(FileHandle->Write, FileHandle, &BufferSize, FileData);
213 refit_call1_wrapper(FileHandle->Close, FileHandle);
214
215 return Status;
216 }
217
218 //
219 // Loading images from files and embedded data
220 //
221
222 // Decode the specified image data. The IconSize parameter is relevant only
223 // for ICNS, for which it selects which ICNS sub-image is decoded.
224 // Returns a pointer to the resulting EG_IMAGE or NULL if decoding failed.
225 static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength, IN UINTN IconSize, IN BOOLEAN WantAlpha)
226 {
227 EG_IMAGE *NewImage = NULL;
228
229 NewImage = egDecodeICNS(FileData, FileDataLength, IconSize, WantAlpha);
230 if (NewImage == NULL)
231 NewImage = egDecodePNG(FileData, FileDataLength, IconSize, WantAlpha);
232 if (NewImage == NULL)
233 NewImage = egDecodeBMP(FileData, FileDataLength, IconSize, WantAlpha);
234
235 return NewImage;
236 }
237
238 EG_IMAGE * egLoadImage(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, IN BOOLEAN WantAlpha)
239 {
240 EFI_STATUS Status;
241 UINT8 *FileData;
242 UINTN FileDataLength;
243 EG_IMAGE *NewImage;
244
245 if (BaseDir == NULL || FileName == NULL)
246 return NULL;
247
248 // load file
249 Status = egLoadFile(BaseDir, FileName, &FileData, &FileDataLength);
250 if (EFI_ERROR(Status))
251 return NULL;
252
253 // decode it
254 NewImage = egDecodeAny(FileData, FileDataLength, 128, WantAlpha);
255 FreePool(FileData);
256
257 return NewImage;
258 }
259
260 // Load an icon from (BaseDir)/Path, extracting the icon of size IconSize x IconSize.
261 // Returns a pointer to the image data, or NULL if the icon could not be loaded.
262 EG_IMAGE * egLoadIcon(IN EFI_FILE* BaseDir, IN CHAR16 *Path, IN UINTN IconSize)
263 {
264 EFI_STATUS Status;
265 UINT8 *FileData;
266 UINTN FileDataLength;
267 EG_IMAGE *NewImage;
268
269 if (BaseDir == NULL || Path == NULL)
270 return NULL;
271
272 // load file
273 Status = egLoadFile(BaseDir, Path, &FileData, &FileDataLength);
274 if (EFI_ERROR(Status))
275 return NULL;
276
277 // decode it
278 NewImage = egDecodeAny(FileData, FileDataLength, IconSize, TRUE);
279 FreePool(FileData);
280 if ((NewImage->Width != IconSize) || (NewImage->Height != IconSize)) {
281 Print(L"Warning: Attempt to load icon of the wrong size from '%s'\n", Path);
282 MyFreePool(NewImage);
283 NewImage = NULL;
284 }
285
286 return NewImage;
287 } // EG_IMAGE *egLoadIcon()
288
289 // Returns an icon of any type from the specified subdirectory using the specified
290 // base name. All directory references are relative to BaseDir. For instance, if
291 // SubdirName is "myicons" and BaseName is "os_linux", this function will return
292 // an image based on "myicons/os_linux.icns" or "myicons/os_linux.png", in that
293 // order of preference. Returns NULL if no such file is a valid icon file.
294 EG_IMAGE * egLoadIconAnyType(IN EFI_FILE *BaseDir, IN CHAR16 *SubdirName, IN CHAR16 *BaseName, IN UINTN IconSize) {
295 EG_IMAGE *Image = NULL;
296 CHAR16 *Extension;
297 CHAR16 FileName[256];
298 UINTN i = 0;
299
300 while (((Extension = FindCommaDelimited(ICON_EXTENSIONS, i++)) != NULL) && (Image == NULL)) {
301 SPrint(FileName, 255, L"%s\\%s.%s", SubdirName, BaseName, Extension);
302 Image = egLoadIcon(BaseDir, FileName, IconSize);
303 MyFreePool(Extension);
304 } // while()
305
306 return Image;
307 } // EG_IMAGE *egLoadIconAnyType()
308
309 // Returns an icon with any extension in ICON_EXTENSIONS from either the directory
310 // specified by GlobalConfig.IconsDir or DEFAULT_ICONS_DIR. The input BaseName
311 // should be the icon name without an extension. For instance, if BaseName is
312 // os_linux, GlobalConfig.IconsDir is myicons, DEFAULT_ICONS_DIR is icons, and
313 // ICON_EXTENSIONS is "icns,png", this function will return myicons/os_linux.icns,
314 // myicons/os_linux.png, icons/os_linux.icns, or icons/os_linux.png, in that
315 // order of preference. Returns NULL if no such icon can be found. All file
316 // references are relative to SelfDir.
317 EG_IMAGE * egFindIcon(IN CHAR16 *BaseName, IN UINTN IconSize) {
318 EG_IMAGE *Image = NULL;
319
320 if (GlobalConfig.IconsDir != NULL) {
321 Image = egLoadIconAnyType(SelfDir, GlobalConfig.IconsDir, BaseName, IconSize);
322 }
323
324 if (Image == NULL) {
325 Image = egLoadIconAnyType(SelfDir, DEFAULT_ICONS_DIR, BaseName, IconSize);
326 }
327
328 return Image;
329 } // EG_IMAGE * egFindIcon()
330
331 EG_IMAGE * egPrepareEmbeddedImage(IN EG_EMBEDDED_IMAGE *EmbeddedImage, IN BOOLEAN WantAlpha)
332 {
333 EG_IMAGE *NewImage;
334 UINT8 *CompData;
335 UINTN CompLen;
336 UINTN PixelCount;
337
338 // sanity check
339 if (EmbeddedImage->PixelMode > EG_MAX_EIPIXELMODE ||
340 (EmbeddedImage->CompressMode != EG_EICOMPMODE_NONE && EmbeddedImage->CompressMode != EG_EICOMPMODE_RLE))
341 return NULL;
342
343 // allocate image structure and pixel buffer
344 NewImage = egCreateImage(EmbeddedImage->Width, EmbeddedImage->Height, WantAlpha);
345 if (NewImage == NULL)
346 return NULL;
347
348 CompData = (UINT8 *)EmbeddedImage->Data; // drop const
349 CompLen = EmbeddedImage->DataLength;
350 PixelCount = EmbeddedImage->Width * EmbeddedImage->Height;
351
352 // FUTURE: for EG_EICOMPMODE_EFICOMPRESS, decompress whole data block here
353
354 if (EmbeddedImage->PixelMode == EG_EIPIXELMODE_GRAY ||
355 EmbeddedImage->PixelMode == EG_EIPIXELMODE_GRAY_ALPHA) {
356
357 // copy grayscale plane and expand
358 if (EmbeddedImage->CompressMode == EG_EICOMPMODE_RLE) {
359 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, r), PixelCount);
360 } else {
361 egInsertPlane(CompData, PLPTR(NewImage, r), PixelCount);
362 CompData += PixelCount;
363 }
364 egCopyPlane(PLPTR(NewImage, r), PLPTR(NewImage, g), PixelCount);
365 egCopyPlane(PLPTR(NewImage, r), PLPTR(NewImage, b), PixelCount);
366
367 } else if (EmbeddedImage->PixelMode == EG_EIPIXELMODE_COLOR ||
368 EmbeddedImage->PixelMode == EG_EIPIXELMODE_COLOR_ALPHA) {
369
370 // copy color planes
371 if (EmbeddedImage->CompressMode == EG_EICOMPMODE_RLE) {
372 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, r), PixelCount);
373 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, g), PixelCount);
374 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, b), PixelCount);
375 } else {
376 egInsertPlane(CompData, PLPTR(NewImage, r), PixelCount);
377 CompData += PixelCount;
378 egInsertPlane(CompData, PLPTR(NewImage, g), PixelCount);
379 CompData += PixelCount;
380 egInsertPlane(CompData, PLPTR(NewImage, b), PixelCount);
381 CompData += PixelCount;
382 }
383
384 } else {
385
386 // set color planes to black
387 egSetPlane(PLPTR(NewImage, r), 0, PixelCount);
388 egSetPlane(PLPTR(NewImage, g), 0, PixelCount);
389 egSetPlane(PLPTR(NewImage, b), 0, PixelCount);
390
391 }
392
393 if (WantAlpha && (EmbeddedImage->PixelMode == EG_EIPIXELMODE_GRAY_ALPHA ||
394 EmbeddedImage->PixelMode == EG_EIPIXELMODE_COLOR_ALPHA ||
395 EmbeddedImage->PixelMode == EG_EIPIXELMODE_ALPHA)) {
396
397 // copy alpha plane
398 if (EmbeddedImage->CompressMode == EG_EICOMPMODE_RLE) {
399 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, a), PixelCount);
400 } else {
401 egInsertPlane(CompData, PLPTR(NewImage, a), PixelCount);
402 CompData += PixelCount;
403 }
404
405 } else {
406 egSetPlane(PLPTR(NewImage, a), WantAlpha ? 255 : 0, PixelCount);
407 }
408
409 return NewImage;
410 }
411
412 //
413 // Compositing
414 //
415
416 VOID egRestrictImageArea(IN EG_IMAGE *Image,
417 IN UINTN AreaPosX, IN UINTN AreaPosY,
418 IN OUT UINTN *AreaWidth, IN OUT UINTN *AreaHeight)
419 {
420 if (AreaPosX >= Image->Width || AreaPosY >= Image->Height) {
421 // out of bounds, operation has no effect
422 *AreaWidth = 0;
423 *AreaHeight = 0;
424 } else {
425 // calculate affected area
426 if (*AreaWidth > Image->Width - AreaPosX)
427 *AreaWidth = Image->Width - AreaPosX;
428 if (*AreaHeight > Image->Height - AreaPosY)
429 *AreaHeight = Image->Height - AreaPosY;
430 }
431 }
432
433 VOID egFillImage(IN OUT EG_IMAGE *CompImage, IN EG_PIXEL *Color)
434 {
435 UINTN i;
436 EG_PIXEL FillColor;
437 EG_PIXEL *PixelPtr;
438
439 FillColor = *Color;
440 if (!CompImage->HasAlpha)
441 FillColor.a = 0;
442
443 PixelPtr = CompImage->PixelData;
444 for (i = 0; i < CompImage->Width * CompImage->Height; i++, PixelPtr++)
445 *PixelPtr = FillColor;
446 }
447
448 VOID egFillImageArea(IN OUT EG_IMAGE *CompImage,
449 IN UINTN AreaPosX, IN UINTN AreaPosY,
450 IN UINTN AreaWidth, IN UINTN AreaHeight,
451 IN EG_PIXEL *Color)
452 {
453 UINTN x, y;
454 EG_PIXEL FillColor;
455 EG_PIXEL *PixelPtr;
456 EG_PIXEL *PixelBasePtr;
457
458 egRestrictImageArea(CompImage, AreaPosX, AreaPosY, &AreaWidth, &AreaHeight);
459
460 if (AreaWidth > 0) {
461 FillColor = *Color;
462 if (!CompImage->HasAlpha)
463 FillColor.a = 0;
464
465 PixelBasePtr = CompImage->PixelData + AreaPosY * CompImage->Width + AreaPosX;
466 for (y = 0; y < AreaHeight; y++) {
467 PixelPtr = PixelBasePtr;
468 for (x = 0; x < AreaWidth; x++, PixelPtr++)
469 *PixelPtr = FillColor;
470 PixelBasePtr += CompImage->Width;
471 }
472 }
473 }
474
475 VOID egRawCopy(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
476 IN UINTN Width, IN UINTN Height,
477 IN UINTN CompLineOffset, IN UINTN TopLineOffset)
478 {
479 UINTN x, y;
480 EG_PIXEL *TopPtr, *CompPtr;
481
482 for (y = 0; y < Height; y++) {
483 TopPtr = TopBasePtr;
484 CompPtr = CompBasePtr;
485 for (x = 0; x < Width; x++) {
486 *CompPtr = *TopPtr;
487 TopPtr++, CompPtr++;
488 }
489 TopBasePtr += TopLineOffset;
490 CompBasePtr += CompLineOffset;
491 }
492 }
493
494 VOID egRawCompose(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
495 IN UINTN Width, IN UINTN Height,
496 IN UINTN CompLineOffset, IN UINTN TopLineOffset)
497 {
498 UINTN x, y;
499 EG_PIXEL *TopPtr, *CompPtr;
500 UINTN Alpha;
501 UINTN RevAlpha;
502 UINTN Temp;
503
504 for (y = 0; y < Height; y++) {
505 TopPtr = TopBasePtr;
506 CompPtr = CompBasePtr;
507 for (x = 0; x < Width; x++) {
508 Alpha = TopPtr->a;
509 RevAlpha = 255 - Alpha;
510 Temp = (UINTN)CompPtr->b * RevAlpha + (UINTN)TopPtr->b * Alpha + 0x80;
511 CompPtr->b = (Temp + (Temp >> 8)) >> 8;
512 Temp = (UINTN)CompPtr->g * RevAlpha + (UINTN)TopPtr->g * Alpha + 0x80;
513 CompPtr->g = (Temp + (Temp >> 8)) >> 8;
514 Temp = (UINTN)CompPtr->r * RevAlpha + (UINTN)TopPtr->r * Alpha + 0x80;
515 CompPtr->r = (Temp + (Temp >> 8)) >> 8;
516 /*
517 CompPtr->b = ((UINTN)CompPtr->b * RevAlpha + (UINTN)TopPtr->b * Alpha) / 255;
518 CompPtr->g = ((UINTN)CompPtr->g * RevAlpha + (UINTN)TopPtr->g * Alpha) / 255;
519 CompPtr->r = ((UINTN)CompPtr->r * RevAlpha + (UINTN)TopPtr->r * Alpha) / 255;
520 */
521 TopPtr++, CompPtr++;
522 }
523 TopBasePtr += TopLineOffset;
524 CompBasePtr += CompLineOffset;
525 }
526 }
527
528 VOID egComposeImage(IN OUT EG_IMAGE *CompImage, IN EG_IMAGE *TopImage, IN UINTN PosX, IN UINTN PosY)
529 {
530 UINTN CompWidth, CompHeight;
531
532 CompWidth = TopImage->Width;
533 CompHeight = TopImage->Height;
534 egRestrictImageArea(CompImage, PosX, PosY, &CompWidth, &CompHeight);
535
536 // compose
537 if (CompWidth > 0) {
538 if (TopImage->HasAlpha) {
539 egRawCompose(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData,
540 CompWidth, CompHeight, CompImage->Width, TopImage->Width);
541 } else {
542 egRawCopy(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData,
543 CompWidth, CompHeight, CompImage->Width, TopImage->Width);
544 }
545 }
546 } /* VOID egComposeImage() */
547
548 EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height, IN EG_PIXEL *Color)
549 {
550 EG_IMAGE *NewImage;
551
552 if (Image == NULL)
553 return NULL;
554 if (Image->Width == Width && Image->Height == Height)
555 return Image;
556
557 NewImage = egCreateFilledImage(Width, Height, Image->HasAlpha, Color);
558 if (NewImage == NULL) {
559 egFreeImage(Image);
560 return NULL;
561 }
562 Image->HasAlpha = FALSE;
563 egComposeImage(NewImage, Image, 0, 0);
564 egFreeImage(Image);
565
566 return NewImage;
567 }
568
569 //
570 // misc internal functions
571 //
572
573 VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
574 {
575 UINTN i;
576
577 for (i = 0; i < PixelCount; i++) {
578 *DestPlanePtr = *SrcDataPtr++;
579 DestPlanePtr += 4;
580 }
581 }
582
583 VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINTN PixelCount)
584 {
585 UINTN i;
586
587 for (i = 0; i < PixelCount; i++) {
588 *DestPlanePtr = Value;
589 DestPlanePtr += 4;
590 }
591 }
592
593 VOID egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
594 {
595 UINTN i;
596
597 for (i = 0; i < PixelCount; i++) {
598 *DestPlanePtr = *SrcPlanePtr;
599 DestPlanePtr += 4, SrcPlanePtr += 4;
600 }
601 }
602
603 /* EOF */