优化pnm格式的加载和保存速度
This commit is contained in:
parent
065a890253
commit
89598f053c
|
@ -1,6 +1,8 @@
|
|||
#include "HGPnm.h"
|
||||
#include "../base/HGInc.h"
|
||||
#include "../base/HGInfo.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
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<char> 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<HGChar> 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<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;
|
||||
}
|
||||
}
|
||||
*image = image2;
|
||||
}
|
||||
else if (pnmType == HGIMGFMT_PNMTYPE_RGB_ASCII)
|
||||
else
|
||||
{
|
||||
std::vector<HGChar> 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);
|
||||
|
|
Loading…
Reference in New Issue