본문 바로가기
코스웨어/15년 스마트컨트롤러

20151121 김태현 WinAPI 8일차 비트맵 뷰어2

by 알 수 없는 사용자 2015. 11. 24.
728x90
반응형

#include <windows.h>

#define  XPOS  20
#define YPOS  20
#define SWIDTH  150
#define SHEIGHT 25
#define YGAP  5
#define XGAP  10
#define XGRAPH  256
#define YGRAPH  256

typedef struct _msgmap
{
  UINT uiMsg;
  LRESULT(*fp)(WPARAM, LPARAM);
}stMsgmap;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT OnDestroy( WPARAM, LPARAM);
LRESULT OnCreate( WPARAM, LPARAM);
LRESULT OnPaint( WPARAM, LPARAM);


stMsgmap Msgmap[] = {
  { WM_PAINT, OnPaint },
  { WM_DESTROY, OnDestroy },
  { WM_CREATE, OnCreate },
  { WM_NULL, 0 }
};

HINSTANCE g_hInst;  
HWND hWnd;
LPSTR lpszClass = L"Viewer"; 
UCHAR *ucpData;
UINT uiPad;
UINT uiImgWidth;
UINT uiImgHeight;
UINT uiImgSize;

static HBITMAP MyBitmap;
HBITMAP HbHisto;
//HDC MemDC;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
  , LPSTR lpszCmdParam, int nCmdShow)
{
  MSG Message;
  WNDCLASS WndClass; 
  g_hInst = hInstance;  

  WndClass.cbClsExtra = 0;
  WndClass.cbWndExtra = 0;
  WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 
  WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); 
  WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  WndClass.hInstance = hInstance;
  WndClass.lpfnWndProc = (WNDPROC)WndProc;
  WndClass.lpszClassName = lpszClass;
  WndClass.lpszMenuName = NULL;
  WndClass.style = CS_HREDRAW | CS_VREDRAW;
  RegisterClass(&WndClass);

  hWnd = CreateWindow(
    lpszClass,
    lpszClass, 
    (WS_CAPTION | WS_SYSMENU | WS_OVERLAPPED | WS_THICKFRAME /*| WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VSCROLL | WS_HSCROLL*/),
    CW_USEDEFAULT, CW_USEDEFAULT, 800800
    NULL, (HMENU)NULL, hInstance, NULL
    );
  ShowWindow(hWnd, nCmdShow); 

  while (GetMessage(&Message, 000)) { 
    TranslateMessage(&Message);
    DispatchMessage(&Message); 
  }
  return Message.wParam; 
}

