2022-05-03 10:25:52 +00:00
|
|
|
|
#include "HGBmp.h"
|
|
|
|
|
#include "../base/HGInc.h"
|
|
|
|
|
extern "C"
|
|
|
|
|
{
|
|
|
|
|
#include "libnsbmp.h"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_CheckBmpFile(const HGChar* fileName, HGBool* isBmp)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == fileName || NULL == isBmp)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGBmpLoadInfo info;
|
|
|
|
|
HGResult ret = HGImgFmt_LoadBmpImage(fileName, &info, 0, 0, NULL);
|
|
|
|
|
*isBmp = (HGBASE_ERR_OK == ret ? HGTRUE : HGFALSE);
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void* bitmap_create(int width, int height, unsigned int state)
|
|
|
|
|
{
|
|
|
|
|
if (width <= 0 || height <= 0)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(void)state; /* unused */
|
|
|
|
|
return calloc((intptr_t)width * (intptr_t)height, 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned char* bitmap_get_buffer(void* bitmap)
|
|
|
|
|
{
|
|
|
|
|
assert(NULL != bitmap);
|
|
|
|
|
return (unsigned char*)bitmap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static size_t bitmap_get_bpp(void* bitmap)
|
|
|
|
|
{
|
|
|
|
|
(void)bitmap; /* unused */
|
|
|
|
|
return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void bitmap_destroy(void* bitmap)
|
|
|
|
|
{
|
|
|
|
|
assert(NULL != bitmap);
|
|
|
|
|
free(bitmap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_LoadBmpImage(const HGChar* fileName, HGBmpLoadInfo* info,
|
|
|
|
|
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == fileName)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL == image)
|
|
|
|
|
{
|
|
|
|
|
if (0 != imgType || 0 != imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (0 != imgType && HGBASE_IMGTYPE_GRAY != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_RGBA != imgType && HGBASE_IMGTYPE_BGR != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGRA != imgType)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE* file = fopen(fileName, "rb");
|
|
|
|
|
if (NULL == file)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(HG_CMP_MSC)
|
|
|
|
|
_fseeki64(file, 0, SEEK_END);
|
|
|
|
|
uint64_t size = _ftelli64(file);
|
|
|
|
|
#else
|
|
|
|
|
fseeko64(file, 0, SEEK_END);
|
|
|
|
|
uint64_t size = ftello64(file);
|
|
|
|
|
#endif
|
|
|
|
|
if (0 == size)
|
|
|
|
|
{
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t* buffer = (uint8_t*)malloc((size_t)size);
|
|
|
|
|
if (NULL == buffer)
|
|
|
|
|
{
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(HG_CMP_MSC)
|
|
|
|
|
_fseeki64(file, 0, SEEK_SET);
|
|
|
|
|
#else
|
|
|
|
|
fseeko64(file, 0, SEEK_SET);
|
|
|
|
|
#endif
|
|
|
|
|
size_t readSize = fread(buffer, 1, (size_t)size, file);
|
|
|
|
|
if (readSize != size)
|
|
|
|
|
{
|
|
|
|
|
free(buffer);
|
|
|
|
|
buffer = NULL;
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bmp_image bmp;
|
|
|
|
|
bmp_bitmap_callback_vt bitmap_callbacks = { bitmap_create, bitmap_destroy, bitmap_get_buffer, bitmap_get_bpp };
|
|
|
|
|
bmp_create(&bmp, &bitmap_callbacks);
|
|
|
|
|
|
|
|
|
|
if (BMP_OK != bmp_analyse(&bmp, (size_t)size, buffer))
|
|
|
|
|
{
|
|
|
|
|
bmp_finalise(&bmp);
|
|
|
|
|
free(buffer);
|
|
|
|
|
buffer = NULL;
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
info->width = bmp.width;
|
|
|
|
|
info->height = bmp.height;
|
|
|
|
|
info->bitCount = bmp.bpp;
|
|
|
|
|
info->compression = (uint32_t)bmp.encoding;
|
|
|
|
|
info->xPelsPerMeter = bmp.x_pels_per_meter;
|
|
|
|
|
info->yPelsPerMeter = bmp.y_pels_per_meter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != image)
|
|
|
|
|
{
|
|
|
|
|
if (BMP_OK != bmp_decode(&bmp))
|
|
|
|
|
{
|
|
|
|
|
bmp_finalise(&bmp);
|
|
|
|
|
free(buffer);
|
|
|
|
|
buffer = NULL;
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 == imgType)
|
|
|
|
|
{
|
|
|
|
|
if (32 == bmp.bpp)
|
|
|
|
|
{
|
|
|
|
|
imgType = HGBASE_IMGTYPE_RGBA;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
if (HGBASE_ERR_OK != HGBase_CreateImage(bmp.width, bmp.height, imgType, imgOrigin, &image2))
|
|
|
|
|
{
|
|
|
|
|
bmp_finalise(&bmp);
|
|
|
|
|
free(buffer);
|
|
|
|
|
buffer = NULL;
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t xDpi = (uint32_t)((double)bmp.x_pels_per_meter / 39.3700787 + 0.5);
|
|
|
|
|
uint32_t yDpi = (uint32_t)((double)bmp.y_pels_per_meter / 39.3700787 + 0.5);
|
|
|
|
|
HGBase_SetImageDpi(image2, xDpi, yDpi);
|
|
|
|
|
|
|
|
|
|
uint8_t* data;
|
|
|
|
|
HGBase_GetImageData(image2, &data);
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
|
|
|
|
|
|
|
|
|
HGByte* src = (HGByte*)bmp.bitmap;
|
|
|
|
|
HGByte* dest = data;
|
|
|
|
|
HGSize destStep = (HGSize)imgInfo.widthStep;
|
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
dest = data + (HGUSize)(bmp.height - 1) * (HGUSize)imgInfo.widthStep;
|
|
|
|
|
destStep = -(HGSize)imgInfo.widthStep;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgType)
|
|
|
|
|
{
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)bmp.height; i++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = src + (HGSize)i * (HGSize)(bmp.width * 4);
|
|
|
|
|
uint8_t* pExEnd = pEx + bmp.width * 4;
|
|
|
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
|
|
|
|
|
|
while (pEx < pExEnd)
|
|
|
|
|
{
|
|
|
|
|
uint8_t value = (pEx[0] * 76 + pEx[1] * 150 + pEx[2] * 30) >> 8;
|
|
|
|
|
*pDestEx = value;
|
|
|
|
|
|
|
|
|
|
pEx += 4;
|
|
|
|
|
++pDestEx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (HGBASE_IMGTYPE_RGB == imgType)
|
|
|
|
|
{
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)bmp.height; i++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = src + (HGSize)i * (HGSize)(bmp.width * 4);
|
|
|
|
|
uint8_t* pExEnd = pEx + bmp.width * 4;
|
|
|
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
|
|
|
|
|
|
while (pEx < pExEnd)
|
|
|
|
|
{
|
|
|
|
|
pDestEx[0] = pEx[0];
|
|
|
|
|
pDestEx[1] = pEx[1];
|
|
|
|
|
pDestEx[2] = pEx[2];
|
|
|
|
|
|
|
|
|
|
pEx += 4;
|
|
|
|
|
pDestEx += 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (HGBASE_IMGTYPE_BGR == imgType)
|
|
|
|
|
{
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)bmp.height; i++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = src + (HGSize)i * (HGSize)(bmp.width * 4);
|
|
|
|
|
uint8_t* pExEnd = pEx + bmp.width * 4;
|
|
|
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
|
|
|
|
|
|
while (pEx < pExEnd)
|
|
|
|
|
{
|
|
|
|
|
pDestEx[2] = pEx[0];
|
|
|
|
|
pDestEx[1] = pEx[1];
|
|
|
|
|
pDestEx[0] = pEx[2];
|
|
|
|
|
|
|
|
|
|
pEx += 4;
|
|
|
|
|
pDestEx += 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (HGBASE_IMGTYPE_BGRA == imgType)
|
|
|
|
|
{
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)bmp.height; i++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = src + (HGSize)i * (HGSize)(bmp.width * 4);
|
|
|
|
|
uint8_t* pExEnd = pEx + bmp.width * 4;
|
|
|
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
|
|
|
|
|
|
while (pEx < pExEnd)
|
|
|
|
|
{
|
|
|
|
|
pDestEx[2] = pEx[0];
|
|
|
|
|
pDestEx[1] = pEx[1];
|
|
|
|
|
pDestEx[0] = pEx[2];
|
|
|
|
|
pDestEx[3] = pEx[3];
|
|
|
|
|
|
|
|
|
|
pEx += 4;
|
|
|
|
|
pDestEx += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
assert(HGBASE_IMGTYPE_RGBA == imgType);
|
|
|
|
|
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)bmp.height; i++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = src + (HGSize)i * (HGSize)(bmp.width * 4);
|
|
|
|
|
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
|
|
|
|
|
memcpy(pDestEx, pEx, bmp.width * 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*image = image2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bmp_finalise(&bmp);
|
|
|
|
|
free(buffer);
|
|
|
|
|
buffer = NULL;
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_SaveBmpImage(HGImage image, const HGBmpSaveInfo* info, const HGChar* fileName)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == image || NULL == fileName)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
// 检查合法性
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
|
|
|
|
|
|
uint32_t width = imgInfo.width;
|
|
|
|
|
uint32_t height = imgInfo.height;
|
|
|
|
|
uint32_t widthStep = imgInfo.widthStep;
|
|
|
|
|
uint32_t type = imgInfo.type;
|
|
|
|
|
uint32_t origin = imgInfo.origin;
|
|
|
|
|
|
|
|
|
|
FILE* file = fopen(fileName, "wb");
|
|
|
|
|
if (NULL == file)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t* data;
|
|
|
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
|
|
|
|
|
|
uint8_t* buffer = (uint8_t*)malloc(widthStep * height);
|
|
|
|
|
if (NULL == buffer)
|
|
|
|
|
{
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_FAIL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t fh[14];
|
|
|
|
|
*(uint16_t*)fh = 0x4D42;
|
|
|
|
|
*(uint16_t*)(fh + 6) = 0;
|
|
|
|
|
*(uint16_t*)(fh + 8) = 0;
|
|
|
|
|
|
|
|
|
|
uint8_t ih[40];
|
|
|
|
|
*(uint32_t*)ih = 40;
|
|
|
|
|
*(int32_t*)(ih + 4) = (int32_t)width;
|
2022-05-11 09:19:50 +00:00
|
|
|
|
*(int32_t*)(ih + 8) = (int32_t)height;
|
2022-05-03 10:25:52 +00:00
|
|
|
|
*(uint16_t*)(ih + 12) = 1;
|
|
|
|
|
*(uint32_t*)(ih + 16) = 0;
|
|
|
|
|
*(uint32_t*)(ih + 20) = (widthStep * height);
|
|
|
|
|
*(int32_t*)(ih + 24) = 0;
|
|
|
|
|
*(int32_t*)(ih + 28) = 0;
|
|
|
|
|
*(uint32_t*)(ih + 32) = 0;
|
|
|
|
|
*(uint32_t*)(ih + 36) = 0;
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
*(int32_t*)(ih + 24) = (int32_t)info->xPelsPerMeter;
|
|
|
|
|
*(int32_t*)(ih + 28) = (int32_t)info->yPelsPerMeter;
|
|
|
|
|
}
|
2022-05-13 12:38:58 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HGUInt xDpi, yDpi;
|
|
|
|
|
HGBase_GetImageDpi(image, &xDpi, &yDpi);
|
|
|
|
|
*(int32_t*)(ih + 24) = (uint32_t)((double)xDpi * 39.3700787 + 0.5);
|
|
|
|
|
*(int32_t*)(ih + 28) = (uint32_t)((double)yDpi * 39.3700787 + 0.5);
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == type)
|
|
|
|
|
{
|
|
|
|
|
*(uint32_t*)(fh + 2) = 54 + 4 * 256 + widthStep * height;
|
|
|
|
|
*(uint32_t*)(fh + 10) = 54 + 4 * 256;
|
|
|
|
|
*(uint16_t*)(ih + 14) = 8;
|
|
|
|
|
|
|
|
|
|
uint32_t colorTable[256];
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < 256; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint32_t v = (i & 0x000000FF) | ((i << 8) & 0x0000FF00) | ((i << 16) & 0x00FF0000);
|
|
|
|
|
colorTable[i] = v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fwrite(fh, 14, 1, file);
|
|
|
|
|
fwrite(ih, 40, 1, file);
|
|
|
|
|
fwrite(colorTable, 4, 256, file);
|
|
|
|
|
|
2022-05-11 09:19:50 +00:00
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
|
|
|
{
|
|
|
|
|
fwrite(data, 1, widthStep * height, file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
|
|
|
while (dataEx >= data)
|
|
|
|
|
{
|
|
|
|
|
fwrite(dataEx, 1, widthStep, file);
|
|
|
|
|
dataEx -= widthStep;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
else if (HGBASE_IMGTYPE_RGB == type)
|
|
|
|
|
{
|
|
|
|
|
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
|
|
|
*(uint32_t*)(fh + 10) = 54;
|
|
|
|
|
*(uint16_t*)(ih + 14) = 24;
|
|
|
|
|
|
|
|
|
|
fwrite(fh, 14, 1, file);
|
|
|
|
|
fwrite(ih, 40, 1, file);
|
|
|
|
|
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = data + (uintptr_t)i * (uintptr_t)widthStep;
|
|
|
|
|
uint8_t* pExEnd = pEx + width * 3;
|
|
|
|
|
uint8_t* pDestEx = buffer + (uintptr_t)i * (uintptr_t)widthStep;
|
|
|
|
|
|
|
|
|
|
while (pEx < pExEnd)
|
|
|
|
|
{
|
|
|
|
|
pDestEx[0] = pEx[2];
|
|
|
|
|
pDestEx[1] = pEx[1];
|
|
|
|
|
pDestEx[2] = pEx[0];
|
|
|
|
|
|
|
|
|
|
pEx += 3;
|
|
|
|
|
pDestEx += 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 09:19:50 +00:00
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
|
|
|
{
|
|
|
|
|
fwrite(buffer, 1, widthStep * height, file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint8_t* bufferEx = buffer + (height - 1) * widthStep;
|
|
|
|
|
while (bufferEx >= buffer)
|
|
|
|
|
{
|
|
|
|
|
fwrite(bufferEx, 1, widthStep, file);
|
|
|
|
|
bufferEx -= widthStep;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
else if (HGBASE_IMGTYPE_BGR == type)
|
|
|
|
|
{
|
|
|
|
|
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
|
|
|
*(uint32_t*)(fh + 10) = 54;
|
|
|
|
|
*(uint16_t*)(ih + 14) = 24;
|
|
|
|
|
|
|
|
|
|
fwrite(fh, 14, 1, file);
|
|
|
|
|
fwrite(ih, 40, 1, file);
|
2022-05-11 09:19:50 +00:00
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
|
|
|
{
|
|
|
|
|
fwrite(data, 1, widthStep * height, file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
|
|
|
while (dataEx >= data)
|
|
|
|
|
{
|
|
|
|
|
fwrite(dataEx, 1, widthStep, file);
|
|
|
|
|
dataEx -= widthStep;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
else if (HGBASE_IMGTYPE_BGRA == type)
|
|
|
|
|
{
|
|
|
|
|
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
|
|
|
*(uint32_t*)(fh + 10) = 54;
|
|
|
|
|
*(uint16_t*)(ih + 14) = 32;
|
|
|
|
|
|
|
|
|
|
fwrite(fh, 14, 1, file);
|
|
|
|
|
fwrite(ih, 40, 1, file);
|
2022-05-11 09:19:50 +00:00
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
|
|
|
{
|
|
|
|
|
fwrite(data, 1, widthStep * height, file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint8_t* dataEx = data + (height - 1) * widthStep;
|
|
|
|
|
while (dataEx >= data)
|
|
|
|
|
{
|
|
|
|
|
fwrite(dataEx, 1, widthStep, file);
|
|
|
|
|
dataEx -= widthStep;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
assert(HGBASE_IMGTYPE_RGBA == type);
|
|
|
|
|
|
|
|
|
|
*(uint32_t*)(fh + 2) = 54 + widthStep * height;
|
|
|
|
|
*(uint32_t*)(fh + 10) = 54;
|
|
|
|
|
*(uint16_t*)(ih + 14) = 32;
|
|
|
|
|
|
|
|
|
|
fwrite(fh, 14, 1, file);
|
|
|
|
|
fwrite(ih, 40, 1, file);
|
|
|
|
|
|
|
|
|
|
//#pragma omp parallel for
|
|
|
|
|
for (int32_t i = 0; i < (int32_t)height; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = data + (uintptr_t)i * (uintptr_t)widthStep;
|
|
|
|
|
uint8_t* pExEnd = pEx + width * 4;
|
|
|
|
|
uint8_t* pDestEx = buffer + (uintptr_t)i * (uintptr_t)widthStep;
|
|
|
|
|
|
|
|
|
|
while (pEx < pExEnd)
|
|
|
|
|
{
|
|
|
|
|
pDestEx[0] = pEx[2];
|
|
|
|
|
pDestEx[1] = pEx[1];
|
|
|
|
|
pDestEx[2] = pEx[0];
|
|
|
|
|
pDestEx[3] = pEx[3];
|
|
|
|
|
|
|
|
|
|
pEx += 4;
|
|
|
|
|
pDestEx += 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-11 09:19:50 +00:00
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == origin)
|
|
|
|
|
{
|
|
|
|
|
fwrite(buffer, 1, widthStep * height, file);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint8_t* bufferEx = buffer + (height - 1) * widthStep;
|
|
|
|
|
while (bufferEx >= buffer)
|
|
|
|
|
{
|
|
|
|
|
fwrite(bufferEx, 1, widthStep, file);
|
|
|
|
|
bufferEx -= widthStep;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-03 10:25:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(buffer);
|
|
|
|
|
buffer = NULL;
|
|
|
|
|
fclose(file);
|
|
|
|
|
file = NULL;
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|