Add bitmap support
This commit is contained in:
290
doc/Manual/en/BH_Bitmap.pod
Normal file
290
doc/Manual/en/BH_Bitmap.pod
Normal file
@@ -0,0 +1,290 @@
|
||||
=encoding UTF-8
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
BH_Bitmap - bitmap/image access
|
||||
|
||||
|
||||
=head1 SYNTAX
|
||||
|
||||
#include <BH/Bitmap.h>
|
||||
|
||||
cc prog.c -o prog -lbh
|
||||
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The BH_Bitmap module provides methods for accessing the pixel data of a bitmap
|
||||
(image) and for converting between different pixel formats.
|
||||
|
||||
|
||||
=head1 FORMATS
|
||||
|
||||
Currently, the following pixel formats are supported:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_INDEX8>
|
||||
|
||||
8-bit indexed/paletted
|
||||
|
||||
=item B<BH_BITMAP_GRAY8>
|
||||
|
||||
8-bit grayscale
|
||||
|
||||
=item B<BH_BITMAP_GRAY16>
|
||||
|
||||
16-bit grayscale
|
||||
|
||||
=item B<BH_BITMAP_RGBA32>
|
||||
|
||||
32-bit RGB with alpha represented in uint32_t value. The layout is: 0xAARRGGBB
|
||||
|
||||
=item B<BH_BITMAP_RGBA64>
|
||||
|
||||
64-bit RGB with alpha represented in uint64_t value. The layout is:
|
||||
0xAAAARRRRGGGGBBBB
|
||||
|
||||
=item B<BH_BITMAP_RGB565>
|
||||
|
||||
16-bit RGB
|
||||
|
||||
=item B<BH_BITMAP_RGB888>
|
||||
|
||||
24-bit RGB
|
||||
|
||||
=item B<BH_BITMAP_RGBA8888>
|
||||
|
||||
32-bit RGB with alpha
|
||||
|
||||
=item B<BH_BITMAP_RGB161616>
|
||||
|
||||
48-bit RGB
|
||||
|
||||
=item B<BH_BITMAP_RGBA16161616>
|
||||
|
||||
64-bit RGB with alpha
|
||||
|
||||
=item B<BH_BITMAP_RGBA1010102>
|
||||
|
||||
32-bit RGB with alpha
|
||||
|
||||
=back
|
||||
|
||||
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_INDEX8>, I<BH_BITMAP_GRAY8>, I<BH_BITMAP_GRAY16>,
|
||||
I<BH_BITMAP_RGBA32> and I<BH_BITMAP_RGBA64>.
|
||||
|
||||
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).
|
||||
|
||||
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
|
||||
|
||||
|
||||
=head2 BH_BitmapNew
|
||||
|
||||
BH_Bitmap *BH_BitmapNew(int width,
|
||||
int height,
|
||||
int format,
|
||||
int flags,
|
||||
void *data,
|
||||
void *palette);
|
||||
|
||||
Creates the bitmap with the specified I<width>, I<height> and pixel I<format>.
|
||||
|
||||
The I<flags> parameter can take a combination of the following values:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_FLAG_ALIGN32>
|
||||
|
||||
Rows are aligned to 32-bit boundary
|
||||
|
||||
=back
|
||||
|
||||
The optional I<data> parameter specifies pointer to the existing data.
|
||||
|
||||
The optional I<palette> parameter specifies pointer to the existing palette.
|
||||
|
||||
This function returns a pointer to a new BH_Bitmap object or NULL.
|
||||
|
||||
|
||||
=head2 BH_BitmapFree
|
||||
|
||||
void BH_BitmapFree(BH_Bitmap *bitmap);
|
||||
|
||||
Destroys the bitmap object.
|
||||
|
||||
|
||||
=head2 BH_BitmapColor
|
||||
|
||||
void BH_BitmapColor(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
BH_Color *value);
|
||||
|
||||
Reads color value of the pixel at specified position.
|
||||
|
||||
The I<x> and I<y> parameters specify a position on the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapSetColor
|
||||
|
||||
void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
const BH_Color *value);
|
||||
|
||||
Writes color value of the pixel at 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,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int shallow);
|
||||
|
||||
Creates a copy of the bitmap region by the given position and size.
|
||||
|
||||
The I<x> and I<y> parameters specify a position on the bitmap.
|
||||
|
||||
The I<width> and I<height> parameters specify size of the new bitmap.
|
||||
|
||||
The I<shallow> parameter specifies whether the new bitmap is a shallow copy (or
|
||||
a view) of the existing bitmap or a deep copy. For the shallow copy to work, the
|
||||
region should be within the existing bitmap.
|
||||
|
||||
This function returns a pointer to a new BH_Bitmap object or NULL.
|
||||
|
||||
|
||||
=head2 BH_BitmapScanline
|
||||
|
||||
void *BH_BitmapScanline(const BH_Bitmap *bitmap,
|
||||
int y);
|
||||
|
||||
Returns address of the scanline in the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapAt
|
||||
|
||||
void *BH_BitmapAt(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
Returns address of the pixel in the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapWidth
|
||||
|
||||
int BH_BitmapWidth(BH_Bitmap *bitmap);
|
||||
|
||||
Returns width of the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapHeight
|
||||
|
||||
int BH_BitmapHeight(BH_Bitmap *bitmap);
|
||||
|
||||
Returns height of the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapFormat
|
||||
|
||||
int BH_BitmapFormat(BH_Bitmap *bitmap);
|
||||
|
||||
Returns pixel format of the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapStride
|
||||
|
||||
size_t BH_BitmapStride(BH_Bitmap *bitmap);
|
||||
|
||||
Returns row stride of the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapData
|
||||
|
||||
void *BH_BitmapData(BH_Bitmap *bitmap);
|
||||
|
||||
Returns pointer to the pixel data of the bitmap.
|
||||
|
||||
|
||||
=head2 BH_BitmapPalette
|
||||
|
||||
void *BH_BitmapPalette(BH_Bitmap *bitmap);
|
||||
|
||||
Returns pointer to the bitmap's palette.
|
||||
|
||||
|
||||
=head2 BH_BitmapFlags
|
||||
|
||||
int BH_BitmapFlags(BH_Bitmap *bitmap);
|
||||
|
||||
Returns bitmap's flags.
|
||||
|
||||
The result can be a combination of the following values:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_FLAG_ALIGN32>
|
||||
|
||||
Rows are aligned to 32-bit boundary
|
||||
|
||||
=item B<BH_BITMAP_FLAG_EXT_DATA>
|
||||
|
||||
Bitmap doesn't own the pixel data
|
||||
|
||||
=item B<BH_BITMAP_FLAG_EXT_PALETTE>
|
||||
|
||||
Bitmap doesn't own palette data
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 BH_BitmapConvertRow
|
||||
|
||||
void BH_BitmapConvertRow(void *src,
|
||||
int srcFormat,
|
||||
void *srcPalette,
|
||||
void *dest,
|
||||
int destFormat,
|
||||
void *destPalette,
|
||||
size_t count);
|
||||
|
||||
Converts a row of source data from one pixel format to another pixel format.
|
||||
|
||||
The parameter I<src> and I<srcFormat> specify the source of the data and its
|
||||
pixel format.
|
||||
|
||||
The parameter I<srcPalette> specify the source palette (if required by the pixel
|
||||
format).
|
||||
|
||||
The parameter I<dest> and I<destFormat> specify the destination of the data and
|
||||
its pixel format.
|
||||
|
||||
The parameter I<destPalette> specify the destination palette (if required by the
|
||||
pixel format).
|
||||
|
||||
The parameter I<count> specifies the number of pixel for conversion.
|
||||
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<BH>
|
||||
@@ -3,6 +3,7 @@ POD2MAN = pod2man
|
||||
|
||||
HTMLS = BH_Algo.html \
|
||||
BH_Args.html \
|
||||
BH_Bitmap.html \
|
||||
BH_Box2f.html \
|
||||
BH_Box3f.html \
|
||||
BH_Color.html \
|
||||
@@ -30,6 +31,7 @@ HTMLS = BH_Algo.html \
|
||||
|
||||
MANS = BH_Algo.3 \
|
||||
BH_Args.3 \
|
||||
BH_Bitmap.3 \
|
||||
BH_Box2f.3 \
|
||||
BH_Box3f.3 \
|
||||
BH_Color.3 \
|
||||
|
||||
297
doc/Manual/ru/BH_Bitmap.pod
Normal file
297
doc/Manual/ru/BH_Bitmap.pod
Normal file
@@ -0,0 +1,297 @@
|
||||
=encoding UTF-8
|
||||
|
||||
|
||||
=head1 НАИМЕНОВАНИЕ
|
||||
|
||||
BH_Bitmap - доступ к растровому изображению/картинке с изображением
|
||||
|
||||
|
||||
=head1 СИНТАКСИС
|
||||
|
||||
#include <BH/Bitmap.h>
|
||||
|
||||
cc prog.c -o prog -lbh
|
||||
|
||||
|
||||
=head1 ОПИСАНИЕ
|
||||
|
||||
Модуль BH_Bitmap предоставляет методы для доступа к пиксельным данным растрового
|
||||
изображения и для преобразования между различными пиксельными форматами.
|
||||
|
||||
|
||||
=head1 ФОРМАТЫ
|
||||
|
||||
В настоящее время поддерживаются следующие пиксельные форматы:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_INDEX8>
|
||||
|
||||
8-разрядный индексированный/палитрированный
|
||||
|
||||
=item B<BH_BITMAP_GRAY8>
|
||||
|
||||
8-разрядные оттенки серого
|
||||
|
||||
=item B<BH_BITMAP_GRAY16>
|
||||
|
||||
16-битные оттенки серого
|
||||
|
||||
=item B<BH_BITMAP_RGBA32>
|
||||
|
||||
32-разрядный RGB с прозрачностью, представленный в виде uint32_t.
|
||||
Формат: 0xAARRGGBB
|
||||
|
||||
=item B<BH_BITMAP_RGBA64>
|
||||
|
||||
64-разрядный RGB с прозрачностью, представленный в виде uint64_t.
|
||||
Формат: 0xAAAARRRRGGGGBBBB
|
||||
|
||||
=item B<BH_BITMAP_RGB565>
|
||||
|
||||
16-разрядный RGB
|
||||
|
||||
=item B<BH_BITMAP_RGB888>
|
||||
|
||||
24-разрядный RGB
|
||||
|
||||
=item B<BH_BITMAP_RGBA8888>
|
||||
|
||||
32-разрядный RGB с прозрачностью
|
||||
|
||||
=item B<BH_BITMAP_RGB161616>
|
||||
|
||||
48-разрядный RGB
|
||||
|
||||
=item B<BH_BITMAP_RGBA16161616>
|
||||
|
||||
64-разрядный RGB с прозрачностью
|
||||
|
||||
=item B<BH_BITMAP_RGBA1010102>
|
||||
|
||||
32-разрядный RGB с прозрачностью
|
||||
|
||||
=back
|
||||
|
||||
Во всех форматах пикселей используется нативный порядок байт.
|
||||
|
||||
Флаг I<BH_BITMAP_BGR> может использоваться для изменения порядка цветовых
|
||||
каналов (RGB -> BGR). Этот флаг не влияет на следующие пиксельные форматы:
|
||||
I<BH_BITMAP_INDEX8>, I<BH_BITMAP_GRAY8>, I<BH_BITMAP_GRAY16>,
|
||||
I<BH_BITMAP_RGBA32> и I<BH_BITMAP_RGBA64>.
|
||||
|
||||
Флаг I<BH_BITMAP_NOALPHA> может использоваться для указания того,
|
||||
что альфа-канал не используется и всегда должен быть установлен в максимальное
|
||||
значение (255 для 8-разрядных и 65535 для 16-разрядных).
|
||||
|
||||
Флаг I<BH_BITMAP_PREMULT> может использоваться для указания того, что значения
|
||||
цвета представлены в предварительно умноженном виде.
|
||||
|
||||
Предполагается, что цветовая палитра содержит ровно 256 цветов и хранится в
|
||||
пиксельном формате I<BH_BITMAP_RGBA32>.
|
||||
|
||||
|
||||
=head1 ВЫЗОВЫ API
|
||||
|
||||
|
||||
=head2 BH_BitmapNew
|
||||
|
||||
BH_Bitmap *BH_BitmapNew(int width,
|
||||
int height,
|
||||
int format,
|
||||
int flags,
|
||||
void *data,
|
||||
void *palette);
|
||||
|
||||
Создает растровое изображение с указанной шириной, высотой и пиксельным
|
||||
форматом.
|
||||
|
||||
Параметры I<width> и I<height> указывают размеры изображения.
|
||||
|
||||
Параметр I<format> указывает используемый пиксельный формат изображения.
|
||||
|
||||
Параметр I<flags> может принимать комбинацию из следующих значений:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_FLAG_ALIGN32>
|
||||
|
||||
Строки выравниваются по 32-разрядной границе
|
||||
|
||||
=back
|
||||
|
||||
Необязательный параметр I<data> указывает на существующие данные.
|
||||
|
||||
Необязательный параметр I<palette> указывает на существующую палитру.
|
||||
|
||||
Эта функция возвращает указатель на новый объект BH_Bitmap или значение NULL.
|
||||
|
||||
|
||||
=head2 BH_BitmapFree
|
||||
|
||||
void BH_BitmapFree(BH_Bitmap *bitmap);
|
||||
|
||||
Уничтожает растровый объект.
|
||||
|
||||
|
||||
=head2 BH_BitmapColor
|
||||
|
||||
void BH_BitmapColor(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
BH_Color *value);
|
||||
|
||||
Считывает значение цвета пикселя в указанной позиции.
|
||||
|
||||
Параметры I<x> и I<y> определяют положение на растровом изображении.
|
||||
|
||||
|
||||
=head2 BH_BitmapSetColor
|
||||
|
||||
void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
const BH_Color *value);
|
||||
|
||||
Записывает значение цвета пикселя в указанной позиции.
|
||||
|
||||
Параметры I<x> и I<y> определяют положение на растровой карте.
|
||||
|
||||
|
||||
=head2 BH_BitmapCopy
|
||||
|
||||
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int shallow);
|
||||
|
||||
Создает копию области растрового изображения с заданным положением и размером.
|
||||
|
||||
Параметры I<x> и I<y> задают положение на растровом изображении.
|
||||
|
||||
Параметры I<width> и I<height> задают размер нового растрового изображения.
|
||||
|
||||
Параметр I<shallow> указывает, является ли новое растровое изображение
|
||||
поверхностной копией (или отображением) существующего растрового изображения или
|
||||
его глубокой копией. Для работы с поверхностной копией область должна находиться
|
||||
в пределах существующего растрового изображения.
|
||||
|
||||
Эта функция возвращает указатель на новый объект BH_Bitmap или NULL.
|
||||
|
||||
|
||||
=head2 BH_BitmapScanline
|
||||
|
||||
void *BH_BitmapScanline(const BH_Bitmap *bitmap,
|
||||
int y);
|
||||
|
||||
Возвращает адрес строки сканирования в растровом изображении.
|
||||
|
||||
|
||||
=head2 BH_BitmapAt
|
||||
|
||||
void *BH_BitmapAt(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
Возвращает адрес пикселя в растровом изображении.
|
||||
|
||||
|
||||
=head2 BH_BitmapWidth
|
||||
|
||||
int BH_BitmapWidth(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает ширину растрового изображения.
|
||||
|
||||
|
||||
=head2 BH_BitmapHeight
|
||||
|
||||
int BH_BitmapHeight(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает высоту растрового изображения.
|
||||
|
||||
|
||||
=head2 BH_BitmapFormat
|
||||
|
||||
int BH_BitmapFormat(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает пиксельный формат растрового изображения.
|
||||
|
||||
|
||||
=head2 BH_BitmapStride
|
||||
|
||||
size_t BH_BitmapStride(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает шаг строки растрового изображения.
|
||||
|
||||
|
||||
=head2 BH_BitmapData
|
||||
|
||||
void *BH_BitmapData(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает указатель на пиксельные данные растрового изображения.
|
||||
|
||||
|
||||
=head2 BH_BitmapPalette
|
||||
|
||||
void *BH_BitmapPalette(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает указатель на палитру растрового изображения.
|
||||
|
||||
|
||||
=head2 BH_BitmapFlags
|
||||
|
||||
int BH_BitmapFlags(BH_Bitmap *bitmap);
|
||||
|
||||
Возвращает флаги растрового изображения.
|
||||
|
||||
Результатом может быть комбинация следующих значений:
|
||||
|
||||
=over
|
||||
|
||||
=item B<BH_BITMAP_FLAG_ALIGN32>
|
||||
|
||||
Строки выравниваются по 32-битной границе
|
||||
|
||||
=item B<BH_BITMAP_FLAG_EXT_DATA>
|
||||
|
||||
Растровому изображению не принадлежат пиксельные данные
|
||||
|
||||
=item B<BH_BITMAP_FLAG_EXT_PALETTE>
|
||||
|
||||
Растровому изображению не принадлежат данные палитры
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 BH_BitmapConvertRow
|
||||
|
||||
void BH_BitmapConvertRow(void *src,
|
||||
int srcFormat,
|
||||
void *srcPalette,
|
||||
void *dest,
|
||||
int destFormat,
|
||||
void *destPalette,
|
||||
size_t count);
|
||||
|
||||
Преобразует строку исходных данных из одного пиксельного формата в другой пиксельный формат.
|
||||
|
||||
Параметры I<src> и I<srcFormat> указывают источник данных и его
|
||||
формат в пикселях.
|
||||
|
||||
Параметр I<srcPalette> указывает исходную палитру (если это требуется
|
||||
для формата в пикселях).
|
||||
|
||||
Параметры I<dest> и I<destFormat> указывают назначение данных и
|
||||
их формат в пикселях.
|
||||
|
||||
Параметр I<destPalette> определяет целевую палитру (если этого требует формат
|
||||
пикселя).
|
||||
|
||||
Параметр I<count> определяет количество пикселей для преобразования.
|
||||
|
||||
|
||||
=head1 СМ. ТАКЖЕ
|
||||
|
||||
L<BH>
|
||||
@@ -3,6 +3,7 @@ POD2MAN = pod2man
|
||||
|
||||
HTMLS = BH_Algo.html \
|
||||
BH_Args.html \
|
||||
BH_Bitmap.html \
|
||||
BH_Box2f.html \
|
||||
BH_Box3f.html \
|
||||
BH_Color.html \
|
||||
@@ -30,6 +31,7 @@ HTMLS = BH_Algo.html \
|
||||
|
||||
MANS = BH_Algo.3 \
|
||||
BH_Args.3 \
|
||||
BH_Bitmap.3 \
|
||||
BH_Box2f.3 \
|
||||
BH_Box3f.3 \
|
||||
BH_Color.3 \
|
||||
|
||||
105
include/BH/Bitmap.h
Normal file
105
include/BH/Bitmap.h
Normal file
@@ -0,0 +1,105 @@
|
||||
#ifndef BH_BITMAP_H
|
||||
#define BH_BITMAP_H
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "Color.h"
|
||||
|
||||
|
||||
typedef struct BH_Bitmap BH_Bitmap;
|
||||
|
||||
|
||||
#define BH_BITMAP_PREMULT 0x1000
|
||||
#define BH_BITMAP_NOALPHA 0x2000
|
||||
#define BH_BITMAP_BGR 0x4000
|
||||
|
||||
|
||||
#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_FLAG_ALIGN32 0x0001
|
||||
#define BH_BITMAP_FLAG_EXT_DATA 0x0002
|
||||
#define BH_BITMAP_FLAG_EXT_PALETTE 0x0004
|
||||
|
||||
|
||||
BH_Bitmap *BH_BitmapNew(int width,
|
||||
int height,
|
||||
int format,
|
||||
int flags,
|
||||
void *data,
|
||||
void *palette);
|
||||
|
||||
|
||||
void BH_BitmapFree(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
void BH_BitmapColor(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
BH_Color *value);
|
||||
|
||||
|
||||
void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
const BH_Color *value);
|
||||
|
||||
|
||||
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int shallow);
|
||||
|
||||
|
||||
void *BH_BitmapScanline(const BH_Bitmap *bitmap,
|
||||
int y);
|
||||
|
||||
|
||||
void *BH_BitmapAt(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
|
||||
int BH_BitmapWidth(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
int BH_BitmapHeight(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
int BH_BitmapFormat(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
size_t BH_BitmapStride(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
void *BH_BitmapData(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
void *BH_BitmapPalette(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
int BH_BitmapFlags(BH_Bitmap *bitmap);
|
||||
|
||||
|
||||
void BH_BitmapConvertRow(void *src,
|
||||
int srcFormat,
|
||||
void *srcPalette,
|
||||
void *dest,
|
||||
int destFormat,
|
||||
void *destPalette,
|
||||
size_t count);
|
||||
|
||||
|
||||
#endif /* BH_BITMAP_H */
|
||||
7
include/BH/Info
Normal file
7
include/BH/Info
Normal file
@@ -0,0 +1,7 @@
|
||||
12345678901234567890123456789012
|
||||
RRRR
|
||||
GGGG
|
||||
BBBB
|
||||
AAAA
|
||||
FFFF
|
||||
|
||||
636
src/Bitmap.c
Normal file
636
src/Bitmap.c
Normal file
@@ -0,0 +1,636 @@
|
||||
#include <BH/Bitmap.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
|
||||
struct BH_Bitmap
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
int flags;
|
||||
size_t step;
|
||||
size_t stride;
|
||||
uint8_t *data;
|
||||
uint32_t *palette;
|
||||
};
|
||||
|
||||
|
||||
static size_t stepFromFormat(int format)
|
||||
{
|
||||
switch (format & 0x8FFF)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static const size_t bitOrder565[][3] =
|
||||
{
|
||||
{11, 5, 0},
|
||||
{0, 5, 11},
|
||||
};
|
||||
|
||||
|
||||
static const size_t bitOrder1010102[][4] =
|
||||
{
|
||||
{0, 10, 20, 30},
|
||||
{20, 10, 0, 30},
|
||||
};
|
||||
|
||||
|
||||
static const size_t unitOrderRGB[][3] =
|
||||
{
|
||||
{0, 1, 2},
|
||||
{2, 1, 0},
|
||||
};
|
||||
|
||||
|
||||
static const size_t unitOrderRGBA[][4] =
|
||||
{
|
||||
{0, 1, 2, 3},
|
||||
{2, 1, 0, 3},
|
||||
};
|
||||
|
||||
|
||||
static void color(void *data,
|
||||
void *palette,
|
||||
int format,
|
||||
BH_Color *value)
|
||||
{
|
||||
switch (format & 0x8FFF)
|
||||
{
|
||||
case BH_BITMAP_INDEX8:
|
||||
{
|
||||
uint32_t color = ((uint32_t *)palette)[*(uint8_t *)data];
|
||||
BH_ColorSetRGBA8(value, color >> 16 & 0xFF, color >> 8 & 0xFF,
|
||||
color & 0xFF, color >> 24 & 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_GRAY8:
|
||||
{
|
||||
uint8_t color = *(uint8_t *)data;
|
||||
BH_ColorSetRGBA8(value, color, color, color, 0xFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_GRAY16:
|
||||
{
|
||||
uint16_t color = *(uint16_t *)data;
|
||||
BH_ColorSetRGBA16(value, color, color, color, 0xFFFF);
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA32:
|
||||
{
|
||||
uint32_t 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 = *(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 = *(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;
|
||||
|
||||
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 orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
|
||||
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;
|
||||
|
||||
case BH_BITMAP_RGBA8888:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
|
||||
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;
|
||||
|
||||
case BH_BITMAP_RGB161616:
|
||||
{
|
||||
uint16_t r, g, b;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
|
||||
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;
|
||||
|
||||
case BH_BITMAP_RGBA16161616:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Fix alpha, if format doesn't support alpha channel */
|
||||
if (format & BH_BITMAP_NOALPHA)
|
||||
value->data.rgba.a = 0xFFFF;
|
||||
}
|
||||
|
||||
|
||||
static size_t bestIndex(uint8_t r,
|
||||
uint8_t g,
|
||||
uint8_t b,
|
||||
uint8_t a,
|
||||
const uint32_t *palette)
|
||||
{
|
||||
uint32_t bestError = -1;
|
||||
size_t i, bestIndex = 0;
|
||||
|
||||
for (i = 0; i < 256; ++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;
|
||||
}
|
||||
}
|
||||
|
||||
return bestIndex;
|
||||
}
|
||||
|
||||
|
||||
static void setColor(void *data,
|
||||
void *palette,
|
||||
int format,
|
||||
const BH_Color *value)
|
||||
{
|
||||
switch (format & 0x8FFF)
|
||||
{
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_GRAY8:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
|
||||
BH_ColorRGBA8(value, &r, &g, &b, &a);
|
||||
*(uint8_t *)data = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_GRAY16:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
|
||||
BH_ColorRGBA16(value, &r, &g, &b, &a);
|
||||
*(uint16_t *)data = r;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA32:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGB565:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
uint16_t color;
|
||||
|
||||
color = 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];
|
||||
|
||||
*(uint16_t *)(data) = color;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGB888:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (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;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA8888:
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
int orderSelector = (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;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGB161616:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (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;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA16161616:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (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;
|
||||
}
|
||||
break;
|
||||
|
||||
case BH_BITMAP_RGBA1010102:
|
||||
{
|
||||
uint16_t r, g, b, a;
|
||||
int orderSelector = (format & BH_BITMAP_BGR) > 0;
|
||||
uint32_t color;
|
||||
|
||||
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];
|
||||
|
||||
*(uint32_t *)data = color;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void BH_BitmapSetColor(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
const BH_Color *value)
|
||||
{
|
||||
setColor(BH_BitmapAt(bitmap, x, y), bitmap->palette, bitmap->format, value);
|
||||
}
|
||||
|
||||
BH_Bitmap *BH_BitmapCopy(BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
int shallow)
|
||||
{
|
||||
BH_Bitmap *result;
|
||||
int i, j;
|
||||
|
||||
/* Check for bogus width and height */
|
||||
if (width < 0 || height < 0)
|
||||
return NULL;
|
||||
|
||||
/* Shallow copy can't go out of bounds of the source bitmap */
|
||||
if (shallow)
|
||||
{
|
||||
if (x < 0 || x > bitmap->width || y < 0 || y > bitmap->height)
|
||||
return NULL;
|
||||
|
||||
if (width < 0 || width > bitmap->width - x ||
|
||||
height < 0 || height > bitmap->height - y)
|
||||
return NULL;
|
||||
|
||||
result = BH_BitmapNew(width, height, bitmap->format, bitmap->flags,
|
||||
BH_BitmapAt(bitmap, x, y), bitmap->palette);
|
||||
result->stride = bitmap->stride;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Deep copy of the bitmap */
|
||||
result = BH_BitmapNew(width, height, bitmap->format, bitmap->flags, NULL, NULL);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
/* Copy the palette if neccesery */
|
||||
if (result->palette)
|
||||
memcpy(result->palette, bitmap->palette, sizeof(uint32_t) * 256);
|
||||
|
||||
for (j = 0; j < height; ++j)
|
||||
{
|
||||
for (i = 0; i < width; ++i)
|
||||
{
|
||||
BH_Color color;
|
||||
memset(&color, 0, sizeof(color));
|
||||
|
||||
|
||||
if (i + x >= 0 && i + x < bitmap->width &&
|
||||
j + y >= 0 && j + y < bitmap->height)
|
||||
BH_BitmapColor(bitmap, i + x, j + y, &color);
|
||||
|
||||
BH_BitmapSetColor(result, i, j, &color);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void *BH_BitmapScanline(const BH_Bitmap *bitmap,
|
||||
int y)
|
||||
{
|
||||
return bitmap->data + y * bitmap->stride;
|
||||
}
|
||||
|
||||
|
||||
void *BH_BitmapAt(const BH_Bitmap *bitmap,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
return BH_BitmapScanline(bitmap, y) + bitmap->step * x;
|
||||
}
|
||||
|
||||
|
||||
int BH_BitmapWidth(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->width;
|
||||
}
|
||||
|
||||
|
||||
int BH_BitmapHeight(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->height;
|
||||
}
|
||||
|
||||
|
||||
int BH_BitmapFormat(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->format;
|
||||
}
|
||||
|
||||
|
||||
size_t BH_BitmapStride(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->stride;
|
||||
}
|
||||
|
||||
|
||||
void *BH_BitmapData(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->data;
|
||||
}
|
||||
|
||||
|
||||
void *BH_BitmapPalette(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->palette;
|
||||
}
|
||||
|
||||
|
||||
int BH_BitmapFlags(BH_Bitmap *bitmap)
|
||||
{
|
||||
return bitmap->flags;
|
||||
}
|
||||
|
||||
|
||||
void BH_BitmapConvertRow(void *src,
|
||||
int srcFormat,
|
||||
void *srcPalette,
|
||||
void *dest,
|
||||
int destFormat,
|
||||
void *destPalette,
|
||||
size_t count)
|
||||
{
|
||||
size_t srcStep, destStep;
|
||||
|
||||
srcStep = stepFromFormat(srcFormat);
|
||||
destStep = stepFromFormat(destFormat);
|
||||
|
||||
for (; count; --count)
|
||||
{
|
||||
BH_Color data;
|
||||
|
||||
color(src, srcPalette, srcFormat, &data);
|
||||
setColor(dest, destPalette, destFormat, &data);
|
||||
src = (uint8_t*)src + srcStep;
|
||||
dest = (uint8_t*)dest + destStep;
|
||||
}
|
||||
}
|
||||
97
test/src/TestBitmap.c
Normal file
97
test/src/TestBitmap.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <BH/Bitmap.h>
|
||||
#include <BH/Color.h>
|
||||
#include <BH/IO.h>
|
||||
#include <BH/Unit.h>
|
||||
|
||||
|
||||
BH_UNIT_TEST(RoundTrip)
|
||||
{
|
||||
size_t i, flag, format;
|
||||
|
||||
uint16_t data[][4] =
|
||||
{
|
||||
{0, 0, 0, 65535},
|
||||
{0, 0, 65535, 65535},
|
||||
{0, 65535, 0, 65535},
|
||||
{65535, 0, 0, 65535},
|
||||
{0, 65535, 65535, 65535},
|
||||
{65535, 0, 65535, 65535},
|
||||
{65535, 65535, 0, 65535},
|
||||
{65535, 65535, 65535, 65535},
|
||||
{0, 0, 0, 0},
|
||||
{0, 0, 65535, 0},
|
||||
{0, 65535, 0, 0},
|
||||
{65535, 0, 0, 0},
|
||||
{0, 65535, 65535, 0},
|
||||
{65535, 0, 65535, 0},
|
||||
{65535, 65535, 0, 0},
|
||||
{65535, 65535, 65535, 0},
|
||||
};
|
||||
|
||||
uint16_t flags[] =
|
||||
{
|
||||
0,
|
||||
BH_BITMAP_BGR,
|
||||
};
|
||||
|
||||
uint16_t formats[] =
|
||||
{
|
||||
BH_BITMAP_RGBA32,
|
||||
BH_BITMAP_RGBA64,
|
||||
BH_BITMAP_RGB888,
|
||||
BH_BITMAP_RGBA8888,
|
||||
BH_BITMAP_RGB161616,
|
||||
BH_BITMAP_RGBA16161616,
|
||||
BH_BITMAP_RGB565,
|
||||
BH_BITMAP_RGBA1010102,
|
||||
BH_BITMAP_RGBA8888 | BH_BITMAP_NOALPHA,
|
||||
BH_BITMAP_RGBA16161616 | BH_BITMAP_NOALPHA,
|
||||
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 (i = 0; i < 16; ++i)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
BH_UNUSED(argc);
|
||||
BH_UNUSED(argv);
|
||||
|
||||
BH_UNIT_ADD(RoundTrip);
|
||||
|
||||
return BH_UnitRun();
|
||||
}
|
||||
Reference in New Issue
Block a user