LRESULT CALLBACK WndProc(HWND hWpWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
  stMsgmap *stpMap = Msgmap;
  hWnd = hWpWnd;
  while (WM_NULL != (*stpMap).uiMsg)
  {
    if (iMessage == (*stpMap).uiMsg)
    {
      return (((*stpMap).fp)(wParam, lParam));
    }
    ++stpMap;
  }

  return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

BOOL DrawBitmap(void)
{
  HDC hdc;
  PAINTSTRUCT ps;
  INT iCntY;
  INT iCntX;
  HDC MemDC;
  UINT uiCnt[256= { 0, };
  UINT uiMaxVal;
  hdc = GetDC(hWnd);
  MyBitmap = CreateCompatibleBitmap(hdc, uiImgWidth, uiImgHeight);
  HbHisto = CreateCompatibleBitmap(hdc, XGRAPH+1, YGRAPH);
  MemDC = CreateCompatibleDC(hdc);

  SelectObject(MemDC, MyBitmap);  
  
  for (iCntY = 0; iCntY < uiImgHeight; ++iCntY)
  {
    for (iCntX = 0; iCntX < uiImgWidth; ++iCntX)
    {
      SetPixel(MemDC, iCntX, uiImgHeight - iCntY, RGB(
        //SetPixel(hdc, iCntX, iCntY, RGB(
        *(ucpData + (3 * (iCntY*uiImgWidth + iCntX)) + 2 + (iCntY*uiPad)),
        *(ucpData + (3 * (iCntY*uiImgWidth + iCntX)) + 1 + (iCntY*uiPad)),
        *(ucpData + (3 * (iCntY*uiImgWidth + iCntX)) + 0 + (iCntY*uiPad))));
      //RGB값을 모두 더한뒤에 3으로 나누기위해서 한곳에 몰아준다.
      ++uiCnt[ucpData[iCntY * (uiImgWidth * 3) + (iCntX * 3) + 0 + iCntY * uiPad]]; //Blue
      ++uiCnt[ucpData[iCntY * (uiImgWidth * 3) + (iCntX * 3) + 1 + iCntY * uiPad]]; //Green
      ++uiCnt[ucpData[iCntY * (uiImgWidth * 3) + (iCntX * 3) + 2 + iCntY * uiPad]]; //Red
      //ucpData[3*(iCnty*uiImgWidth + iCntX) + 2 + (iCntY*uiPad)],
      //ucpData[3 * (iCnty*uiImgWidth + iCntX) + 1 + (iCntY*uiPad)],
      //ucpData[3 * (iCnty*uiImgWidth + iCntX) + 0 + (iCntY*uiPad)],
      //ucpData[(iCntY*uiImgWidth * 3) + (iCntX * 3) + 2 + (iCntY*uiPad)],
      //ucpData[(iCntY*uiImgWidth * 3) + (iCntX * 3) + 1 + (iCntY*uiPad)],
      //ucpData[(iCntY*uiImgWidth * 3) + (iCntX * 3) + 0 + (iCntY*uiPad)]));
    }
  }
  uiMaxVal = 0;
  for (iCntX = 0; iCntX < 255; ++iCntX)
  {
    uiCnt[iCntX] = uiCnt[iCntX] / 3;
    if (uiMaxVal < uiCnt[iCntX])
    {
      uiMaxVal = uiCnt[iCntX];
    }
  }
  for (iCntX = 0; iCntX < 255; ++iCntX)
  {
    uiCnt[iCntX] = (uiCnt[iCntX]* XGRAPH)/uiMaxVal;
  }
  DeleteDC(MemDC);
  free(ucpData);
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, HbHisto);
  for (iCntX=0;iCntX < XGRAPH+1;++iCntX)
  {
    SetPixel(MemDC, iCntX, YGRAPH-1, RGB(25500));
  }
  DeleteDC(MemDC);
  ReleaseDC(hWnd, hdc);
  return TRUE;
}

LRESULT OnPaint(WPARAM wParam, LPARAM lParam)
{
  HDC hdc;
  HDC MemDC; // 전역으로 해도 동작은 됨
  PAINTSTRUCT ps;

  hdc = BeginPaint(hWnd, &ps);
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, MyBitmap);

  BitBlt(hdc, 00, uiImgWidth, uiImgHeight, MemDC, 00, SRCCOPY);

  DeleteDC(MemDC);
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, HbHisto);

  BitBlt(hdc, uiImgWidth + (SWIDTH*2)+(XGAP*2)+XPOS, 0, XGRAPH+1, YGRAPH, MemDC, 00, SRCCOPY);

  DeleteDC(MemDC);
  EndPaint(hWnd, &ps);
  return 0;
}

LRESULT OnDestroy(WPARAM wParam, LPARAM lParam)
{  
  //free(ucpData);
  //DeleteDC(MemDC);
  PostQuitMessage(0);
  return 0;
}

