主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Boo: C#で書いていたコードをBooで書いてみる

                
今回はBooがC#に取って代われる可能性があるかを確認したい。そのためにC#で書かれたコードをBooに直してみる。

Pythonの影響を受けたBooのスクリプトの可読性は価値がある。
.NET上でC#にとって代わりたいならIronPythonという選択肢もある。なぜIronPythonでなくBooかというと、IronPythonは根本がPythonなので、C#に似た書き方ができない。C#には属性があったりrefによる参照渡しがあったり。これをIronPythonで真似するのは手間がかかる。
BooはPythonの皮をかぶったC#だ。属性もrefによる参照渡しもある。パフォーマンスだってC#に遜色ないどころか、若干勝ることもある。それならBooでもいいじゃないか。
http://elicon.blog57.fc2.com/blog-entry-253.html

まずはMicrosoft Expression Encoder 4 SDKを使った、動画からサムネイルを作るクラスをBooで書いてみる。
↓これを……
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using Microsoft.Expression.Encoder;

namespace Generator
{
public static class ThumbnailGenerator
{

public static void SaveThumbnail(string src, string outputName, double point)
{
Bitmap thumbnail = GetThumbnail(src, point);

// sets thumbnail name unique and saves
thumbnail.Save(outputName, ImageFormat.Jpeg);

thumbnail.Dispose();
}

public static Bitmap GetThumbnail(string src, double point)
{
Bitmap thumbnail;
//string bitmapDir = Environment.CurrentDirectory;

if (!File.Exists(src))
{
System.ArgumentException argEx = new System.ArgumentException("Source file not found");
throw argEx;
}
AudioVideoFile avFile = null;
try
{
avFile = new AudioVideoFile(src);
}
catch (Exception ex)
{
System.ArgumentException argEx = new System.ArgumentException(ex.Message);
throw argEx;
}

// Gets the time for each thumbnail.
if (point > avFile.Duration.TotalSeconds)
{
Console.WriteLine(avFile.Duration.TotalSeconds);
System.ArgumentException argEx = new System.ArgumentException("Over a duration");
throw argEx;
}

// Create ThumbnailGenerator object to get thumbs from AudioVideoFile
Microsoft.Expression.Encoder.ThumbnailGenerator generator = avFile.CreateThumbnailGenerator(avFile.VideoStreams[0].VideoSize);

// Gets image based on timing
thumbnail = generator.CreateThumbnail(TimeSpan.FromSeconds(point));

generator.Dispose();
return thumbnail;
}
}
}


Booで上記のコードを書きかえる
namespace BooThumbnailGenerator

import System
import System.Drawing
import System.Drawing.Imaging
import System.IO
import Microsoft.Expression.Encoder

public static class ThumbnailGenerator:
public def SaveThumbnail(src as string, outputName as string, point as double) as void:
thumbnail = GetThumbnail(src, point) as Bitmap

// sets thumbnail name unique and saves
thumbnail.Save(outputName, ImageFormat.Jpeg)

thumbnail.Dispose()

public def GetThumbnail(src as string, point as double) as Bitmap:
thumbnail as Bitmap

if not File.Exists(src):
raise "Source file not found"
avFile = null as AudioVideoFile
try:
avFile = AudioVideoFile(src)
except e:
raise e

// Gets the time for each thumbnail.
if point > avFile.Duration.TotalSeconds:
print(avFile.Duration.TotalSeconds)
raise "Over a duration"

// Create ThumbnailGenerator object to get thumbs from AudioVideoFile
generator = avFile.CreateThumbnailGenerator(avFile.VideoStreams[0].VideoSize) as Microsoft.Expression.Encoder.ThumbnailGenerator

// Gets image based on timing
thumbnail = generator.CreateThumbnail(TimeSpan.FromSeconds(point))

generator.Dispose()
return thumbnail


クラスなので、コンパイルでDLL化すれば.NET上ならC#, VB, IronPython, IronRuby, Booなどどの言語からだって使える。動作はIronPythonで確認したが、問題なく動いた。
import  clr

clr.AddReference('BooThumbnailGenerator')
clr.AddReference('System.Drawing')

from BooThumbnailGenerator import ThumbnailGenerator
from System.Drawing import Bitmap

ThumbnailGenerator.SaveThumbnail(r"C:\Users\h\Videos\B'z\B'z _ C'mon.mp4",
r'hoge.jpg',
10)

bitmap = ThumbnailGenerator.GetThumbnail(r"C:\Users\h\Videos\B'z\B'z _ C'mon.mp4",
3.3)
bitmap.Save("hoge.png")




続いて、DllImportを使用して、マウスイベントを下に重なっているウィンドウにスルーパスするWPFウィンドウを作ってみる。ウィンドウにスルー機能を持たせるクラスはC#で以下のように。
using System;

using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace WindowServices
{
public static class WindowsServices
{
const int WS_EX_TRANSPARENT = 0x00000020;
const int GWL_EXSTYLE = (-20);

[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hwnd, int index);

[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

public static void SetWindowExTransparent(IntPtr hwnd)
{
var extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
}
}
}


上記のクラスをBooで書き、そのままウィンドウ表示までやってみる。
namespace BooWPF

import System
import System.Windows
import System.Windows.Media

import System.Windows.Interop
import System.Runtime.InteropServices

static class WindowsServices:
WS_EX_TRANSPARENT = 0x00000020
GWL_EXSTYLE = -20

[DllImport("user32.dll")]
def GetWindowLong(hwnd as IntPtr, index as int) as int:
pass

[DllImport("user32.dll")]
def SetWindowLong(hwnd as IntPtr, index as int, newStyle as int) as int:
pass

public def SetWindowExTransparent(hwnd as IntPtr) as void:
extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT)


class Window1(Window):
def constructor():
WindowStyle = WindowStyle.None
Topmost = true
Background = BrushesBlue
AllowsTransparency = true
Opacity = 0.5
Show()


[STAThread]
def Main():
app = Application()
w = Window1()
hwnd = WindowInteropHelper(w).Handle
WindowsServices.SetWindowExTransparent(hwnd)
app.Run()


上記のコードでやっているのは、半透明で青色のコントロールなしウィンドウを表示して、マウスイベント(クリックやドラッグ)をその背後にあるウィンドウに渡すということ。このコードも難なく動いた。


IronPythonでC#のまねごとをしようとすると、言語の持つ機能の違いがモロに出て厄介なことになる。その点、BooでC#のまねごとをしようとすると、割とすんなりいく。このあたりはBooはPythonの皮をかぶったC#であるんじゃないかと常々感じる。
まあなんにしろ、Booは読みやすくてなおかつ書きやすい言語だ。.NETでDLL化したいクラスをつくるときはこの言語を使っていくのがいいと思う。
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。