CG関係のプログラミングをやってるとコードから画像を作成して内容を確認したいといった時がある。PPMで出力して確認していたが何かと面倒だし、だからといってOpenGLでテクスチャに表示するのはさらに面倒なので確認用のウィンドウを作成したい。前回作ったウィンドウ表示用のクラスに、画像表示機能を付ける
#pragma once #include "gwindbg.hpp" #include <mutex>
//! @brief DIBを扱う struct DIBData { BITMAPINFO m_bmpInfo; //!< CreateDIBSectionに渡す構造体 LPDWORD m_lpPixel; //!< 画素へのポインタ HBITMAP m_hBitmap; //!< 作成したMDCのビットマップハンドル HDC m_hMemDC; //!< 作成したMDCのハンドル int m_imagesizemax; //!< 合計画素数(width*height) int m_width; //!< 画像の幅(ピクセル,自然数) int m_height; //!< 画像の高さ(ピクセル,自然数) int m_bitcount; DIBData() { DeleteDC(m_hMemDC); DeleteObject(m_hBitmap); } ~DIBData() { m_hBitmap = nullptr; m_hMemDC = nullptr; m_lpPixel = nullptr; m_width = 0; m_height = 0; m_bitcount = 0; } void create(int width, int height, int bitcount) { if (width != m_width || height != m_height) { if (m_hBitmap) { DeleteObject(m_hBitmap); m_hBitmap = nullptr; } if (m_hMemDC) { DeleteDC(m_hMemDC); m_hMemDC = nullptr; } //DIBの情報を設定する m_bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); m_bmpInfo.bmiHeader.biWidth = width; m_bmpInfo.bmiHeader.biHeight = -height; //-を指定しないと上下逆になる m_bmpInfo.bmiHeader.biPlanes = 1; m_bmpInfo.bmiHeader.biBitCount = bitcount; m_bmpInfo.bmiHeader.biCompression = BI_RGB; HDC hdc = GetDC(nullptr); m_hBitmap = CreateDIBSection(hdc, &m_bmpInfo, DIB_RGB_COLORS, (void**)&m_lpPixel, nullptr, 0); m_hMemDC = CreateCompatibleDC(hdc); SelectObject(m_hMemDC, m_hBitmap); ReleaseDC(nullptr, hdc); m_width = width; m_height = height; m_bitcount = bitcount; } } };
class CRGBViewWindow : public GraphicDebugWindow { DIBData dibdata; //! @brief 表示倍率 int m_magnification; std::mutex m_mainmuitex; public: CRGBViewWindow() { }
//! @brief 画像表示関数 //! @param [in] width 画像幅 //! @param [in] height 画像高さ //! @param [in] magnification 表示倍率。小さすぎる画像を大きく表示できる //! @param [in] p 画像データ。RGBRGBRGB... //! @return なし void display(int width, int height, int magnification, unsigned char* p) { m_magnification = magnification; int pixelcount = 3; m_mainmuitex.lock(); dibdata.create(width, height, 24); if (p) {// 画像を仮想スクリーンへコピー for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { int pos = (y * width + x)*pixelcount; SetPixel(dibdata.m_hMemDC, x, y, RGB(p[pos + 0], p[pos + 1], p[pos + 2])); } } } m_mainmuitex.unlock(); }
virtual LRESULT WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)override { PAINTSTRUCT ps; HDC hdc; switch (msg) { case WM_SIZING: InvalidateRect(hWnd, nullptr, TRUE); break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); m_mainmuitex.lock();
//DIBの内容をウィンドウに表示
if (dibdata.m_hMemDC) { StretchBlt( hdc, 0, 0, dibdata.m_width * m_magnification, dibdata.m_height * m_magnification, dibdata.m_hMemDC, 0, 0, dibdata.m_width, dibdata.m_height, SRCCOPY); }
m_mainmuitex.unlock(); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wp, lp); }
};
#include <iostream> #include<vector> #include "CRGBViewWindow.hpp" #pragma warning(disable:4996) int main() { CRGBViewWindow gw; gw.open(TEXT("2×2×RGB画像を表示"), 100, 100, 300, 300); typedef unsigned char rgb_t[3]; rgb_t texdata[2*3]; texdata[0][0] = 0; texdata[0][1] = 255; texdata[0][2] = 0; texdata[1][0] = 255; texdata[1][1] = 0; texdata[1][2] = 0; texdata[2][0] = 255; texdata[2][1] = 0; texdata[2][2] = 0; texdata[3][0] = 0; texdata[3][1] = 255; texdata[3][2] = 0; texdata[4][0] = 0; texdata[4][1] = 255; texdata[4][2] = 0; texdata[5][0] = 255; texdata[5][1] = 0; texdata[5][2] = 0; gw.display(2, 3, 50, &texdata[0][0]); gw.join(); }