OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcCompressionLib.c
Go to the documentation of this file.
1
16
17UINT32
19 OUT UINT8 *Dst,
20 IN UINT32 DstLen,
21 IN UINT8 *Src,
22 IN UINT32 SrcLen,
23 IN UINT8 *Mask,
24 IN UINT32 MaskLen,
25 IN BOOLEAN Premultiply
26 )
27{
28 //
29 // Data is encoded in three runs one by one: red, green, blue.
30 // The amount of pixels is equal to mask size, as it is 8-bit unencoded.
31 //
32 // Unlike normal RLE, where we process a <N><B><N><B> sequence (N standing
33 // for repeat count byte, and B for value byte), this one is more similar
34 // to LZ algorithms:
35 // 1. <C> & BIT7 != 0 is a normal repeat with N = <C> - 125 bytes.
36 // 2. <C> & BIT7 == 0 is a raw sequence of <C> + 1 bytes.
37 // Despite this obviously being more a variant of an LZ algorithm, I follow
38 // suit by calling it RLE24 just as others do.
39 //
40
41 UINT8 *SrcEnd;
42 UINT8 *SrcLast;
43 UINT8 *DstCur;
44 UINT8 *DstEnd;
45 UINT8 ControlValue;
46 UINT8 DstValue;
47 UINT8 RunIndex;
48
49 if ((SrcLen < 2) || (MaskLen != DstLen / sizeof (UINT32))) {
50 return 0;
51 }
52
53 SrcEnd = Src + SrcLen;
54 SrcLast = SrcEnd - 1;
55
56 //
57 // Run over all channels.
58 //
59 for (RunIndex = 0; RunIndex < 3 && Src < SrcLast; ++RunIndex) {
60 //
61 // The resulting image is in BGRA format.
62 //
63 DstCur = Dst + 2 - RunIndex;
64 DstEnd = DstCur + MaskLen * sizeof (UINT32);
65
66 //
67 // Iterate as long as we have enough control values.
68 //
69 while (Src < SrcLast && DstCur < DstEnd) {
70 //
71 // Process repeat sequences.
72 //
73 ControlValue = *Src++;
74 if (ControlValue & BIT7) {
75 ControlValue -= 125;
76 DstValue = *Src++;
77
78 //
79 // Early exit on not enough bytes to fill.
80 //
81 if ((UINT32)(DstEnd - DstCur) < ControlValue * sizeof (UINT32)) {
82 return 0;
83 }
84
85 while (ControlValue > 0) {
86 *DstCur = DstValue;
87 DstCur += sizeof (UINT32);
88 --ControlValue;
89 }
90 } else {
91 ++ControlValue;
92
93 //
94 // Early exit on not enough bytes to read or fill.
95 //
96 if (((UINT32)(SrcEnd - Src) < ControlValue) || ((UINT32)(DstEnd - DstCur) < ControlValue * sizeof (UINT32))) {
97 return 0;
98 }
99
100 while (ControlValue > 0) {
101 *DstCur = *Src++;
102 DstCur += sizeof (UINT32);
103 --ControlValue;
104 }
105 }
106 }
107
108 //
109 // We failed fill the current run, abort.
110 //
111 if (DstCur != DstEnd) {
112 return 0;
113 }
114 }
115
116 //
117 // Add mask to the resulting BGRA image.
118 //
119 if (Premultiply) {
120 DstCur = Dst;
121 SrcEnd = Mask + MaskLen;
122 while (Mask < SrcEnd) {
123 DstValue = *Mask++;
124 DstCur[0] = (UINT8)((DstCur[0] * DstValue) / 0xFF);
125 DstCur[1] = (UINT8)((DstCur[1] * DstValue) / 0xFF);
126 DstCur[2] = (UINT8)((DstCur[2] * DstValue) / 0xFF);
127 DstCur[3] = DstValue;
128 DstCur += sizeof (UINT32);
129 }
130 } else {
131 DstCur = Dst + 3;
132 SrcEnd = Mask + MaskLen;
133 while (Mask < SrcEnd) {
134 *DstCur = *Mask++;
135 DstCur += sizeof (UINT32);
136 }
137 }
138
139 return MaskLen * sizeof (UINT32);
140}
UINT32 DecompressMaskedRLE24(OUT UINT8 *Dst, IN UINT32 DstLen, IN UINT8 *Src, IN UINT32 SrcLen, IN UINT8 *Mask, IN UINT32 MaskLen, IN BOOLEAN Premultiply)