bool loadBmpFile( LPCTSTR bmpFileName, int& outWidth, int& outHeight, int& outBpp, BYTE*& outBmpData )
{
FILE *fp = fopen(bmpFileName, "rb");
if(!fp)
return false;
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
RGBQUAD rgb[3];
fread(&bfh, sizeof(BITMAPFILEHEADER), 1, fp);
fread(&bih, sizeof(BITMAPINFOHEADER), 1, fp);
// 16비트는 추가적으로 rgb가 12바이트 들어있다.
if(bih.biBitCount == 16) {
fread(rgb, sizeof(RGBQUAD), 3, fp);
}
LPBYTE buffer = new BYTE[bih.biSizeImage];
fread(buffer, sizeof(BYTE), bih.biSizeImage, fp);
fclose(fp);
outWidth = bih.biWidth;
outHeight = bih.biHeight;
outBpp = bih.biBitCount;
// height는 뒤집어 준다.
if(outHeight < 0) {
outHeight *= -1;
}
outBmpData = buffer;
return true;
}
bool saveBmpFile( LPCTSTR bmpFileName, int width, int height, int bpp, BYTE* bmpData )
{
PBITMAPINFO pbmi;
if(height < 0)
height *= -1;
// 16비트는 추가적으로 rgb가 12바이트 들어있다.
if (bpp == 16) {
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * 3);
}
else {// 24,32비트
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
}
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = width;
pbmi->bmiHeader.biHeight = height;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = bpp;
if (bpp == 16) {// 16비트 565일 경우의 bit mask를 채워준다. 그리고 rgb가 아니라 bitfields로 셋팅한다.
pbmi->bmiHeader.biClrUsed = 3;
pbmi->bmiHeader.biCompression = BI_BITFIELDS;
memset(pbmi->bmiColors, 0, sizeof(RGBQUAD)*3);
pbmi->bmiColors[0].rgbGreen = 248;
pbmi->bmiColors[1].rgbBlue = 224;
pbmi->bmiColors[1].rgbGreen = 7;
pbmi->bmiColors[2].rgbBlue = 31;
}
else {
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biCompression = BI_RGB;
}
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * bpp +31) & ~31) /8
* pbmi->bmiHeader.biHeight;
pbmi->bmiHeader.biClrImportant = 0;
// height는 뒤집어 준다.
if(pbmi->bmiHeader.biHeight > 0) {
pbmi->bmiHeader.biHeight *= -1;
}
HANDLE hf; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
DWORD dwTotal; // total count of bytes
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;
// Create the .BMP file.
hf = CreateFile(bmpFileName,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
return false;
hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
// Compute the size of the entire file.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbmi->bmiHeader.biSize + pbmi->bmiHeader.biClrUsed
* sizeof(RGBQUAD) + pbmi->bmiHeader.biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbmi->bmiHeader.biSize + pbmi->bmiHeader.biClrUsed
* sizeof (RGBQUAD);
// Copy the BITMAPFILEHEADER into the .BMP file.
if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
(LPDWORD) &dwTmp, NULL))
{
return false;
}
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
if (!WriteFile(hf, (LPVOID) &pbmi->bmiHeader, sizeof(BITMAPINFOHEADER)
+ pbmi->bmiHeader.biClrUsed * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, ( NULL)))
return false;
// Copy the array of color indices into the .BMP file.
dwTotal = cb = pbmi->bmiHeader.biSizeImage;
hp = bmpData;
if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
return false;
// Close the .BMP file.
if (!CloseHandle(hf))
return false;
return true;
}