Skip to content

Commit fbc39f8

Browse files
committed
Added: better support for alpha channel in 32 bit bitmap
1 parent d08fbcd commit fbc39f8

1 file changed

Lines changed: 39 additions & 9 deletions

File tree

Codecs/CodecBMP/Source/CodecBMP.h

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,36 @@ namespace IMCodec
228228
// Normal color
229229
case 16:
230230
case 24:
231+
{
232+
if (VerifyFileSize(reinterpret_cast<const uint8_t*>(buffer), baseSourceAddress, size
233+
, sourceRowPitch * imageItem->descriptor.height))
234+
{
235+
for (size_t line = 0; line < imageItem->descriptor.height; line++)
236+
{
237+
auto sourceLineOffset = (imageItem->descriptor.height - line - 1) * imageItem->descriptor.rowPitchInBytes;
238+
auto destLineOffset = line * imageItem->descriptor.rowPitchInBytes;
239+
const auto sourceLineAddress = baseSourceAddress + sourceLineOffset;
240+
auto destLineAddress = reinterpret_cast<uint8_t*>(imageItem->data.data()) + destLineOffset;
241+
memcpy(destLineAddress, sourceLineAddress, imageItem->descriptor.rowPitchInBytes);
242+
}
243+
244+
out_image = std::make_shared<Image>(imageItem, ImageItemType::Unknown);
245+
result = ImageResult::Success;
246+
}
247+
else
248+
{
249+
result = ImageResult::FileIsCorrupted;
250+
}
251+
252+
break;
253+
}
231254
case 32:
232255
{
233256

234257
if (VerifyFileSize(reinterpret_cast<const uint8_t*>(buffer), baseSourceAddress, size
235258
, sourceRowPitch * imageItem->descriptor.height))
236259
{
260+
uint8_t transparencyOr = 0;
237261

238262
for (size_t line = 0; line < imageItem->descriptor.height; line++)
239263
{
@@ -242,23 +266,29 @@ namespace IMCodec
242266
const auto sourceLineAddress = baseSourceAddress + sourceLineOffset;
243267
auto destLineAddress = reinterpret_cast<uint8_t*>(imageItem->data.data()) + destLineOffset;
244268

245-
if (bmpInfo.biBitCount == 32)
269+
for (size_t x = 0; x < imageItem->descriptor.width; x += 1)
246270
{
247-
//If it's a 32 bit bitmap, override alpha channel with full opacity.
248-
//some application write just zeros to the alpha channel of 32 bit bitmaps.
271+
using color32 = std::array<uint8_t, 4>;
272+
reinterpret_cast<color32*>(destLineAddress)[x] = reinterpret_cast<const color32*>(sourceLineAddress)[x];
273+
transparencyOr |= reinterpret_cast<color32*>(destLineAddress)[x][3];
274+
}
275+
}
276+
277+
//If it's a 32 bit bitmap and all alpha values are '0' , inject alpha 255
278+
//Since some application write just zeros to the alpha channel of 32 bit bitmaps.
279+
if (transparencyOr == 0)
280+
{
281+
for (size_t line = 0; line < imageItem->descriptor.height; line++)
282+
{
283+
const auto destLineOffset = line * imageItem->descriptor.rowPitchInBytes;
284+
const auto destLineAddress = reinterpret_cast<uint8_t*>(imageItem->data.data()) + destLineOffset;
249285

250286
for (size_t x = 0; x < imageItem->descriptor.width; x += 1)
251287
{
252288
using color32 = std::array<uint8_t, 4>;
253-
reinterpret_cast<color32*>(destLineAddress)[x] = reinterpret_cast<const color32*>(sourceLineAddress)[x];
254289
reinterpret_cast<color32*>(destLineAddress)[x][3] = 255;
255290
}
256291
}
257-
else
258-
{
259-
memcpy(destLineAddress, sourceLineAddress, imageItem->descriptor.rowPitchInBytes);
260-
}
261-
262292
}
263293
out_image = std::make_shared<Image>(imageItem, ImageItemType::Unknown);
264294
result = ImageResult::Success;

0 commit comments

Comments
 (0)