Fine tuned the alpha channel handling - it should now work as expected,
even with stupid apps like ArtPaint that use the alpha channel with B_RGB32 bitmaps. May now need some work for apps that use B_RGB32 as it should be used, though :-) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11289 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2b05778c88
commit
79b649126a
@ -13,7 +13,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_ICO
|
//#define TRACE_ICO
|
||||||
#ifdef TRACE_ICO
|
#ifdef TRACE_ICO
|
||||||
# define TRACE(x) printf x
|
# define TRACE(x) printf x
|
||||||
#else
|
#else
|
||||||
@ -190,9 +190,16 @@ get_ico_color_from_bits(TranslatorBitmap &bitsHeader, uint8 *data, int32 x, int3
|
|||||||
|
|
||||||
switch (bitsHeader.colors) {
|
switch (bitsHeader.colors) {
|
||||||
case B_RGBA32:
|
case B_RGBA32:
|
||||||
|
return *(ico_color *)(data + 4 * x);
|
||||||
case B_RGB32:
|
case B_RGB32:
|
||||||
default:
|
default:
|
||||||
return *(ico_color *)(data + 4 * x);
|
// stupid applications like ArtPaint use the alpha channel in B_RGB32 images...
|
||||||
|
ico_color color = *(ico_color *)(data + 4 * x);
|
||||||
|
if (color.alpha >= 128)
|
||||||
|
color.alpha = 255;
|
||||||
|
else
|
||||||
|
color.alpha = 0;
|
||||||
|
return color;
|
||||||
// ToDo: support some more color spaces...
|
// ToDo: support some more color spaces...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,6 +220,8 @@ fill_palette(TranslatorBitmap &bitsHeader, uint8 *data, ico_color *palette)
|
|||||||
if (numColors == 256)
|
if (numColors == 256)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
color.alpha = 0;
|
||||||
|
// the alpha channel is actually unused
|
||||||
palette[numColors++] = color;
|
palette[numColors++] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,6 +318,8 @@ convert_data_to_bits(ico_dir_entry &entry, ico_bitmap_header &header,
|
|||||||
// set alpha channel
|
// set alpha channel
|
||||||
if (get_1_bit_per_pixel(get_data_row(andData, andDataSize, andRowBytes, row), x))
|
if (get_1_bit_per_pixel(get_data_row(andData, andDataSize, andRowBytes, row), x))
|
||||||
outRowData[x] = B_TRANSPARENT_MAGIC_RGBA32;
|
outRowData[x] = B_TRANSPARENT_MAGIC_RGBA32;
|
||||||
|
else
|
||||||
|
((ico_color *)&outRowData[x])->alpha = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +400,7 @@ convert_bits_to_data(TranslatorBitmap &bitsHeader, uint8 *bitsData, ico_dir_entr
|
|||||||
for (uint32 row = entry.height; row-- > 0;) {
|
for (uint32 row = entry.height; row-- > 0;) {
|
||||||
for (uint32 x = 0; x < entry.width; x++) {
|
for (uint32 x = 0; x < entry.width; x++) {
|
||||||
ico_color color = get_ico_color_from_bits(bitsHeader, bitsData, x, row);
|
ico_color color = get_ico_color_from_bits(bitsHeader, bitsData, x, row);
|
||||||
bool transparent = *(uint32 *)&color == B_TRANSPARENT_MAGIC_RGBA32;
|
bool transparent = *(uint32 *)&color == B_TRANSPARENT_MAGIC_RGBA32 || color.alpha == 0;
|
||||||
|
|
||||||
set_1_bit_per_pixel(andRowData, x, transparent ? 1 : 0);
|
set_1_bit_per_pixel(andRowData, x, transparent ? 1 : 0);
|
||||||
}
|
}
|
||||||
@ -572,6 +583,8 @@ ICO::convert_bits_to_ico(BPositionIO &source, TranslatorBitmap &bitsHeader, BPos
|
|||||||
if (bitsHeader.colors != B_RGBA32
|
if (bitsHeader.colors != B_RGBA32
|
||||||
|| !has_true_alpha_channel(bitsHeader.colors, bitsData,
|
|| !has_true_alpha_channel(bitsHeader.colors, bitsData,
|
||||||
width, height, bitsHeader.rowBytes)) {
|
width, height, bitsHeader.rowBytes)) {
|
||||||
|
memset(palette, 0, sizeof(palette));
|
||||||
|
|
||||||
// count colors
|
// count colors
|
||||||
int32 colors = fill_palette(bitsHeader, bitsData, palette);
|
int32 colors = fill_palette(bitsHeader, bitsData, palette);
|
||||||
if (colors != -1) {
|
if (colors != -1) {
|
||||||
@ -585,6 +598,7 @@ ICO::convert_bits_to_ico(BPositionIO &source, TranslatorBitmap &bitsHeader, BPos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int32 numColors = 1 << bitsPerPixel;
|
||||||
|
|
||||||
ico_header header;
|
ico_header header;
|
||||||
header.type = B_HOST_TO_LENDIAN_INT16(1);
|
header.type = B_HOST_TO_LENDIAN_INT16(1);
|
||||||
@ -602,7 +616,7 @@ ICO::convert_bits_to_ico(BPositionIO &source, TranslatorBitmap &bitsHeader, BPos
|
|||||||
entry.bits_per_pixel = bitsPerPixel;
|
entry.bits_per_pixel = bitsPerPixel;
|
||||||
entry.color_count = 0;
|
entry.color_count = 0;
|
||||||
if (bitsPerPixel <= 8)
|
if (bitsPerPixel <= 8)
|
||||||
entry.color_count = 1 << bitsPerPixel;
|
entry.color_count = numColors;
|
||||||
|
|
||||||
// When bits_per_pixel == 32, the data already contains the alpha channel
|
// When bits_per_pixel == 32, the data already contains the alpha channel
|
||||||
|
|
||||||
@ -612,6 +626,8 @@ ICO::convert_bits_to_ico(BPositionIO &source, TranslatorBitmap &bitsHeader, BPos
|
|||||||
andRowBytes = get_bytes_per_row(width, 1);
|
andRowBytes = get_bytes_per_row(width, 1);
|
||||||
|
|
||||||
entry.size = sizeof(ico_bitmap_header) + width * (xorRowBytes + andRowBytes);
|
entry.size = sizeof(ico_bitmap_header) + width * (xorRowBytes + andRowBytes);
|
||||||
|
if (bitsPerPixel <= 8)
|
||||||
|
entry.size += numColors * sizeof(ico_color);
|
||||||
entry.offset = sizeof(ico_header) + sizeof(ico_dir_entry);
|
entry.offset = sizeof(ico_header) + sizeof(ico_dir_entry);
|
||||||
entry.reserved = 0;
|
entry.reserved = 0;
|
||||||
|
|
||||||
@ -623,6 +639,8 @@ ICO::convert_bits_to_ico(BPositionIO &source, TranslatorBitmap &bitsHeader, BPos
|
|||||||
bitmapHeader.bits_per_pixel = bitsPerPixel;
|
bitmapHeader.bits_per_pixel = bitsPerPixel;
|
||||||
bitmapHeader.planes = 1;
|
bitmapHeader.planes = 1;
|
||||||
bitmapHeader.image_size = 0;
|
bitmapHeader.image_size = 0;
|
||||||
|
if (bitsPerPixel <= 8)
|
||||||
|
bitmapHeader.colors_used = numColors;
|
||||||
|
|
||||||
entry.SwapFromHost();
|
entry.SwapFromHost();
|
||||||
bitmapHeader.SwapFromHost();
|
bitmapHeader.SwapFromHost();
|
||||||
@ -640,7 +658,7 @@ ICO::convert_bits_to_ico(BPositionIO &source, TranslatorBitmap &bitsHeader, BPos
|
|||||||
bitmapHeader.SwapToHost();
|
bitmapHeader.SwapToHost();
|
||||||
|
|
||||||
if (bitsPerPixel <= 8) {
|
if (bitsPerPixel <= 8) {
|
||||||
bytesWritten = target.Write(palette, (1L << bitsPerPixel) * sizeof(ico_color));
|
bytesWritten = target.Write(palette, numColors * sizeof(ico_color));
|
||||||
if (bytesWritten < B_OK)
|
if (bytesWritten < B_OK)
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ struct ico_color {
|
|||||||
inline bool
|
inline bool
|
||||||
operator==(const ico_color& other) const
|
operator==(const ico_color& other) const
|
||||||
{
|
{
|
||||||
return *(const uint32 *)this == *(const uint32 *)&other;
|
return red == other.red && green == other.green && blue == other.blue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user