增加pnm的Ascii格式的加载和保存

This commit is contained in:
yangjiaxuan 2022-11-04 11:57:55 +08:00
parent 57721f5912
commit df2ccc5b14
2 changed files with 241 additions and 31 deletions

View File

@ -1,7 +1,25 @@
#include "HGPnm.h"
#include "HGPnm.h"
#include "../base/HGInc.h"
#include <vector>
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));
}
HGResult HGAPI HGImgFmt_CheckPnmFile(const HGChar* fileName, HGBool* isPnm)
{
if (NULL == fileName || NULL == isPnm)
@ -15,7 +33,7 @@ HGResult HGAPI HGImgFmt_CheckPnmFile(const HGChar* fileName, HGBool* isPnm)
return HGBASE_ERR_OK;
}
static HGResult BnmLoadBinaryInfo(FILE* file, HGChar colorType, HGUInt *width, HGUInt *height, HGUInt *maxColor)
static HGResult BnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *height, HGUInt *maxColor)
{
assert(NULL != file && NULL != width && NULL != height && NULL != maxColor);
@ -83,7 +101,7 @@ static HGResult BnmLoadBinaryInfo(FILE* file, HGChar colorType, HGUInt *width, H
return HGBASE_ERR_INVALIDDATA;
}
if ('5' == colorType || '6' == colorType)
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
{
if (getMaxColor)
{
@ -102,37 +120,37 @@ static HGResult BnmLoadBinaryInfo(FILE* file, HGChar colorType, HGUInt *width, H
return HGBASE_ERR_OK;
}
static HGResult BnmLoadBinaryImage(FILE* file, HGChar colorType, 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;
HGResult ret = BnmLoadBinaryInfo(file , colorType, &width, &height, &maxColor);
HGResult ret = BnmLoadInfo(file , pnmType, &width, &height, &maxColor);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY)
{
if (maxColor > 255 || maxColor < 0)
return HGBASE_ERR_INVALIDDATA;
}
if (NULL != info)
{
info->width = width;
info->height = height;
if ('4' == colorType)
info->type = HGIMGFMT_PNMTYPE_BINARY_BINARY;
else if('5' == colorType)
info->type = HGIMGFMT_PNMTYPE_GRAY_BINARY;
else
info->type = HGIMGFMT_PNMTYPE_RGB_BINARY;
info->type = pnmType;
}
if (NULL != image)
{
if (imgType == 0)
{
if ('4' == colorType)
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
imgType = HGBASE_IMGTYPE_BINARY;
else if ('5' == colorType)
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
imgType = HGBASE_IMGTYPE_GRAY;
else
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
imgType = HGBASE_IMGTYPE_RGB;
}
@ -143,11 +161,11 @@ static HGResult BnmLoadBinaryImage(FILE* file, HGChar colorType, HGPnmLoadInfo*
HGImage image2 = NULL;
if (colorType == '4')
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_BINARY, HGBASE_IMGORIGIN_TOP, &image2);
else if (colorType == '5')
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_GRAY, HGBASE_IMGORIGIN_TOP, &image2);
else
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
ret = HGBase_CreateImage(width, height, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
if (HGBASE_ERR_OK != ret)
@ -155,12 +173,13 @@ static HGResult BnmLoadBinaryImage(FILE* file, HGChar colorType, HGPnmLoadInfo*
return ret;
}
std::vector<char> buf;
uint8_t* data;
HGBase_GetImageData(image2, &data);
HGImageInfo imgInfo;
HGBase_GetImageInfo(image2, &imgInfo);
if ('4' == colorType)
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
{
for (HGUInt i = 0; i < height; ++i)
{
@ -188,7 +207,7 @@ static HGResult BnmLoadBinaryImage(FILE* file, HGChar colorType, HGPnmLoadInfo*
}
}
else if ('5' == colorType)
else if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY)
{
for (HGUInt i = 0; i < height; ++i)
{
@ -214,7 +233,7 @@ static HGResult BnmLoadBinaryImage(FILE* file, HGChar colorType, HGPnmLoadInfo*
}
}
}
else
else if(pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY)
{
for (HGUInt i = 0; i < height; ++i)
{
@ -240,8 +259,119 @@ static HGResult BnmLoadBinaryImage(FILE* file, HGChar colorType, HGPnmLoadInfo*
}
}
}
else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII)
{
HGByte* p = data;
HGUInt idx = 0;
if ('4' == colorType)
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;
}
}
}
if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY)
{
HGBase_ReverseImage(image2, image2);
}
@ -293,11 +423,37 @@ HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* info
}
HGResult ret = HGBASE_ERR_INVALIDDATA;
if (magicKey[0] == 'P' && (magicKey[1] == '4' || magicKey[1] == '5' || magicKey[1] == '6'))
HGUInt pnmType = 0;
if (magicKey[0] == 'P' && (magicKey[1] == '1'))
{
HGChar colorType = magicKey[1];
ret = BnmLoadBinaryImage(file, colorType, info, imgType, imgOrigin, image);
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
{
return HGBASE_ERR_INVALIDARG;
}
ret = BnmLoadImage(file, pnmType, info, imgType, imgOrigin, image);
fclose(file);
return ret;
@ -318,7 +474,19 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
HGBase_GetImageData(image, &data);
char magicKey[4] = {0};
if (HGIMGFMT_PNMTYPE_BINARY_BINARY == type)
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)
{
strcpy(magicKey, "P4\n");
}
@ -339,7 +507,7 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
fwrite(width, 1, strlen(width), file);
fwrite(height, 1, strlen(height), file);
if (HGIMGFMT_PNMTYPE_GRAY_BINARY == type || HGIMGFMT_PNMTYPE_RGB_BINARY == type)
if (HGIMGFMT_PNMTYPE_BINARY_ASCII != type && HGIMGFMT_PNMTYPE_BINARY_BINARY != type)
{
char maxColor[] = "255\n";
fwrite(maxColor, 1, strlen(maxColor), file);
@ -353,7 +521,7 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
step = -(HGInt)imgInfo.widthStep;
}
if (imgInfo.type == HGBASE_IMGTYPE_BINARY)
if (type == HGIMGFMT_PNMTYPE_BINARY_BINARY)
{
HGUInt lineSize = ((imgInfo.width + 7) & ~7) >> 3;
HGByte* buf = (HGByte*)malloc(lineSize);
@ -372,7 +540,7 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
free(buf);
}
else if (imgInfo.type == HGBASE_IMGTYPE_GRAY)
else if (type == HGIMGFMT_PNMTYPE_GRAY_BINARY)
{
for (HGUInt i = 0; i < imgInfo.height; ++i)
{
@ -380,7 +548,7 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
fwrite(pEx, 1, imgInfo.width, file);
}
}
else
else if (type == HGIMGFMT_PNMTYPE_RGB_BINARY)
{
for (HGUInt i = 0; i < imgInfo.height; ++i)
{
@ -388,6 +556,48 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type)
fwrite(pEx, 1, imgInfo.width * 3, file);
}
}
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;
}
}
fclose(file);
return HGBASE_ERR_OK;

View File

@ -1,4 +1,4 @@
#ifndef __HGPNM_H__
#ifndef __HGPNM_H__
#define __HGPNM_H__
#include "../base/HGDef.h"