SkBitmapは、SetPixels関数を使うと書き込む先のメモリを自分で管理している者に設定することができる。
以下はWin32APIのDIBSectionを指定してSkia経由で描画した例。
// Skiaがminmaxを使用するので、Windowsと一緒に使う場合はNOMINMAXを定義 #define NOMINMAX #include <Windows.h> #include <tchar.h> // skia #include "include/core/SkCanvas.h" #include "include/core/SkBitmap.h"
// DIB Sectionに設定するピクセルの構造体 struct rgbu_t { unsigned char b; unsigned char g; unsigned char r; unsigned char u;// unused rgbu_t(unsigned char R, unsigned char G, unsigned char B) :b(B), g(G), r(R) {} static const rgbu_t White; static const rgbu_t Black; }; // DIBSectionを作成する関数 void createDIBsection32( HBITMAP* hBitmap, HDC* hMemDC, BITMAPINFO* bmpInfo, rgbu_t** m_lpPixel, LONG width, LONG height) { //DIBの情報を設定する bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo->bmiHeader.biWidth = width; bmpInfo->bmiHeader.biHeight = -height; //-を指定しないと上下逆になる bmpInfo->bmiHeader.biPlanes = 1; bmpInfo->bmiHeader.biBitCount = 32; bmpInfo->bmiHeader.biCompression = BI_RGB; HDC hdc = CreateDC(_T("DISPLAY"), 0, 0, 0); *hBitmap = CreateDIBSection(hdc, bmpInfo, DIB_RGB_COLORS, (void**)m_lpPixel, NULL, 0); *hMemDC = CreateCompatibleDC(hdc); DeleteDC(hdc); SelectObject(*hMemDC, *hBitmap); } // DIBSectionを削除する関数 void deleteDIBsection32(HDC hMemDC, HBITMAP hBitmap) { DeleteDC(hMemDC); DeleteObject(hBitmap); } // DIBSectionの情報 HBITMAP dib_hBitmap; HDC dib_hMemDC; BITMAPINFO dib_bmpInfo; rgbu_t* dib_lpPixel;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { HDC hdc; RECT rect; static int width; static int height; static SkBitmap skbitmap; switch (msg) { case WM_CREATE: GetClientRect(hwnd, &rect); //DIB Sectionを作成(32Bit) createDIBsection32( &dib_hBitmap, &dib_hMemDC, &dib_bmpInfo, &dib_lpPixel, rect.right, rect.bottom ); width = rect.right; height = rect.bottom; // dib_lpPixel 経由でDIBSectionを赤で塗りつぶす for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { dib_lpPixel[y * width + x] = rgbu_t(0, 0, 255); } }
{ skbitmap.setInfo(SkImageInfo::MakeN32Premul(width, height)); // SkiaのBitmapにDIBSectionの情報を設定 skbitmap.setPixels(dib_lpPixel); SkCanvas canvas(skbitmap); // 図形の描画 SkPaint paint; paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(5); paint.setColor(SK_ColorRED); canvas.drawCircle(200, 200, 100, paint); }
break; case WM_PAINT: { // 画像を表示 PAINTSTRUCT ps; HDC hDC = BeginPaint(hwnd, &ps); BitBlt(hDC, 0, 0, width, height, dib_hMemDC, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); break; } case WM_DESTROY: deleteDIBsection32(dib_hMemDC, dib_hBitmap); PostQuitMessage(0); return 0; case WM_LBUTTONDOWN: hdc = GetDC(hwnd); ReleaseDC(hwnd, hdc); return 0; } return DefWindowProc(hwnd, msg, wp, lp); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { HWND hwnd; WNDCLASS winc; MSG msg; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL, IDI_APPLICATION); winc.hCursor = LoadCursor(NULL, IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("SZL_WINDOW"); if (!RegisterClass(&winc)) return 0; hwnd = CreateWindow( TEXT("SZL_WINDOW"), TEXT("szl window"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 600, 400, NULL, NULL, hInstance, NULL ); if (hwnd == NULL) return 0; while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg); return msg.wParam; }