yspngで画像を表示します。
ysflight.com
http://ysflight.in.coocan.jp/
PNG Encoder / Decoder in C++
http://ysflight.in.coocan.jp/programming/pngdecoder/pngdecoderj.html
にある、yspng.zip をダウンロードします。
yspngはフリーソフトでも商用ソフトでも作者様に連絡しなくても使用できるようです。
オープンソースでもプロプライエタリ(クローズド)でも自由に使用できるようです。
出展の記述なども要らないそうです。素晴らしいですね。
プロジェクトに yspng.cpp と yspng.h を追加して下記のコードを入力すると
yspngでPNG画像を表示する事ができます。
ファイル |
main.cpp |
yspng.cpp |
yspng.h |
resource.h |
|
resource.h
#define ID_STATUS 100 |
main.cpp
#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib, "comctl32.lib")
#include <GL/freeglut/freeglut.h>
#include <windows.h>
#include <stdio.h>
#include <commctrl.h> //CreateStatusWindow()のために必要
#include "yspng.h"
#include "resource.h"
#define WIDTH 640
#define HEIGHT 480
//FreeGlutのウインドウプロシージャを置き換える為の変数
WNDPROC WndProc = NULL; //元のウィンドウプロシージャ
HWND hWnd2 = NULL; //ウィンドウハンドル
HMENU hMenu = NULL; //メニュー
HWND hStatusbar; // ステータスバーのハンドル
static void LoadPng(const char fn[]);
static HWND hWnd = NULL;
static HDC bmpDc = NULL;
static HBITMAP hBmp = NULL;
static int bmpWid, bmpHei;
static void LoadPng(const char fn[])
{
YsRawPngDecoder pngDecoder;
pngDecoder.Initialize();
if (pngDecoder.Decode(fn) ==
YSOK)
{
BITMAPINFOHEADER bmiHeader;
void* bitBuf;
if (bmpDc == NULL)
{
bmpDc =
CreateCompatibleDC(GetDC(hWnd));
}
if (hBmp != NULL)
{
DeleteObject(hBmp);
hBmp = NULL;
}
bmpWid = (pngDecoder.wid + 3) &
(~3);
bmpHei = pngDecoder.hei;
bmiHeader.biSize =
sizeof(bmiHeader);
bmiHeader.biWidth = bmpWid;
bmiHeader.biHeight =
-bmpHei;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 24;
bmiHeader.biCompression =
BI_RGB;
bmiHeader.biSizeImage = 0;
bmiHeader.biXPelsPerMeter =
2048;
bmiHeader.biYPelsPerMeter =
2048;
bmiHeader.biClrUsed = 0;
bmiHeader.biClrImportant =
0;
hBmp = CreateDIBSection(bmpDc,
(BITMAPINFO*)&bmiHeader, DIB_RGB_COLORS, &bitBuf, NULL,
0);
int x, y;
unsigned char* buf;
buf = (unsigned
char*)bitBuf;
for (y = 0; y < bmpHei;
y++)
{
for (x = 0; x < bmpWid;
x++)
{
const unsigned char* rgba;
if (x < pngDecoder.wid)
{
rgba = pngDecoder.rgba + (y *
pngDecoder.wid + x) * 4;
}
else
{
rgba = pngDecoder.rgba + (y *
pngDecoder.wid + pngDecoder.wid - 1) * 4;
}
buf[(y * bmpWid + x) * 3] =
rgba[2];
buf[(y * bmpWid + x) * 3 + 1] =
rgba[1];
buf[(y * bmpWid + x) * 3 + 2] =
rgba[0];
}
}
InvalidateRect(hWnd, NULL,
FALSE);
}
}
//置き換えた後のプロシージャ
LRESULT CALLBACK WndProc2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
lParam) {
HDC hdc;
switch (msg) {
case WM_PAINT:
hdc = GetDC(hWnd);
if (bmpDc != NULL && hBmp !=
NULL)
{
HBITMAP hBmpSave;
RECT rect;
hBmpSave = (HBITMAP)SelectObject(bmpDc,
hBmp);
GetClientRect(hWnd,
&rect);
BitBlt(hdc, 0, 0, bmpWid, bmpHei, bmpDc,
0, 0, SRCCOPY);
SelectObject(bmpDc,
hBmpSave);
}
ReleaseDC(hWnd, hdc);
break;
case WM_SIZE:
SendMessage(hStatusbar, WM_SIZE, wParam,
lParam);
break;
case WM_COMMAND:
break;
case WM_DESTROY:
exit(0);
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
default:
if (WndProc) {
return CallWindowProc(WndProc, hWnd,
msg, wParam, lParam);
}
else {
return DefWindowProc(hWnd, msg, wParam,
lParam);
}
}
return 0;
}
//ウィンドウの検索
BOOL CALLBACK enumWindowsProc(HWND hWnd, LPARAM lParam) {
HANDLE hModule =
(__int64*)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
if (GetModuleHandle(NULL) == hModule)
{
wchar_t ClassName[256];
GetClassNameW(hWnd, ClassName,
sizeof(ClassName) / sizeof(ClassName[0]));
if (wcsncmp(ClassName, L"FREEGLUT",
wcslen(ClassName)) == 0) {
hWnd2 = hWnd;
return FALSE;
}
}
return TRUE;
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0.0, WIDTH, HEIGHT, 0.0, -1.0,
1.0);
glutSwapBuffers();
}
void idle(void)
{
glutPostRedisplay();
}
void Init() {
glClearColor(0.0, 0.0, 0.0,
1.0);
glOrtho(0, WIDTH, HEIGHT, 0, -1,
1);
LoadPng("maptip.png");
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitWindowPosition(100,
100);
glutInitWindowSize(WIDTH,
HEIGHT);
glutInitDisplayMode(GLUT_RGBA |
GLUT_DOUBLE);
glutCreateWindow("yspngで画像を表示する");
//FreeGlutのウインドウハンドルとウインドウプロシージャを置き換える
EnumWindows(enumWindowsProc,
0);
if (hWnd2) {
WndProc =
(WNDPROC)GetWindowLongPtrW(hWnd2, GWLP_WNDPROC);
SetWindowLongPtrW(hWnd2, GWLP_WNDPROC,
(LRESULT)WndProc2);
}
else {
return false;
}
// コモンコントロール関係の初期化
InitCommonControls();
// ステータスバーを作成
hStatusbar =
CreateStatusWindowW(WS_CHILD | WS_VISIBLE | CCS_BOTTOM |
SBARS_SIZEGRIP,
L"yspngで画像を表示しています。", hWnd2,
ID_STATUS);
glutDisplayFunc(display);
glutIdleFunc(idle);
Init();
glutMainLoop();
return 0;
}
|