Чтение BMP файла
#include <fstream.h>
#include <math.h>
void SaveBMP(char *name,TCanvas *im2, int W, int H,unsigned long bitpixel)
{
bitpixel=exp(log(2)*bitpixel);
HDC hdcScreen; // DC for entire screen
HDC hdcScreenCompat; // memory DC for screen
HBITMAP hbmpCompat; // bitmap handle for old DC
BITMAP bmp; // bitmap data structure
HDC MBM , MDC,CDC;
hdcScreenCompat = CreateCompatibleDC(im2->Handle);
bmp.bmBitsPixel = (BYTE) GetDeviceCaps(im2->Handle, BITSPIXEL);
bmp.bmPlanes = (BYTE) GetDeviceCaps(im2->Handle, PLANES);
bmp.bmWidth =W;
bmp.bmHeight =H;
// The width must be byte-aligned.
bmp.bmWidthBytes = ((bmp.bmWidth + 15) & ~15) / 8;
// Create a bitmap for the compatible DC.
hbmpCompat = ::CreateCompatibleBitmap(im2->Handle,bmp.bmWidth ,bmp.bmHeight);
// Select the bitmap for the compatible DC.
HGDIOBJ oldObj = ::SelectObject(hdcScreenCompat, hbmpCompat);
::BitBlt(hdcScreenCompat, 0, 0, bmp.bmWidth, bmp.bmHeight, im2->Handle, 0, 0, SRCCOPY);
::SelectObject(hdcScreenCompat, oldObj);
// Write BMP to file
// 256 - is a maximum. We alloc so much just in case
DWORD dwHeaderSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
BITMAPINFO * pBmpInfo = (BITMAPINFO*)calloc(dwHeaderSize, 1);
BYTE * pData;
pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biWidth = bmp.bmWidth;
pBmpInfo->bmiHeader.biHeight = bmp.bmHeight;
pBmpInfo->bmiHeader.biPlanes = 1;
int nSize = 0;
switch(bitpixel)
{
case 2:
pBmpInfo->bmiHeader.biBitCount = 1;
nSize = bmp.bmWidth * bmp.bmHeight / 8;
break;
case 16:
pBmpInfo->bmiHeader.biBitCount = 4;
nSize = bmp.bmWidth * bmp.bmHeight / 2;
break;
case 256:
pBmpInfo->bmiHeader.biBitCount = 8;
nSize = bmp.bmWidth * bmp.bmHeight;
break;
case 65535:
pBmpInfo->bmiHeader.biBitCount = 16;
nSize = bmp.bmWidth * bmp.bmHeight * 2;
break;
case 16777215:
pBmpInfo->bmiHeader.biBitCount = 24;
nSize = bmp.bmWidth * bmp.bmHeight * 3;
break;
case 4294967295:
pBmpInfo->bmiHeader.biBitCount = 32;
nSize = bmp.bmWidth * bmp.bmHeight * 4;
break;
}
pBmpInfo->bmiHeader.biClrUsed = bitpixel;
pData = (BYTE*)calloc(nSize, 1);
::GetDIBits(hdcScreenCompat, hbmpCompat, 0, bmp.bmHeight, pData, pBmpInfo, DIB_RGB_COLORS);
//pBmpInfo->bmiHeader.biClrUsed = g_nColors;
::DeleteDC(hdcScreenCompat);
::DeleteDC(hdcScreen);
ofstream op;
op.open(name,ios::out | ios::binary);
if (op.is_open())
{
BITMAPFILEHEADER hdr;
hdr.bfType = 0x4d42;
hdr.bfSize = (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nSize);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
if (pBmpInfo->bmiHeader.biClrUsed > 0 && pBmpInfo->bmiHeader.biClrUsed <= 256)
{
hdr.bfSize += sizeof(RGBQUAD) * pBmpInfo->bmiHeader.biClrUsed;
hdr.bfOffBits += sizeof(RGBQUAD) * pBmpInfo->bmiHeader.biClrUsed;
}
op.write((const char*)&hdr, sizeof(hdr));
op.write((const char*)&pBmpInfo->bmiHeader, sizeof(BITMAPINFOHEADER));
if (pBmpInfo->bmiHeader.biClrUsed > 0 && pBmpInfo->bmiHeader.biClrUsed <= 256)
{
op.write((const char*)&pBmpInfo->bmiColors, sizeof(RGBQUAD) * pBmpInfo->bmiHeader.biClrUsed);
}
op.write((const char*)pData, nSize);
op.close();
}
free(pBmpInfo);
free(pData);
}
У меня при чтении возникают проблемы с палитрой.
Если кто может помогите с исходным кодом записи BMP.
:(
case 256:
pBmpInfo->bmiHeader.biBitCount = 8;
nSize = bmp.bmWidth * bmp.bmHeight;
break;
case 65535:
pBmpInfo->bmiHeader.biBitCount = 16;
nSize = bmp.bmWidth * bmp.bmHeight * 2;
break;
case 16777215:
pBmpInfo->bmiHeader.biBitCount = 24;
nSize = bmp.bmWidth * bmp.bmHeight * 3;
break;
case 4294967295:
pBmpInfo->bmiHeader.biBitCount = 32;
nSize = bmp.bmWidth * bmp.bmHeight * 4;
break;
}
pBmpInfo->bmiHeader.biClrUsed = bitpixel;
У меня при чтении возникают проблемы с палитрой.
:(
На сколько я понимаю, ошибка в величине biClrUsed - она используется для определения длины палитры в форматах реально ее имеющих (в твоем случае до 256 включительно - но не более!)
Вот кусок кода "нормального" определения длины палитры
...
i=BMPInfoHead->biClrUsed;
if(!i) { i=BMPInfoHead->biClrImportant;
if(!i) { switch(BMPInfoHead->biBitCount)
{ case 1: i=2; break;
case 4: i=16; break;
case 8: i=256; break;
case 16:
case 32: Application->MessageBox("Извините, но данная версия не поддерживает\n"
"16-ти и 32-х битовые форматы BMP-файлов.",
"ошибка загрузки кадра",MB_OK|MB_ICONSTOP);
return (false);// Close();
// break;
}
}
}
PalSize=i;
if(PalSize) { Len=PalSize*4;//реальная длина палитры
adrFrame=adrPalet+Len;//BMPFileHead->bfOffBits;не всегда верно !!!
... }
Как видишь, PalSize определяется только для 2,16 и 256- цветных изображений - у "более крутых" палитра просто отсутствует
На сколько я понимаю, ошибка в величине biClrUsed - она используется для определения длины палитры в форматах реально ее имеющих (в твоем случае до 256 включительно - но не более!)
Вот кусок кода "нормального" определения длины палитры
...
i=BMPInfoHead->biClrUsed;
if(!i) { i=BMPInfoHead->biClrImportant;
if(!i) { switch(BMPInfoHead->biBitCount)
{ case 1: i=2; break;
case 4: i=16; break;
case 8: i=256; break;
case 16:
case 32: Application->MessageBox("Извините, но данная версия не поддерживает\n"
"16-ти и 32-х битовые форматы BMP-файлов.",
"ошибка загрузки кадра",MB_OK|MB_ICONSTOP);
return (false);// Close();
// break;
}
}
}
PalSize=i;
if(PalSize) { Len=PalSize*4;//реальная длина палитры
adrFrame=adrPalet+Len;//BMPFileHead->bfOffBits;не всегда верно !!!
... }
Как видишь, PalSize определяется только для 2,16 и 256- цветных изображений - у "более крутых" палитра просто отсутствует
Спасибо большое буду дальше разбираться :)