]> code.delx.au - refind/blob - libeg/image.c
Support for transparency of icons & main menu text over large
[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
43 #define MAX_FILE_SIZE (1024*1024*1024)
44
45 #ifndef __MAKEWITH_GNUEFI
46 #define LibLocateHandle gBS->LocateHandleBuffer
47 #define LibOpenRoot EfiLibOpenRoot
48 #endif
49
50 //
51 // Basic image handling
52 //
53
54 EG_IMAGE * egCreateImage(IN UINTN Width, IN UINTN Height, IN BOOLEAN HasAlpha)
55 {
56 EG_IMAGE *NewImage;
57
58 NewImage = (EG_IMAGE *) AllocatePool(sizeof(EG_IMAGE));
59 if (NewImage == NULL)
60 return NULL;
61 NewImage->PixelData = (EG_PIXEL *) AllocatePool(Width * Height * sizeof(EG_PIXEL));
62 if (NewImage->PixelData == NULL) {
63 FreePool(NewImage);
64 return NULL;
65 }
66
67 NewImage->Width = Width;
68 NewImage->Height = Height;
69 NewImage->HasAlpha = HasAlpha;
70 return NewImage;
71 }
72
73 EG_IMAGE * egCreateFilledImage(IN UINTN Width, IN UINTN Height, IN BOOLEAN HasAlpha, IN EG_PIXEL *Color)
74 {
75 EG_IMAGE *NewImage;
76
77 NewImage = egCreateImage(Width, Height, HasAlpha);
78 if (NewImage == NULL)
79 return NULL;
80
81 egFillImage(NewImage, Color);
82 return NewImage;
83 }
84
85 EG_IMAGE * egCopyImage(IN EG_IMAGE *Image)
86 {
87 EG_IMAGE *NewImage;
88
89 NewImage = egCreateImage(Image->Width, Image->Height, Image->HasAlpha);
90 if (NewImage == NULL)
91 return NULL;
92
93 CopyMem(NewImage->PixelData, Image->PixelData, Image->Width * Image->Height * sizeof(EG_PIXEL));
94 return NewImage;
95 }
96
97 // Returns a smaller image composed of the specified crop area from the larger area.
98 // If the specified area is larger than is in the original, returns NULL.
99 EG_IMAGE * egCropImage(IN EG_IMAGE *Image, IN UINTN StartX, IN UINTN StartY, IN UINTN Width, IN UINTN Height) {
100 EG_IMAGE *NewImage = NULL;
101 UINTN x, y;
102
103 if (((StartX + Width) > Image->Width) || ((StartY + Height) > Image->Height))
104 return NULL;
105
106 NewImage = egCreateImage(Width, Height, Image->HasAlpha);
107 if (NewImage == NULL)
108 return NULL;
109
110 for (y = 0; y < Height; y++) {
111 for (x = 0; x < Width; x++) {
112 NewImage->PixelData[y * NewImage->Width + x] = Image->PixelData[(y + StartY) * Image->Width + x + StartX];
113 }
114 }
115 return NewImage;
116 } // EG_IMAGE * egCropImage()
117
118 VOID egFreeImage(IN EG_IMAGE *Image)
119 {
120 if (Image != NULL) {
121 if (Image->PixelData != NULL)
122 FreePool(Image->PixelData);
123 FreePool(Image);
124 }
125 }
126
127 //
128 // Basic file operations
129 //
130
131 EFI_STATUS egLoadFile(IN EFI_FILE* BaseDir, IN CHAR16 *FileName,
132 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 static CHAR16 * egFindExtension(IN CHAR16 *FileName)
223 {
224 UINTN i;
225
226 for (i = StrLen(FileName); i >= 0; i--) {
227 if (FileName[i] == '.')
228 return FileName + i + 1;
229 if (FileName[i] == '/' || FileName[i] == '\\')
230 break;
231 }
232 return FileName + StrLen(FileName);
233 }
234
235 static EG_IMAGE * egDecodeAny(IN UINT8 *FileData, IN UINTN FileDataLength,
236 IN CHAR16 *Format, IN UINTN IconSize, IN BOOLEAN WantAlpha)
237 {
238 EG_IMAGE *NewImage = NULL;
239
240 // Note: The UEFI implementation in Gigabyte's Hybrid EFI is buggy and does
241 // a case-sensitive comparison in StriCmp rather than the case-insensitive
242 // comparison that the spec says should be done. As a workaround, we repeat
243 // the comparison twice here.
244 // dispatch by extension
245 if ((StriCmp(Format, L"BMP") == 0) || (StriCmp(Format, L"bmp") == 0)) {
246 NewImage = egDecodeBMP(FileData, FileDataLength, IconSize, WantAlpha);
247 } else if ((StriCmp(Format, L"ICNS") == 0) || (StriCmp(Format, L"icns") == 0)) {
248 NewImage = egDecodeICNS(FileData, FileDataLength, IconSize, WantAlpha);
249 } // if/else
250
251 return NewImage;
252 }
253
254 EG_IMAGE * egLoadImage(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, IN BOOLEAN WantAlpha)
255 {
256 EFI_STATUS Status;
257 UINT8 *FileData;
258 UINTN FileDataLength;
259 EG_IMAGE *NewImage;
260
261 if (BaseDir == NULL || FileName == NULL)
262 return NULL;
263
264 // load file
265 Status = egLoadFile(BaseDir, FileName, &FileData, &FileDataLength);
266 if (EFI_ERROR(Status))
267 return NULL;
268
269 // decode it
270 NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(FileName), 128, WantAlpha);
271 FreePool(FileData);
272
273 return NewImage;
274 }
275
276 // Load an icon from (BaseDir)/Path, extracting the icon of size IconSize x IconSize.
277 // If the initial attempt is unsuccessful, try again, replacing the directory
278 // component of Path with DEFAULT_ICONS_DIR.
279 // Note: The assumption is that BaseDir points to rEFInd's home directory and Path
280 // includes one subdirectory level. If this changes in future revisions, it may be
281 // necessary to alter the code that tries again with DEFAULT_ICONS_DIR.
282 // Returns a pointer to the image data, or NULL if the icon could not be loaded.
283 EG_IMAGE * egLoadIcon(IN EFI_FILE* BaseDir, IN CHAR16 *Path, IN UINTN IconSize)
284 {
285 EFI_STATUS Status;
286 UINT8 *FileData;
287 UINTN FileDataLength;
288 CHAR16 *FileName, FileName2[256];
289 EG_IMAGE *NewImage;
290
291 if (BaseDir == NULL || Path == NULL)
292 return NULL;
293
294 // load file
295 Status = egLoadFile(BaseDir, Path, &FileData, &FileDataLength);
296 if (EFI_ERROR(Status)) {
297 FileName = Basename(Path); // Note: FileName is a pointer within Path; DON'T FREE IT!
298 SPrint(FileName2, 255, L"%s\\%s", DEFAULT_ICONS_DIR, FileName);
299 Status = egLoadFile(BaseDir, FileName2, &FileData, &FileDataLength);
300 if (EFI_ERROR(Status))
301 return NULL;
302 }
303
304 // decode it
305 NewImage = egDecodeAny(FileData, FileDataLength, egFindExtension(Path), IconSize, TRUE);
306 FreePool(FileData);
307
308 return NewImage;
309 } // EG_IMAGE *egLoadIcon()
310
311 EG_IMAGE * egDecodeImage(IN UINT8 *FileData, IN UINTN FileDataLength, IN CHAR16 *Format, IN BOOLEAN WantAlpha)
312 {
313 return egDecodeAny(FileData, FileDataLength, Format, 128, WantAlpha);
314 }
315
316 EG_IMAGE * egPrepareEmbeddedImage(IN EG_EMBEDDED_IMAGE *EmbeddedImage, IN BOOLEAN WantAlpha)
317 {
318 EG_IMAGE *NewImage;
319 UINT8 *CompData;
320 UINTN CompLen;
321 UINTN PixelCount;
322
323 // sanity check
324 if (EmbeddedImage->PixelMode > EG_MAX_EIPIXELMODE ||
325 (EmbeddedImage->CompressMode != EG_EICOMPMODE_NONE && EmbeddedImage->CompressMode != EG_EICOMPMODE_RLE))
326 return NULL;
327
328 // allocate image structure and pixel buffer
329 NewImage = egCreateImage(EmbeddedImage->Width, EmbeddedImage->Height, WantAlpha);
330 if (NewImage == NULL)
331 return NULL;
332
333 CompData = (UINT8 *)EmbeddedImage->Data; // drop const
334 CompLen = EmbeddedImage->DataLength;
335 PixelCount = EmbeddedImage->Width * EmbeddedImage->Height;
336
337 // FUTURE: for EG_EICOMPMODE_EFICOMPRESS, decompress whole data block here
338
339 if (EmbeddedImage->PixelMode == EG_EIPIXELMODE_GRAY ||
340 EmbeddedImage->PixelMode == EG_EIPIXELMODE_GRAY_ALPHA) {
341
342 // copy grayscale plane and expand
343 if (EmbeddedImage->CompressMode == EG_EICOMPMODE_RLE) {
344 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, r), PixelCount);
345 } else {
346 egInsertPlane(CompData, PLPTR(NewImage, r), PixelCount);
347 CompData += PixelCount;
348 }
349 egCopyPlane(PLPTR(NewImage, r), PLPTR(NewImage, g), PixelCount);
350 egCopyPlane(PLPTR(NewImage, r), PLPTR(NewImage, b), PixelCount);
351
352 } else if (EmbeddedImage->PixelMode == EG_EIPIXELMODE_COLOR ||
353 EmbeddedImage->PixelMode == EG_EIPIXELMODE_COLOR_ALPHA) {
354
355 // copy color planes
356 if (EmbeddedImage->CompressMode == EG_EICOMPMODE_RLE) {
357 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, r), PixelCount);
358 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, g), PixelCount);
359 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, b), PixelCount);
360 } else {
361 egInsertPlane(CompData, PLPTR(NewImage, r), PixelCount);
362 CompData += PixelCount;
363 egInsertPlane(CompData, PLPTR(NewImage, g), PixelCount);
364 CompData += PixelCount;
365 egInsertPlane(CompData, PLPTR(NewImage, b), PixelCount);
366 CompData += PixelCount;
367 }
368
369 } else {
370
371 // set color planes to black
372 egSetPlane(PLPTR(NewImage, r), 0, PixelCount);
373 egSetPlane(PLPTR(NewImage, g), 0, PixelCount);
374 egSetPlane(PLPTR(NewImage, b), 0, PixelCount);
375
376 }
377
378 if (WantAlpha && (EmbeddedImage->PixelMode == EG_EIPIXELMODE_GRAY_ALPHA ||
379 EmbeddedImage->PixelMode == EG_EIPIXELMODE_COLOR_ALPHA ||
380 EmbeddedImage->PixelMode == EG_EIPIXELMODE_ALPHA)) {
381
382 // copy alpha plane
383 if (EmbeddedImage->CompressMode == EG_EICOMPMODE_RLE) {
384 egDecompressIcnsRLE(&CompData, &CompLen, PLPTR(NewImage, a), PixelCount);
385 } else {
386 egInsertPlane(CompData, PLPTR(NewImage, a), PixelCount);
387 CompData += PixelCount;
388 }
389
390 } else {
391 egSetPlane(PLPTR(NewImage, a), WantAlpha ? 255 : 0, PixelCount);
392 }
393
394 return NewImage;
395 }
396
397 //
398 // Compositing
399 //
400
401 VOID egRestrictImageArea(IN EG_IMAGE *Image,
402 IN UINTN AreaPosX, IN UINTN AreaPosY,
403 IN OUT UINTN *AreaWidth, IN OUT UINTN *AreaHeight)
404 {
405 if (AreaPosX >= Image->Width || AreaPosY >= Image->Height) {
406 // out of bounds, operation has no effect
407 *AreaWidth = 0;
408 *AreaHeight = 0;
409 } else {
410 // calculate affected area
411 if (*AreaWidth > Image->Width - AreaPosX)
412 *AreaWidth = Image->Width - AreaPosX;
413 if (*AreaHeight > Image->Height - AreaPosY)
414 *AreaHeight = Image->Height - AreaPosY;
415 }
416 }
417
418 VOID egFillImage(IN OUT EG_IMAGE *CompImage, IN EG_PIXEL *Color)
419 {
420 UINTN i;
421 EG_PIXEL FillColor;
422 EG_PIXEL *PixelPtr;
423
424 FillColor = *Color;
425 if (!CompImage->HasAlpha)
426 FillColor.a = 0;
427
428 PixelPtr = CompImage->PixelData;
429 for (i = 0; i < CompImage->Width * CompImage->Height; i++, PixelPtr++)
430 *PixelPtr = FillColor;
431 }
432
433 VOID egFillImageArea(IN OUT EG_IMAGE *CompImage,
434 IN UINTN AreaPosX, IN UINTN AreaPosY,
435 IN UINTN AreaWidth, IN UINTN AreaHeight,
436 IN EG_PIXEL *Color)
437 {
438 UINTN x, y;
439 EG_PIXEL FillColor;
440 EG_PIXEL *PixelPtr;
441 EG_PIXEL *PixelBasePtr;
442
443 egRestrictImageArea(CompImage, AreaPosX, AreaPosY, &AreaWidth, &AreaHeight);
444
445 if (AreaWidth > 0) {
446 FillColor = *Color;
447 if (!CompImage->HasAlpha)
448 FillColor.a = 0;
449
450 PixelBasePtr = CompImage->PixelData + AreaPosY * CompImage->Width + AreaPosX;
451 for (y = 0; y < AreaHeight; y++) {
452 PixelPtr = PixelBasePtr;
453 for (x = 0; x < AreaWidth; x++, PixelPtr++)
454 *PixelPtr = FillColor;
455 PixelBasePtr += CompImage->Width;
456 }
457 }
458 }
459
460 VOID egRawCopy(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
461 IN UINTN Width, IN UINTN Height,
462 IN UINTN CompLineOffset, IN UINTN TopLineOffset)
463 {
464 UINTN x, y;
465 EG_PIXEL *TopPtr, *CompPtr;
466
467 for (y = 0; y < Height; y++) {
468 TopPtr = TopBasePtr;
469 CompPtr = CompBasePtr;
470 for (x = 0; x < Width; x++) {
471 *CompPtr = *TopPtr;
472 TopPtr++, CompPtr++;
473 }
474 TopBasePtr += TopLineOffset;
475 CompBasePtr += CompLineOffset;
476 }
477 }
478
479 VOID egRawCompose(IN OUT EG_PIXEL *CompBasePtr, IN EG_PIXEL *TopBasePtr,
480 IN UINTN Width, IN UINTN Height,
481 IN UINTN CompLineOffset, IN UINTN TopLineOffset)
482 {
483 UINTN x, y;
484 EG_PIXEL *TopPtr, *CompPtr;
485 UINTN Alpha;
486 UINTN RevAlpha;
487 UINTN Temp;
488
489 for (y = 0; y < Height; y++) {
490 TopPtr = TopBasePtr;
491 CompPtr = CompBasePtr;
492 for (x = 0; x < Width; x++) {
493 Alpha = TopPtr->a;
494 RevAlpha = 255 - Alpha;
495 Temp = (UINTN)CompPtr->b * RevAlpha + (UINTN)TopPtr->b * Alpha + 0x80;
496 CompPtr->b = (Temp + (Temp >> 8)) >> 8;
497 Temp = (UINTN)CompPtr->g * RevAlpha + (UINTN)TopPtr->g * Alpha + 0x80;
498 CompPtr->g = (Temp + (Temp >> 8)) >> 8;
499 Temp = (UINTN)CompPtr->r * RevAlpha + (UINTN)TopPtr->r * Alpha + 0x80;
500 CompPtr->r = (Temp + (Temp >> 8)) >> 8;
501 /*
502 CompPtr->b = ((UINTN)CompPtr->b * RevAlpha + (UINTN)TopPtr->b * Alpha) / 255;
503 CompPtr->g = ((UINTN)CompPtr->g * RevAlpha + (UINTN)TopPtr->g * Alpha) / 255;
504 CompPtr->r = ((UINTN)CompPtr->r * RevAlpha + (UINTN)TopPtr->r * Alpha) / 255;
505 */
506 TopPtr++, CompPtr++;
507 }
508 TopBasePtr += TopLineOffset;
509 CompBasePtr += CompLineOffset;
510 }
511 }
512
513 VOID egComposeImage(IN OUT EG_IMAGE *CompImage, IN EG_IMAGE *TopImage, IN UINTN PosX, IN UINTN PosY)
514 {
515 UINTN CompWidth, CompHeight;
516
517 CompWidth = TopImage->Width;
518 CompHeight = TopImage->Height;
519 egRestrictImageArea(CompImage, PosX, PosY, &CompWidth, &CompHeight);
520
521 // compose
522 if (CompWidth > 0) {
523 // if (CompImage->HasAlpha) {
524 // CompImage->HasAlpha = FALSE;
525 // egSetPlane(PLPTR(CompImage, a), 0, CompImage->Width * CompImage->Height);
526 // }
527
528 if (TopImage->HasAlpha) {
529 egRawCompose(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData,
530 CompWidth, CompHeight, CompImage->Width, TopImage->Width);
531 } else {
532 egRawCopy(CompImage->PixelData + PosY * CompImage->Width + PosX, TopImage->PixelData,
533 CompWidth, CompHeight, CompImage->Width, TopImage->Width);
534 }
535 }
536 }
537
538 EG_IMAGE * egEnsureImageSize(IN EG_IMAGE *Image, IN UINTN Width, IN UINTN Height, IN EG_PIXEL *Color)
539 {
540 EG_IMAGE *NewImage;
541
542 if (Image == NULL)
543 return NULL;
544 if (Image->Width == Width && Image->Height == Height)
545 return Image;
546
547 NewImage = egCreateFilledImage(Width, Height, Image->HasAlpha, Color);
548 if (NewImage == NULL) {
549 egFreeImage(Image);
550 return NULL;
551 }
552 egComposeImage(NewImage, Image, 0, 0);
553 egFreeImage(Image);
554
555 return NewImage;
556 }
557
558 //
559 // misc internal functions
560 //
561
562 VOID egInsertPlane(IN UINT8 *SrcDataPtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
563 {
564 UINTN i;
565
566 for (i = 0; i < PixelCount; i++) {
567 *DestPlanePtr = *SrcDataPtr++;
568 DestPlanePtr += 4;
569 }
570 }
571
572 VOID egSetPlane(IN UINT8 *DestPlanePtr, IN UINT8 Value, IN UINTN PixelCount)
573 {
574 UINTN i;
575
576 for (i = 0; i < PixelCount; i++) {
577 *DestPlanePtr = Value;
578 DestPlanePtr += 4;
579 }
580 }
581
582 VOID egCopyPlane(IN UINT8 *SrcPlanePtr, IN UINT8 *DestPlanePtr, IN UINTN PixelCount)
583 {
584 UINTN i;
585
586 for (i = 0; i < PixelCount; i++) {
587 *DestPlanePtr = *SrcPlanePtr;
588 DestPlanePtr += 4, SrcPlanePtr += 4;
589 }
590 }
591
592 /* EOF */