diff --git a/modules/imgfmt/HGPnm.cpp b/modules/imgfmt/HGPnm.cpp index 4b634966..f0196462 100644 --- a/modules/imgfmt/HGPnm.cpp +++ b/modules/imgfmt/HGPnm.cpp @@ -1,6 +1,8 @@ #include "HGPnm.h" #include "../base/HGInc.h" +#include "../base/HGInfo.h" #include +#include static inline HGByte GetBit(const HGByte* data, HGUInt index) { @@ -20,6 +22,21 @@ static inline void SetBit(HGByte* data, HGUInt index, HGByte value) data[byteIndex] &= ~(1 << (7 - bitIndex)); } +static inline HGUInt MyAtoi(const HGChar* c) +{ + HGUInt value = 0; + + const HGChar* p = c; + while (0 != *p) + { + value *= 10; + value += (HGUInt)(*p - '0'); + p++; + } + + return value; +} + HGResult HGAPI HGImgFmt_CheckPnmFile(const HGChar* fileName, HGBool* isPnm) { if (NULL == fileName || NULL == isPnm) @@ -40,7 +57,8 @@ static HGResult BnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *h bool getWidth = false; bool getHeight = false; bool getMaxColor = false; - std::vector buf; + char buf[256]; + int bufLen = 0; while (1) { @@ -52,33 +70,33 @@ static HGResult BnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *h if (c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ') { - if (!buf.empty()) + if (0 != bufLen) { - buf.push_back(0); + buf[bufLen] = 0; if (!getWidth) { - *width = atoi(&buf[0]); + *width = MyAtoi(buf); if (*width == 0) return HGBASE_ERR_INVALIDDATA; getWidth = true; } else if (!getHeight) { - *height = atoi(&buf[0]); + *height = MyAtoi(buf); if (*height == 0) return HGBASE_ERR_INVALIDDATA; getHeight = true; } else if (!getMaxColor) { - *maxColor = atoi(&buf[0]); + *maxColor = MyAtoi(buf); if (*maxColor == 0) return HGBASE_ERR_INVALIDDATA; getMaxColor = true; } - buf.clear(); + bufLen = 0; } if (c == '#') @@ -94,7 +112,8 @@ static HGResult BnmLoadInfo(FILE* file, HGUInt pnmType, HGUInt *width, HGUInt *h } else if (c >= '0' && c <= '9') { - buf.push_back(c); + buf[bufLen] = c; + ++bufLen; } else { @@ -122,7 +141,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; + HGUInt width = 0, height = 0, maxColor = 0; HGResult ret = BnmLoadInfo(file, pnmType, &width, &height, &maxColor); if (HGBASE_ERR_OK != ret) { @@ -131,9 +150,13 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG if (pnmType != HGIMGFMT_PNMTYPE_BINARY_ASCII && pnmType != HGIMGFMT_PNMTYPE_BINARY_BINARY) { - if (maxColor > 255) + if (maxColor != 255) return HGBASE_ERR_INVALIDDATA; } + else + { + maxColor = 1; + } if (NULL != info) { @@ -177,9 +200,14 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG HGImageInfo imgInfo; HGBase_GetImageInfo(image2, &imgInfo); - if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY) + if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY || pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY || pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) { HGUInt lineSize = ((width + 7) & ~7) >> 3; + if (pnmType == HGIMGFMT_PNMTYPE_GRAY_BINARY) + lineSize = width; + else if (pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) + lineSize = width * 3; + for (HGUInt i = 0; i < height; ++i) { if (lineSize != fread(data + i * imgInfo.widthStep, 1, lineSize, file)) @@ -189,115 +217,97 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG } } - HGBase_ReverseImage(image2, image2); - - if (HGBASE_IMGTYPE_BINARY == imgType && HGBASE_IMGORIGIN_TOP == imgOrigin) + if (pnmType == HGIMGFMT_PNMTYPE_BINARY_BINARY) { - *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_BINARY) - { - 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; - } + HGBase_ReverseImage(image2, image2); } } - else if (pnmType == HGIMGFMT_PNMTYPE_RGB_BINARY) + else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII || pnmType == HGIMGFMT_PNMTYPE_GRAY_ASCII || pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII) { - 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; - } - } - - 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; - } - } - } - else if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII) - { - std::vector buf; + HGChar readBuf[2048]; + HGUInt readBufLen = 0; + HGChar* curReadPos = readBuf; + HGChar buf[256]; + HGUInt bufLen = 0; 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 (0 == readBufLen) { - if (!buf.empty()) + readBufLen = fread(readBuf, 1, 2048, file); + curReadPos = readBuf; + } + + HGByte c = 0; + HGBool getChar = HGFALSE; + if (0 != readBufLen) + { + c = *curReadPos; + ++curReadPos; + --readBufLen; + getChar = HGTRUE; + } + + if (!getChar || c == '#' || c == '\n' || c == '\r' || c == '\t' || c == ' ') + { + if (0 != bufLen) { - buf.push_back(0); - HGInt pixel = atoi(&buf[0]); - if (0 != pixel && 1 != pixel) + buf[bufLen] = 0; + HGUInt pixel = MyAtoi(buf); + if (pixel < 0 || pixel > maxColor) { HGBase_DestroyImage(image2); return HGBASE_ERR_INVALIDDATA; } - SetBit(p, idx, (HGByte)pixel); + if (pnmType == HGIMGFMT_PNMTYPE_BINARY_ASCII) + SetBit(p, idx, (pixel == 0) ? 1 : 0); + else + p[idx] = (HGByte)pixel; + + HGUInt step = width; + if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII) + step = width * 3; + ++idx; - if (idx == width) + if (idx == step) { p += imgInfo.widthStep; idx = 0; } - buf.clear(); + bufLen = 0; } - if (1 != readSize) + if (!getChar) { - break; + if (p == data + height * imgInfo.widthStep) + { + break; + } + else + { + HGBase_DestroyImage(image2); + return HGBASE_ERR_INVALIDDATA; + } } - - if (c == '#') + else if (c == '#') { while (c != '\n') { - if (1 != fread(&c, 1, 1, file)) + c = 0; + HGBool getChar = HGFALSE; + if (0 != readBufLen) + { + c = *curReadPos; + ++curReadPos; + --readBufLen; + getChar = HGTRUE; + } + + if (!getChar) { HGBase_DestroyImage(image2); return HGBASE_ERR_INVALIDDATA; @@ -307,7 +317,8 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG } else if (c >= '0' && c <= '9') { - buf.push_back(c); + buf[bufLen] = c; + ++bufLen; } else { @@ -320,181 +331,19 @@ static HGResult BnmLoadImage(FILE* file, HGUInt pnmType, HGPnmLoadInfo* info, HG 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) + + if (imgInfo.type == imgType && imgInfo.origin == imgOrigin) { - 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; - } - } + *image = image2; } - else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII) + else { - std::vector buf; - HGByte* p = data; - HGUInt idx = 0; - - while (1) + ret = HGBase_CloneImage(image2, imgType, imgOrigin, image); + HGBase_DestroyImage(image2); + if (HGBASE_ERR_OK != ret) { - 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_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; - } + return ret; } } } @@ -647,14 +496,18 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type) { HGUInt lineSize = ((imgInfo.width + 7) & ~7) >> 3; HGByte* buf = (HGByte*)malloc(lineSize); - assert(NULL != buf); + if (NULL == buf) + { + fclose(file); + return HGBASE_ERR_OUTOFMEMORY; + } 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]; //黑白反色 + buf[j] = ~pEx[j]; // 黑白反色 } fwrite(buf, 1, lineSize, file); @@ -680,45 +533,63 @@ static HGResult BnmSaveImage(HGImage image, const HGChar* fileName, HGUInt type) } 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; - + HGUInt w = imgInfo.width; 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; + w = imgInfo.width * 3; + + char *buf = (char *)malloc(w * 5 + 1); + if (NULL == buf) + { + fclose(file); + return HGBASE_ERR_OUTOFMEMORY; + } + + std::string pixelStr[256]; + for (int i = 0; i < 256; ++i) + { + char str[6]; + sprintf(str, "%d", i); + pixelStr[i] = str; + } 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]); + int bufLen = 0; + int lineSize = 0; - if (bufSize + strlen(buf2) >= 70) + uint8_t* pEx = p + (HGSize)i * (HGSize)step; + for (HGUInt j = 0; j < w; ++j) + { + if (lineSize >= 70) { - strcat(buf, "\n"); - fwrite(buf, 1, strlen(buf), file); - buf[0] = 0; - bufSize = 0; + buf[bufLen] = '\n'; + ++bufLen; + lineSize = 0; } - strcat(buf, buf2); - bufSize += strlen(buf2); + HGUInt idx; + if (type == HGIMGFMT_PNMTYPE_BINARY_ASCII) + idx = (0 == GetBit(pEx, j) ? 1 : 0); + else + idx = pEx[j]; + + strcpy(buf + bufLen, pixelStr[idx].c_str()); + bufLen += pixelStr[idx].size(); + lineSize += pixelStr[idx].size(); + + buf[bufLen] = ' '; + ++bufLen; + ++lineSize; } + + buf[bufLen] = '\n'; + ++bufLen; + lineSize = 0; + + fwrite(buf, 1, bufLen, file); } - if (0 != bufSize) - { - fwrite(buf, 1, strlen(buf), file); - buf[0] = 0; - bufSize = 0; - } + free(buf); } fclose(file);