wagashi1349のブログ

気になったことを色々と

Javaで組み合わせ(Combination)

用意されてる言語もあるけど、これくらい書けたほうがいいよねってことでメモがてら。
組み合わせの場合は同じ要素を見なくて良いので、再帰で渡してるindexを+1してる。
第二引数に1以下を渡すとバグるけど無視でw

実行結果
[[a, b, c], [a, b, d], [a, c, d], [b, c, d]]

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

public class Test {
    public static void main(String[] args) {
        List list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        List ret = combination(list, 3);
        System.out.println(ret);
    }

    public static List<List<String>> combination(List list, int count) {
        List ret = new ArrayList<List<String>>();
        for (int i = 0; i < list.size(); i++) {
            if (i + count > list.size()) {
                break;
            }
            Stack stack = new Stack<String>();
            stack.push(list.get(i));
            _combination(ret, list, stack, i + 1, count);
        }
        return ret;
    }

    private static void _combination(List ret, List list, Stack stack, int index, int count) {
        for (int i = index; i < list.size(); i++) {
            stack.push(list.get(i));
            if (stack.size() == count) {
                ret.add(Arrays.asList(stack.toArray()));
                stack.pop();
                continue;
            }
            _combination(ret, list, stack, i + 1, count);
            stack.pop();
        }
    }
}

Microsoft Band ファーストインプレッション

f:id:wagashi1349:20141107210017j:plain:w300

MSからもフィットネス用のバンド(以下MSBand)が出たので買ってみた。
自分はJawbone UP、Fitbit Flex、Fitbit Force、FuenBand SEを今まで使っている。
MSBandは60gと他の比べるとちょっと重たい印象を持ったけど付けてる分には
あんまり違いが判らない。一回りごついのでそっちの方が気になるかも…。
防水ではないがある程度の水しぶきには対応出来てるらしい。
ちなみに付けたままシャワーは大丈夫だった。

物理キーは二つ。電源と各項目の切り替え。
メイン画面は切り替えボタンで日付、カロリー、歩数、移動距離、心拍数が切り替えられる。
f:id:wagashi1349:20141108223926j:plain:w200 f:id:wagashi1349:20141108224103j:plain:w200


個人的にすごく気に入ったのがWatch Mode。通常だとディスプレイは電源ボタンを入れないと
表示されないけど、このように時計だけ表示されて暗闇でも見える。
f:id:wagashi1349:20141108173504j:plain:w200

天気も一週間分表示可能。Phone側と同期してるみたいで、Phoneの場所の天気が表示されるっぽい。
f:id:wagashi1349:20141108214537j:plain:w200 f:id:wagashi1349:20141108214459j:plain:w200

一日使った印象だとランニングに特化した作りかな?と思った。
1km走るごとにバイブでタイムを知らせてくれる。
タイマーやストップウォッチもあるので人によっては便利かも。

使用手順

Bluetoothでペアリングして使うのでまずはアプリをダウンロード。
Windows Phone/Android/iOSから利用出来るが、今回はWindows Phoneを使用。
個人的にはタイルの背景は透明の方がいいなー。
f:id:wagashi1349:20141109174817p:plain:w200 f:id:wagashi1349:20141109174812p:plain:w200


アプリを起動すると身長やら体重やらを入力、んでMSBandとペアリング。

f:id:wagashi1349:20141109174748p:plain:w200
f:id:wagashi1349:20141107224515j:plain:w300

背景やカラー、表示するタイルはアプリ側から設定できる。
f:id:wagashi1349:20141109174802p:plain:w200 f:id:wagashi1349:20141109174804p:plain:w200 f:id:wagashi1349:20141109174806p:plain:w200


見慣れたタイルも。
f:id:wagashi1349:20141107232427j:plain:w300

ちょっと走ってみた

柏市にある柏の葉公園一周(約3km)を軽く走ってきた。バスケ後だったのできついw
Windows Phoneユーザお馴染みのマップですなw これが改善されないと日本では出ないでしょう。
f:id:wagashi1349:20141109174810p:plain:w200 f:id:wagashi1349:20141109174808p:plain:w200


一日使った感じだと割といいかな?と思った。バッテリーは48時間みたいなのでほぼ毎日充電が
必要だけど80%まではすぐ充電できる。アラームは1個しか設定できないのは残念。
Phoneと同期取れればいいと思う。1週間経ったらまた何か書いてみようと思う。

Kinect v2で画像を操作する

使い方を兼ねてメモ。

左手を挙げて開いた状態から手を閉じて手前に持ってくるとズーム。

右手を挙げて開いた状態から人差し指を立てて動かすと画像スクロール。

再度手を開くと操作が止まる。

