Refactor bitmap, add new formats
Small refactoring of the bitmap module and added more indexed formats.
This commit is contained in:
@@ -25,6 +25,18 @@ Currently, the following pixel formats are supported:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_INDEX1>
|
||||
|
||||
1-bit indexed/paletted
|
||||
|
||||
=item B<BH_BITMAP_INDEX2>
|
||||
|
||||
2-bit indexed/paletted
|
||||
|
||||
=item B<BH_BITMAP_INDEX4>
|
||||
|
||||
4-bit indexed/paletted
|
||||
|
||||
=item B<BH_BITMAP_INDEX8>
|
||||
|
||||
8-bit indexed/paletted
|
||||
@@ -76,9 +88,15 @@ 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).
|
||||
@@ -152,6 +170,29 @@ Writes color value of the pixel at specified position.
|
||||
The I<x> and I<y> parameters specify a position on the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapIndex
|
||||
|
||||
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
Returns the index value at the specified position.
|
||||
|
||||
The I<x> and I<y> parameters specify a position on the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapSetIndex
|
||||
|
||||
void BH_BitmapSetIndex(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
uint8_t index);
|
||||
|
||||
Sets the index value at the specified position.
|
||||
|
||||
The I<x> and I<y> parameters specify a position on the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapCopy
|
||||
|
||||
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
|
||||
@@ -25,6 +25,18 @@ BH_Bitmap - доступ к растровому изображению/карт
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_INDEX1>
|
||||
|
||||
1-разрядный индексированный/палитрированный
|
||||
|
||||
=item B<BH_BITMAP_INDEX2>
|
||||
|
||||
2-разрядный индексированный/палитрированный
|
||||
|
||||
=item B<BH_BITMAP_INDEX4>
|
||||
|
||||
4-разрядный индексированный/палитрированный
|
||||
|
||||
=item B<BH_BITMAP_INDEX8>
|
||||
|
||||
8-разрядный индексированный/палитрированный
|
||||
@@ -77,9 +89,15 @@ 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-разрядных).
|
||||
@@ -155,7 +173,30 @@ I<BH_BITMAP_RGBA32> и I<BH_BITMAP_RGBA64>.
|
||||
|
||||
Записывает значение цвета пикселя в указанной позиции.
|
||||
|
||||
Параметры I<x> и I<y> определяют положение на растровой карте.
|
||||
Параметры I<x> и I<y> определяют положение на растровом изображении.
|
||||
|
||||
|
||||
=head2 BH_BitmapIndex
|
||||
|
||||
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
Возвращает значение индекса в указанной позиции.
|
||||
|
||||
Параметры I<x> и I<y> определяют положение на растровом изображении.
|
||||
|
||||
|
||||
=head2 BH_BitmapSetIndex
|
||||
|
||||
void BH_BitmapSetIndex(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
uint8_t index);
|
||||
|
||||
Устанавливает значение индекса в указанной позиции.
|
||||
|
||||
Параметры I<x> и I<y> определяют положение на растровом изображении.
|
||||
|
||||
|
||||
=head2 BH_BitmapCopy
|
||||
|
||||
@@ -12,19 +12,22 @@ 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_INDEX8 0x0000
|
||||
#define BH_BITMAP_GRAY8 0x0001
|
||||
#define BH_BITMAP_GRAY16 0x0002
|
||||
#define BH_BITMAP_RGBA32 0x0003
|
||||
#define BH_BITMAP_RGBA64 0x0004
|
||||
#define BH_BITMAP_RGB565 0x8000
|
||||
#define BH_BITMAP_RGB888 0x8001
|
||||
#define BH_BITMAP_RGBA8888 0x8002
|
||||
#define BH_BITMAP_RGB161616 0x8003
|
||||
#define BH_BITMAP_RGBA16161616 0x8004
|
||||
#define BH_BITMAP_RGBA1010102 0x8005
|
||||
#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_FLAG_ALIGN32 0x0001
|
||||
@@ -55,6 +58,17 @@ void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
const BH_Color *value);
|
||||
|
||||
|
||||
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
|
||||
void BH_BitmapSetIndex(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
uint8_t index);
|
||||
|
||||
|
||||
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
|
||||
636
src/Bitmap.c
636
src/Bitmap.c
@@ -20,109 +20,47 @@ struct BH_Bitmap
|
||||
};
|
||||
|
||||
|
||||
static size_t stepFromFormat(int format)
|
||||
/* Bit and unit order arrays for working with RGB/BGR and MSB/LSB */
|
||||
static const size_t bitOrder1[][8] =
|
||||
{
|
||||
switch (format & 0x8FFF)
|
||||
{7, 6, 5, 4, 3, 2, 1, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7},
|
||||
};
|
||||
|
||||
|
||||
static const size_t bitMask1[][8] =
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
{0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01},
|
||||
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80},
|
||||
};
|
||||
|
||||
|
||||
BH_Bitmap *BH_BitmapNew(int width,
|
||||
int height,
|
||||
int format,
|
||||
int flags,
|
||||
void *data,
|
||||
void *palette)
|
||||
static const size_t bitOrder2[][4] =
|
||||
{
|
||||
BH_Bitmap *result;
|
||||
int needPalette;
|
||||
size_t header, body, trailer, stride, step;
|
||||
{6, 4, 2, 0},
|
||||
{0, 2, 4, 6},
|
||||
};
|
||||
|
||||
/* Unset internal flags */
|
||||
flags &= ~BH_BITMAP_FLAG_EXT_DATA;
|
||||
flags &= ~BH_BITMAP_FLAG_EXT_PALETTE;
|
||||
|
||||
/* Calculate size of the bitmap with headers */
|
||||
needPalette = (format & 0x8FFF) == BH_BITMAP_INDEX8;
|
||||
step = stepFromFormat(format);
|
||||
stride = step * width;
|
||||
if (flags & BH_BITMAP_FLAG_ALIGN32)
|
||||
stride = (stride + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
|
||||
|
||||
header = sizeof(*result);
|
||||
header = (header + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1);
|
||||
body = (stride * height + (sizeof(uint32_t) - 1)) & ~(sizeof(uint32_t) - 1);
|
||||
trailer = sizeof(uint32_t) * 256;
|
||||
|
||||
/* Adjust body and trailer size if ext data or palette is provided */
|
||||
if (!needPalette)
|
||||
trailer = 0;
|
||||
|
||||
if (palette)
|
||||
static const size_t bitMask2[][4] =
|
||||
{
|
||||
flags |= BH_BITMAP_FLAG_EXT_PALETTE;
|
||||
trailer = 0;
|
||||
}
|
||||
{0xC0, 0x30, 0x0C, 0x03},
|
||||
{0x03, 0x0C, 0x30, 0xC0},
|
||||
};
|
||||
|
||||
if (data)
|
||||
|
||||
static const size_t bitOrder4[][2] =
|
||||
{
|
||||
flags |= BH_BITMAP_FLAG_EXT_DATA;
|
||||
body = 0;
|
||||
}
|
||||
|
||||
/* Allocate and setup bitmap data */
|
||||
result = malloc(header + body + trailer);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
if (!data)
|
||||
data = (uint8_t *)result + header;
|
||||
|
||||
if (!palette && needPalette)
|
||||
palette = (uint8_t *)result + header + body;
|
||||
|
||||
result->width = width;
|
||||
result->height = height;
|
||||
result->format = format;
|
||||
result->flags = flags;
|
||||
result->step = step;
|
||||
result->stride = stride;
|
||||
result->data = data;
|
||||
result->palette = palette;
|
||||
|
||||
return result;
|
||||
}
|
||||
{4, 0},
|
||||
{0, 4},
|
||||
};
|
||||
|
||||
|
||||
void BH_BitmapFree(BH_Bitmap *bitmap)
|
||||
static const size_t bitMask4[][2] =
|
||||
{
|
||||
free(bitmap);
|
||||
}
|
||||
{0xF0, 0x0F},
|
||||
{0x0F, 0xF0},
|
||||
};
|
||||
|
||||
|
||||
static const size_t bitOrder565[][3] =
|
||||
@@ -153,16 +91,153 @@ static const size_t unitOrderRGBA[][4] =
|
||||
};
|
||||
|
||||
|
||||
static void color(void *data,
|
||||
/* Private functions */
|
||||
static size_t calculateStep(int format)
|
||||
{
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t bitmapIndex(void *data,
|
||||
int format,
|
||||
int x)
|
||||
{
|
||||
int isLSB;
|
||||
uint8_t octet;
|
||||
|
||||
isLSB = (format & BH_BITMAP_LSB) > 0;
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void setBitmapIndex(void *data,
|
||||
int format,
|
||||
int x,
|
||||
uint8_t index)
|
||||
{
|
||||
int isLSB;
|
||||
uint8_t octet;
|
||||
|
||||
isLSB = (format & BH_BITMAP_LSB) > 0;
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void bitmapColor(void *data,
|
||||
void *palette,
|
||||
int format,
|
||||
BH_Color *value)
|
||||
BH_Color *value,
|
||||
int x)
|
||||
{
|
||||
switch (format & 0x8FFF)
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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 = ((uint32_t *)palette)[*(uint8_t *)data];
|
||||
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);
|
||||
}
|
||||
@@ -170,21 +245,27 @@ static void color(void *data,
|
||||
|
||||
case BH_BITMAP_GRAY8:
|
||||
{
|
||||
uint8_t color = *(uint8_t *)data;
|
||||
uint8_t color;
|
||||
|
||||
color = *(uint8_t *)data;
|
||||
BH_ColorSetRGBA8(value, color, color, color, 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_GRAY16:
|
||||
{
|
||||
uint16_t color = *(uint16_t *)data;
|
||||
uint16_t color;
|
||||
|
||||
color = *(uint16_t *)data;
|
||||
BH_ColorSetRGBA16(value, color, color, color, 0xFFFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA32:
|
||||
{
|
||||
uint32_t color = *(uint32_t *)data;
|
||||
uint32_t color;
|
||||
|
||||
color = *(uint32_t *)data;
|
||||
BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
|
||||
color & 0xFF, color >> 24 & 0xFF);
|
||||
}
|
||||
@@ -192,7 +273,9 @@ static void color(void *data,
|
||||
|
||||
case BH_BITMAP_RGBA64:
|
||||
{
|
||||
uint64_t color = *(uint64_t *)data;
|
||||
uint64_t color;
|
||||
|
||||
color = *(uint64_t *)data;
|
||||
BH_ColorSetRGBA16(value, color >> 32 & 0xFFFF, color >> 16 & 0xFFFF,
|
||||
color & 0xFFFF, color >> 48 & 0xFFFF);
|
||||
}
|
||||
@@ -201,16 +284,18 @@ static void color(void *data,
|
||||
case BH_BITMAP_RGB565:
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
uint16_t color = *(uint16_t *)data;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
|
||||
r = color >> bitOrder565[orderSelector][0] & 0x1F;
|
||||
g = color >> bitOrder565[orderSelector][1] & 0x3F;
|
||||
b = color >> bitOrder565[orderSelector][2] & 0x1F;
|
||||
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;
|
||||
@@ -218,11 +303,13 @@ static void color(void *data,
|
||||
case BH_BITMAP_RGB888:
|
||||
{
|
||||
uint8_t r, g, b;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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]];
|
||||
|
||||
r = ((uint8_t *)data)[unitOrderRGB[orderSelector][0]];
|
||||
g = ((uint8_t *)data)[unitOrderRGB[orderSelector][1]];
|
||||
b = ((uint8_t *)data)[unitOrderRGB[orderSelector][2]];
|
||||
BH_ColorSetRGBA8(value, r, g, b, 0xFF);
|
||||
}
|
||||
break;
|
||||
@@ -230,12 +317,14 @@ static void color(void *data,
|
||||
case BH_BITMAP_RGBA8888:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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]];
|
||||
|
||||
r = ((uint8_t *)data)[unitOrderRGBA[orderSelector][0]];
|
||||
g = ((uint8_t *)data)[unitOrderRGBA[orderSelector][1]];
|
||||
b = ((uint8_t *)data)[unitOrderRGBA[orderSelector][2]];
|
||||
a = ((uint8_t *)data)[unitOrderRGBA[orderSelector][3]];
|
||||
BH_ColorSetRGBA8(value, r, g, b, a);
|
||||
}
|
||||
break;
|
||||
@@ -243,11 +332,13 @@ static void color(void *data,
|
||||
case BH_BITMAP_RGB161616:
|
||||
{
|
||||
uint16_t r, g, b;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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]];
|
||||
|
||||
r = ((uint16_t *)data)[unitOrderRGB[orderSelector][0]];
|
||||
g = ((uint16_t *)data)[unitOrderRGB[orderSelector][1]];
|
||||
b = ((uint16_t *)data)[unitOrderRGB[orderSelector][2]];
|
||||
BH_ColorSetRGBA16(value, r, g, b, 0xFFFF);
|
||||
}
|
||||
break;
|
||||
@@ -255,12 +346,14 @@ static void color(void *data,
|
||||
case BH_BITMAP_RGBA16161616:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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]];
|
||||
|
||||
r = ((uint16_t *)data)[unitOrderRGBA[orderSelector][0]];
|
||||
g = ((uint16_t *)data)[unitOrderRGBA[orderSelector][1]];
|
||||
b = ((uint16_t *)data)[unitOrderRGBA[orderSelector][2]];
|
||||
a = ((uint16_t *)data)[unitOrderRGBA[orderSelector][3]];
|
||||
BH_ColorSetRGBA16(value, r, g, b, a);
|
||||
}
|
||||
break;
|
||||
@@ -268,20 +361,22 @@ static void color(void *data,
|
||||
case BH_BITMAP_RGBA1010102:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
uint32_t color = *(uint32_t *)data;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
|
||||
r = color >> bitOrder1010102[orderSelector][0] & 0x3FF;
|
||||
g = color >> bitOrder1010102[orderSelector][1] & 0x3FF;
|
||||
b = color >> bitOrder1010102[orderSelector][2] & 0x3FF;
|
||||
a = color >> bitOrder1010102[orderSelector][3] & 0x3;
|
||||
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;
|
||||
@@ -293,16 +388,17 @@ static void color(void *data,
|
||||
}
|
||||
|
||||
|
||||
static size_t bestIndex(uint8_t r,
|
||||
static size_t bestPaletteIndex(uint8_t r,
|
||||
uint8_t g,
|
||||
uint8_t b,
|
||||
uint8_t a,
|
||||
const uint32_t *palette)
|
||||
const uint32_t *palette,
|
||||
size_t paletteSize)
|
||||
{
|
||||
uint32_t bestError = -1;
|
||||
size_t i, bestIndex = 0;
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
for (i = 0; i < paletteSize; ++i) {
|
||||
int32_t dr, dg, db, da;
|
||||
uint32_t currentError;
|
||||
|
||||
@@ -323,19 +419,47 @@ static size_t bestIndex(uint8_t r,
|
||||
}
|
||||
|
||||
|
||||
static void setColor(void *data,
|
||||
static void setBitmapColor(void *data,
|
||||
void *palette,
|
||||
int format,
|
||||
const BH_Color *value)
|
||||
const BH_Color *value,
|
||||
int x)
|
||||
{
|
||||
switch (format & 0x8FFF)
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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);
|
||||
*(uint8_t *)data = bestIndex(r, g, b, a, palette);
|
||||
setBitmapIndex(data, format, x, bestPaletteIndex(r, g, b, a, palette, 256));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -386,14 +510,15 @@ static void setColor(void *data,
|
||||
case BH_BITMAP_RGB565:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
uint16_t color;
|
||||
int isBGR;
|
||||
|
||||
color = 0;
|
||||
isBGR = (format & BH_BITMAP_BGR) > 0;
|
||||
BH_ColorRGBA8(value, &r, &g, &b, &a);
|
||||
color |= (r >> 3) << bitOrder565[orderSelector][0];
|
||||
color |= (g >> 2) << bitOrder565[orderSelector][1];
|
||||
color |= (b >> 3) << bitOrder565[orderSelector][2];
|
||||
color = 0;
|
||||
color |= (r >> 3) << bitOrder565[isBGR][0];
|
||||
color |= (g >> 2) << bitOrder565[isBGR][1];
|
||||
color |= (b >> 3) << bitOrder565[isBGR][2];
|
||||
|
||||
*(uint16_t *)(data) = color;
|
||||
}
|
||||
@@ -402,74 +527,79 @@ static void setColor(void *data,
|
||||
case BH_BITMAP_RGB888:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
int isBGR;
|
||||
|
||||
isBGR = (format & BH_BITMAP_BGR) > 0;
|
||||
BH_ColorRGBA8(value, &r, &g, &b, &a);
|
||||
((uint8_t *)data)[unitOrderRGB[orderSelector][0]] = r;
|
||||
((uint8_t *)data)[unitOrderRGB[orderSelector][1]] = g;
|
||||
((uint8_t *)data)[unitOrderRGB[orderSelector][2]] = b;
|
||||
((uint8_t *)data)[unitOrderRGB[isBGR][0]] = r;
|
||||
((uint8_t *)data)[unitOrderRGB[isBGR][1]] = g;
|
||||
((uint8_t *)data)[unitOrderRGB[isBGR][2]] = b;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA8888:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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[orderSelector][0]] = r;
|
||||
((uint8_t *)data)[unitOrderRGBA[orderSelector][1]] = g;
|
||||
((uint8_t *)data)[unitOrderRGBA[orderSelector][2]] = b;
|
||||
((uint8_t *)data)[unitOrderRGBA[orderSelector][3]] = a;
|
||||
((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 orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
int isBGR;
|
||||
|
||||
isBGR = (format & BH_BITMAP_BGR) > 0;
|
||||
BH_ColorRGBA16(value, &r, &g, &b, &a);
|
||||
((uint16_t *)data)[unitOrderRGB[orderSelector][0]] = r;
|
||||
((uint16_t *)data)[unitOrderRGB[orderSelector][1]] = g;
|
||||
((uint16_t *)data)[unitOrderRGB[orderSelector][2]] = b;
|
||||
((uint16_t *)data)[unitOrderRGB[isBGR][0]] = r;
|
||||
((uint16_t *)data)[unitOrderRGB[isBGR][1]] = g;
|
||||
((uint16_t *)data)[unitOrderRGB[isBGR][2]] = b;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA16161616:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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[orderSelector][0]] = r;
|
||||
((uint16_t *)data)[unitOrderRGBA[orderSelector][1]] = g;
|
||||
((uint16_t *)data)[unitOrderRGBA[orderSelector][2]] = b;
|
||||
((uint16_t *)data)[unitOrderRGBA[orderSelector][3]] = a;
|
||||
((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;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA1010102:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
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[orderSelector][0];
|
||||
color |= (g >> 6) << bitOrder1010102[orderSelector][1];
|
||||
color |= (b >> 6) << bitOrder1010102[orderSelector][2];
|
||||
color |= (a >> 10) << bitOrder1010102[orderSelector][3];
|
||||
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;
|
||||
}
|
||||
@@ -478,12 +608,148 @@ static void setColor(void *data,
|
||||
}
|
||||
|
||||
|
||||
static void *rowAt(void *data,
|
||||
int format,
|
||||
int step,
|
||||
int x)
|
||||
{
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
case BH_BITMAP_INDEX1:
|
||||
return (uint8_t *)data + x / 8;
|
||||
|
||||
case BH_BITMAP_INDEX2:
|
||||
return (uint8_t *)data + x / 4;
|
||||
|
||||
case BH_BITMAP_INDEX4:
|
||||
return (uint8_t *)data + x / 2;
|
||||
|
||||
default:
|
||||
return (uint8_t *)data + step * x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static size_t calculateStride(int format,
|
||||
int width)
|
||||
{
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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 BH_BITMAP_INDEX8: return width * calculateStep(format);
|
||||
}
|
||||
return width * calculateStep(format);
|
||||
}
|
||||
|
||||
|
||||
static int isPaletteNeeded(int format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case BH_BITMAP_INDEX1:
|
||||
case BH_BITMAP_INDEX2:
|
||||
case BH_BITMAP_INDEX4:
|
||||
case BH_BITMAP_INDEX8:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static size_t calculateTrailer(int format)
|
||||
{
|
||||
switch (format & 0x0FFF)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Public functions */
|
||||
BH_Bitmap *BH_BitmapNew(int width,
|
||||
int height,
|
||||
int format,
|
||||
int flags,
|
||||
void *data,
|
||||
void *palette)
|
||||
{
|
||||
BH_Bitmap *result;
|
||||
int needPalette;
|
||||
size_t header, body, trailer, stride, step;
|
||||
|
||||
/* 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);
|
||||
|
||||
if (flags & BH_BITMAP_FLAG_ALIGN32)
|
||||
stride = (stride + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1);
|
||||
|
||||
header = sizeof(*result);
|
||||
header = (header + (sizeof(uint64_t) - 1)) & ~(sizeof(uint64_t) - 1);
|
||||
body = (stride * height + (sizeof(uint32_t) - 1)) & ~(sizeof(uint32_t) - 1);
|
||||
trailer = calculateTrailer(format);
|
||||
|
||||
/* Adjust body and trailer size if ext data or palette is provided */
|
||||
if (palette)
|
||||
{
|
||||
flags |= BH_BITMAP_FLAG_EXT_PALETTE;
|
||||
trailer = 0;
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
flags |= BH_BITMAP_FLAG_EXT_DATA;
|
||||
body = 0;
|
||||
}
|
||||
|
||||
/* Allocate and setup bitmap data */
|
||||
result = malloc(header + body + trailer);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
if (!data)
|
||||
data = (uint8_t *)result + header;
|
||||
|
||||
if (!palette && needPalette)
|
||||
palette = (uint8_t *)result + header + body;
|
||||
|
||||
result->width = width;
|
||||
result->height = height;
|
||||
result->format = format;
|
||||
result->flags = flags;
|
||||
result->step = step;
|
||||
result->stride = stride;
|
||||
result->data = data;
|
||||
result->palette = palette;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void BH_BitmapFree(BH_Bitmap *bitmap)
|
||||
{
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
|
||||
void BH_BitmapColor(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
BH_Color *value)
|
||||
{
|
||||
color(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value);
|
||||
bitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x);
|
||||
}
|
||||
|
||||
void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
@@ -491,9 +757,10 @@ void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
int y,
|
||||
const BH_Color *value)
|
||||
{
|
||||
setColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value);
|
||||
setBitmapColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value, x);
|
||||
}
|
||||
|
||||
|
||||
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
@@ -554,6 +821,23 @@ BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
}
|
||||
|
||||
|
||||
uint8_t BH_BitmapIndex(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
return bitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x);
|
||||
}
|
||||
|
||||
|
||||
void BH_BitmapSetIndex(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
uint8_t index)
|
||||
{
|
||||
setBitmapIndex(BH_BitmapAt(bitmap, x, y), bitmap->format, x, index);
|
||||
}
|
||||
|
||||
|
||||
void *BH_BitmapScanline(const BH_Bitmap *bitmap,
|
||||
int y)
|
||||
{
|
||||
@@ -565,7 +849,7 @@ void *BH_BitmapAt(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
return BH_BitmapScanline(bitmap, y) + bitmap->step * x;
|
||||
return rowAt(BH_BitmapScanline(bitmap, y), bitmap->format, bitmap->step, x);
|
||||
}
|
||||
|
||||
|
||||
@@ -619,18 +903,18 @@ void BH_BitmapConvertRow(void *src,
|
||||
void *destPalette,
|
||||
size_t count)
|
||||
{
|
||||
size_t srcStep, destStep;
|
||||
size_t srcStep, destStep, x;
|
||||
srcStep = calculateStep(srcFormat);
|
||||
destStep = calculateStep(destFormat);
|
||||
|
||||
srcStep = stepFromFormat(srcFormat);
|
||||
destStep = stepFromFormat(destFormat);
|
||||
|
||||
for (; count; --count)
|
||||
for (x = 0; count; --count, ++x)
|
||||
{
|
||||
void *srcAt, *destAt;
|
||||
BH_Color data;
|
||||
|
||||
color(src, srcPalette, srcFormat, &data);
|
||||
setColor(dest, destPalette, destFormat, &data);
|
||||
src = (uint8_t*)src + srcStep;
|
||||
dest = (uint8_t*)dest + destStep;
|
||||
srcAt = rowAt(src, srcFormat, srcStep, x);
|
||||
destAt = rowAt(dest, destFormat, destStep, x);
|
||||
bitmapColor(srcAt, srcPalette, srcFormat, &data, x);
|
||||
setBitmapColor(destAt, destPalette, destFormat, &data, x);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user