酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

C#で書いたWindows Phone 8アプリケーションからC++で実装したライブラリを使う

説明はあとで書く。

基本的には、「C++/Cx で書いたクラスを C#で書いたWindowsストアアプリで使う」と同じです。

ライブラリ(ネイティブプロジェクト)側

WindowsPhoneRuntimeComponent1.h
#pragma once

namespace WindowsPhoneRuntimeComponent1
{
    public ref class WindowsPhoneRuntimeComponent sealed
    {
    public:
        WindowsPhoneRuntimeComponent();
		void sepia(int width, int height, const Platform::Array<uint8>^ srcBytes, 
			Platform::WriteOnlyArray<uint8>^ dstBytes);
    };
}
WindowsPhoneRuntimeComponent1.cpp
// WindowsPhoneRuntimeComponent1.cpp
#include "pch.h"
#include "WindowsPhoneRuntimeComponent1.h"

using namespace WindowsPhoneRuntimeComponent1;
using namespace Platform;

WindowsPhoneRuntimeComponent::WindowsPhoneRuntimeComponent()
{
}

void WindowsPhoneRuntimeComponent::sepia(int width, int height, 
			const Platform::Array<uint8>^ srcBytes, Platform::WriteOnlyArray<uint8>^ dstBytes)
{
	int pixels = width * height;
	for (int i = 0; i < pixels; i++) {
		int index = i * 4;

		uint8 b = srcBytes[index + 0];
		uint8 g = srcBytes[index + 1];
		uint8 r = srcBytes[index + 2];
		uint8 a = srcBytes[index + 3];

		// 単純平均法で輝度を求める
        double y = (double)(r + g + b) / 3;

        // 輝度に対して指定の比率を掛けてセピア調に変換する
        uint8 db = y * 0.4;
        uint8 dg = y * 0.7;
        uint8 dr = y;

		dstBytes[index + 0] = db;
		dstBytes[index + 1] = dg;
		dstBytes[index + 2] = dr;
		dstBytes[index + 3] = a;
	}
}

アプリケーション(マネージコードプロジェクト)側

MainPage.xaml
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Image x:Name="effectImage" HorizontalAlignment="Left" Height="478" Margin="12,29,0,0" Grid.Row="1" 
               VerticalAlignment="Top" Width="458" Source="Assets/nekoicon.png"/>
            <Button Content="Convert" HorizontalAlignment="Left" Margin="326,513,0,0" VerticalAlignment="Top" Click="Button_Click_1"/>
        </Grid>
    </Grid>
MainPage.xaml.cs
using Microsoft.Phone.Controls;
using System;
using System.Windows;
using System.Windows.Media.Imaging;

namespace NaviteCodeSample
{
    public partial class MainPage : PhoneApplicationPage
    {
        // コンストラクター
        public MainPage()
        {
            InitializeComponent();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            // 俺俺ライブラリを使って、WriteableBitmapオブジェクトを生成する
            var res = Application.GetResourceStream(new Uri("Assets/nekoicon.png", UriKind.Relative));
            var img = new BitmapImage(); img.SetSource(res.Stream);
            var bitmap = new WriteableBitmap(img);

            var w = bitmap.PixelWidth;
            var h = bitmap.PixelHeight;

            // 元画像と出力画像用のバッファの生成
            var srcBytes = new byte[bitmap.Pixels.Length * sizeof(int)];
            System.Buffer.BlockCopy(bitmap.Pixels, 0, srcBytes, 0, srcBytes.Length);
            var dstBytes = new byte[srcBytes.Length];

            // C++/Cxのライブラリで画像処理をしてみる
            var nativeLibrary = new WindowsPhoneRuntimeComponent1.WindowsPhoneRuntimeComponent();
            nativeLibrary.sepia(w, h, srcBytes, dstBytes);

            // Imageコントロールにセピア調化した画像を表示する
            bitmap = new WriteableBitmap(w, h);
            System.Buffer.BlockCopy(dstBytes, 0, bitmap.Pixels, 0, dstBytes.Length);
            effectImage.Source = bitmap;

        }
    }
}

ネイティブコードで書いたライブラリってどこまでWindows PhoneとWindows ストア アプリで共通化することが可能なんだろうか。