結構長いソースそのまま張り付けるけど気にしない。

f:id:wagashi1349:20140814003459p:plain

#include<stdio.h>
#include<windows.h>
#include<wincodec.h>
#include<d2d1.h>
#include<Kinect.h>

#ifndef _DEBUG
#define OutputDebugStringA(x) ((void)0)
#define OutputDebugStringW(x) ((void)0)
#endif

HWND hWnd;
RECT rect;
ID2D1Factory *factory = nullptr;
ID2D1HwndRenderTarget *target = nullptr;
ID2D1Bitmap *bitmap = nullptr;
ID2D1Bitmap *bgBitmap = nullptr;
IWICImagingFactory *wicFactory = nullptr;

IKinectSensor *sensor = nullptr;
IBodyIndexFrameSource *bodyIndexFrameSource = nullptr;
IBodyIndexFrameReader* bodyIndexFrameReader = nullptr;
IBodyFrameSource *bodyFrameSource = nullptr;
IBodyFrameReader *bodyFrameReader = nullptr;
ICoordinateMapper *coordinateMapper = nullptr;

ID2D1SolidColorBrush *brush = nullptr;

Joint joints[JointType_Count];
D2D1_POINT_2F jointPoints[JointType_Count];
D2D1_POINT_2F point = { 0, 0 };
D2D1_ELLIPSE ellipse = D2D1::Ellipse(point, 6, 6);

char buf[256];
UINT32 mem[512 * 424];
HRESULT hr;
HandState leftHandState[3] = { HandState::HandState_Unknown};
HandState rightHandState[3] = { HandState::HandState_Unknown };
int scrollState = 0;
int zoomState = 0;
int baseX = 0;
int baseY = 0;
float baseZ = 0;
int scrollBaseX = 0;
int scrollBaseY = 0;
float zoomBaseZ = 0;

float x, y, z = 0.0f;
D2D1_RECT_F d2dSrcRect, d2dDestRect, d2dBodyRect;


template<class Interface>
inline void SafeRelease(
	Interface **ppInterfaceToRelease
	)
{
	if (*ppInterfaceToRelease != NULL)
	{
		(*ppInterfaceToRelease)->Release();

		(*ppInterfaceToRelease) = NULL;
	}
}

D2D1_POINT_2F BodyToScreen(const CameraSpacePoint& bodyPoint, int width, int height){
	DepthSpacePoint depthPoint = { 0 };
	coordinateMapper->MapCameraPointToDepthSpace(bodyPoint, &depthPoint);

	float screenPointX = depthPoint.X;// static_cast<float>(depthPoint.X * width) / 512;
	float screenPointY = depthPoint.Y;// static_cast<float>(depthPoint.Y * height) / 424;

	return D2D1::Point2F(screenPointX, screenPointY);
}