void PrintBmpInfo(BITMAPFILEHEADER *stpFH, BITMAPINFOHEADER *stpIH)
{
  UINT uiYCnt;

  WCHAR *ucTitle[] = {
    L"Magic Number:", 
    L"
파일크기:",
    L"
데이터 오프셋:",
    L"
Info 헤더사이즈:",
    L"
가로:",
    L"
세로:",
    L"
비트 플레인:",
    L"
픽셀당 비트:",
    L"
압축 유형:",
    L"
데이터 크기:",
    L"
수평 해상도:",
    L"
수직 해상도:",
    L"
사용 칼라인덱스 수:",
    L"
중요 칼라인덱스 수:"
  };

  WCHAR ucValue[14][30];

  wsprintf(ucValue[0], L"
[%c][%c]", *(((unsigned char *)(stpFH)) + 0), *(((unsigned char *)(stpFH)) + 1));
  wsprintf(ucValue[1], L"
%d Bytes", stpFH->bfSize);
  wsprintf(ucValue[2], L"%d", stpFH->bfOffBits);
  wsprintf(ucValue[3], L"%d", stpIH->biSize);
  wsprintf(ucValue[4], L"%d pixel", stpIH->biWidth);
  wsprintf(ucValue[5], L"%d pixel", stpIH->biHeight);
  wsprintf(ucValue[6], L"%d", stpIH->biPlanes);
  wsprintf(ucValue[7], L"%d", stpIH->biBitCount);
  switch (stpIH->biCompression)
  {
    case 0:
      wsprintf(ucValue[8], L"[BI_RGB]");
      break;
    case 1:
      wsprintf(ucValue[8], L"
[BI_RLE8]");
      break;
    case 2:
      wsprintf(ucValue[8], L"
[BI_RLE4]");
      break;
    case 3:
      wsprintf(ucValue[8], L"
[BI_BITFIELDS]");
      break;
    default:
      break;
  }
  //wsprintf(ucValue[8], L"
%d", stpIH->biCompression);
  wsprintf(ucValue[9], L"%d Bytes", stpIH->biSizeImage);
  wsprintf(ucValue[10], L"%d", stpIH->biXPelsPerMeter);
  wsprintf(ucValue[11], L"%d", stpIH->biYPelsPerMeter);
  wsprintf(ucValue[12], L"%d", stpIH->biClrUsed);
  wsprintf(ucValue[13], L"%d", stpIH->biClrImportant);

  for (uiYCnt = 0; uiYCnt < 14; ++uiYCnt)
  {  
    CreateWindow(L"static", ucTitle[uiYCnt], WS_CHILD | WS_VISIBLE | ES_RIGHT,
      XPOS + stpIH->biWidth, YPOS + ((SHEIGHT + YGAP)*uiYCnt), SWIDTH, SHEIGHT, hWnd, (HMENU)-1, g_hInst, NULL);
    
    CreateWindow(L"edit", ucValue[uiYCnt], WS_CHILD | WS_VISIBLE | WS_BORDER | ES_READONLY | ES_CENTER,
      XPOS + stpIH->biWidth + SWIDTH + XGAP, YPOS + ((SHEIGHT + YGAP)*uiYCnt), SWIDTH, SHEIGHT, hWnd, (HMENU)-1, g_hInst, NULL);

  }
  return;
}

LRESULT OnCreate(WPARAM wParam, LPARAM lParam)
{
  HDC hdc;

  HANDLE hFile;

  BITMAPFILEHEADER stBFHead;
  BITMAPINFOHEADER stBFInfo;
  BOOL bRet;
  DWORD dwCnt;

  hFile = CreateFile(L"2.bmp", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (INVALID_HANDLE_VALUE == hFile)
  {
    MessageBox(hWnd, L"Open Error", L"ERROR", MB_OK);
    PostQuitMessage(0);
    return 0;
  }

  bRet = ReadFile(hFile, &stBFHead, sizeof(BITMAPFILEHEADER), &dwCnt, NULL);
  if (FALSE == bRet)
  {
    MessageBox(hWnd, L"File헤더 Read Error", L"ERROR", MB_OK);
    CloseHandle(hFile);
    PostQuitMessage(0);
    return 0;
  }

  bRet = ReadFile(hFile, &stBFInfo, sizeof(BITMAPINFOHEADER), &dwCnt, NULL);
  if (FALSE == bRet)
  {
    MessageBox(hWnd, L"Info헤더 Read Error", L"ERROR", MB_OK);
    CloseHandle(hFile);
    PostQuitMessage(0);
    return 0;
  }
  uiPad = stBFInfo.biWidth % 4;// padding 추출
  uiImgWidth = stBFInfo.biWidth;
  uiImgHeight = stBFInfo.biHeight;
  uiImgSize = stBFInfo.biSizeImage;
  PrintBmpInfo(&stBFHead, &stBFInfo);
  
  ucpData = malloc(stBFInfo.biSizeImage);
  if (0 == ucpData)
  {
    MessageBox(hWnd, L"Malloc Error", L"ERROR", MB_OK);
    CloseHandle(hFile);
    PostQuitMessage(0);
    return 0;
  }

  bRet = ReadFile(hFile, ucpData, stBFInfo.biSizeImage, &dwCnt, NULL);
  if (FALSE == bRet)
  {
    MessageBox(hWnd, L"Image Data Read Error", L"ERROR", MB_OK);
    CloseHandle(hFile);
    free(ucpData);
    PostQuitMessage(0);
    return 0;
  }

  bRet = DrawBitmap();
  if (FALSE == bRet)
  {
    MessageBox(hWnd, L"Draw Failed", L"ERROR", MB_OK);
    CloseHandle(hFile);
    free(ucpData);
    //DeleteDC(MemDC);
    PostQuitMessage(0);
    return 0;
  }
  CloseHandle(hFile);
  return 0;
}

728x90