2022-11-04 03:57:55 +00:00
|
|
|
|
#include "HGPnm.h"
|
2022-10-27 10:31:51 +00:00
|
|
|
|
#include "../base/HGInc.h"
|
2022-10-28 02:53:54 +00:00
|
|
|
|
#include <vector>
|
2022-10-27 10:31:51 +00:00
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
static inline HGByte GetBit(const HGByte* data, HGUInt index)
|
|
|
|
|
{
|
|
|
|
|
HGUInt byteIndex = index / 8;
|
|
|
|
|
HGUInt bitIndex = index % 8;
|
|
|
|
|
return (data[byteIndex] >> (7 - bitIndex)) & 0x01;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void SetBit(HGByte* data, HGUInt index, HGByte value)
|
|
|
|
|
{
|
|
|
|
|
assert(0 == value || 1 == value);
|
|
|
|
|
HGUInt byteIndex = index / 8;
|
|
|
|
|
HGUInt bitIndex = index % 8;
|
|
|
|
|
if (1 == value)
|
|
|
|
|
data[byteIndex] |= (1 << (7 - bitIndex));
|
|
|
|
|
else
|
|
|
|
|
data[byteIndex] &= ~(1 << (7 - bitIndex));
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 10:31:51 +00:00
|
|
|
|
HGResult HGAPI HGImgFmt_CheckPnmFile(const HGChar* fileName, HGBool* isPnm)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == fileName || NULL == isPnm)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGPnmLoadInfo info;
|
|
|
|
|
HGResult ret = HGImgFmt_LoadPnmImage(fileName, &info, 0, 0, NULL);
|
|
|
|
|
*isPnm = (HGBASE_ERR_OK == ret ? HGTRUE : HGFALSE);
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
static HGResult BnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *height, HGUInt *maxColor)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
assert(NULL != file && NULL != width && NULL != height && NULL != maxColor);
|
2022-10-27 10:31:51 +00:00
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
bool getWidth = false;
|
|
|
|
|
bool getHeight = false;
|
|
|
|
|
bool getMaxColor = false;
|
|
|
|
|
std::vector<char> buf;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
while (1)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
HGByte c = 0;
|
|
|
|
|
if (1 != fread(&c, 1, 1, file))
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (!buf.empty())
|
|
|
|
|
{
|
|
|
|
|
buf.push_back(0);
|
|
|
|
|
|
|
|
|
|
if (!getWidth)
|
|
|
|
|
{
|
|
|
|
|
*width = atoi(&buf[0]);
|
|
|
|
|
if (*width == 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
getWidth = true;
|
|
|
|
|
}
|
|
|
|
|
else if (!getHeight)
|
|
|
|
|
{
|
|
|
|
|
*height = atoi(&buf[0]);
|
|
|
|
|
if (*height == 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
getHeight = true;
|
|
|
|
|
}
|
|
|
|
|
else if (!getMaxColor)
|
|
|
|
|
{
|
|
|
|
|
*maxColor = atoi(&buf[0]);
|
|
|
|
|
if (*maxColor == 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
getMaxColor = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (c == '#')
|
|
|
|
|
{
|
|
|
|
|
while (c != '\n')
|
|
|
|
|
{
|
|
|
|
|
if (1 != fread(&c, 1, 1, file))
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
2022-10-28 02:53:54 +00:00
|
|
|
|
else if (c >= '0' && c <= '9')
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
buf.push_back(c);
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
2022-10-28 02:53:54 +00:00
|
|
|
|
else
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
2022-10-28 02:53:54 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
if (getMaxColor)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (getHeight)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-10-28 02:53:54 +00:00
|
|
|
|
}
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
2022-10-27 10:31:51 +00:00
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image)
|
2022-10-28 02:53:54 +00:00
|
|
|
|
{
|
|
|
|
|
HGUInt width, height, maxColor;
|
2022-11-04 03:57:55 +00:00
|
|
|
|
HGResult ret = BnmLoadInfo(file , pnmType, &width, &height, &maxColor);
|
2022-11-01 07:01:58 +00:00
|
|
|
|
if (HGBASE_ERR_OK != ret)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
return ret;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
|
|
|
{
|
|
|
|
|
if (maxColor > 255 || maxColor < 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (NULL != info)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
|
|
|
|
info->width = width;
|
|
|
|
|
info->height = height;
|
2022-11-04 03:57:55 +00:00
|
|
|
|
info->type = pnmType;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (NULL != image)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
|
|
|
|
if (imgType == 0)
|
|
|
|
|
{
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
imgType = HGBASE_IMGTYPE_BINARY;
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
2022-10-28 02:53:54 +00:00
|
|
|
|
}
|
2022-10-27 10:31:51 +00:00
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (imgOrigin == 0)
|
|
|
|
|
{
|
|
|
|
|
imgOrigin = HGBASE_IMGORIGIN_TOP;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
HGImage image2 = NULL;
|
2022-11-01 07:01:58 +00:00
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_BINARY, HGBASE_IMGORIGIN_TOP, &image2);
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (HGBASE_ERR_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2022-10-27 10:31:51 +00:00
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
std::vector<char> buf;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
uint8_t* data;
|
|
|
|
|
HGBase_GetImageData(image2, &data);
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image2, &imgInfo);
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
2022-10-28 02:53:54 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
for (HGUInt i = 0; i < height; ++i)
|
2022-10-28 02:53:54 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
HGUInt lineSize = ((width + 7) & ~7) >> 3;
|
|
|
|
|
if (lineSize != fread(data + i * imgInfo.widthStep, 1, lineSize, file))
|
|
|
|
|
{
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGTYPE_BINARY == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
*image = image2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
2022-10-28 02:53:54 +00:00
|
|
|
|
HGBase_DestroyImage(image2);
|
2022-11-01 07:01:58 +00:00
|
|
|
|
|
|
|
|
|
if (HGBASE_ERR_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2022-10-28 02:53:54 +00:00
|
|
|
|
}
|
2022-11-01 07:01:58 +00:00
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
}
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
for (HGUInt i = 0; i < height; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (width != fread(data + i * imgInfo.widthStep, 1, width, file))
|
|
|
|
|
{
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
*image = image2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
|
|
|
|
|
if (HGBASE_ERR_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-28 09:45:37 +00:00
|
|
|
|
}
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if(pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
2022-10-28 09:45:37 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
for (HGUInt i = 0; i < height; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (width * 3 != fread(data + i * imgInfo.widthStep, 1, width * 3, file))
|
|
|
|
|
{
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-28 09:45:37 +00:00
|
|
|
|
|
2022-11-01 07:01:58 +00:00
|
|
|
|
if (HGBASE_IMGTYPE_RGB == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin)
|
2022-10-28 09:45:37 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
*image = image2;
|
2022-10-28 09:45:37 +00:00
|
|
|
|
}
|
2022-11-01 07:01:58 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
|
|
|
|
|
if (HGBASE_ERR_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII)
|
|
|
|
|
{
|
|
|
|
|
HGByte* p = data;
|
|
|
|
|
HGUInt idx = 0;
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
HGByte c = 0;
|
|
|
|
|
if (1 != fread(&c, 1, 1, file))
|
|
|
|
|
{
|
|
|
|
|
if (!buf.empty())
|
|
|
|
|
{
|
|
|
|
|
buf.push_back(0);
|
|
|
|
|
HGInt pixel = atoi(&buf[0]);
|
|
|
|
|
|
|
|
|
|
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
|
|
|
{
|
|
|
|
|
if (pixel > 255 || pixel < 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (pixel > 1 || pixel < 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p[idx] = pixel;
|
|
|
|
|
++idx;
|
|
|
|
|
if (idx == width * 3)
|
|
|
|
|
{
|
|
|
|
|
p += imgInfo.widthStep;
|
|
|
|
|
idx = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
|
|
|
|
|
{
|
|
|
|
|
if (!buf.empty())
|
|
|
|
|
{
|
|
|
|
|
buf.push_back(0);
|
|
|
|
|
HGInt pixel = atoi(&buf[0]);
|
|
|
|
|
|
|
|
|
|
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
|
|
|
{
|
|
|
|
|
if (pixel > 255 || pixel < 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (pixel > 1 || pixel < 0)
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
p[idx] = pixel;
|
|
|
|
|
++idx;
|
|
|
|
|
if (idx == width * 3)
|
|
|
|
|
{
|
|
|
|
|
p += imgInfo.widthStep;
|
|
|
|
|
idx = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (c == '#')
|
|
|
|
|
{
|
|
|
|
|
while (c != '\n')
|
|
|
|
|
{
|
|
|
|
|
if (1 != fread(&c, 1, 1, file))
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (c >= '0' && c <= '9')
|
|
|
|
|
{
|
|
|
|
|
buf.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p == data + height * imgInfo.widthStep)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (HGBASE_IMGTYPE_RGB == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin)
|
|
|
|
|
{
|
|
|
|
|
*image = image2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
|
|
|
|
|
if (HGBASE_ERR_OK != ret)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-01 07:01:58 +00:00
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
{
|
|
|
|
|
HGBase_ReverseImage(image2, image2);
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* 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_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
|
|
|
|
|
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != imgType)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
if (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE* file = fopen(fileName, "rb");
|
|
|
|
|
if (NULL == file)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
HGByte magicKey[2] = {0};
|
|
|
|
|
if (2 != fread(magicKey, 1, 2, file))
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 02:53:54 +00:00
|
|
|
|
return HGBASE_ERR_INVALIDDATA;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
HGResult ret = HGBASE_ERR_INVALIDDATA;
|
2022-11-04 03:57:55 +00:00
|
|
|
|
HGUInt pnmType = 0;
|
|
|
|
|
if (magicKey[0] == 'P' && (magicKey[1] == '1'))
|
|
|
|
|
{
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_BINARY_ASCII;
|
|
|
|
|
}
|
|
|
|
|
else if (magicKey[0] == 'P' && (magicKey[1] == '2'))
|
|
|
|
|
{
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_GRAY_ASCII;
|
|
|
|
|
}
|
|
|
|
|
else if (magicKey[0] == 'P' && (magicKey[1] == '3'))
|
|
|
|
|
{
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_RGB_ASCII;
|
|
|
|
|
}
|
|
|
|
|
else if (magicKey[0] == 'P' && (magicKey[1] == '4'))
|
|
|
|
|
{
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_BINARY_BINARY;
|
|
|
|
|
}
|
|
|
|
|
else if (magicKey[0] == 'P' && (magicKey[1] == '5'))
|
|
|
|
|
{
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_GRAY_BINARY;
|
|
|
|
|
}
|
|
|
|
|
else if (magicKey[0] == 'P' && (magicKey[1] == '6'))
|
|
|
|
|
{
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
|
|
|
}
|
|
|
|
|
else
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-11-04 03:57:55 +00:00
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
ret = BnmLoadImage(file, pnmType, info, imgType, imgOrigin, image);
|
|
|
|
|
|
2022-10-28 02:53:54 +00:00
|
|
|
|
fclose(file);
|
|
|
|
|
return ret;
|
2022-10-27 10:31:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-01 07:01:58 +00:00
|
|
|
|
static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
|
2022-10-27 10:31:51 +00:00
|
|
|
|
{
|
2022-10-28 03:17:16 +00:00
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
|
|
|
|
|
|
|
|
|
FILE* file = fopen(fileName, "wb");
|
|
|
|
|
if (NULL == file)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_ACCESSDENIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGByte* data = NULL;
|
|
|
|
|
HGBase_GetImageData(image, &data);
|
|
|
|
|
|
2022-11-01 07:01:58 +00:00
|
|
|
|
char magicKey[4] = {0};
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (HGIMGFMT_PNMTYPE_BINARY_ASCII == type)
|
|
|
|
|
{
|
|
|
|
|
strcpy(magicKey, "P1\n");
|
|
|
|
|
}
|
|
|
|
|
else if (HGIMGFMT_PNMTYPE_GRAY_ASCII == type)
|
|
|
|
|
{
|
|
|
|
|
strcpy(magicKey, "P2\n");
|
|
|
|
|
}
|
|
|
|
|
else if (HGIMGFMT_PNMTYPE_RGB_ASCII == type)
|
|
|
|
|
{
|
|
|
|
|
strcpy(magicKey, "P3\n");
|
|
|
|
|
}
|
|
|
|
|
else if (HGIMGFMT_PNMTYPE_BINARY_BINARY == type)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
{
|
|
|
|
|
strcpy(magicKey, "P4\n");
|
|
|
|
|
}
|
|
|
|
|
else if (HGIMGFMT_PNMTYPE_GRAY_BINARY == type)
|
|
|
|
|
{
|
|
|
|
|
strcpy(magicKey, "P5\n");
|
|
|
|
|
}
|
|
|
|
|
else if (HGIMGFMT_PNMTYPE_RGB_BINARY == type)
|
|
|
|
|
{
|
|
|
|
|
strcpy(magicKey, "P6\n");
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-28 03:17:16 +00:00
|
|
|
|
fwrite(magicKey, 1, strlen(magicKey), file);
|
|
|
|
|
|
|
|
|
|
char width[20], height[20];
|
|
|
|
|
sprintf(width, "%u\n", imgInfo.width);
|
|
|
|
|
sprintf(height, "%u\n", imgInfo.height);
|
|
|
|
|
fwrite(width, 1, strlen(width), file);
|
|
|
|
|
fwrite(height, 1, strlen(height), file);
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (HGIMGFMT_PNMTYPE_BINARY_ASCII != type && HGIMGFMT_PNMTYPE_BINARY_BINARY != type)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
{
|
|
|
|
|
char maxColor[] = "255\n";
|
|
|
|
|
fwrite(maxColor, 1, strlen(maxColor), file);
|
|
|
|
|
}
|
2022-10-28 03:17:16 +00:00
|
|
|
|
|
|
|
|
|
HGByte* p = data;
|
|
|
|
|
HGInt step = (HGInt)imgInfo.widthStep;
|
|
|
|
|
if (HGBASE_IMGORIGIN_BOTTOM == imgInfo.origin)
|
|
|
|
|
{
|
|
|
|
|
p = data + (imgInfo.height - 1) * imgInfo.widthStep;
|
|
|
|
|
step = -(HGInt)imgInfo.widthStep;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 03:57:55 +00:00
|
|
|
|
if (type == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
{
|
|
|
|
|
HGUInt lineSize = ((imgInfo.width + 7) & ~7) >> 3;
|
|
|
|
|
HGByte* buf = (HGByte*)malloc(lineSize);
|
|
|
|
|
assert(NULL != buf);
|
|
|
|
|
|
|
|
|
|
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
|
|
|
for (HGUInt j = 0; j < lineSize; ++j)
|
|
|
|
|
{
|
|
|
|
|
buf[j] = ~pEx[j]; //黑白反色
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fwrite(buf, 1, lineSize, file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
|
}
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (type == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
2022-10-28 03:17:16 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
|
|
|
fwrite(pEx, 1, imgInfo.width, file);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (type == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
2022-11-01 07:01:58 +00:00
|
|
|
|
{
|
|
|
|
|
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
|
|
|
fwrite(pEx, 1, imgInfo.width * 3, file);
|
|
|
|
|
}
|
2022-10-28 03:17:16 +00:00
|
|
|
|
}
|
2022-11-04 03:57:55 +00:00
|
|
|
|
else if (type == HGIMGFMT_PNMTYPE_RGB_ASCII || type == HGIMGFMT_PNMTYPE_GRAY_ASCII || type == HGIMGFMT_PNMTYPE_BINARY_ASCII)
|
|
|
|
|
{
|
|
|
|
|
char buf[72] = {0};
|
|
|
|
|
int bufSize = 0;
|
|
|
|
|
HGUInt imgWidth = 0;
|
|
|
|
|
|
|
|
|
|
if (HGIMGFMT_PNMTYPE_RGB_ASCII == type)
|
|
|
|
|
imgWidth = imgInfo.width * 3;
|
|
|
|
|
else if (HGIMGFMT_PNMTYPE_GRAY_ASCII == type || HGIMGFMT_PNMTYPE_BINARY_ASCII == type)
|
|
|
|
|
imgWidth = imgInfo.width;
|
|
|
|
|
|
|
|
|
|
for (HGUInt i = 0; i < imgInfo.height; ++i)
|
|
|
|
|
{
|
|
|
|
|
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
|
|
|
|
|
for (HGUInt j = 0; j < imgWidth; ++j)
|
|
|
|
|
{
|
|
|
|
|
char buf2[6];
|
|
|
|
|
if (type == HGIMGFMT_PNMTYPE_BINARY_ASCII)
|
|
|
|
|
sprintf(buf2, "%d ", (0 == GetBit(pEx, j)) ? 1 : 0);
|
|
|
|
|
else
|
|
|
|
|
sprintf(buf2, "%d ", pEx[j]);
|
|
|
|
|
|
|
|
|
|
if (bufSize + strlen(buf2) >= 70)
|
|
|
|
|
{
|
|
|
|
|
strcat(buf, "\n");
|
|
|
|
|
fwrite(buf, 1, strlen(buf), file);
|
|
|
|
|
buf[0] = 0;
|
|
|
|
|
bufSize = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcat(buf, buf2);
|
|
|
|
|
bufSize += strlen(buf2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 != bufSize)
|
|
|
|
|
{
|
|
|
|
|
fwrite(buf, 1, strlen(buf), file);
|
|
|
|
|
buf[0] = 0;
|
|
|
|
|
bufSize = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-28 03:17:16 +00:00
|
|
|
|
|
|
|
|
|
fclose(file);
|
2022-10-27 10:31:51 +00:00
|
|
|
|
return HGBASE_ERR_OK;
|
|
|
|
|
}
|
2022-10-28 03:17:16 +00:00
|
|
|
|
|
|
|
|
|
HGResult HGAPI HGImgFmt_SavePnmImage(HGImage image, const HGPnmSaveInfo* info, const HGChar* fileName)
|
|
|
|
|
{
|
|
|
|
|
if (NULL == image || NULL == fileName)
|
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
if (info->type < HGIMGFMT_PNMTYPE_BINARY_ASCII || info->type > HGIMGFMT_PNMTYPE_RGB_BINARY)
|
2022-10-28 03:17:16 +00:00
|
|
|
|
{
|
|
|
|
|
return HGBASE_ERR_INVALIDARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGImageInfo imgInfo;
|
|
|
|
|
HGBase_GetImageInfo(image, &imgInfo);
|
2022-11-01 07:01:58 +00:00
|
|
|
|
if (imgInfo.type == HGBASE_IMGTYPE_BGR || imgInfo.type == HGBASE_IMGTYPE_RGBA || imgInfo.type == HGBASE_IMGTYPE_BGRA)
|
2022-10-28 03:17:16 +00:00
|
|
|
|
{
|
2022-11-01 07:01:58 +00:00
|
|
|
|
HGUInt imgType = HGBASE_IMGTYPE_RGB;
|
|
|
|
|
HGUInt pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
pnmType = info->type;
|
|
|
|
|
if (info->type == HGIMGFMT_PNMTYPE_BINARY_ASCII || info->type == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_BINARY;
|
|
|
|
|
else if (info->type == HGIMGFMT_PNMTYPE_GRAY_ASCII || info->type == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
HGResult ret = HGBase_CloneImage(image, imgType, HGBASE_IMGORIGIN_TOP, &image2);
|
|
|
|
|
if (ret != HGBASE_ERR_OK)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = BnmSaveImage(image2, fileName, pnmType);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HGImage image2 = NULL;
|
|
|
|
|
HGUInt pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
|
|
|
|
|
if (HGBASE_IMGTYPE_GRAY == imgInfo.type)
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_GRAY_BINARY;
|
|
|
|
|
else if (HGBASE_IMGTYPE_BINARY == imgInfo.type)
|
|
|
|
|
pnmType = HGIMGFMT_PNMTYPE_BINARY_BINARY;
|
|
|
|
|
|
|
|
|
|
if (NULL != info)
|
|
|
|
|
{
|
|
|
|
|
HGUInt imgType = imgInfo.type;
|
|
|
|
|
pnmType = info->type;
|
|
|
|
|
|
|
|
|
|
if (info->type == HGIMGFMT_PNMTYPE_BINARY_ASCII || info->type == HGIMGFMT_PNMTYPE_BINARY_BINARY)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_BINARY;
|
|
|
|
|
else if (info->type == HGIMGFMT_PNMTYPE_GRAY_ASCII || info->type == HGIMGFMT_PNMTYPE_GRAY_BINARY)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_GRAY;
|
|
|
|
|
else if (info->type == HGIMGFMT_PNMTYPE_RGB_ASCII || info->type == HGIMGFMT_PNMTYPE_RGB_BINARY)
|
|
|
|
|
imgType = HGBASE_IMGTYPE_RGB;
|
|
|
|
|
|
|
|
|
|
if (imgInfo.type != imgType)
|
|
|
|
|
{
|
|
|
|
|
HGResult ret = HGBase_CloneImage(image, imgType, HGBASE_IMGORIGIN_TOP, &image2);
|
|
|
|
|
if (ret != HGBASE_ERR_OK)
|
|
|
|
|
{
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (NULL != image2)
|
|
|
|
|
{
|
|
|
|
|
HGResult ret = BnmSaveImage(image2, fileName, pnmType);
|
|
|
|
|
HGBase_DestroyImage(image2);
|
|
|
|
|
return ret;
|
2022-10-28 03:17:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-01 07:01:58 +00:00
|
|
|
|
return BnmSaveImage(image, fileName, pnmType);
|
2022-10-28 03:17:16 +00:00
|
|
|
|
}
|