pnm格式优化

This commit is contained in:
luoliangyi 2022-11-04 16:55:46 +08:00
parent d4abcf0240
commit 065a890253
1 changed files with 190 additions and 68 deletions

View File

@ -123,7 +123,7 @@ static HGResult BnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *h
static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image) static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HGUInt imgType, HGUInt imgOrigin, HGImage* image)
{ {
HGUInt width, height, maxColor; HGUInt width, height, maxColor;
HGResult ret = BnmLoadInfo(file , pnmType, &width, &height, &maxColor); HGResult ret = BnmLoadInfo(file, pnmType, &width, &height, &maxColor);
if (HGBASE_ERR_OK != ret) if (HGBASE_ERR_OK != ret)
{ {
return ret; return ret;
@ -131,7 +131,7 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY) if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
{ {
if (maxColor > 255 || maxColor < 0) if (maxColor > 255)
return HGBASE_ERR_INVALIDDATA; return HGBASE_ERR_INVALIDDATA;
} }
@ -167,13 +167,11 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2); ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2); ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
if (HGBASE_ERR_OK != ret) if (HGBASE_ERR_OK != ret)
{ {
return ret; return ret;
} }
std::vector<char> buf;
uint8_t* data; uint8_t* data;
HGBase_GetImageData(image2, &data); HGBase_GetImageData(image2, &data);
HGImageInfo imgInfo; HGImageInfo imgInfo;
@ -181,9 +179,9 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY) if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
{ {
HGUInt lineSize = ((width + 7) & ~7) >> 3;
for (HGUInt i = 0; i < height; ++i) for (HGUInt i = 0; i < height; ++i)
{ {
HGUInt lineSize = ((width + 7) & ~7) >> 3;
if (lineSize != fread(data + i * imgInfo.widthStep, 1, lineSize, file)) if (lineSize != fread(data + i * imgInfo.widthStep, 1, lineSize, file))
{ {
HGBase_DestroyImage(image2); HGBase_DestroyImage(image2);
@ -191,6 +189,8 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
} }
} }
HGBase_ReverseImage(image2, image2);
if (HGBASE_IMGTYPE_BINARY == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin) if (HGBASE_IMGTYPE_BINARY == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin)
{ {
*image = image2; *image = image2;
@ -199,13 +199,11 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
{ {
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
HGBase_DestroyImage(image2); HGBase_DestroyImage(image2);
if (HGBASE_ERR_OK != ret) if (HGBASE_ERR_OK != ret)
{ {
return ret; return ret;
} }
} }
} }
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY) else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
{ {
@ -226,14 +224,13 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
{ {
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
HGBase_DestroyImage(image2); HGBase_DestroyImage(image2);
if (HGBASE_ERR_OK != ret) if (HGBASE_ERR_OK != ret)
{ {
return ret; return ret;
} }
} }
} }
else if(pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) else if (pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
{ {
for (HGUInt i = 0; i < height; ++i) for (HGUInt i = 0; i < height; ++i)
{ {
@ -252,42 +249,37 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
{ {
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
HGBase_DestroyImage(image2); HGBase_DestroyImage(image2);
if (HGBASE_ERR_OK != ret) if (HGBASE_ERR_OK != ret)
{ {
return ret; return ret;
} }
} }
} }
else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII) else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII)
{ {
std::vector<HGChar> buf;
HGByte* p = data; HGByte* p = data;
HGUInt idx = 0; HGUInt idx = 0;
while (1) while (1)
{ {
HGByte c = 0; HGByte c = 0;
if (1 != fread(&c, 1, 1, file)) size_t readSize = fread(&c, 1, 1, file);
if (1 != readSize || c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
{ {
if (!buf.empty()) if (!buf.empty())
{ {
buf.push_back(0); buf.push_back(0);
HGInt pixel = atoi(&buf[0]); HGInt pixel = atoi(&buf[0]);
if (0 != pixel && 1 != pixel)
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
{ {
if (pixel > 255 || pixel < 0) HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA; return HGBASE_ERR_INVALIDDATA;
}
else
{
if (pixel > 1 || pixel < 0)
return HGBASE_ERR_INVALIDDATA;
} }
p[idx] = pixel; SetBit(p, idx, (HGByte)pixel);
++idx; ++idx;
if (idx == width * 3) if (idx == width)
{ {
p += imgInfo.widthStep; p += imgInfo.widthStep;
idx = 0; idx = 0;
@ -296,37 +288,9 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
buf.clear(); buf.clear();
} }
break; if (1 != readSize)
}
if (c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
{
if (!buf.empty())
{ {
buf.push_back(0); break;
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 == '#') if (c == '#')
@ -335,6 +299,7 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
{ {
if (1 != fread(&c, 1, 1, file)) if (1 != fread(&c, 1, 1, file))
{ {
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA; return HGBASE_ERR_INVALIDDATA;
} }
} }
@ -346,6 +311,169 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
} }
else else
{ {
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA;
}
if (p == data + height * imgInfo.widthStep)
{
break;
}
}
HGBase_ReverseImage(image2, image2);
if (HGBASE_IMGTYPE_BINARY == 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;
}
}
}
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII)
{
std::vector<HGChar> buf;
HGByte* p = data;
HGUInt idx = 0;
while (1)
{
HGByte c = 0;
size_t readSize = fread(&c, 1, 1, file);
if (1 != readSize || c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
{
if (!buf.empty())
{
buf.push_back(0);
HGInt pixel = atoi(&buf[0]);
if (pixel < 0 || pixel > 255)
{
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA;
}
p[idx] = (HGByte)pixel;
++idx;
if (idx == width)
{
p += imgInfo.widthStep;
idx = 0;
}
buf.clear();
}
if (1 != readSize)
{
break;
}
if (c == '#')
{
while (c != '\n')
{
if (1 != fread(&c, 1, 1, file))
{
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA;
}
}
}
}
else if (c >= '0' && c <= '9')
{
buf.push_back(c);
}
else
{
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA;
}
if (p == data + height * imgInfo.widthStep)
{
break;
}
}
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;
}
}
}
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII)
{
std::vector<HGChar> buf;
HGByte* p = data;
HGUInt idx = 0;
while (1)
{
HGByte c = 0;
size_t readSize = fread(&c, 1, 1, file);
if (1 != readSize || c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ')
{
if (!buf.empty())
{
buf.push_back(0);
HGInt pixel = atoi(&buf[0]);
if (pixel < 0 || pixel > 255)
{
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA;
}
p[idx] = (HGByte)pixel;
++idx;
if (idx == width)
{
p += imgInfo.widthStep;
idx = 0;
}
buf.clear();
}
if (1 != readSize)
{
break;
}
if (c == '#')
{
while (c != '\n')
{
if (1 != fread(&c, 1, 1, file))
{
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA;
}
}
}
}
else if (c >= '0' && c <= '9')
{
buf.push_back(c);
}
else
{
HGBase_DestroyImage(image2);
return HGBASE_ERR_INVALIDDATA; return HGBASE_ERR_INVALIDDATA;
} }
@ -363,18 +491,12 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG
{ {
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
HGBase_DestroyImage(image2); HGBase_DestroyImage(image2);
if (HGBASE_ERR_OK != ret) if (HGBASE_ERR_OK != ret)
{ {
return ret; return ret;
} }
} }
} }
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
{
HGBase_ReverseImage(image2, image2);
}
} }
return HGBASE_ERR_OK; return HGBASE_ERR_OK;
@ -419,10 +541,10 @@ HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* info
HGByte magicKey[2] = {0}; HGByte magicKey[2] = {0};
if (2 != fread(magicKey, 1, 2, file)) if (2 != fread(magicKey, 1, 2, file))
{ {
fclose(file);
return HGBASE_ERR_INVALIDDATA; return HGBASE_ERR_INVALIDDATA;
} }
HGResult ret = HGBASE_ERR_INVALIDDATA;
HGUInt pnmType = 0; HGUInt pnmType = 0;
if (magicKey[0] == 'P' && (magicKey[1] == '1')) if (magicKey[0] == 'P' && (magicKey[1] == '1'))
{ {
@ -448,22 +570,20 @@ HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* info
{ {
pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY; pnmType = HGIMGFMT_PNMTYPE_RGB_BINARY;
} }
else
if (0 == pnmType)
{ {
return HGBASE_ERR_INVALIDARG; fclose(file);
return HGBASE_ERR_INVALIDDATA;
} }
ret = BnmLoadImage(file, pnmType, info, imgType, imgOrigin, image); HGResult ret = BnmLoadImage(file, pnmType, info, imgType, imgOrigin, image);
fclose(file); fclose(file);
return ret; return ret;
} }
static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type) static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
{ {
HGImageInfo imgInfo;
HGBase_GetImageInfo(image, &imgInfo);
FILE* file = fopen(fileName, "wb"); FILE* file = fopen(fileName, "wb");
if (NULL == file) if (NULL == file)
{ {
@ -472,6 +592,8 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
HGByte* data = NULL; HGByte* data = NULL;
HGBase_GetImageData(image, &data); HGBase_GetImageData(image, &data);
HGImageInfo imgInfo;
HGBase_GetImageInfo(image, &imgInfo);
char magicKey[4] = {0}; char magicKey[4] = {0};
if (HGIMGFMT_PNMTYPE_BINARY_ASCII == type) if (HGIMGFMT_PNMTYPE_BINARY_ASCII == type)