diff --git a/modules/imgfmt/HGPnm.cpp b/modules/imgfmt/HGPnm.cpp index 1a6061fc..4b634966 100644 --- a/modules/imgfmt/HGPnm.cpp +++ b/modules/imgfmt/HGPnm.cpp @@ -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) { 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) { 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 (maxColor > 255 || maxColor < 0) + if (maxColor > 255) 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); 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) { return ret; } - std::vector buf; uint8_t* data; HGBase_GetImageData(image2, &data); HGImageInfo imgInfo; @@ -181,9 +179,9 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY) { + HGUInt lineSize = ((width + 7) & ~7) >> 3; for (HGUInt i = 0; i < height; ++i) { - HGUInt lineSize = ((width + 7) & ~7) >> 3; if (lineSize != fread(data + i * imgInfo.widthStep, 1, lineSize, file)) { 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) { *image = image2; @@ -199,13 +199,11 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG { ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); HGBase_DestroyImage(image2); - if (HGBASE_ERR_OK != ret) { return ret; } - } - + } } 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); HGBase_DestroyImage(image2); - if (HGBASE_ERR_OK != ret) { return ret; } } } - else if(pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) + else if (pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) { 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); HGBase_DestroyImage(image2); - if (HGBASE_ERR_OK != 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 buf; HGByte* p = data; HGUInt idx = 0; while (1) { 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()) { buf.push_back(0); HGInt pixel = atoi(&buf[0]); - - if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY) + if (0 != pixel && 1 != pixel) { - if (pixel > 255 || pixel < 0) - return HGBASE_ERR_INVALIDDATA; - } - else - { - if (pixel > 1 || pixel < 0) - return HGBASE_ERR_INVALIDDATA; + HGBase_DestroyImage(image2); + return HGBASE_ERR_INVALIDDATA; } - p[idx] = pixel; + SetBit(p, idx, (HGByte)pixel); ++idx; - if (idx == width * 3) + if (idx == width) { p += imgInfo.widthStep; idx = 0; @@ -296,37 +288,9 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG buf.clear(); } - break; - } - - if (c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ') - { - if (!buf.empty()) + if (1 != readSize) { - 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 == '#') @@ -335,6 +299,7 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG { if (1 != fread(&c, 1, 1, file)) { + HGBase_DestroyImage(image2); return HGBASE_ERR_INVALIDDATA; } } @@ -346,6 +311,169 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG } 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 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 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; } @@ -363,18 +491,12 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG { 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); - } } return HGBASE_ERR_OK; @@ -419,10 +541,10 @@ HGResult HGAPI HGImgFmt_LoadPnmImage(const HGChar* fileName, HGPnmLoadInfo* info HGByte magicKey[2] = {0}; if (2 != fread(magicKey, 1, 2, file)) { + fclose(file); return HGBASE_ERR_INVALIDDATA; } - HGResult ret = HGBASE_ERR_INVALIDDATA; HGUInt pnmType = 0; 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; } - 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); return ret; } static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type) { - HGImageInfo imgInfo; - HGBase_GetImageInfo(image, &imgInfo); - FILE* file = fopen(fileName, "wb"); if (NULL == file) { @@ -472,6 +592,8 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type) HGByte* data = NULL; HGBase_GetImageData(image, &data); + HGImageInfo imgInfo; + HGBase_GetImageInfo(image, &imgInfo); char magicKey[4] = {0}; if (HGIMGFMT_PNMTYPE_BINARY_ASCII == type)