📄 abmloader.cpp
字号:
return file_size;
}
/*****************************************************************************
* FUNCTION
* parse_bitmap
* DESCRIPTION
* parse and verify the bitmap header (BITMAPFILEHEADER and BITMAPINFO)
* PARAMETERS
* bitmap_p [IN]
* RETURNS
* void
*****************************************************************************/
static S32 parse_bitmap(U8* bmp_data_p, U32 input_bmp_file_size)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
U32 bmp_w, bmp_h, bmp_bpp;
S32 i;
U32 bi_size;
U32 line_size;
U8 *pal_color_p;
mycolor pal_first_color;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
/* check the "BM" magic number */
if ((bmp_data_p[0] != 'B') || (bmp_data_p[1] != 'M'))
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* verify the bitmap file size */
if (GET_32(bmp_data_p + 2) != input_bmp_file_size)
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* verify the BITMAPINFO HEADER size field */
bi_size = GET_32(bmp_data_p + 14);
if (bi_size < BITMAPINFO_HEADER_SIZE)
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* get bitmap width, height, and bits per pixel */
bmp_w = GET_32(bmp_data_p + 18);
bmp_h = GET_32(bmp_data_p + 22);
bmp_bpp = GET_16(bmp_data_p + 28);
/* only support 8, 24, and 32 bpp */
if ((bmp_bpp != 8) && (bmp_bpp != 24) && (bmp_bpp != 32))
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* only support bottom-up bitmap */
if (((S32)bmp_h <= 0) || ((S32)bmp_w <= 0))
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* limit image dimension to 1024x1024 */
if (((S32)bmp_h > 1024) || ((S32)bmp_w > 1024))
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* get the palette color num */
if (bmp_bpp == 8)
{
abm_enc->bmp_palette_num = GET_32(bmp_data_p + 46);
if (abm_enc->bmp_palette_num == 0)
{
abm_enc->bmp_palette_num = 256;
}
}
else
{
abm_enc->bmp_palette_num = 0;
}
/* make sure palette color number is 256 maximally */
if (abm_enc->bmp_palette_num > 256)
{
return ABM_ENC_INPUT_BITMAP_ERROR;
}
/* line size in bytes */
line_size = bmp_bpp * bmp_w / 8;
abm_enc->line_padding_bytes = (line_size + 3) / 4 * 4 - line_size;
abm_enc->bmp_width = bmp_w;
abm_enc->bmp_height = bmp_h;
abm_enc->bmp_bpp = bmp_bpp;
/* get palette */
pal_color_p = bmp_data_p + BITMAPFILEHEADER_SIZE + bi_size;
pal_first_color = GET_32(pal_color_p);
for (i = 0; i < abm_enc->bmp_palette_num; i++)
{
abm_enc->bmp_palette[i] = GET_32(pal_color_p + i * 4);
/* A of ARGB quad is reserved as 0, convert it to opacity 255 */
if (abm_enc->src_key_color_enable && (abm_enc->bmp_palette[i] == pal_first_color))
{
/*
* The transparency color is the first color in the palette.
* Any equivalent color is also the transpareny color.
*
* ONLY VALID FOR PBM AND BMP FILES.
*/
abm_enc->bmp_palette[i] = 0; /* force alpha value 0 */
}
else
{
abm_enc->bmp_palette[i] |= 0xFF000000; /* opaque color, alpha value 255 */
}
}
/* bitmap pixel start offset */
abm_enc->bmp_pixel_start_p = bmp_data_p + GET_32(bmp_data_p + 10);
return ABM_ENC_OK;
}
/*****************************************************************************
* FUNCTION
* update_image_bounding_box
* DESCRIPTION
* update image bounding box (piggy-back in the first pass)
* PARAMETERS
* x [IN] x coordinate of non-transparent color
* y [IN] y coordinate of non-transparent color
* RETURNS
* void
*****************************************************************************/
static void update_image_bounding_box(S32 x, S32 y)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S32 x1, x2, y1, y2;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
x1 = abm_enc->x1;
y1 = abm_enc->y1;
x2 = abm_enc->x2;
y2 = abm_enc->y2;
/* x1 = min(x of non-transparent color) */
if (x < x1)
{
x1 = x;
}
/* y1 = min(y of non-transparent color) */
if (y < y1)
{
y1 = y;
}
/* x2 = max(x of non-transparent color) */
if (x > x2)
{
x2 = x;
}
/* y2 = max(y of non-transparent color) */
if (y > y2)
{
y2 = y;
}
abm_enc->x1 = x1;
abm_enc->y1 = y1;
abm_enc->x2 = x2;
abm_enc->y2 = y2;
}
/*****************************************************************************
* FUNCTION
* limit_image_bounding_box
* DESCRIPTION
* limit the x1, y1, x2, and y2 within 8-bit
* PARAMETERS
* void
* RETURNS
* void
*****************************************************************************/
static void limit_image_bounding_box(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S32 w, h, bottom_right_off_w, bottom_right_off_h;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
w = abm_enc->bmp_width;
h = abm_enc->bmp_height;
if (abm_enc->x1 > 255)
{
abm_enc->x1 = 255;
}
if (abm_enc->y1 > 255)
{
abm_enc->y1 = 255;
}
bottom_right_off_w = w - 1 - abm_enc->x2;
if (bottom_right_off_w > 255)
{
abm_enc->x2 = w - 1 - bottom_right_off_w;
}
bottom_right_off_h = h - 1 - abm_enc->y2;
if (bottom_right_off_h > 255)
{
abm_enc->y2 = h - 1 - bottom_right_off_h;
}
}
/*****************************************************************************
* FUNCTION
* abmenc_build_color_index_table
* DESCRIPTION
* build the color index table (first pass)
* PARAMETERS
* void
* RETURNS
* void
*****************************************************************************/
static void abmenc_build_color_index_table(void)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S32 x, y, w, h;
S32 line_padding_bytes;
U8 *pixel_p, *img_p;
U32 bmp_bpp;
mycolor c;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
w = abm_enc->bmp_width;
h = abm_enc->bmp_height;
line_padding_bytes = abm_enc->line_padding_bytes;
bmp_bpp = abm_enc->bmp_bpp;
img_p = abm_enc->bmp_pixel_start_p;
/* initialize image bounding box */
abm_enc->x1 = w;
abm_enc->y1 = h;
abm_enc->x2 = 0;
abm_enc->y2 = 0;
/* first pass: build color index table and find the image bounding box */
pixel_p = img_p;
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
{
/* read pixel */
if (bmp_bpp == 32)
{ /* 32-bit bitmap */
c = GET_32(pixel_p);
pixel_p += 4;
/* Windows 32-bit BMP is always 0x00RRGGBB. */
if (abm_enc->is_windows_bmp)
{
c |= 0xFF000000;
}
if (abm_enc->src_key_color_enable && (c == TRANSPARENT_COLOR_32))
{ /* transparent color, alpha = 0 */
c = 0;
}
}
else if (bmp_bpp == 24)
{ /* 24-bit bitmap */
c = GET_24(pixel_p);
pixel_p += 3;
if (abm_enc->src_key_color_enable && (c == TRANSPARENT_COLOR_24))
{ /* transparent color, alpha = 0 */
c = 0;
}
else
{ /* opaque color, alpha = 255 */
c |= 0xFF000000;
}
}
else
{ /* 8-bit bitmap */
c = abm_enc->bmp_palette[*pixel_p++];
}
/* add color if the color is not transparent color */
if (A_OF_ARGB8888(c) != 0)
{
/* only add unique color */
add_color_if_new(COLOR_REDUCE(c));
/* update image bounding box (notice bitmap is flipped, so we have to invert y here) */
update_image_bounding_box(x, h - 1 - y);
}
}
pixel_p += line_padding_bytes;
}
limit_image_bounding_box();
/* handle special case, all transparent color */
if (abm_enc->x2 < abm_enc->x1)
{
abm_enc->x1 = 0;
abm_enc->y1 = 0;
abm_enc->x2 = 0;
abm_enc->y2 = 0;
}
}
/*****************************************************************************
* FUNCTION
* log2_ceiling
* DESCRIPTION
* calculate ceiling(log2(x))
* PARAMETERS
* x [IN] x must be in the range of [0, 65535]
* RETURNS
* ceiling(log2(x))
*****************************************************************************/
static U32 log2_ceiling(U32 x)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S32 i;
/*----------------------------------------------------------------*/
/* Code Body */
/*----------------------------------------------------------------*/
for (i = 0; i < 15; i++)
{
if (x <= log2_table[i])
break;
}
return i + 1;
}
/*****************************************************************************
* FUNCTION
* abmenc_encode
* DESCRIPTION
* abm encoder main routine
* PARAMETERS
* out_mem_p [OUT] output memory pointer
* RETURNS
* ABM data size
*****************************************************************************/
static U32 abmenc_encode(U8* out_mem_p)
{
/*----------------------------------------------------------------*/
/* Local Variables */
/*----------------------------------------------------------------*/
S32 x, y, w, h, bottom_right_off_w, bottom_right_off_h;
S32 bound_box_w, bound_box_h;
S32 line_padding_bytes;
U8 *pixel_p, *img_p, *mem8_p;
U32 p;
U32 bpp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -