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

20151125 임현수 업무일지 WIN32API #10 영상 밝기 그래프, 알파값 처리

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


■ 영상 밝기 그래프



#include <windows.h>
#include <Vfw.h>

//#pragma comment (lib, "vfw32.lib")

#define XSCALE  320
#define YSCALE  240

#define XGRAPH  256
#define YGRAPH  256

typedef struct _stMSG_Map
{
  UINT    uiMSG;
  LRESULT(*fp)(WPARAM, LPARAM);

}stMSG_Map;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT On_Paint(WPARAM, LPARAM);
LRESULT On_Create(WPARAM, LPARAM);
LRESULT On_Destroy(WPARAM, LPARAM);
LRESULT capture(HWND, LPVIDEOHDR);

HWND hWnd;
BITMAPINFO stBMPInfo;
HINSTANCE g_hInst;

static HBITMAP Histo;

LPSTR lpszClass = TEXT("영상처리");

stMSG_Map stMap[] = {
  { WM_PAINT, On_Paint },
  { WM_CREATE, On_Create },
  { WM_DESTROY, On_Destroy },
  { WM_NULL, 0 }
};

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_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
    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)
{
  hWnd = hwpWnd;
  stMSG_Map * stpMap = stMap;

  while (WM_NULL != ((*stpMap).uiMSG))
  {
    if (iMessage == ((*stpMap).uiMSG))
    {
      return (((*stpMap).fp)(wParam, lParam));
    }
    ++stpMap;
  }

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

LRESULT On_Paint(WPARAM wParam, LPARAM lParam)
{
  HDC hdc;
  PAINTSTRUCT ps;
  hdc = BeginPaint(hWnd, &ps);
  EndPaint(hWnd, &ps);
  return 0;
}

LRESULT On_Create(WPARAM wParam, LPARAM lParam)
{
  HDC hdc;
  HWND hCamera;
  BOOL bRet;

  hdc = GetDC(hWnd);
  
  Histo = CreateCompatibleBitmap(hdc, XGRAPH+1, YGRAPH);  // 비트맵을 생성

  // 화면을 띄울 창 마련
  hCamera = capCreateCaptureWindow(TEXT("smart"), WS_CHILD | WS_VISIBLE, 00, XSCALE, YSCALE, hWnd, 0);
  if (NULL == hCamera)
  {
    MessageBox(hWnd, TEXT("윈도우를 생성할 수 없습니다"), TEXT("에러"), MB_OK);
    PostQuitMessage(0);
  }
  
  // 카메라와 연결 2번째 인자는 장착된 카메라 갯수번호
  bRet = capDriverConnect(hCamera, 0);
  if (FALSE == bRet)
  {
    MessageBox(hWnd, TEXT("카메라를 연결할 수 없습니다"), TEXT("에러"), MB_OK);
    PostQuitMessage(0);
  }

  // 화면에 보이는 속도
  capPreviewRate(hCamera, 1);

  // hCamera의 정보를 BInfo에 저장
  capGetVideoFormat(hCamera, &stBMPInfo, sizeof(stBMPInfo));

  // 카메라 해상도 셋팅
  stBMPInfo.bmiHeader.biWidth = XSCALE;
  stBMPInfo.bmiHeader.biHeight = YSCALE;

  // BInfo를 hCamera에 저장
  capSetVideoFormat(hCamera, &stBMPInfo, sizeof(stBMPInfo));

  capSetCallbackOnFrame(hCamera, capture);

  // 출력
  capPreview(hCamera, TRUE);

  ReleaseDC(hWnd, hdc);
  return 0;
}

LRESULT On_Destroy(WPARAM wParam, LPARAM lParam)
{
  PostQuitMessage(0);
  return 0;
}

LRESULT capture(HWND hwpWnd, LPVIDEOHDR lpVHdr)
{
  HDC hdc;
  HDC MemDC;
  unsigned int uiCntX;
  unsigned int uiCntY;
  unsigned int uiMaxVal;
  unsigned char cBuf[20];

  static BYTE vData[XSCALE * YSCALE * 3];

  hdc = GetDC(hWnd);

  memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);

  unsigned int uiCnt[256= { 0, };
  unsigned int uiCntR[256= { 0, };
  unsigned int uiCntG[256= { 0, };
  unsigned int uiCntB[256= { 0, };

  /*
  unsigned int uiSumR[256];
  unsigned int uiSumG[256];
  unsigned int uiSumB[256];
  */

  
  for (uiCntY = 0; uiCntY < YSCALE; ++uiCntY)
  {
    for (uiCntX = 0; uiCntX < XSCALE; ++uiCntX)
    {
      // 평활화 1단계
      ++uiCnt[vData[uiCntY * (XSCALE * 3) + uiCntX * 3 + 2]];
      ++uiCnt[vData[uiCntY * (XSCALE * 3) + uiCntX * 3 + 1]];
      ++uiCnt[vData[uiCntY * (XSCALE * 3) + uiCntX * 3 + 0]];
      ++uiCntR[vData[uiCntY * (XSCALE * 3) + uiCntX * 3 + 2]];
      ++uiCntG[vData[uiCntY * (XSCALE * 3) + uiCntX * 3 + 1]];
      ++uiCntB[vData[uiCntY * (XSCALE * 3) + uiCntX * 3 + 0]];
    }
  }

  uiMaxVal = 0;
  for (uiCntX = 0; uiCntX < XGRAPH; ++uiCntX)
  {
    uiCnt[uiCntX] = uiCnt[uiCntX] / 3;
    if (uiMaxVal < uiCnt[uiCntX])
    {
      uiMaxVal = uiCnt[uiCntX];
    }
  }

  for (uiCntX = 0; uiCntX < XGRAPH; ++uiCntX)
  {
    uiCnt[uiCntX] = (uiCnt[uiCntX] * XGRAPH) / uiMaxVal; // 0~255사이의 값을 갖는다. 오차를 줄이기 위해 곱하기를 먼저한다.
    uiCntR[uiCntX] = (uiCntR[uiCntX] * XGRAPH) / uiMaxVal;
    uiCntG[uiCntX] = (uiCntG[uiCntX] * XGRAPH) / uiMaxVal;
    uiCntB[uiCntX] = (uiCntB[uiCntX] * XGRAPH) / uiMaxVal;
  }


  // Everage Histo
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, Histo);

  // PatBlt으로 배경을 흰색으로 바꾼다.
  PatBlt(MemDC, 00, XGRAPH + 1, YGRAPH, WHITENESS);

  for (uiCntY = 0; uiCntY < YGRAPH; ++uiCntY)
  {
    for (uiCntX = 0; uiCntX < XGRAPH; ++uiCntX)
    {
      // y축 draw
      SetPixel(MemDC, 0, uiCntY, RGB(000));

      // y축 높이보다 값이 크면 점을 찍는다.
      if ((YGRAPH - 1 - uiCntY) <= uiCnt[uiCntX])
      {
        SetPixel(MemDC, (uiCntX + 1), uiCntY
          , RGB(((uiCntX - 30>255) ? 0 : (uiCntX - 20))
            , ((uiCntX - 30>255) ? 0 : (uiCntX - 20))
            , ((uiCntX - 30>255) ? 0 : (uiCntX - 20))));
      }
    }
  }
  BitBlt(hdc, XSCALE * 2+20, XGRAPH + 1, YGRAPH, MemDC, 00, SRCCOPY);
  DeleteDC(MemDC);

  // R Histo
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, Histo);

  PatBlt(MemDC, 00, XGRAPH + 1, YGRAPH, WHITENESS);

  for (uiCntY = 0; uiCntY < YGRAPH; ++uiCntY)
  {
    for (uiCntX = 0; uiCntX < XGRAPH; ++uiCntX)
    {
      SetPixel(MemDC, 0, uiCntY, RGB(000));

      if ((YGRAPH - 1 - uiCntY) <= uiCntR[uiCntX])
      {
        SetPixel(MemDC, (uiCntX + 1), uiCntY, RGB(uiCntX, 00));
      }
    }
  }
  BitBlt(hdc, XSCALE * 2 + 6 + XGRAPH, 0, XGRAPH + 1, YGRAPH, MemDC, 00, SRCCOPY);
  DeleteDC(MemDC);

  // G Histo
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, Histo);

  PatBlt(MemDC, 00, XGRAPH + 1, YGRAPH, WHITENESS);
  for (uiCntY = 0; uiCntY < YGRAPH; ++uiCntY)
  {
    for (uiCntX = 0; uiCntX < XGRAPH; ++uiCntX)
    {
      SetPixel(MemDC, 0, uiCntY, RGB(000));

      if ((YGRAPH - 1 - uiCntY) <= uiCntG[uiCntX])
      {
        SetPixel(MemDC, (uiCntX + 1), uiCntY, RGB(0, uiCntX, 0));
      }
    }
  }
  BitBlt(hdc, XSCALE * 2 + 2, YGRAPH+2, XGRAPH + 1, YGRAPH, MemDC, 00, SRCCOPY);
  DeleteDC(MemDC);

  // B Histo
  MemDC = CreateCompatibleDC(hdc);
  SelectObject(MemDC, Histo);

  PatBlt(MemDC, 00, XGRAPH + 1, YGRAPH, WHITENESS);
  for (uiCntY = 0; uiCntY < YGRAPH; ++uiCntY)
  {
    for (uiCntX = 0; uiCntX < XGRAPH; ++uiCntX)
    {
      SetPixel(MemDC, 0, uiCntY, RGB(000));

      if ((YGRAPH - 1 - uiCntY) <= uiCntB[uiCntX])
      {
        SetPixel(MemDC, (uiCntX + 1), uiCntY, RGB(00, uiCntX));
      }
    }
  }
  BitBlt(hdc, XSCALE * 2 + 6 + XGRAPH, YGRAPH+2, XGRAPH + 1, YGRAPH, MemDC, 00, SRCCOPY);
  DeleteDC(MemDC);


  /////////////////////////////////////////////////////////////////////////
  for (uiCntX = 0; uiCntX < XSCALE; uiCntX++)
  {
    for (uiCntY = 0; uiCntY < YSCALE; uiCntY++)
    {
      //*(vData + (uiCntY * XSCALE + uiCntX) * 3 + 0) = 0;  // B
      *(vData + (uiCntY * XSCALE + uiCntX) * 3 + 1= 0;    // G
      *(vData + (uiCntY * XSCALE + uiCntX) * 3 + 2= 0;    // R
    }
  }

  StretchDIBits(hdc
    , XSCALE
    , 0
    , XSCALE
    , YSCALE
    , 0
    , 0
    , XSCALE
    , YSCALE
    , vData
    , &stBMPInfo
    , DIB_RGB_COLORS
    , SRCCOPY);


  /////////////////////////////////////////////////////////////////////////
  memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);

  for (uiCntX = 0; uiCntX < XSCALE; uiCntX++)
  {
    for (uiCntY = 0; uiCntY < YSCALE; uiCntY++)
    {
      *(vData + (uiCntY * XSCALE + uiCntX) * 3 + 0= 0;  // B
      //*(vData + (uiCntY * XSCALE + uiCntX) * 3 + 1) = 0;    // G
      *(vData + (uiCntY * XSCALE + uiCntX) * 3 + 2= 0;    // R
    }
  }

  StretchDIBits(hdc
    , 0
    , YSCALE
    , XSCALE
    , YSCALE
    , 0
    , 0
    , XSCALE
    , YSCALE
    , vData
    , &stBMPInfo
    , DIB_RGB_COLORS
    , SRCCOPY);


  /////////////////////////////////////////////////////////////////////////
  memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);

  for (uiCntX = 0; uiCntX < XSCALE; uiCntX++)
  {
    for (uiCntY = 0; uiCntY < YSCALE; uiCntY++)
    {
      *(vData + (uiCntY * XSCALE + uiCntX) * 3 + 0= 0;  // B
      *(vData + (uiCntY * XSCALE + uiCntX) * 3 + 1= 0;    // G
      //*(vData + (uiCntY * XSCALE + uiCntX) * 3 + 2) = 0;    // R
    }
  }

  StretchDIBits(hdc
    , XSCALE
    , YSCALE
    , XSCALE
    , YSCALE
    , 0
    , 0
    , XSCALE
    , YSCALE
    , vData
    , &stBMPInfo
    , DIB_RGB_COLORS
    , SRCCOPY);


  
  //wsprintf(cBuf, TEXT("[%u]"), lpVHdr->dwBufferLength);
  //SetWindowText(hWnd, cBuf);



  ReleaseDC(hWnd, hdc);
  return 0;
}


■ 알파값 처리

 알파값이란? 색깔을 투명한 색상으로 변경

일기예보 보면...
실제로 캐스터의 배경은 빈화면이다.
방송에서 배경을 비트맵으로 대체시켜 보여주는 것이다.

칠판을 다른색깔로 대체시켜야한다.
그러러면 특정한 칠판 색깔을 찾아내야한다.

칠판에서 가장 많이 분포된 값을 알파값으로 사용한다.

영상처리도 임베디드시스템에서 활용된다.
품질검사 같은 부분. 



▲ GAP 이 10일때 +10 ~ -10의 오차까지 커버한다.

▲ GAP 이 20일때 +20 ~ -20의 오차까지 커버한다.


#ifndef __SMART_H__
#define __SMART_H__

#define XSCALE 320
#define YSCALE 240

#define XGRAPH 256
#define YGRAPH 256

#define MALPHA      177
#define GALPHA      25         // gap
#define HALPHA      (MALPHA + GALPHA)
#define LALPHA      (MALPHA - GALPHA)

#endif    // __SMART_H__

#include <windows.h>
#include <Vfw.h>
#include "smart.h"

//#pragma comment (lib, "vfw32.lib")

typedef struct _stMSG_Map
{
     UINT    uiMSG;
     LRESULT(*fp)( WPARAM, LPARAM);
}stMSG_Map;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT On_Paint(WPARAM , LPARAM );
LRESULT On_Create(WPARAM , LPARAM );
LRESULT On_Destroy(WPARAM , LPARAM );
LRESULT capture(HWND , LPVIDEOHDR );

HWND hWnd;
BITMAPINFO stBMPInfo;
HINSTANCE g_hInst;

static HBITMAP hBack;

BITMAPFILEHEADER stBFHead;
BITMAPINFOHEADER stBFInfo;

unsigned int uiPad;
static BYTE BData[XSCALE * YSCALE * 3];

LPSTR lpszClass = TEXT ("영상처리" );

stMSG_Map stMap[] = {
     { WM_PAINT, On_Paint },
     { WM_CREATE, On_Create },
     { WM_DESTROY, On_Destroy },
     { WM_NULL, 0 }
};


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_OVERLAPPEDWINDOW,
           CW_USEDEFAULT, CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT,
           NULL, ( HMENU) NULL, hInstance, NULL );
     ShowWindow(hWnd, nCmdShow);

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

LRESULT CALLBACK WndProc(HWND hwpWnd, UINT iMessage, WPARAM wParam , LPARAM lParam )
{
     hWnd = hwpWnd;
     stMSG_Map * stpMap = stMap;

     while (WM_NULL != ((*stpMap).uiMSG))
     {
           if ( iMessage == ((*stpMap).uiMSG))
          {
               return (((*stpMap).fp)( wParam, lParam));
          }
          ++stpMap;
     }

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

LRESULT On_Paint(WPARAM wParam , LPARAM lParam )
{
     HDC hdc;
     PAINTSTRUCT ps;
     hdc = BeginPaint(hWnd, &ps);
     EndPaint(hWnd, &ps);
     return 0;
}

LRESULT On_Create(WPARAM wParam , LPARAM lParam )
{
     HDC hdc;
     HWND hCamera;
     BOOL bRet;

     HANDLE hFile;
     DWORD dwCnt;

     hdc = GetDC(hWnd);

     hBack = CreateCompatibleBitmap(hdc, XSCALE, YSCALE);      // 비트맵을 생성

     // 화면을 띄울 창 마련
     hCamera = capCreateCaptureWindow(TEXT ("smart" ), WS_CHILD | WS_VISIBLE , 0, 0, XSCALE , YSCALE , hWnd, 0);
     if (NULL == hCamera)
     {
           MessageBox(hWnd, TEXT ("윈도우를 생성할 수 없습니다"), TEXT("에러"), MB_OK);
          PostQuitMessage(0);
     }

     // 카메라와 연결 2번째 인자는 장착된 카메라 갯수번호
     bRet = capDriverConnect(hCamera, 0);
     if (FALSE == bRet)
     {
           MessageBox(hWnd, TEXT ("카메라를 연결할 수 없습니다"), TEXT("에러"), MB_OK);
          PostQuitMessage(0);
     }

     // 화면에 보이는 속도
     capPreviewRate(hCamera, 1);

     // hCamera의 정보를 BInfo에 저장
     capGetVideoFormat(hCamera, &stBMPInfo, sizeof(stBMPInfo));

     // 카메라 해상도 셋팅
     stBMPInfo.bmiHeader.biWidth = XSCALE;
     stBMPInfo.bmiHeader.biHeight = YSCALE;

     // BInfo를 hCamera에 저장
     capSetVideoFormat(hCamera, &stBMPInfo, sizeof(stBMPInfo));

     capSetCallbackOnFrame(hCamera, capture);

     // 출력
     capPreview(hCamera, TRUE);

     hFile = CreateFile(TEXT ("s.bmp" )
          , GENERIC_READ
          , 0
          , NULL
          , OPEN_EXISTING
          , FILE_ATTRIBUTE_NORMAL
          , NULL);

     if (INVALID_HANDLE_VALUE == hFile)
     {
           MessageBox(hWnd, TEXT ("파일을 열 수 없습니다." ), TEXT("에러" ), MB_OK );
          PostQuitMessage(0);
     }

     bRet = ReadFile(hFile, &stBFHead, sizeof(stBFHead), &dwCnt, NULL);
     if (FALSE == bRet)
     {
           MessageBox(hWnd, TEXT ("파일헤더를 열 수 없습니다."), TEXT( "에러"), MB_OK );
          CloseHandle(hFile);
          PostQuitMessage(0);
     }

     uiPad = (stBFInfo.biWidth % 4);

     bRet = ReadFile(hFile, &stBFInfo, sizeof(stBFInfo), &dwCnt, NULL);
     if (FALSE == bRet)
     {
           MessageBox(hWnd, TEXT ("인포헤더를 열 수 없습니다."), TEXT( "에러"), MB_OK );
          CloseHandle(hFile);
          PostQuitMessage(0);
     }

     if (stBFInfo.biWidth!= XSCALE)
     {
           MessageBox(hWnd, TEXT ("가로가 320픽셀이 아닙니다."), TEXT( "에러"), MB_OK );
          CloseHandle(hFile);
          PostQuitMessage(0);
     }

     if (stBFInfo.biHeight!= YSCALE)
     {
           MessageBox(hWnd, TEXT ("세로가 240픽셀이 아닙니다."), TEXT( "에러"), MB_OK );
          CloseHandle(hFile);
          PostQuitMessage(0);
     }

     _llseek(hFile, stBFHead.bfOffBits, SEEK_SET);
     bRet = ReadFile(hFile, BData, stBFInfo.biSizeImage, &dwCnt, NULL);
     if (FALSE == bRet)
     {
           MessageBox(hWnd, TEXT ("데이터 Read 실패" ), TEXT("에러" ), MB_OK );
          CloseHandle(hFile);
          PostQuitMessage(0);
     }

     CloseHandle(hFile);
     ReleaseDC(hWnd, hdc);
     return 0;
}

LRESULT On_Destroy(WPARAM wParam , LPARAM lParam )
{
     PostQuitMessage(0);
     return 0;
}

LRESULT capture(HWND hwpWnd , LPVIDEOHDR lpVHdr )
{
     HDC hdc;
     unsigned int uiCntX;
     unsigned int uiCntY;
     unsigned char cBuf[20];
     int iCal;
     PAINTSTRUCT ps;

     static BYTE vData[XSCALE * YSCALE * 3];
     
     hdc = GetDC(hWnd);
     //memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength);

     for (uiCntY = 0; uiCntY < YSCALE; uiCntY++)
     {
           for (uiCntX = 0; uiCntX < XSCALE; uiCntX++)
          {
              iCal = (uiCntY * XSCALE * 3) + (uiCntX * 3);
              vData[iCal + 0] = *(( lpVHdr->lpData) + iCal + 0);
              vData[iCal + 1] = *(( lpVHdr->lpData) + iCal + 1);
              vData[iCal + 2] = *(( lpVHdr->lpData) + iCal + 2);

               if ( HALPHA < vData[iCal + 0])
              {
                    continue;
              }
               if ( LALPHA > vData[iCal + 0])
              {
                    continue;
              }
               if ( HALPHA < vData[iCal + 1])
              {
                    continue;
              }
               if ( LALPHA > vData[iCal + 1])
              {
                    continue;
              }
               if ( HALPHA < vData[iCal + 2])
              {
                    continue;
              }
               if ( LALPHA > vData[iCal + 2])
              {
                    continue;
              }
              vData[iCal + 0] = BData[iCal + 0];
              vData[iCal + 1] = BData[iCal + 1];
              vData[iCal + 2] = BData[iCal + 2];
          }
     }

     StretchDIBits(hdc
          , XSCALE
          , 0
          , XSCALE
          , YSCALE
          , 0
          , 0
          , XSCALE
          , YSCALE
          , vData
          , &stBMPInfo
          , DIB_RGB_COLORS
          , SRCCOPY);

     ReleaseDC(hWnd, hdc);
     return 0;
}


728x90