#include "stdafx.h"
#include "testBM.h"
#define MAX_LOADSTRING 100
// Макрос для определения количества байт в выровненной по DWORD строке
// BPP - бит на пиксел
#define BYTESPERLINE(Width, BPP) ((WORD)((((DWORD)(Width)*(DWORD)(BPP)+31) >> 5)) << 2)
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HDC image_dc;
BITMAP bitmap;
HBITMAP hbitmap;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TESTBM, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TESTBM);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TESTBM);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCTSTR)IDC_TESTBM;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
// Сохранение
PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp, HWND hWnd)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
// Получаем размер картинки
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
{
MessageBox(hWnd, "Размер картинки не получен", "Error", MB_ICONERROR|MB_OK);
return NULL;
}
if(bmp.bmBitsPixel > 24) bmp.bmBitsPixel = 24;
cClrBits = (WORD)(bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else
cClrBits = 24;
if (cClrBits < 16)
pbmi = (PBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * (1<<cClrBits)];
else // палитры нет
pbmi = (PBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)];
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0;
if (cClrBits < 16)
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage =
BYTESPERLINE(pbmi->bmiHeader.biWidth, cClrBits) * pbmi->bmiHeader.biHeight;
// Все цвета изображения важны
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
BOOL SaveBitmapToBMPFile(char *fName, HBITMAP &BMP, HDC &hDC, HWND hWnd)
{
HANDLE hf = NULL; // указатель на файл
BITMAPFILEHEADER hdr; // заголовок BMP-файла
PBITMAPINFOHEADER pbih; // заголовок картинки
BYTE *pBits = NULL; // указатель на растровые данные
DWORD dwWidthBytes = 0; // длина строки растровых данных в байтах
DWORD dwTmp = 0; // для временный потребностей
// Создаем структуру - заголовок растра
PBITMAPINFO pbmi = CreateBitmapInfoStruct(BMP, hWnd);
pbih = (PBITMAPINFOHEADER) pbmi;
// Выделим память
pBits = new BYTE[pbih->biSizeImage];
if (!pBits)
{
MessageBox(hWnd, "Память не выделена", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
// Получаем растровые данные
if (!GetDIBits(hDC, BMP, 0, (WORD) pbih->biHeight, pBits, pbmi, DIB_RGB_COLORS))
{
MessageBox(hWnd, "Растровые данные не получены", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
hf = CreateFile(fName, GENERIC_READ|GENERIC_WRITE,
(DWORD) 0, (LPSECURITY_ATTRIBUTES) NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
{
MessageBox(hWnd, "Файл не создан", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
hdr.bfType = 0x4d42;
// Размер всего файла вместе с заголовком и данными
hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Смещения до начала растровых данных
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD);
// Записываем заголовок файла - структуру BITMAPFILEHEADER
if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
{
MessageBox(hWnd, "Заголовок файла не записан", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
//... структуру BITMAPINFOHEADER и палитру RGBQUAD
if (!WriteFile(hf, (LPVOID)pbih, sizeof(BITMAPINFOHEADER) +
pbih->biClrUsed * sizeof(RGBQUAD),
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
{
MessageBox(hWnd, "Записать палитру и структуру не удалось", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
//.... растровые данные
dwWidthBytes = BYTESPERLINE(pbih->biWidth, pbih->biBitCount);
LONG i = 0, j = 0;
BYTE *pCurStr = NULL; // указатель на текущую строку
pCurStr = pBits;
for(i = 0; i < pbih->biHeight; i++) // записываем по строкам
{
if(!WriteFile(hf, (LPSTR) pCurStr, (int) dwWidthBytes,
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
{
MessageBox(hWnd, "Не удалось записать строку", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
pCurStr += dwWidthBytes;
}
if (!CloseHandle(hf))
{
MessageBox(hWnd, "Файл не закрыт", "Error", MB_ICONERROR|MB_OK);
return FALSE;
}
// Освобождаем память
if(pBits!=NULL) delete[] pBits;
if(pbmi!=NULL) delete[] pbmi;
return TRUE;
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
// Загрузка файла
void LoadBMTrue(HWND hWnd, char *fin)
{
hbitmap = (HBITMAP)LoadImage(hInst,"1.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
if (!hbitmap)
MessageBox(hWnd, "File 1.bmp do not found", "Error", MB_ICONERROR|MB_OK);
else
{
GetObject(hbitmap, sizeof(BITMAP), (LPSTR)&bitmap);
HDC hdc = GetDC(hWnd); // Получаем контекст устройства созданного нами окна
image_dc = CreateCompatibleDC(hdc);
// При выборе нового объекта, нужно сохранить старый
HBITMAP old_hbitmap = (HBITMAP)SelectObject(image_dc,hbitmap);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_about :
MessageBox(hWnd, "Program by Myhov Kirill. Program is decriptor.",
"About", MB_ICONINFORMATION|MB_OK);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case ID_FILE_LOADBM:
LoadBMTrue(hWnd, "1.bmp");
InvalidateRect(hWnd,0,TRUE);
break;
case ID_FILE_SAVEBM:
SaveBitmapToBMPFile("2.bmp", hbitmap, hdc, hWnd);
break;
case ID_SERVICE_MONO:
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Эта функция отображает картинку.
BitBlt(hdc,50,50,320,192,image_dc,0,0,SRCCOPY);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
Почему-то не сохраняется bmp! Никак не найду проблему!
Все! Я разобрался! просто нужно было использовать контекст картинки, а не контекст устройства, тогда палитра загружается корректно =) Всем спасибо за внимание!