void SafeRelease() {
	SafeRelease(&brush);

	SafeRelease(&coordinateMapper);
	SafeRelease(&bodyIndexFrameReader);
	SafeRelease(&bodyIndexFrameSource);
	SafeRelease(&bodyFrameReader);
	SafeRelease(&bodyFrameSource);
	SafeRelease(&sensor);
	SafeRelease(&bgBitmap);
	SafeRelease(&bitmap);
	SafeRelease(&target);
	SafeRelease(&wicFactory);
	SafeRelease(&factory);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
	MSG msg = { 0 };
	int screen_width = GetSystemMetrics(SM_CXSCREEN);
	int screen_height = GetSystemMetrics(SM_CYSCREEN);

	hr = CoInitialize(NULL);
	if (FAILED(hr)) {
		OutputDebugString("CoInitialize");
		return -1;
	}

	hr = GetDefaultKinectSensor(&sensor);
	if (FAILED(hr) || !sensor) {
		OutputDebugString("Failed GetDefaultKinectSensor()");
		return -1;
	}

	hr = sensor->Open();
	if (FAILED(hr)) {
		OutputDebugString("Failed sensor->Open()");
		return -1;
	}

	hr = sensor->get_BodyFrameSource(&bodyFrameSource);
	if (FAILED(hr)) {
		OutputDebugString("Failed get_BodyFrameSource()");
		return -1;
	}

	hr = bodyFrameSource->OpenReader(&bodyFrameReader);
	if (FAILED(hr)){
		OutputDebugString("Failed OpenReader()");
		return -1;
	}

	hr = sensor->get_CoordinateMapper(&coordinateMapper);
	if (FAILED(hr)) {
		OutputDebugString("Failed get_CoordinateMapper()");
		return -1;
	}

	hr = sensor->get_BodyIndexFrameSource(&bodyIndexFrameSource);
	if (FAILED(hr)){
		OutputDebugString("Failed get_BodyIndexFrameSource()");
		return -1;
	}

	hr = bodyIndexFrameSource->OpenReader(&bodyIndexFrameReader);
	if (FAILED(hr)){
		OutputDebugString("Failed OpenReader()");
		return -1;
	}

	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
	if (FAILED(hr)) {
		OutputDebugString("Failed D2D1CreateFactory()");
		return -1;
	}

	hr = CoCreateInstance(
		CLSID_WICImagingFactory,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IWICImagingFactory,
		reinterpret_cast<void **>(&wicFactory)
		);

	if (FAILED(hr)) {
		OutputDebugString("Failed CoCreateInstance()");
		SafeRelease();
		return -1;
	}

	WNDCLASSEX wc;
	wc.hInstance = hInst;
	wc.lpszClassName = "Kinect Sample";
	wc.lpfnWndProc = WndProc;
	wc.style = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInst, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

	if (!RegisterClassEx(&wc))
		return -1;

	hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		wc.lpszClassName,
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE,
		(screen_width - 640) >> 1,
		(screen_height - 480) >> 1,
		640,
		480,
		NULL,
		NULL,
		hInst,
		NULL);

	ShowWindow(hWnd, nWinMode);
	UpdateWindow(hWnd);

	while (WM_QUIT != msg.message){
		while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)){
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	CoUninitialize();
	return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	switch (message){
		case WM_SIZE:
			if (target){
				GetClientRect(hWnd, &rect);
				d2dDestRect.top = rect.top;
				d2dDestRect.left = rect.left;
				d2dDestRect.bottom = rect.bottom;
				d2dDestRect.right = rect.right;
				x = (1920 - rect.right - rect.left) >> 1;
				y = (1200 - rect.bottom - rect.top) >> 1;
				target->Resize(D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top));
				d2dBodyRect.left = ((rect.right - rect.left) >> 1) - 256;
				d2dBodyRect.right = d2dBodyRect.left + 512;
				d2dBodyRect.top = rect.bottom - rect.top - 424;
				d2dBodyRect.bottom = d2dBodyRect.top + 424;
			}
		case WM_PAINT:
			if (!target){
				D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
				GetClientRect(hWnd, &rect);
				factory->CreateHwndRenderTarget(
					D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, pixelFormat),
					D2D1::HwndRenderTargetProperties(
						hWnd,
						D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top)),
					&target);

				IWICBitmapDecoder *decoder = nullptr;
				IWICBitmapFrameDecode *source = nullptr;
				IWICFormatConverter *converter = nullptr;

				hr = wicFactory->CreateDecoderFromFilename(
					L"bg.jpg",
					NULL,
					GENERIC_READ,
					WICDecodeMetadataCacheOnLoad,
					&decoder);

				if (FAILED(hr)) {
					OutputDebugString("Failed CreateDecoderFromFilename()");
					SafeRelease();
					return -1;
				}

				hr = decoder->GetFrame(0, &source);
				if (FAILED(hr)) {
					OutputDebugString("Failed GetFrame()");
					SafeRelease();
					return -1;
				}

				hr = wicFactory->CreateFormatConverter(&converter);
				if (FAILED(hr)) {
					OutputDebugString("Failed CreateFormatConverter()");
					SafeRelease();
					return -1;
				}

				hr = converter->Initialize(
					source,
					GUID_WICPixelFormat32bppPBGRA,
					WICBitmapDitherTypeNone,
					NULL,
					0.f,
					WICBitmapPaletteTypeMedianCut
					);

				if (FAILED(hr)) {
					OutputDebugString("Failed Initialize()");
					SafeRelease();
					return -1;
				}

				hr = target->CreateBitmapFromWicBitmap(
					converter,
					NULL,
					&bgBitmap
					);

				if (FAILED(hr)) {
					OutputDebugString("Failed CreateBitmapFromWicBitmap()");
					SafeRelease();
					return -1;
				}

				SafeRelease(&converter);
				SafeRelease(&source);
				SafeRelease(&decoder);

				for (int i = 0; i < 512 * 424; i++) {
					mem[i] = 0;
				}
				target->CreateBitmap(D2D1::SizeU(512, 424), D2D1::BitmapProperties(pixelFormat), &bitmap);

				target->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::PaleGreen, 0.6f), &brush);
			}

			if (target){
				IBodyIndexFrame* bodyIndexFrame = nullptr;
				hr = bodyIndexFrameReader->AcquireLatestFrame(&bodyIndexFrame);
				if (SUCCEEDED(hr)) {
					unsigned int bufferSize = 0;
					unsigned char* buffer = nullptr;
					hr = bodyIndexFrame->AccessUnderlyingBuffer(&bufferSize, &buffer);
					if (SUCCEEDED(hr)) {
						for (int i = 0; i < 512 * 424; i++) {
							if (buffer[i] == 0xFF)
								mem[i] = 0;
							else
								mem[i] = 0xFF0000FF;
						}
					}
				}
				SafeRelease(&bodyIndexFrame);
				d2dSrcRect.left = x + (z * 1.92f);
				d2dSrcRect.top = y + (z * 1.20f);
				d2dSrcRect.right = x + d2dDestRect.right - (z * 1.92f);
				d2dSrcRect.bottom = y + d2dDestRect.bottom - (z * 1.20f);

				IBodyFrame *bodyFrame = nullptr;
				hr = bodyFrameReader->AcquireLatestFrame(&bodyFrame);
				if (SUCCEEDED(hr)) {
					IBody *body[BODY_COUNT] = { 0 };
					hr = bodyFrame->GetAndRefreshBodyData(BODY_COUNT, body);
					if (SUCCEEDED(hr)){
						BOOLEAN tracked;
						for (int i = 0; i < BODY_COUNT; i++){
							tracked = false;
							hr = body[i]->get_IsTracked(&tracked);
							if (SUCCEEDED(hr) && tracked) {

								hr = body[i]->GetJoints(_countof(joints), joints);
								if (SUCCEEDED(hr)) {
									for (int j = 0; j < _countof(joints); ++j) {
										jointPoints[j] = BodyToScreen(joints[j].Position, rect.right, rect.bottom);
									}

									//右手
									if (scrollState == 1 || jointPoints[JointType_ShoulderRight].y > jointPoints[JointType_HandRight].y){
										hr = body[i]->get_HandRightState(&rightHandState[2]);
										if (SUCCEEDED(hr)) {
											rightHandState[1] = rightHandState[0];
											rightHandState[0] = rightHandState[2];
											if (rightHandState[1] == HandState::HandState_Open && (rightHandState[0] == HandState::HandState_Lasso || rightHandState[0] == HandState::HandState_Closed)) {
												scrollState = 1;
												baseX = x;
												baseY = y;
												scrollBaseX = jointPoints[JointType_HandTipRight].x;
												scrollBaseY = jointPoints[JointType_HandTipRight].y;
											}
											else if (rightHandState[0] != HandState::HandState_Open && scrollState == 1) {
												x = baseX + (jointPoints[JointType_HandTipRight].x - scrollBaseX);
												y = baseY + (jointPoints[JointType_HandTipRight].y - scrollBaseY);
											}
											else {
												scrollState = 0;
											}
										}
									}
									else {
										rightHandState[0] = rightHandState[1] = HandState::HandState_Unknown;
										scrollState = 0;
									}


									//左手
									if (zoomState == 1 || jointPoints[JointType_ShoulderLeft].y > jointPoints[JointType_HandLeft].y){
										hr = body[i]->get_HandLeftState(&leftHandState[2]);
										if (SUCCEEDED(hr)) {
											leftHandState[1] = leftHandState[0];
											leftHandState[0] = leftHandState[2];
											if (leftHandState[1] == HandState::HandState_Open && leftHandState[0] == HandState::HandState_Closed) {
												zoomState = 1;
												baseZ = z;
												zoomBaseZ = joints[JointType_HandTipLeft].Position.Z;
											}
											else if (leftHandState[0] != HandState::HandState_Open && zoomState == 1) {
												//sprintf_s(buf, "%f\n", joints[JointType_HandLeft].Position.Z);
												//OutputDebugString(buf);
												z = baseZ + ((joints[JointType_HandTipLeft].Position.Z - zoomBaseZ) * 200);
												if (z < 0) z = 0;
											}
											else {
												zoomState = 0;
											}

										}
									}
									else {
										leftHandState[0] = leftHandState[1] = HandState::HandState_Unknown;
										zoomState = 0;
									}

								}
							}
						}
						SafeRelease(&bodyFrame);
					}
				}

				bitmap->CopyFromMemory(NULL, mem, 512 * sizeof(UINT32));
				target->BeginDraw();
				target->DrawBitmap(bgBitmap, d2dDestRect, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, d2dSrcRect);
				target->DrawBitmap(bitmap, d2dBodyRect, 0.5f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
				for (int i = 0; i < _countof(jointPoints); i++){
					ellipse.point.x = d2dBodyRect.left + jointPoints[i].x;
					ellipse.point.y = d2dBodyRect.top + jointPoints[i].y;
					target->FillEllipse(ellipse, brush);
				}
				target->EndDraw();
				InvalidateRect(hWnd, NULL, false);
			}
			break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
			SafeRelease();
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;
}

