aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Romanko <me@blankhex.com>2025-08-07 22:05:12 +0300
committerMikhail Romanko <me@blankhex.com>2025-08-07 22:05:12 +0300
commitd05efc5f85fa4d820c476a73d262abf5f6a58228 (patch)
treecd7dcff6d03a7484a6a662cf5f9c5da9307cc39b
parent4ce443f0d9143b4485c2e2627180bb0275abfdbe (diff)
downloadbhlib-d05efc5f85fa4d820c476a73d262abf5f6a58228.tar.gz
Refactor bitmap, add extra accessor for color data
-rw-r--r--doc/Manual/en/BH_Bitmap.pod50
-rw-r--r--doc/Manual/ru/BH_Bitmap.pod50
-rw-r--r--include/BH/Bitmap.h50
-rw-r--r--include/BH/Color.h1
-rw-r--r--src/Bitmap.c904
-rw-r--r--test/src/TestBitmap.c52
6 files changed, 426 insertions, 681 deletions
diff --git a/doc/Manual/en/BH_Bitmap.pod b/doc/Manual/en/BH_Bitmap.pod
index 9b8ff57..f5a450f 100644
--- a/doc/Manual/en/BH_Bitmap.pod
+++ b/doc/Manual/en/BH_Bitmap.pod
@@ -27,15 +27,27 @@ Currently, the following pixel formats are supported:
=item B<BH_BITMAP_INDEX1>
-1-bit indexed/paletted
+1-bit indexed/paletted (bits are packed with most significant bit first)
+
+=item B<BH_BITMAP_INDEX1_LSB>
+
+1-bit index/paletted with (bits are packed with least significant bit first)
=item B<BH_BITMAP_INDEX2>
-2-bit indexed/paletted
+2-bit indexed/paletted (bits are packed with most significant bit first)
+
+=item B<BH_BITMAP_INDEX2_LSB>
+
+2-bit indexed/paletted (bits are packed with least significant bit first)
=item B<BH_BITMAP_INDEX4>
-4-bit indexed/paletted
+4-bit indexed/paletted (bits are packed with most significant bit first)
+
+=item B<BH_BITMAP_INDEX4_LSB>
+
+4-bit indexed/paletted (bits are packed with least significant bit first)
=item B<BH_BITMAP_INDEX8>
@@ -58,27 +70,27 @@ Currently, the following pixel formats are supported:
64-bit RGB with alpha represented in uint64_t value. The layout is:
0xAAAARRRRGGGGBBBB
-=item B<BH_BITMAP_RGB565>
+=item B<BH_BITMAP_RGB565>, B<BH_BITMAP_BGR565>
16-bit RGB
-=item B<BH_BITMAP_RGB888>
+=item B<BH_BITMAP_RGB888>, B<BH_BITMAP_BGR888>
24-bit RGB
-=item B<BH_BITMAP_RGBA8888>
+=item B<BH_BITMAP_RGBA8888>, B<BH_BITMAP_BGRA8888>, B<BH_BITMAP_ARGB8888>, B<BH_BITMAP_ABGR8888>
32-bit RGB with alpha
-=item B<BH_BITMAP_RGB161616>
+=item B<BH_BITMAP_RGB161616>, B<BH_BITMAP_BGR161616>
48-bit RGB
-=item B<BH_BITMAP_RGBA16161616>
+=item B<BH_BITMAP_RGBA16161616>, B<BH_BITMAP_BGRA16161616>, B<BH_BITMAP_ARGB16161616>, B<BH_BITMAP_ABGR16161616>
64-bit RGB with alpha
-=item B<BH_BITMAP_RGBA1010102>
+=item B<BH_BITMAP_RGBA1010102>, B<BH_BITMAP_BGRA1010102>, B<BH_BITMAP_ARGB1010102>, B<BH_BITMAP_ABGR1010102>
32-bit RGB with alpha
@@ -86,17 +98,6 @@ Currently, the following pixel formats are supported:
All pixel formats use the current machine endianness.
-The flag I<BH_BITMAP_BGR> can be used to change the order of the color channels
-(RGB -> BGR). The flag has no effect on the following pixel formats:
-I<BH_BITMAP_INDEX1>, I<BH_BITMAP_INDEX2>, I<BH_BITMAP_INDEX4>,
-I<BH_BITMAP_INDEX8>, I<BH_BITMAP_GRAY8>, I<BH_BITMAP_GRAY16>,
-I<BH_BITMAP_RGBA32> and I<BH_BITMAP_RGBA64>.
-
-The flag I<BH_BITMAP_LSB> can be used to change the start of the bit order for
-indexed images. This flag only affects the following pixel formats:
-I<BH_BITMAP_INDEX1>, I<BH_BITMAP_INDEX2>, I<BH_BITMAP_INDEX4> and
-I<BH_BITMAP_INDEX8>.
-
The flag I<BH_BITMAP_NOALPHA> can be used to indicate that the alpha channel is
not used and should always be set to the maximum value (255 for 8-bit and 65535
for 16-bit).
@@ -104,9 +105,6 @@ for 16-bit).
The flag I<BH_BITMAP_PREMULT> can be used to indicate that color values are in
premultiplied form.
-The color palette is assumed to contain exactly 256 colors and is stored in the
-I<BH_BITMAP_RGBA32> pixel format.
-
=head1 API CALLS
@@ -118,7 +116,7 @@ I<BH_BITMAP_RGBA32> pixel format.
int format,
int flags,
void *data,
- void *palette);
+ BH_Color *palette);
Creates the bitmap with the specified I<width>, I<height> and pixel I<format>.
@@ -303,10 +301,10 @@ Bitmap doesn't own palette data
void BH_BitmapConvertRow(void *src,
int srcFormat,
- void *srcPalette,
+ const BH_Color *srcPalette,
void *dest,
int destFormat,
- void *destPalette,
+ const BH_Color *destPalette,
size_t count);
Converts a row of source data from one pixel format to another pixel format.
diff --git a/doc/Manual/ru/BH_Bitmap.pod b/doc/Manual/ru/BH_Bitmap.pod
index 6154cee..4188691 100644
--- a/doc/Manual/ru/BH_Bitmap.pod
+++ b/doc/Manual/ru/BH_Bitmap.pod
@@ -27,15 +27,27 @@ BH_Bitmap - доступ к растровому изображению/карт
=item B<BH_BITMAP_INDEX1>
-1-разрядный индексированный/палитрированный
+1-разрядный индексированный/палитрированный (биты упаковываются начиная с самого старшего бита)
+
+=item B<BH_BITMAP_INDEX1_LSB>
+
+1-разрядный индексированный/палитрированный (биты упаковываются начиная с самого младшего бита)
=item B<BH_BITMAP_INDEX2>
-2-разрядный индексированный/палитрированный
+2-разрядный индексированный/палитрированный (биты упаковываются начиная с самого старшего бита)
+
+=item B<BH_BITMAP_INDEX2_LSB>
+
+2-разрядный индексированный/палитрированный (биты упаковываются начиная с самого младшего бита)
=item B<BH_BITMAP_INDEX4>
-4-разрядный индексированный/палитрированный
+4-разрядный индексированный/палитрированный (биты упаковываются начиная с самого старшего бита)
+
+=item B<BH_BITMAP_INDEX4_LSB>
+
+4-разрядный индексированный/палитрированный (биты упаковываются начиная с самого младшего бита)
=item B<BH_BITMAP_INDEX8>
@@ -59,27 +71,27 @@ BH_Bitmap - доступ к растровому изображению/карт
64-разрядный RGB с прозрачностью, представленный в виде uint64_t.
Формат: 0xAAAARRRRGGGGBBBB
-=item B<BH_BITMAP_RGB565>
+=item B<BH_BITMAP_RGB565>, B<BH_BITMAP_BGR565>
16-разрядный RGB
-=item B<BH_BITMAP_RGB888>
+=item B<BH_BITMAP_RGB888>, B<BH_BITMAP_BGR888>
24-разрядный RGB
-=item B<BH_BITMAP_RGBA8888>
+=item B<BH_BITMAP_RGBA8888>, B<BH_BITMAP_BGRA8888>, B<BH_BITMAP_ARGB8888>, B<BH_BITMAP_ABGR8888>
32-разрядный RGB с прозрачностью
-=item B<BH_BITMAP_RGB161616>
+=item B<BH_BITMAP_RGB161616>, B<BH_BITMAP_BGR161616>
48-разрядный RGB
-=item B<BH_BITMAP_RGBA16161616>
+=item B<BH_BITMAP_RGBA16161616>, B<BH_BITMAP_BGRA16161616>, B<BH_BITMAP_ARGB16161616>, B<BH_BITMAP_ABGR16161616>
64-разрядный RGB с прозрачностью
-=item B<BH_BITMAP_RGBA1010102>
+=item B<BH_BITMAP_RGBA1010102>, B<BH_BITMAP_BGRA1010102>, B<BH_BITMAP_ARGB1010102>, B<BH_BITMAP_ABGR1010102>
32-разрядный RGB с прозрачностью
@@ -87,17 +99,6 @@ BH_Bitmap - доступ к растровому изображению/карт
Во всех форматах пикселей используется нативный порядок байт.
-Флаг I<BH_BITMAP_BGR> может использоваться для изменения порядка цветовых
-каналов (RGB -> BGR). Этот флаг не влияет на следующие пиксельные форматы:
-I<BH_BITMAP_INDEX1>, I<BH_BITMAP_INDEX2>, I<BH_BITMAP_INDEX4>,
-I<BH_BITMAP_INDEX8>, I<BH_BITMAP_GRAY8>, I<BH_BITMAP_GRAY16>,
-I<BH_BITMAP_RGBA32> и I<BH_BITMAP_RGBA64>.
-
-Флаг I<BH_BITMAP_LSB> может использоваться для изменения начала отсчета порядка
-бит для индексированных изображений. Этот флаг влияет только на следующие
-пиксельные форматы: I<BH_BITMAP_INDEX1>, I<BH_BITMAP_INDEX2>,
-I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
-
Флаг I<BH_BITMAP_NOALPHA> может использоваться для указания того,
что альфа-канал не используется и всегда должен быть установлен в максимальное
значение (255 для 8-разрядных и 65535 для 16-разрядных).
@@ -105,9 +106,6 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
Флаг I<BH_BITMAP_PREMULT> может использоваться для указания того, что значения
цвета представлены в предварительно умноженном виде.
-Предполагается, что цветовая палитра содержит ровно 256 цветов и хранится в
-пиксельном формате I<BH_BITMAP_RGBA32>.
-
=head1 ВЫЗОВЫ API
@@ -119,7 +117,7 @@ I<BH_BITMAP_INDEX4> и I<BH_BITMAP_INDEX8>.
int format,
int flags,
void *data,
- void *palette);
+ BH_Color *palette);
Создает растровое изображение с указанной шириной, высотой и пиксельным
форматом.
@@ -310,10 +308,10 @@ void BH_BitmapSetIndex(BH_Bitmap *bitmap,
void BH_BitmapConvertRow(void *src,
int srcFormat,
- void *srcPalette,
+ const BH_Color *srcPalette,
void *dest,
int destFormat,
- void *destPalette,
+ const BH_Color *destPalette,
size_t count);
Преобразует строку исходных данных из одного пиксельного формата в другой пиксельный формат.
diff --git a/include/BH/Bitmap.h b/include/BH/Bitmap.h
index 5146f89..32d23a8 100644
--- a/include/BH/Bitmap.h
+++ b/include/BH/Bitmap.h
@@ -11,24 +11,36 @@ typedef struct BH_Bitmap BH_Bitmap;
#define BH_BITMAP_PREMULT 0x1000
#define BH_BITMAP_NOALPHA 0x2000
-#define BH_BITMAP_BGR 0x4000
-#define BH_BITMAP_LSB 0x8000
#define BH_BITMAP_INDEX1 0x0000
-#define BH_BITMAP_INDEX2 0x0001
-#define BH_BITMAP_INDEX4 0x0002
-#define BH_BITMAP_INDEX8 0x0003
-#define BH_BITMAP_GRAY8 0x0004
-#define BH_BITMAP_GRAY16 0x0005
-#define BH_BITMAP_RGBA32 0x0006
-#define BH_BITMAP_RGBA64 0x0007
-#define BH_BITMAP_RGB565 0x0008
-#define BH_BITMAP_RGB888 0x0009
-#define BH_BITMAP_RGBA8888 0x000A
-#define BH_BITMAP_RGB161616 0x000B
-#define BH_BITMAP_RGBA16161616 0x000C
-#define BH_BITMAP_RGBA1010102 0x000D
-
+#define BH_BITMAP_INDEX1_LSB 0x0001
+#define BH_BITMAP_INDEX2 0x0002
+#define BH_BITMAP_INDEX2_LSB 0x0003
+#define BH_BITMAP_INDEX4 0x0004
+#define BH_BITMAP_INDEX4_LSB 0x0005
+#define BH_BITMAP_INDEX8 0x0006
+#define BH_BITMAP_GRAY8 0x0007
+#define BH_BITMAP_GRAY16 0x0008
+#define BH_BITMAP_RGBA32 0x0009
+#define BH_BITMAP_RGBA64 0x000A
+#define BH_BITMAP_RGB565 0x000B
+#define BH_BITMAP_BGR565 0x000C
+#define BH_BITMAP_RGB888 0x000D
+#define BH_BITMAP_BGR888 0x000E
+#define BH_BITMAP_RGBA8888 0x000F
+#define BH_BITMAP_BGRA8888 0x0010
+#define BH_BITMAP_ARGB8888 0x0011
+#define BH_BITMAP_ABGR8888 0x0012
+#define BH_BITMAP_RGB161616 0x0013
+#define BH_BITMAP_BGR161616 0x0014
+#define BH_BITMAP_RGBA16161616 0x0015
+#define BH_BITMAP_BGRA16161616 0x0016
+#define BH_BITMAP_ARGB16161616 0x0017
+#define BH_BITMAP_ABGR16161616 0x0018
+#define BH_BITMAP_RGBA1010102 0x0019
+#define BH_BITMAP_BGRA1010102 0x001A
+#define BH_BITMAP_ARGB2101010 0x001B
+#define BH_BITMAP_ABGR2101010 0x001C
#define BH_BITMAP_FLAG_ALIGN32 0x0001
#define BH_BITMAP_FLAG_EXT_DATA 0x0002
@@ -40,7 +52,7 @@ BH_Bitmap *BH_BitmapNew(uint32_t width,
int format,
int flags,
void *data,
- void *palette);
+ BH_Color *palette);
void BH_BitmapFree(BH_Bitmap *bitmap);
@@ -109,10 +121,10 @@ int BH_BitmapFlags(BH_Bitmap *bitmap);
void BH_BitmapConvertRow(void *src,
int srcFormat,
- void *srcPalette,
+ const BH_Color *srcPalette,
void *dest,
int destFormat,
- void *destPalette,
+ const BH_Color *destPalette,
size_t count);
diff --git a/include/BH/Color.h b/include/BH/Color.h
index 1fb2d73..2cb8b76 100644
--- a/include/BH/Color.h
+++ b/include/BH/Color.h
@@ -56,6 +56,7 @@ typedef struct BH_Color
uint16_t l;
uint16_t a;
} hsla;
+ uint16_t channel[4];
} data;
} BH_Color;
diff --git a/src/Bitmap.c b/src/Bitmap.c
index 5ce35d6..674393d 100644
--- a/src/Bitmap.c
+++ b/src/Bitmap.c
@@ -7,657 +7,388 @@
#define MAX(a,b) ((a)>(b)?(a):(b))
-struct BH_Bitmap
-{
- uint32_t width;
- uint32_t height;
- int format;
- int flags;
- size_t step;
- size_t stride;
- uint8_t *data;
- uint32_t *palette;
+#define TYPE_PACKED 0x0000
+#define TYPE_INDEX 0x0100
+#define TYPE_ARRAY 0x0200
+
+
+#define TYPE_PACKED8 (0x00 | TYPE_PACKED)
+#define TYPE_PACKED16 (0x01 | TYPE_PACKED)
+#define TYPE_PACKED32 (0x02 | TYPE_PACKED)
+#define TYPE_PACKED64 (0x03 | TYPE_PACKED)
+#define TYPE_INDEX1 (0x00 | TYPE_INDEX)
+#define TYPE_INDEX2 (0x01 | TYPE_INDEX)
+#define TYPE_INDEX4 (0x02 | TYPE_INDEX)
+#define TYPE_INDEX8 (0x03 | TYPE_INDEX)
+#define TYPE_ARRAY8 (0x00 | TYPE_ARRAY)
+#define TYPE_ARRAY16 (0x01 | TYPE_ARRAY)
+
+
+typedef struct FormatInfo
+{
+ int type;
+ int channels;
+ uint16_t masks[4];
+ uint8_t shifts[8];
+ int size;
+} FormatInfo;
+
+
+const static struct FormatInfo formats[] =
+{
+ {TYPE_INDEX1, 7, {0x0001}, {7, 6, 5, 4, 3, 2, 1, 0}, 0}, /* BH_BITMAP_INDEX1 */
+ {TYPE_INDEX1, 7, {0x0001}, {0, 1, 2, 3, 4, 5, 6, 7}, 0}, /* BH_BITMAP_INDEX1_LSB */
+ {TYPE_INDEX2, 3, {0x0003}, {3, 2, 1, 0}, 0}, /* BH_BITMAP_INDEX2 */
+ {TYPE_INDEX2, 3, {0x0003}, {0, 1, 2, 3}, 0}, /* BH_BITMAP_INDEX2_LSB */
+ {TYPE_INDEX4, 1, {0x000F}, {1, 0}, 0}, /* BH_BITMAP_INDEX4 */
+ {TYPE_INDEX4, 1, {0x000F}, {0, 1}, 0}, /* BH_BITMAP_INDEX4_LSB */
+ {TYPE_INDEX8, 0, {0x00FF}, {0}, 1}, /* BH_BITMAP_INDEX8 */
+ {TYPE_PACKED8, 1, {0x00FF}, {0}, 1}, /* BH_BITMAP_GRAY8 */
+ {TYPE_PACKED16, 1, {0xFFFF}, {0}, 2}, /* BH_BITMAP_GRAY16 */
+ {TYPE_PACKED32, 4, {0x00FF, 0x00FF, 0x00FF, 0x00FF}, {16, 8, 0, 24}, 4}, /* BH_BITMAP_RGBA32 */
+ {TYPE_PACKED64, 4, {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, {32, 16, 0, 48}, 8}, /* BH_BITMAP_RGBA64 */
+ {TYPE_PACKED16, 3, {0x001F, 0x003F, 0x001F}, {11, 5, 0}, 2}, /* BH_BITMAP_RGB565 */
+ {TYPE_PACKED16, 3, {0x001F, 0x003F, 0x001F}, {0, 5, 11}, 2}, /* BH_BITMAP_BGR565 */
+ {TYPE_ARRAY8, 3, {0x00FF, 0x00FF, 0x00FF}, {0, 1, 2}, 3}, /* BH_BITMAP_RGB888 */
+ {TYPE_ARRAY8, 3, {0x00FF, 0x00FF, 0x00FF}, {2, 1, 0}, 3}, /* BH_BITMAP_BGR888 */
+ {TYPE_ARRAY8, 4, {0x00FF, 0x00FF, 0x00FF, 0x00FF}, {0, 1, 2, 3}, 4}, /* BH_BITMAP_RGBA8888 */
+ {TYPE_ARRAY8, 4, {0x00FF, 0x00FF, 0x00FF, 0x00FF}, {2, 1, 0, 3}, 4}, /* BH_BITMAP_BGRA8888 */
+ {TYPE_ARRAY8, 4, {0x00FF, 0x00FF, 0x00FF, 0x00FF}, {1, 2, 3, 0}, 4}, /* BH_BITMAP_ARGB8888 */
+ {TYPE_ARRAY8, 4, {0x00FF, 0x00FF, 0x00FF, 0x00FF}, {3, 2, 1, 0}, 4}, /* BH_BITMAP_ABGR8888 */
+ {TYPE_ARRAY16, 3, {0xFFFF, 0xFFFF, 0xFFFF}, {0, 1, 2}, 6}, /* BH_BITMAP_RGB161616 */
+ {TYPE_ARRAY16, 3, {0xFFFF, 0xFFFF, 0xFFFF}, {2, 1, 0}, 6}, /* BH_BITMAP_BGR161616 */
+ {TYPE_ARRAY16, 4, {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, {0, 1, 2, 3}, 8}, /* BH_BITMAP_RGBA16161616 */
+ {TYPE_ARRAY16, 4, {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, {2, 1, 0, 3}, 8}, /* BH_BITMAP_BGRA16161616 */
+ {TYPE_ARRAY16, 4, {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, {1, 2, 3, 0}, 8}, /* BH_BITMAP_ARGB16161616 */
+ {TYPE_ARRAY16, 4, {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, {3, 2, 1, 0}, 8}, /* BH_BITMAP_ABGR16161616 */
+ {TYPE_PACKED32, 4, {0x03FF, 0x03FF, 0x03FF, 0x0003}, {22, 12, 2, 0}, 4}, /* BH_BITMAP_RGBA1010102 */
+ {TYPE_PACKED32, 4, {0x03FF, 0x03FF, 0x03FF, 0x0003}, {2, 12, 22, 0}, 4}, /* BH_BITMAP_BGRA1010102 */
+ {TYPE_PACKED32, 4, {0x03FF, 0x03FF, 0x03FF, 0x0003}, {20, 10, 0, 30}, 4}, /* BH_BITMAP_ARGB2101010 */
+ {TYPE_PACKED32, 4, {0x03FF, 0x03FF, 0x03FF, 0x0003}, {0, 10, 20, 30}, 4}, /* BH_BITMAP_ABGR2101010 */
};
-/* Bit and unit order arrays for working with RGB/BGR and MSB/LSB */
-static const size_t bitOrder1[][8] =
+static uint16_t normilize(uint16_t mask,
+ uint16_t value)
{
- {7, 6, 5, 4, 3, 2, 1, 0},
- {0, 1, 2, 3, 4, 5, 6, 7},
-};
+ return ((uint32_t)(value & mask) * 65535) / mask;
+}
-static const size_t bitMask1[][8] =
+static uint16_t denormilize(uint16_t mask,
+ uint16_t value)
{
- {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01},
- {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80},
-};
+ return (((uint32_t)(value * mask)) / 65535) & mask;
+}
-static const size_t bitOrder2[][4] =
+static size_t bestPaletteIndex(BH_Color *color,
+ const BH_Color *palette,
+ const FormatInfo *formatInfo)
{
- {6, 4, 2, 0},
- {0, 2, 4, 6},
-};
-
+ uint32_t bestError = -1;
+ size_t i, bestIndex = 0, paletteSize;
-static const size_t bitMask2[][4] =
-{
- {0xC0, 0x30, 0x0C, 0x03},
- {0x03, 0x0C, 0x30, 0xC0},
-};
+ switch (formatInfo->type)
+ {
+ case TYPE_INDEX1: paletteSize = 2; break;
+ case TYPE_INDEX2: paletteSize = 4; break;
+ case TYPE_INDEX4: paletteSize = 16; break;
+ case TYPE_INDEX8: paletteSize = 256; break;
+ }
+ for (i = 0; i < paletteSize; ++i) {
+ int32_t delta[4];
+ uint32_t currentError;
-static const size_t bitOrder4[][2] =
-{
- {4, 0},
- {0, 4},
-};
+ switch (palette[i].type)
+ {
+ case BH_COLOR_TYPE_HSLA: BH_ColorToHSLA(color, color); break;
+ case BH_COLOR_TYPE_HSVA: BH_ColorToHSVA(color, color); break;
+ case BH_COLOR_TYPE_RGBA: BH_ColorToRGBA(color, color); break;
+ }
+ delta[0] = (int32_t)color->data.channel[0] - palette[i].data.channel[0];
+ delta[1] = (int32_t)color->data.channel[1] - palette[i].data.channel[1];
+ delta[2] = (int32_t)color->data.channel[2] - palette[i].data.channel[2];
+ delta[3] = (int32_t)color->data.channel[3] - palette[i].data.channel[3];
-static const size_t bitMask4[][2] =
-{
- {0xF0, 0x0F},
- {0x0F, 0xF0},
-};
+ currentError = delta[0] * delta[0] + delta[1] * delta[1] +
+ delta[2] * delta[2] + delta[3] * delta[3];
+ if (currentError < bestError)
+ {
+ bestError = currentError;
+ bestIndex = i;
+ }
+ }
-static const size_t bitOrder565[][3] =
-{
- {11, 5, 0},
- {0, 5, 11},
-};
+ return bestIndex;
+}
-static const size_t bitOrder1010102[][4] =
+static void readPacked(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- {0, 10, 20, 30},
- {20, 10, 0, 30},
-};
-
+ uint64_t raw;
+
+ switch (formatInfo->type)
+ {
+ case TYPE_PACKED8: raw = *(uint8_t *)data; break;
+ case TYPE_PACKED16: raw = *(uint16_t *)data; break;
+ case TYPE_PACKED32: raw = *(uint32_t *)data; break;
+ case TYPE_PACKED64: raw = *(uint64_t *)data; break;
+ }
-static const size_t unitOrderRGB[][3] =
-{
- {0, 1, 2},
- {2, 1, 0},
-};
+ switch (formatInfo->channels)
+ {
+ case 4: value->data.channel[3] = normilize(formatInfo->masks[3], raw >> formatInfo->shifts[3]);
+ case 3: value->data.channel[2] = normilize(formatInfo->masks[2], raw >> formatInfo->shifts[2]);
+ case 2: value->data.channel[1] = normilize(formatInfo->masks[1], raw >> formatInfo->shifts[1]);
+ case 1: value->data.channel[0] = normilize(formatInfo->masks[0], raw >> formatInfo->shifts[0]);
+ }
+}
-static const size_t unitOrderRGBA[][4] =
+static void writePacked(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- {0, 1, 2, 3},
- {2, 1, 0, 3},
-};
-
+ uint64_t raw;
-/* Private functions */
-static size_t calculateStep(int format)
-{
- switch (format & 0x0FFF)
+ raw = 0;
+ switch (formatInfo->channels)
{
- case BH_BITMAP_INDEX1:
- case BH_BITMAP_INDEX2:
- case BH_BITMAP_INDEX4:
- return 0;
-
- case BH_BITMAP_INDEX8:
- case BH_BITMAP_GRAY8:
- return 1;
-
- case BH_BITMAP_GRAY16:
- case BH_BITMAP_RGB565:
- return 2;
-
- case BH_BITMAP_RGB888:
- return 3;
-
- case BH_BITMAP_RGBA32:
- case BH_BITMAP_RGBA8888:
- case BH_BITMAP_RGBA1010102:
- return 4;
-
- case BH_BITMAP_RGB161616:
- return 6;
-
- case BH_BITMAP_RGBA64:
- case BH_BITMAP_RGBA16161616:
- return 8;
+ case 4: raw |= (uint64_t)denormilize(formatInfo->masks[3], value->data.channel[3]) << formatInfo->shifts[3];
+ case 3: raw |= (uint64_t)denormilize(formatInfo->masks[2], value->data.channel[2]) << formatInfo->shifts[2];
+ case 2: raw |= (uint64_t)denormilize(formatInfo->masks[1], value->data.channel[1]) << formatInfo->shifts[1];
+ case 1: raw |= (uint64_t)denormilize(formatInfo->masks[0], value->data.channel[0]) << formatInfo->shifts[0];
}
- return 0;
+ switch (formatInfo->type)
+ {
+ case TYPE_PACKED8: *(uint8_t *)data = raw; break;
+ case TYPE_PACKED16: *(uint16_t *)data = raw; break;
+ case TYPE_PACKED32: *(uint32_t *)data = raw; break;
+ case TYPE_PACKED64: *(uint64_t *)data = raw; break;
+ }
}
-static uint8_t bitmapIndex(void *data,
- int format,
- uint32_t x)
+static void readArray8(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- int isLSB;
- uint8_t octet;
-
- isLSB = (format & BH_BITMAP_LSB) > 0;
- switch (format & 0x0FFF)
+ switch (formatInfo->channels)
{
- case BH_BITMAP_INDEX1:
- octet = (*(uint8_t *)data) & bitMask1[isLSB][x & 7];
- return octet >> bitOrder1[isLSB][x & 7];
-
- case BH_BITMAP_INDEX2:
- octet = (*(uint8_t *)data) & bitMask2[isLSB][x & 3];
- return octet >> bitOrder2[isLSB][x & 3];
-
- case BH_BITMAP_INDEX4:
- octet = (*(uint8_t *)data) & bitMask4[isLSB][x & 1];
- return octet >> bitOrder4[isLSB][x & 1];
-
- case BH_BITMAP_INDEX8:
- return *(uint8_t *)data;
+ case 4: value->data.channel[3] = normilize(formatInfo->masks[3], ((uint8_t *)data)[formatInfo->shifts[3]]);
+ case 3: value->data.channel[2] = normilize(formatInfo->masks[2], ((uint8_t *)data)[formatInfo->shifts[2]]);
+ case 2: value->data.channel[1] = normilize(formatInfo->masks[1], ((uint8_t *)data)[formatInfo->shifts[1]]);
+ case 1: value->data.channel[0] = normilize(formatInfo->masks[0], ((uint8_t *)data)[formatInfo->shifts[0]]);
}
-
- return 0;
}
-static void setBitmapIndex(void *data,
- int format,
- uint32_t x,
- uint8_t index)
+static void writeArray8(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- int isLSB;
- uint8_t octet;
-
- isLSB = (format & BH_BITMAP_LSB) > 0;
- switch (format & 0x0FFF)
+ switch (formatInfo->channels)
{
- case BH_BITMAP_INDEX1:
- octet = (*(uint8_t *)data) & ~bitMask1[isLSB][x & 7];
- octet |= (index & 0x1) << bitOrder1[isLSB][x & 7];
- *(uint8_t *)data = octet;
- break;
-
- case BH_BITMAP_INDEX2:
- octet = (*(uint8_t *)data) & ~bitMask2[isLSB][x & 3];
- octet |= (index & 0x3) << bitOrder2[isLSB][x & 3];
- *(uint8_t *)data = octet;
- break;
-
- case BH_BITMAP_INDEX4:
- octet = (*(uint8_t *)data) & ~bitMask4[isLSB][x & 1];
- octet |= (index & 0xF) << bitOrder4[isLSB][x & 1];
- *(uint8_t *)data = octet;
- break;
-
- case BH_BITMAP_INDEX8:
- *(uint8_t *)data = index;
- break;
+ case 4: ((uint8_t *)data)[formatInfo->shifts[3]] = denormilize(formatInfo->masks[3], value->data.channel[3]);
+ case 3: ((uint8_t *)data)[formatInfo->shifts[2]] = denormilize(formatInfo->masks[2], value->data.channel[2]);
+ case 2: ((uint8_t *)data)[formatInfo->shifts[1]] = denormilize(formatInfo->masks[1], value->data.channel[1]);
+ case 1: ((uint8_t *)data)[formatInfo->shifts[0]] = denormilize(formatInfo->masks[0], value->data.channel[0]);
}
}
-static void bitmapColor(void *data,
- void *palette,
- int format,
- BH_Color *value,
- uint32_t x)
+static void readArray16(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- switch (format & 0x0FFF)
+ value->type = BH_COLOR_TYPE_RGBA;
+ switch (formatInfo->channels)
{
- case BH_BITMAP_INDEX1:
- {
- uint32_t color;
- color = ((uint32_t *)palette)[bitmapIndex(data, format, x)];
-
- BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
- color & 0xFF, color >> 24 & 0xFF);
- }
- break;
-
- case BH_BITMAP_INDEX2:
- {
- uint32_t color;
- color = ((uint32_t *)palette)[bitmapIndex(data, format, x)];
-
- BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
- color & 0xFF, color >> 24 & 0xFF);
- }
- break;
-
- case BH_BITMAP_INDEX4:
- {
- uint32_t color;
- color = ((uint32_t *)palette)[bitmapIndex(data, format, x)];
-
- BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
- color & 0xFF, color >> 24 & 0xFF);
- }
- break;
-
- case BH_BITMAP_INDEX8:
- {
- uint32_t color;
- color = ((uint32_t *)palette)[bitmapIndex(data, format, x)];
-
- BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
- color & 0xFF, color >> 24 & 0xFF);
- }
- break;
-
- case BH_BITMAP_GRAY8:
- {
- uint8_t color;
-
- color = *(uint8_t *)data;
- BH_ColorSetRGBA8(value, color, color, color, 0xFF);
- }
- break;
-
- case BH_BITMAP_GRAY16:
- {
- uint16_t color;
-
- color = *(uint16_t *)data;
- BH_ColorSetRGBA16(value, color, color, color, 0xFFFF);
- }
- break;
-
- case BH_BITMAP_RGBA32:
- {
- uint32_t color;
-
- color = *(uint32_t *)data;
- BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
- color & 0xFF, color >> 24 & 0xFF);
- }
- break;
-
- case BH_BITMAP_RGBA64:
- {
- uint64_t color;
-
- color = *(uint64_t *)data;
- BH_ColorSetRGBA16(value, color >> 32 & 0xFFFF, color >> 16 & 0xFFFF,
- color & 0xFFFF, color >> 48 & 0xFFFF);
- }
- break;
-
- case BH_BITMAP_RGB565:
- {
- uint8_t r, g, b;
- uint16_t color;
- int isBGR;
-
- color = *(uint16_t *)data;
- isBGR = (format & BH_BITMAP_BGR) > 0;
- r = color >> bitOrder565[isBGR][0] & 0x1F;
- g = color >> bitOrder565[isBGR][1] & 0x3F;
- b = color >> bitOrder565[isBGR][2] & 0x1F;
- r = r << 3 | r >> 2;
- g = g << 2 | g >> 4;
- b = b << 3 | b >> 2;
-
- BH_ColorSetRGBA8(value, r, g, b, 0xFF);
- }
- break;
-
- case BH_BITMAP_RGB888:
- {
- uint8_t r, g, b;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- r = ((uint8_t *)data)[unitOrderRGB[isBGR][0]];
- g = ((uint8_t *)data)[unitOrderRGB[isBGR][1]];
- b = ((uint8_t *)data)[unitOrderRGB[isBGR][2]];
-
- BH_ColorSetRGBA8(value, r, g, b, 0xFF);
- }
- break;
-
- case BH_BITMAP_RGBA8888:
- {
- uint8_t r, g, b, a;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- r = ((uint8_t *)data)[unitOrderRGBA[isBGR][0]];
- g = ((uint8_t *)data)[unitOrderRGBA[isBGR][1]];
- b = ((uint8_t *)data)[unitOrderRGBA[isBGR][2]];
- a = ((uint8_t *)data)[unitOrderRGBA[isBGR][3]];
-
- BH_ColorSetRGBA8(value, r, g, b, a);
- }
- break;
-
- case BH_BITMAP_RGB161616:
- {
- uint16_t r, g, b;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- r = ((uint16_t *)data)[unitOrderRGB[isBGR][0]];
- g = ((uint16_t *)data)[unitOrderRGB[isBGR][1]];
- b = ((uint16_t *)data)[unitOrderRGB[isBGR][2]];
-
- BH_ColorSetRGBA16(value, r, g, b, 0xFFFF);
- }
- break;
-
- case BH_BITMAP_RGBA16161616:
- {
- uint16_t r, g, b, a;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- r = ((uint16_t *)data)[unitOrderRGBA[isBGR][0]];
- g = ((uint16_t *)data)[unitOrderRGBA[isBGR][1]];
- b = ((uint16_t *)data)[unitOrderRGBA[isBGR][2]];
- a = ((uint16_t *)data)[unitOrderRGBA[isBGR][3]];
-
- BH_ColorSetRGBA16(value, r, g, b, a);
- }
- break;
-
- case BH_BITMAP_RGBA1010102:
- {
- uint16_t r, g, b, a;
- uint32_t color;
- int isBGR;
-
- color = *(uint32_t *)data;
- isBGR = (format & BH_BITMAP_BGR) > 0;
- r = color >> bitOrder1010102[isBGR][0] & 0x3FF;
- g = color >> bitOrder1010102[isBGR][1] & 0x3FF;
- b = color >> bitOrder1010102[isBGR][2] & 0x3FF;
- a = color >> bitOrder1010102[isBGR][3] & 0x3;
- r = r << 6 | r >> 4;
- g = g << 6 | g >> 4;
- b = b << 6 | b >> 4;
- a = a << 2 | a;
- a = a << 4 | a;
- a = a << 8 | a;
-
- BH_ColorSetRGBA16(value, r, g, b, a);
- }
- break;
+ case 4: value->data.channel[3] = normilize(formatInfo->masks[3], ((uint16_t *)data)[formatInfo->shifts[3]]);
+ case 3: value->data.channel[2] = normilize(formatInfo->masks[2], ((uint16_t *)data)[formatInfo->shifts[2]]);
+ case 2: value->data.channel[1] = normilize(formatInfo->masks[1], ((uint16_t *)data)[formatInfo->shifts[1]]);
+ case 1: value->data.channel[0] = normilize(formatInfo->masks[0], ((uint16_t *)data)[formatInfo->shifts[0]]);
}
-
- /* Fix alpha, if format doesn't support alpha channel */
- if (format & BH_BITMAP_NOALPHA)
- value->data.rgba.a = 0xFFFF;
}
-static size_t bestPaletteIndex(uint8_t r,
- uint8_t g,
- uint8_t b,
- uint8_t a,
- const uint32_t *palette,
- size_t paletteSize)
+static void writeArray16(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- uint32_t bestError = -1;
- size_t i, bestIndex = 0;
-
- for (i = 0; i < paletteSize; ++i) {
- int32_t dr, dg, db, da;
- uint32_t currentError;
-
- dr = (int32_t)r - (palette[i] >> 16 & 0xFF);
- dg = (int32_t)g - (palette[i] >> 8 & 0xFF);
- db = (int32_t)b - (palette[i] & 0xFF);
- da = (int32_t)a - (palette[i] >> 24 & 0xFF);
-
- currentError = dr * dr + dg * dg + db * db + da * da;
- if (currentError < bestError)
- {
- bestError = currentError;
- bestIndex = i;
- }
+ switch (formatInfo->channels)
+ {
+ case 4: ((uint16_t *)data)[formatInfo->shifts[3]] = denormilize(formatInfo->masks[3], value->data.channel[3]);
+ case 3: ((uint16_t *)data)[formatInfo->shifts[2]] = denormilize(formatInfo->masks[2], value->data.channel[2]);
+ case 2: ((uint16_t *)data)[formatInfo->shifts[1]] = denormilize(formatInfo->masks[1], value->data.channel[1]);
+ case 1: ((uint16_t *)data)[formatInfo->shifts[0]] = denormilize(formatInfo->masks[0], value->data.channel[0]);
}
-
- return bestIndex;
}
-static void setBitmapColor(void *data,
- void *palette,
- int format,
- const BH_Color *value,
- uint32_t x)
+static void readArray(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
{
- switch (format & 0x0FFF)
+ switch (formatInfo->type)
{
- case BH_BITMAP_INDEX1:
- {
- uint8_t r, g, b, a;
-
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- setBitmapIndex(data, format, x, bestPaletteIndex(r, g, b, a, palette, 1));
- }
- break;
-
- case BH_BITMAP_INDEX2:
- {
- uint8_t r, g, b, a;
-
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- setBitmapIndex(data, format, x, bestPaletteIndex(r, g, b, a, palette, 4));
- }
- break;
-
- case BH_BITMAP_INDEX4:
- {
- uint8_t r, g, b, a;
-
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- setBitmapIndex(data, format, x, bestPaletteIndex(r, g, b, a, palette, 16));
- }
- break;
-
- case BH_BITMAP_INDEX8:
- {
- uint8_t r, g, b, a;
-
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- setBitmapIndex(data, format, x, bestPaletteIndex(r, g, b, a, palette, 256));
- }
- break;
-
- case BH_BITMAP_GRAY8:
- {
- uint8_t r, g, b, a;
+ case TYPE_ARRAY8: readArray8(formatInfo, data, x, value); break;
+ case TYPE_ARRAY16: readArray16(formatInfo, data, x, value); break;
+ }
+}
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- *(uint8_t *)data = r;
- }
- break;
- case BH_BITMAP_GRAY16:
- {
- uint16_t r, g, b, a;
+static void writeArray(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value)
+{
+ switch (formatInfo->type)
+ {
+ case TYPE_ARRAY8: writeArray8(formatInfo, data, x, value); break;
+ case TYPE_ARRAY16: writeArray16(formatInfo, data, x, value); break;
+ }
+}
- BH_ColorRGBA16(value, &r, &g, &b, &a);
- *(uint16_t *)data = r;
- }
- break;
- case BH_BITMAP_RGBA32:
- {
- uint8_t r, g, b, a;
+static uint8_t readIndex(const FormatInfo *formatInfo,
+ void *data,
+ int x)
+{
+ uint8_t value = *(uint8_t *)data;
+ return (value >> formatInfo->shifts[x & formatInfo->channels]) & formatInfo->masks[0];
+}
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- if (format & BH_BITMAP_NOALPHA)
- a = 0xFF;
- *(uint32_t *)data = (uint32_t)r << 16 | (uint32_t)g << 8 |
- (uint32_t)b | (uint32_t)a << 24;
- }
- break;
-
- case BH_BITMAP_RGBA64:
- {
- uint16_t r, g, b, a;
+static void writeIndex(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ uint8_t index)
+{
+ uint8_t mask = ~(formatInfo->masks[0] << formatInfo->shifts[x & formatInfo->channels]);
+ uint8_t value = (index & formatInfo->masks[0]) << formatInfo->shifts[x & formatInfo->channels];
+ *(uint8_t *)data = (*(uint8_t *)data & mask) | value;
+}
- BH_ColorRGBA16(value, &r, &g, &b, &a);
- if (format & BH_BITMAP_NOALPHA)
- a = 0xFFFF;
- *(uint64_t *)data = (uint64_t)r << 32 | (uint64_t)g << 16 |
- (uint64_t)b | (uint64_t)a << 48;
- }
+void readData(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value,
+ const BH_Color *palette)
+{
+ switch (formatInfo->type & 0x0F00)
+ {
+ case TYPE_PACKED:
+ readPacked(formatInfo, data, x, value);
+ value->type = BH_COLOR_TYPE_RGBA;
break;
- case BH_BITMAP_RGB565:
- {
- uint8_t r, g, b, a;
- uint16_t color;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- color = 0;
- color |= (r >> 3) << bitOrder565[isBGR][0];
- color |= (g >> 2) << bitOrder565[isBGR][1];
- color |= (b >> 3) << bitOrder565[isBGR][2];
-
- *(uint16_t *)(data) = color;
- }
+ case TYPE_INDEX:
+ *value = palette[readIndex(formatInfo, data, x)];
break;
-
- case BH_BITMAP_RGB888:
- {
- uint8_t r, g, b, a;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- ((uint8_t *)data)[unitOrderRGB[isBGR][0]] = r;
- ((uint8_t *)data)[unitOrderRGB[isBGR][1]] = g;
- ((uint8_t *)data)[unitOrderRGB[isBGR][2]] = b;
- }
+
+ case TYPE_ARRAY:
+ readArray(formatInfo, data, x, value);
+ value->type = BH_COLOR_TYPE_RGBA;
break;
+ }
+}
- case BH_BITMAP_RGBA8888:
- {
- uint8_t r, g, b, a;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- BH_ColorRGBA8(value, &r, &g, &b, &a);
- if (format & BH_BITMAP_NOALPHA)
- a = 0xFF;
-
- ((uint8_t *)data)[unitOrderRGBA[isBGR][0]] = r;
- ((uint8_t *)data)[unitOrderRGBA[isBGR][1]] = g;
- ((uint8_t *)data)[unitOrderRGBA[isBGR][2]] = b;
- ((uint8_t *)data)[unitOrderRGBA[isBGR][3]] = a;
- }
- break;
- case BH_BITMAP_RGB161616:
- {
- uint16_t r, g, b, a;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- BH_ColorRGBA16(value, &r, &g, &b, &a);
- ((uint16_t *)data)[unitOrderRGB[isBGR][0]] = r;
- ((uint16_t *)data)[unitOrderRGB[isBGR][1]] = g;
- ((uint16_t *)data)[unitOrderRGB[isBGR][2]] = b;
- }
+void writeData(const FormatInfo *formatInfo,
+ void *data,
+ int x,
+ BH_Color *value,
+ const BH_Color *palette)
+{
+ switch (formatInfo->type & 0x0F00)
+ {
+ case TYPE_PACKED:
+ BH_ColorToRGBA(value, value);
+ writePacked(formatInfo, data, x, value);
break;
- case BH_BITMAP_RGBA16161616:
- {
- uint16_t r, g, b, a;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- BH_ColorRGBA16(value, &r, &g, &b, &a);
- if (format & BH_BITMAP_NOALPHA)
- a = 0xFFFF;
-
- ((uint16_t *)data)[unitOrderRGBA[isBGR][0]] = r;
- ((uint16_t *)data)[unitOrderRGBA[isBGR][1]] = g;
- ((uint16_t *)data)[unitOrderRGBA[isBGR][2]] = b;
- ((uint16_t *)data)[unitOrderRGBA[isBGR][3]] = a;
- }
+ case TYPE_INDEX:
+ writeIndex(formatInfo, data, x, bestPaletteIndex(value, palette, formatInfo));
break;
-
- case BH_BITMAP_RGBA1010102:
- {
- uint16_t r, g, b, a;
- uint32_t color;
- int isBGR;
-
- isBGR = (format & BH_BITMAP_BGR) > 0;
- BH_ColorRGBA16(value, &r, &g, &b, &a);
- if (format & BH_BITMAP_NOALPHA)
- a = 0xFFFF;
-
- color = 0;
- color |= (r >> 6) << bitOrder1010102[isBGR][0];
- color |= (g >> 6) << bitOrder1010102[isBGR][1];
- color |= (b >> 6) << bitOrder1010102[isBGR][2];
- color |= (a >> 10) << bitOrder1010102[isBGR][3];
-
- *(uint32_t *)data = color;
- }
+
+ case TYPE_ARRAY:
+ BH_ColorToRGBA(value, value);
+ writeArray(formatInfo, data, x, value);
break;
}
}
-static void *rowAt(void *data,
- int format,
- int step,
- uint32_t x)
+struct BH_Bitmap
{
- switch (format & 0x0FFF)
- {
- case BH_BITMAP_INDEX1:
- return (uint8_t *)data + x / 8;
-
- case BH_BITMAP_INDEX2:
- return (uint8_t *)data + x / 4;
+ uint32_t width;
+ uint32_t height;
+ int format;
+ const FormatInfo *formatInfo;
+ int flags;
+ size_t stride;
+ uint8_t *data;
+ BH_Color *palette;
+};
- case BH_BITMAP_INDEX4:
- return (uint8_t *)data + x / 2;
- default:
- return (uint8_t *)data + step * x;
+static void *rowAt(const FormatInfo *formatInfo,
+ void *data,
+ uint32_t x)
+{
+ switch (formatInfo->type)
+ {
+ case TYPE_INDEX1: return (uint8_t *)data + x / 8;
+ case TYPE_INDEX2: return (uint8_t *)data + x / 4;
+ case TYPE_INDEX4: return (uint8_t *)data + x / 2;
+ default: return (uint8_t *)data + formatInfo->size * x;
}
}
-static size_t calculateStride(int format,
+static size_t calculateStride(const FormatInfo *formatInfo,
uint32_t width)
{
size_t step;
- switch (format & 0x0FFF)
+ switch (formatInfo->type)
{
- case BH_BITMAP_INDEX1: return (width + 7) / 8;
- case BH_BITMAP_INDEX2: return (width + 3) / 4;
- case BH_BITMAP_INDEX4: return (width + 1) / 2;
+ case TYPE_INDEX1: return (width + 7) / 8;
+ case TYPE_INDEX2: return (width + 3) / 4;
+ case TYPE_INDEX4: return (width + 1) / 2;
}
- step = calculateStep(format);
- if (BH_CHECK_UMUL_WRAP(step, width, size_t))
+ if (BH_CHECK_UMUL_WRAP(formatInfo->size, width, size_t))
return 0;
- return step * width;
+ return formatInfo->size * width;
}
-static int isPaletteNeeded(int format)
+static int isPaletteNeeded(const FormatInfo *formatInfo)
{
- switch (format)
+ switch (formatInfo->type)
{
- case BH_BITMAP_INDEX1:
- case BH_BITMAP_INDEX2:
- case BH_BITMAP_INDEX4:
- case BH_BITMAP_INDEX8:
+ case TYPE_INDEX1:
+ case TYPE_INDEX2:
+ case TYPE_INDEX4:
+ case TYPE_INDEX8:
return 1;
}
@@ -665,14 +396,14 @@ static int isPaletteNeeded(int format)
}
-static size_t calculateTrailer(int format)
+static size_t calculateTrailer(const FormatInfo *formatInfo)
{
- switch (format & 0x0FFF)
+ switch (formatInfo->type)
{
- case BH_BITMAP_INDEX1: return sizeof(uint32_t) * 2;
- case BH_BITMAP_INDEX2: return sizeof(uint32_t) * 4;
- case BH_BITMAP_INDEX4: return sizeof(uint32_t) * 16;
- case BH_BITMAP_INDEX8: return sizeof(uint32_t) * 256;
+ case TYPE_INDEX1: return sizeof(BH_Color) * 2;
+ case TYPE_INDEX2: return sizeof(BH_Color) * 4;
+ case TYPE_INDEX4: return sizeof(BH_Color) * 16;
+ case TYPE_INDEX8: return sizeof(BH_Color) * 256;
}
return 0;
}
@@ -684,9 +415,10 @@ BH_Bitmap *BH_BitmapNew(uint32_t width,
int format,
int flags,
void *data,
- void *palette)
+ BH_Color *palette)
{
BH_Bitmap *result;
+ const FormatInfo *formatInfo;
int needPalette;
size_t header, body, allocSize, stride, step;
@@ -695,14 +427,16 @@ BH_Bitmap *BH_BitmapNew(uint32_t width,
height == 0 || height >= 0x7FFFFFFF)
return NULL;
+ /* Get format information */
+ formatInfo = formats + (format & 0x0FFF);
+
/* Unset internal flags */
flags &= ~BH_BITMAP_FLAG_EXT_DATA;
flags &= ~BH_BITMAP_FLAG_EXT_PALETTE;
/* Calculate size of the bitmap with headers */
- step = calculateStep(format);
- stride = calculateStride(format, width);
- needPalette = isPaletteNeeded(format);
+ stride = calculateStride(formatInfo, width);
+ needPalette = isPaletteNeeded(formatInfo);
/* Check stride overflow */
if (!stride)
@@ -718,7 +452,7 @@ BH_Bitmap *BH_BitmapNew(uint32_t width,
header = sizeof(*result);
header = (header + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1);
- allocSize = calculateTrailer(format);
+ allocSize = calculateTrailer(formatInfo);
body = stride * height;
if (BH_CHECK_UMUL_WRAP(stride, height, size_t))
@@ -758,13 +492,13 @@ BH_Bitmap *BH_BitmapNew(uint32_t width,
data = (uint8_t *)result + header;
if (!palette && needPalette)
- palette = (uint8_t *)result + header + body;
+ palette = (BH_Color *)((uint8_t *)result + header + body);
result->width = width;
result->height = height;
result->format = format;
+ result->formatInfo = formatInfo;
result->flags = flags;
- result->step = step;
result->stride = stride;
result->data = data;
result->palette = palette;
@@ -784,7 +518,9 @@ void BH_BitmapColor(const BH_Bitmap *bitmap,
uint32_t y,
BH_Color *value)
{
- bitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x);
+ readData(bitmap->formatInfo, BH_BitmapAt(bitmap, x, y), x, value, bitmap->palette);
+ if (bitmap->format & BH_BITMAP_NOALPHA || bitmap->formatInfo->channels < 4)
+ value->data.rgba.a = 65535;
}
void BH_BitmapSetColor(BH_Bitmap *bitmap,
@@ -792,7 +528,12 @@ void BH_BitmapSetColor(BH_Bitmap *bitmap,
uint32_t y,
const BH_Color *value)
{
- setBitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x);
+ BH_Color tmp;
+ tmp = *value;
+
+ if (bitmap->format & BH_BITMAP_NOALPHA || bitmap->formatInfo->channels < 4)
+ tmp.data.rgba.a = 65535;
+ writeData(bitmap->formatInfo, BH_BitmapAt(bitmap, x, y), x, &tmp, bitmap->palette);
}
@@ -849,7 +590,7 @@ uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
uint32_t x,
uint32_t y)
{
- return bitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x);
+ return readIndex(bitmap->formatInfo, BH_BitmapAt(bitmap, x, y), x);
}
@@ -858,7 +599,7 @@ void BH_BitmapSetIndex(BH_Bitmap *bitmap,
uint32_t y,
uint8_t index)
{
- setBitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x, index);
+ writeIndex(bitmap->formatInfo, BH_BitmapAt(bitmap, x, y), x, index);
}
@@ -873,7 +614,7 @@ void *BH_BitmapAt(const BH_Bitmap *bitmap,
uint32_t x,
uint32_t y)
{
- return rowAt(BH_BitmapScanline(bitmap, y), bitmap->format, bitmap->step, x);
+ return rowAt(bitmap->formatInfo, BH_BitmapScanline(bitmap, y), x);
}
@@ -921,24 +662,29 @@ int BH_BitmapFlags(BH_Bitmap *bitmap)
void BH_BitmapConvertRow(void *src,
int srcFormat,
- void *srcPalette,
+ const BH_Color *srcPalette,
void *dest,
int destFormat,
- void *destPalette,
+ const BH_Color *destPalette,
size_t count)
{
- size_t srcStep, destStep, x;
- srcStep = calculateStep(srcFormat);
- destStep = calculateStep(destFormat);
+ size_t x;
+ const FormatInfo *srcInfo, *destInfo;
+
+ srcInfo = formats + (srcFormat & 0x0FFF);
+ destInfo = formats + (destFormat & 0x0FFF);
for (x = 0; count; --count, ++x)
{
void *srcAt, *destAt;
BH_Color data;
- srcAt = rowAt(src, srcFormat, srcStep, x);
- destAt = rowAt(dest, destFormat, destStep, x);
- bitmapColor(srcAt, srcPalette, srcFormat, &data, x);
- setBitmapColor(destAt, destPalette, destFormat, &data, x);
+ srcAt = rowAt(srcInfo, src, x);
+ destAt = rowAt(destInfo, dest, x);
+ readData(srcInfo, srcAt, x, &data, srcPalette);
+ if (srcFormat & BH_BITMAP_NOALPHA || destFormat & BH_BITMAP_NOALPHA ||
+ srcInfo->channels < 4 || destInfo->channels < 4)
+ data.data.rgba.a = 65535;
+ writeData(destInfo, destAt, x, &data, destPalette);
}
}
diff --git a/test/src/TestBitmap.c b/test/src/TestBitmap.c
index 349a157..bda74cd 100644
--- a/test/src/TestBitmap.c
+++ b/test/src/TestBitmap.c
@@ -28,12 +28,6 @@ BH_UNIT_TEST(RoundTrip)
{65535, 65535, 65535, 0},
};
- uint16_t flags[] =
- {
- 0,
- BH_BITMAP_BGR,
- };
-
uint16_t formats[] =
{
BH_BITMAP_RGBA32,
@@ -49,36 +43,32 @@ BH_UNIT_TEST(RoundTrip)
BH_BITMAP_RGBA1010102 | BH_BITMAP_NOALPHA,
};
- for (flag = 0; flag < sizeof(flags) / sizeof(uint16_t); ++flag)
+ for (format = 0; format < sizeof(formats) / sizeof(uint16_t); ++format)
{
- for (format = 0; format < sizeof(formats) / sizeof(uint16_t); ++format)
+ for (i = 0; i < 16; ++i)
{
- for (i = 0; i < 16; ++i)
- {
- BH_Color source, destination;
- uint64_t temp;
+ BH_Color source, destination;
+ uint64_t temp;
- BH_ColorSetRGBA16(&source, data[i][0], data[i][1], data[i][2],
- data[i][3]);
- BH_BitmapConvertRow(&source.data, BH_BITMAP_RGBA16161616, NULL,
- &temp, formats[format] | flags[flag], NULL,
- 1);
- BH_BitmapConvertRow(&temp, formats[format] | flags[flag], NULL,
- &destination.data, BH_BITMAP_RGBA16161616,
- NULL, 1);
+ temp = 0;
+ BH_ColorSetRGBA16(&source, data[i][0], data[i][1], data[i][2],
+ data[i][3]);
+ BH_BitmapConvertRow(&source.data, BH_BITMAP_RGBA16161616, NULL,
+ &temp, formats[format], NULL, 1);
+ BH_BitmapConvertRow(&temp, formats[format], NULL, &destination.data,
+ BH_BITMAP_RGBA16161616, NULL, 1);
- BH_VERIFY(source.data.rgba.r == destination.data.rgba.r);
- BH_VERIFY(source.data.rgba.g == destination.data.rgba.g);
- BH_VERIFY(source.data.rgba.b == destination.data.rgba.b);
+ BH_VERIFY(source.data.rgba.r == destination.data.rgba.r);
+ BH_VERIFY(source.data.rgba.g == destination.data.rgba.g);
+ BH_VERIFY(source.data.rgba.b == destination.data.rgba.b);
- if (formats[format] == BH_BITMAP_RGB888 ||
- formats[format] == BH_BITMAP_RGB161616 ||
- formats[format] == BH_BITMAP_RGB565 ||
- (formats[format] | flags[flag]) & BH_BITMAP_NOALPHA)
- BH_VERIFY(destination.data.rgba.a == 65535);
- else
- BH_VERIFY(source.data.rgba.a == destination.data.rgba.a);
- }
+ if (formats[format] == BH_BITMAP_RGB888 ||
+ formats[format] == BH_BITMAP_RGB161616 ||
+ formats[format] == BH_BITMAP_RGB565 ||
+ formats[format] & BH_BITMAP_NOALPHA)
+ BH_VERIFY(destination.data.rgba.a == 65535);
+ else
+ BH_VERIFY(source.data.rgba.a == destination.data.rgba.a);
}
}