Kinect v2のBodyIndexを描画する

やっとのこと、BodyIndexを描画するところまで出来た。

人物以外もなんか描画されてるけど、6体認識できる人物全部同じ色で塗りつぶしてるからかもしれない。

判別してないので詳細は不明だけど。

人に見せられるようなソースじゃないんで、自分用のメモw

f:id:wagashi1349:20140808005148p:plain

#include<windows.h>
#include<wincodec.h>
#include<d2d1.h>
#include<Kinect.h>

template<class Interface>
inline void SafeRelease(
	Interface **ppInterfaceToRelease
	)
{
	if (*ppInterfaceToRelease != NULL)
	{
		(*ppInterfaceToRelease)->Release();

		(*ppInterfaceToRelease) = NULL;
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

HWND hWnd;
ID2D1Factory *factory = nullptr;
ID2D1HwndRenderTarget *target = nullptr;
ID2D1Bitmap *bitmap = nullptr;
ID2D1Bitmap *bgBitmap = nullptr;
IWICImagingFactory *wicFactory = nullptr;

IKinectSensor *sensor = nullptr;
IBodyIndexFrameSource *bodyIndexFrameSource = nullptr;
IBodyIndexFrameReader* bodyIndexFrameReader = nullptr;
IBodyFrameSource *bodyFrameSource = nullptr;
IBodyFrameReader *bodyFrameReader = nullptr;
IBodyFrame *bodyFrame = nullptr;

UINT32 mem[512 * 424];
HRESULT hr;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
	MSG msg;
	RECT rect;
	int screen_width = GetSystemMetrics(SM_CXSCREEN);
	int screen_height = GetSystemMetrics(SM_CYSCREEN);

	hr = CoInitialize(NULL);
	if (FAILED(hr)) {
		OutputDebugString("CoInitialize");
		return -1;
	}

	hr = GetDefaultKinectSensor(&sensor);
	if (FAILED(hr) || !sensor) {
		OutputDebugString("Failed GetDefaultKinectSensor()");
		return -1;
	}

	hr = sensor->Open();
	if (FAILED(hr)) {
		OutputDebugString("Failed sensor->Open()");
		return -1;
	}

	hr = sensor->get_BodyIndexFrameSource(&bodyIndexFrameSource);
	if (FAILED(hr)){
		OutputDebugString("Failed get_BodyIndexFrameSource()");
		return -1;
	}

	hr = bodyIndexFrameSource->OpenReader(&bodyIndexFrameReader);
	if (FAILED(hr)){
		OutputDebugString("Failed bodyIndexFrameReader()");
		return -1;
	}

	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
	if (FAILED(hr)) {
		OutputDebugString("Failed D2D1CreateFactory()");
		return -1;
	}

	hr = CoCreateInstance(
		CLSID_WICImagingFactory,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IWICImagingFactory,
		reinterpret_cast<void **>(&wicFactory)
		);

	if (FAILED(hr)) {
		OutputDebugString("Failed CoCreateInstance()");
		SafeRelease(&factory);
		return -1;
	}

	WNDCLASSEX wc;
	wc.hInstance = hInst;
	wc.lpszClassName = "Kinect Sample";
	wc.lpfnWndProc = WndProc;
	wc.style = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInst, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

	if (!RegisterClassEx(&wc))
		return -1;

	hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		wc.lpszClassName,
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE,
		(screen_width - 640) >> 1,
		(screen_height - 480) >> 1,
		640,
		480,
		NULL,
		NULL,
		hInst,
		NULL);

	ShowWindow(hWnd, nWinMode);
	UpdateWindow(hWnd);

	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	CoUninitialize();
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT rect;
	PAINTSTRUCT ps;
	switch (message){
		case WM_SIZE:
			if (target){
				GetClientRect(hWnd, &rect);
				target->Resize(D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top));
			}
		case WM_PAINT:
			if (!target){
				D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
				GetClientRect(hWnd, &rect);
				factory->CreateHwndRenderTarget(
					D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, pixelFormat),
					D2D1::HwndRenderTargetProperties(
						hWnd,
						D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top)),
					&target);

				IWICBitmapDecoder *decoder = nullptr;
				IWICBitmapFrameDecode *source = nullptr;
				IWICFormatConverter *converter = nullptr;

				hr = wicFactory->CreateDecoderFromFilename(
					L"bg.jpg",
					NULL,
					GENERIC_READ,
					WICDecodeMetadataCacheOnLoad,
					&decoder);

				if (FAILED(hr)) {
					OutputDebugString("Failed CreateDecoderFromFilename()");
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = decoder->GetFrame(0, &source);
				if (FAILED(hr)) {
					OutputDebugString("Failed GetFrame()");
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = wicFactory->CreateFormatConverter(&converter);
				if (FAILED(hr)) {
					OutputDebugString("Failed CreateFormatConverter()");
					SafeRelease(&source);
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = converter->Initialize(
					source,
					GUID_WICPixelFormat32bppPBGRA,
					WICBitmapDitherTypeNone,
					NULL,
					0.f,
					WICBitmapPaletteTypeMedianCut
					);

				if (FAILED(hr)) {
					OutputDebugString("Failed Initialize()");
					SafeRelease(&source);
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = target->CreateBitmapFromWicBitmap(
					converter,
					NULL,
					&bgBitmap
					);

				if (FAILED(hr)) {
					OutputDebugString("Failed CreateBitmapFromWicBitmap()");
					SafeRelease(&source);
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				SafeRelease(&converter);
				SafeRelease(&source);
				SafeRelease(&decoder);

				for (int i = 0; i < 512 * 424; i++) {
					mem[i] = 0xFF0000FF;
				}
				target->CreateBitmap(D2D1::SizeU(512, 424), D2D1::BitmapProperties(pixelFormat), &bitmap);
				//target->CreateBitmap(D2D1::SizeU(512, 424), mem, 512 * sizeof(UINT32), D2D1::BitmapProperties(pixelFormat), &bitmap);
			}

			if (target){
				IBodyIndexFrame* bodyIndexFrame = nullptr;
				hr = bodyIndexFrameReader->AcquireLatestFrame(&bodyIndexFrame);
				if (SUCCEEDED(hr)) {
					unsigned int bufferSize = 0;
					unsigned char* buffer = nullptr;
					hr = bodyIndexFrame->AccessUnderlyingBuffer(&bufferSize, &buffer);
					if (SUCCEEDED(hr)) {
						for (int i = 0; i < 512 * 424; i++) {
							if (buffer[i] == 0xFF)
								mem[i] = 0;
							else
								mem[i] = 0xFF0000FF;
						}
					}
				}
				SafeRelease(&bodyIndexFrame);
				bitmap->CopyFromMemory(NULL, mem, 512 * sizeof(UINT32));
				target->BeginDraw();
				target->DrawBitmap(bgBitmap);
				target->DrawBitmap(bitmap, 0, 0.6f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
				target->EndDraw();
				InvalidateRect(hWnd, NULL, false);
			}
			break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
			SafeRelease(&bodyIndexFrameReader);
			SafeRelease(&bodyIndexFrameSource);
			SafeRelease(&sensor);
			SafeRelease(&bgBitmap);
			SafeRelease(&bitmap);
			SafeRelease(&target);
			SafeRelease(&wicFactory);
			SafeRelease(&factory);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;
}

WICを使って画像を読み込むスケルトンプログラム(メモ用)

何も考えずに書いてたらかなり長くなってしまったので自分メモ用に。

#include<windows.h>
#include<wincodec.h>
#include<d2d1.h>

template<class Interface>
inline void SafeRelease(
	Interface **ppInterfaceToRelease
	)
{
	if (*ppInterfaceToRelease != NULL)
	{
		(*ppInterfaceToRelease)->Release();

		(*ppInterfaceToRelease) = NULL;
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

HWND hWnd;
ID2D1Factory *factory = nullptr;
ID2D1HwndRenderTarget *target = nullptr;
ID2D1Bitmap *bitmap = nullptr;
ID2D1Bitmap *bgBitmap = nullptr;
IWICImagingFactory *wicFactory = nullptr;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
	MSG msg;
	RECT rect;
	HRESULT hr;
	int screen_width = GetSystemMetrics(SM_CXSCREEN);
	int screen_height = GetSystemMetrics(SM_CYSCREEN);

	hr = CoInitialize(NULL);
	if (FAILED(hr)) {
		OutputDebugString("CoInitialize");
		return -1;
	}


	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
	if (FAILED(hr)) {
		OutputDebugString("Failed D2D1CreateFactory()");
		return -1;
	}

	hr = CoCreateInstance(
		CLSID_WICImagingFactory,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IWICImagingFactory,
		reinterpret_cast<void **>(&wicFactory)
		);

	if (FAILED(hr)) {
		OutputDebugString("Failed CoCreateInstance()");
		SafeRelease(&factory);
		return -1;
	}

	WNDCLASSEX wc;
	wc.hInstance = hInst;
	wc.lpszClassName = "Kinect Sample";
	wc.lpfnWndProc = WndProc;
	wc.style = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInst, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

	if (!RegisterClassEx(&wc))
		return -1;

	hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		wc.lpszClassName,
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE,
		(screen_width - 800) >> 1,
		(screen_height - 600) >> 1,
		800,
		600,
		NULL,
		NULL,
		hInst,
		NULL);

	ShowWindow(hWnd, nWinMode);
	UpdateWindow(hWnd);

	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	CoUninitialize();
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT rect;
	PAINTSTRUCT ps;
	switch (message){
		case WM_SIZE:
			if (target){
				GetClientRect(hWnd, &rect);
				target->Resize(D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top));
			}
		case WM_PAINT:
			if (!target){
				HRESULT hr;
				D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
				GetClientRect(hWnd, &rect);
				factory->CreateHwndRenderTarget(
					D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, pixelFormat),
					D2D1::HwndRenderTargetProperties(
						hWnd,
						D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top)),
					&target);

				IWICBitmapDecoder *decoder = nullptr;
				IWICBitmapFrameDecode *source = nullptr;
				IWICFormatConverter *converter = nullptr;

				hr = wicFactory->CreateDecoderFromFilename(
					L"bg.jpg",
					NULL,
					GENERIC_READ,
					WICDecodeMetadataCacheOnLoad,
					&decoder);

				if (FAILED(hr)) {
					OutputDebugString("Failed CreateDecoderFromFilename()");
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = decoder->GetFrame(0, &source);
				if (FAILED(hr)) {
					OutputDebugString("Failed GetFrame()");
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = wicFactory->CreateFormatConverter(&converter);
				if (FAILED(hr)) {
					OutputDebugString("Failed CreateFormatConverter()");
					SafeRelease(&source);
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = converter->Initialize(
					source,
					GUID_WICPixelFormat32bppPBGRA,
					WICBitmapDitherTypeNone,
					NULL,
					0.f,
					WICBitmapPaletteTypeMedianCut
					);

				if (FAILED(hr)) {
					OutputDebugString("Failed Initialize()");
					SafeRelease(&source);
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				hr = target->CreateBitmapFromWicBitmap(
					converter,
					NULL,
					&bgBitmap
					);

				if (FAILED(hr)) {
					OutputDebugString("Failed CreateBitmapFromWicBitmap()");
					SafeRelease(&source);
					SafeRelease(&decoder);
					SafeRelease(&wicFactory);
					SafeRelease(&factory);
					return -1;
				}

				SafeRelease(&converter);
				SafeRelease(&source);
				SafeRelease(&decoder);

				UINT32 *mem = new UINT32[512 * 424];
				for (int i = 0; i < 512 * 424; i++) {
					mem[i] = 0xFF0000FF;
				}
				target->CreateBitmap(D2D1::SizeU(512, 424), mem, 512 * sizeof(UINT32), D2D1::BitmapProperties(pixelFormat), &bitmap);
				delete[] mem;
			}

			if (target){
				target->BeginDraw();
				target->DrawBitmap(bgBitmap);
				target->DrawBitmap(bitmap, 0, 0.6f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
				target->EndDraw();
				ValidateRect(hWnd, NULL);
			}
			break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
			SafeRelease(&bgBitmap);
			SafeRelease(&bitmap);
			SafeRelease(&target);
			SafeRelease(&wicFactory);
			SafeRelease(&factory);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;

}

Direct2Dのスケルトンプログラム その2

配列からBitmapを作ってそれを描画するスケルトンプログラム。

Kinectから取得するBodyIndex用なのでサイズは固定の512x424で作ってる。

それっぽく表示されたので多分大丈夫w

f:id:wagashi1349:20140804231424p:plain

#include<windows.h>
#include<d2d1.h>
#pragma comment (lib, "d2d1.lib")

template<class Interface>
inline void SafeRelease(
	Interface **ppInterfaceToRelease
	)
{
	if (*ppInterfaceToRelease != NULL)
	{
		(*ppInterfaceToRelease)->Release();

		(*ppInterfaceToRelease) = NULL;
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

HWND hWnd;
ID2D1Factory *factory = nullptr;
ID2D1HwndRenderTarget *target = nullptr;
ID2D1Bitmap *bitmap;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
	MSG msg;
	RECT rect;
	HRESULT hr;
	int screen_width = GetSystemMetrics(SM_CXSCREEN);
	int screen_height = GetSystemMetrics(SM_CYSCREEN);

	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
	if (FAILED(hr)) {
		OutputDebugString("Failed D2D1CreateFactory()");
		return -1;
	}

	WNDCLASSEX wc;
	wc.hInstance = hInst;
	wc.lpszClassName = "Kinect Sample";
	wc.lpfnWndProc = WndProc;
	wc.style = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInst, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

	if (!RegisterClassEx(&wc))
		return -1;

	hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		wc.lpszClassName,
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE,
		(screen_width - 800) >> 1,
		(screen_height - 600) >> 1,
		800,
		600,
		NULL,
		NULL,
		hInst,
		NULL);

	ShowWindow(hWnd, nWinMode);
	UpdateWindow(hWnd);

	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT rect;
	PAINTSTRUCT ps;
	switch (message){
		case WM_SIZE:
			if (target){
				GetClientRect(hWnd, &rect);
				target->Resize(D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top));
			}
		case WM_PAINT:
			if (!target){
				GetClientRect(hWnd, &rect);
				factory->CreateHwndRenderTarget(
					D2D1::RenderTargetProperties(),
					D2D1::HwndRenderTargetProperties(
						hWnd,
						D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top)),
					&target);

				UINT32 *mem = new UINT32[512 * 424];
				for (int i = 0; i < 512 * 424; i++) {
					mem[i] = 0x7F7F7F7F;
				}
				D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE);
				target->CreateBitmap(D2D1::SizeU(512, 424), mem, 512 * sizeof(UINT32), D2D1::BitmapProperties(pixelFormat), &bitmap);
				delete[] mem;
			}

			if (target){
				target->BeginDraw();
				target->Clear(D2D1::ColorF(D2D1::ColorF::Black));
				target->DrawBitmap(bitmap);
				target->EndDraw();
				ValidateRect(hWnd, NULL);
			}
			break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
			SafeRelease(&bitmap);
			SafeRelease(&target);
			SafeRelease(&factory);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;

}

Direct2Dのスケルトンプログラム

ID2D1Factoryインタフェースを作ってそれから

ID2D1HwndRenderTargetインタフェースを作って描画するって流れみたい。

CreateWindow()の後にWM_PAINTが来るのでウィンドウハンドルが必要な

ID2D1HwndRenderTargetインタフェースの作成はウィンドウプロシージャの中でやってる。

本当はWinMain()の中でやりたいのだが。ウィンドウ表示するだけなのに長いw

#include<windows.h>
#include<d2d1.h>
#pragma comment (lib, "d2d1.lib")

template<class Interface>
inline void SafeRelease(
	Interface **ppInterfaceToRelease
	)
{
	if (*ppInterfaceToRelease != NULL)
	{
		(*ppInterfaceToRelease)->Release();

		(*ppInterfaceToRelease) = NULL;
	}
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

HWND hWnd;
ID2D1Factory *factory = nullptr;
ID2D1HwndRenderTarget *target = nullptr;
ID2D1SolidColorBrush *brush = nullptr;

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszArgs, int nWinMode)
{
	MSG msg;
	RECT rect;
	HRESULT hr;
	int screen_width = GetSystemMetrics(SM_CXSCREEN);
	int screen_height = GetSystemMetrics(SM_CYSCREEN);

	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
	if (FAILED(hr)) {
		OutputDebugString("Failed D2D1CreateFactory()");
		return -1;
	}

	WNDCLASSEX wc;
	wc.hInstance = hInst;
	wc.lpszClassName = "Kinect Sample";
	wc.lpfnWndProc = WndProc;
	wc.style = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInst, IDI_WINLOGO);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

	if (!RegisterClassEx(&wc))
		return -1;

	hWnd = CreateWindowEx(
		0,
		wc.lpszClassName,
		wc.lpszClassName,
		WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZE,
		(screen_width - 800) >> 1,
		(screen_height - 600) >> 1,
		800,
		600,
		NULL,
		NULL,
		hInst,
		NULL);

	ShowWindow(hWnd, nWinMode);
	UpdateWindow(hWnd);

	while (GetMessage(&msg, NULL, 0, 0)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	RECT rect;
	PAINTSTRUCT ps;
	switch (message){
		case WM_SIZE:
			if (target){
				GetClientRect(hWnd, &rect);
				target->Resize(D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top));
			}
		case WM_PAINT:
			if (!target){
				GetClientRect(hWnd, &rect);
				factory->CreateHwndRenderTarget(
					D2D1::RenderTargetProperties(),
					D2D1::HwndRenderTargetProperties(
						hWnd,
						D2D1::SizeU(rect.right - rect.left, rect.bottom - rect.top)),
					&target);

			}

			if (target){
				target->BeginDraw();
				target->Clear(D2D1::ColorF(D2D1::ColorF::Cyan));
				target->EndDraw();
				ValidateRect(hWnd, NULL);
			}
			break;
		
		case WM_DESTROY:
			PostQuitMessage(0);
			SafeRelease(&target);
			SafeRelease(&factory);
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;

}