ファイラーその1
WPFのデータバインディング等が思ったより難解でちっともペースが上がらない。
手の込んだものを作るのは無理そうなので、
listboxの練習にfiler的なものを作ってみる。
FileView.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Collections.ObjectModel; using System.IO; namespace filer { // DataContextに使う class FileView : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String propertyName = "") { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } private DirectoryInfo current_; // TextBox.Textにバインドする public String Path { get { return current_.FullName; } set { current_ = new DirectoryInfo(value); NotifyPropertyChanged("Path"); files_ = new ObservableCollection<FileSystemInfo>( current_.GetFileSystemInfos().ToArray()); } } private ObservableCollection<FileSystemInfo> files_ = new ObservableCollection<FileSystemInfo>(); // ListBox.ItemsSouceにバインドする public ReadOnlyObservableCollection<FileSystemInfo> Files { get { return new ReadOnlyObservableCollection<FileSystemInfo>(files_); } } public FileView(String path) { Path = path; } } }
MainWindow.xaml
<Window x:Class="filer.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:IO="clr-namespace:System.IO;assembly=mscorlib" Title="Filer" Height="350" Width="525"> <Window.Resources> <!-- Directory向け --> <DataTemplate DataType="{x:Type IO:DirectoryInfo}"> <Label Content="{Binding Path=Name}" Foreground="#FF2222"/> </DataTemplate> <!-- File向け --> <DataTemplate DataType="{x:Type IO:FileInfo}"> <StackPanel Orientation="Horizontal"> <Label Width="100" Content="{Binding Path=Name}"/> <Label Width="100" Content="{Binding Path=Length}"/> </StackPanel> </DataTemplate> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBox Grid.Row="0" Name="currentFolder" Text="{Binding Path=Path}" /> <ScrollViewer Grid.Row="1" > <ListBox Name="currentFolderFiles" ItemsSource="{Binding Path=Files}"> <!-- Resourcesで定義したDataTypeつきのDataTemplateが自動的に選択される --> </ListBox> </ScrollViewer> </Grid> </Window>
DataTemplateのDataTypeを利用してlistboxのitemの種類に応じて、動的に適用するDataTemplateを変える手法を使っている。
この方法を使うには、DataTemplateをResoucesに配置することが必要。
MainWindow.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace filer { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext=new FileView("C:\\"); } } }
WPFことはじめ
WPFをはじめてみた。
いくつかwpfの記事や書籍を見たのだが小さく始まるお手軽なチュートリアルが無くて、
わりと学習曲線が急に感じられる(抽象から入る説明が苦手w)。
どうやら、WPFはWindowsFormsのようにWin32apiをラップしたものでは無くてDirectXの上に再構築したGUIらしい。
調べていくとこれが意外とよさげで、現時点のWindowsのGUIではベストな選択のような気がしてきた。
その代わりに最初に飲み込むべき概念がちょっと多いようだ。
メモしながら整理することにした。
まずは、ツリービューから。
モデル(追加 -> 新規クラス -> Node.cs)
namespace Sample { class Node { // プロパティじゃないとBindingできない private List<Node> children_ = new List<Node>(); public List<Node> Children { get { return children_; } } // プロパティじゃないとBindingできない public string Name { get; set; } public Node(string name) { Name = name; } public Node AddChild(Node node) { children_.Add(node); return node; } } }
ビュー(MainWindow.xaml)
<Window x:Class="Sample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <TreeView Width="200" Height="200" ItemsSource="{Binding Path=Children}"><!-- DataContext.Childrenの意らしい --> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding Path=Children}"><!-- 再帰的。ChildrenのChildren --> <TextBlock Text="{Binding Path=Name}"/><!-- ノード一個分。Node.Name --> </HierarchicalDataTemplate> </TreeView.ItemTemplate> </TreeView> </Grid> </Window>
ビューがモデルを参照する(MainWindow.xaml.cs)
namespace Sample { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); var tree=new Node("root"); var node1=tree.AddChild(new Node("node1")); var node1_1 = node1.AddChild(new Node("node1_1")); var node1_2 = node1.AddChild(new Node("node1_2")); // ビューはDataContextを通してBindingする DataContext = tree; } } }
実行してみた。"root"より下の階層が表示された。
rootのChildrenのChildrenから表示される。
モデルの更新通知を導入する
まず、モデルを更新するボタンを追加する
<Button Height="23" HorizontalAlignment="Left" Margin="152,262,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click"> AddNode </Button>
namespace Sample { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { private Node root_; public MainWindow() { InitializeComponent(); // 変更できるようにメンバ変数にとっておく root_=new Node("root"); var node1=root_.AddChild(new Node("node1")); var node1_1 = node1.AddChild(new Node("node1_1")); var node1_2 = node1.AddChild(new Node("node1_2")); DataContext = root_; } private void button1_Click(object sender, RoutedEventArgs e) { // モデルを更新 root_.AddChild(new Node("AddNode")); } } }
ボタンを押しても画面は変化しない。
ListをObservableCollectionに置換する。
using System.Collections.ObjectModel; namespace Sample { class Node { // プロパティじゃないとBindingできない private ObservableCollection<Node> children_ = new ObservableCollection<Node>(); public ObservableCollection<Node> Children { get { return children_; } } // 省略 } }
ボタンを押すとノードが追加されるようになった。
macbook airにgentoo linuxをインストールする
gentoo-3.3.8
その2
その3
ubuntuのusbメモリから起動して、
handbookを見てインストールを進める
fdisk
1 /dev/sda1 boot EFI領域 # 温存 2 /dev/sda2 HFS+ OSX # 温存 3 /dev/sda3 swap 1G 4 /dev/sda4 ext4 残り全部
必要なカーネルオプション
素の状態からmake menuconfigしたものから変更した部分のメモ
General .config Processor core2 FileSystem ext4 fuse dos codepage 932 charset utf8 NTFS Network CIFS # samba Miscellaneous HFS+ Device NetWork Wireless 80211 # 後でブロードコムの内臓無線ドライバをビルドするのに必要 USB asix # 外付けのUSB-ether USB roothub transaction # タッチパッドの認識に必要 http://forums.gentoo.org/viewtopic-t-878287-start-0.html InputDevice Mice BCM5974 # タッチパッド Graphics agp Intel440 DRM Sound alsa pci Intel HD # カーネル組み込みからモジュールに変更した
broadcomのドライバをビルドしてインストールする
その4
grub2をefiサポートでビルドする
- http://spurint.org/misc/installing-gentoo-on-a-macbookair31/
- http://lists.gnu.org/archive/html/bug-grub/2012-06/msg00056.html
--disable-werror --disable-nls
起動成功
その5 ネットワーク設定
wpa_supplicant
コミットのユーザ名を修正する
こちらに書いてあった
http://d.hatena.ne.jp/idesaku/20090908/1252419890
set -x git filter-branch --commit-filter ' GIT_AUTHOR_NAME="ousttrue" GIT_AUTHOR_EMAIL="ousttrue@gmail.com" GIT_COMMITER_NAME="ousttrue" GIT_COMMITER_EMAIL="ousttrue@gmail.com" git commit-tree "$@" ' HEAD^^^..HEAD # HEAD^^ HEAD^ HEADが対象(HEAD^^^は入らない)
DirectShowを入力として、OpenCVで画像処理して、DirectXでテクスチャとして表示するサンプル
を作った。
https://github.com/ousttrue/dscvd3d
とりあえずOpenCVの画像処理にはカメラキャリブレーションとその補正をやってみたのだけど、歪んでない画像が補正したことによりより歪んでしまう状態になってしまった。使い方が間違っているのかもしれない。
メモ
rgbaの配列をOpenCVで処理して、書き戻すメモ。
メモリを新しく確保しているところが無駄だがとりあえず。
#include <opencv2/core/core.hpp> void Process(unsigned char *data, int w, int h) { // 8bit Unsigned 4Channel cv::Mat image(h, w, CV_8UC4); // input memcpy(&image.at<cv::Vec4b>(0, 0), data, w*h*4); // 処理ネガポジ反転 image = ~image; // output memcpy(data, &image.at<cv::Vec4b>(0, 0), w*h*4); }
↑はだめな方法。
下記のようにできた。
cv::Mat image(h, w, CV_8UC4, data);
// 処理
image = ~image;
USBカメラを静止画で取得する(サンプルグラバ)
DirectXのテクスチャにDirectShowを出力する方法を試してみた。
最初に、
を参考にしたのだが、
strmbase.lib(strmbasd.lib)をVC2010でビルドするのに失敗して
コンパイルを通すことがそもそもできなかったorz
仕方ないのでDirectShow基本ライブラリに含まれるCBaseVideoRendererを使うのはおいておいて、SampleGrabberを使う手法をやってみた。
SampleGrabberを使う
こちらを参考にした。
qedit.hが無い
VC2010とは別にインストールした古いWindowsSDKに含まれていた
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\qedit.h
昔のDirectX(DirectShowが含まれているやつ)でもいいらしい
dxtrans.hが無い
C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\qedit.h
を直接修正するらしい
ようやく実装開始
DirectShowは含まれるライブラリが転々としているせいで、どこにインクルードやリンクがあるのか探すので苦労する・・・
入力と出力を持つフィルタを作って、これらをグラフに追加して連結する仕組みだとわかった。
ということで、出力を持つUSBカメラフィルタと入力をもつサンプルグラバを連結した。
ComMovie.h
#pragma once #include <atlbase.h> #include <dshow.h> #include <qedit.h> #pragma comment(lib, "strmiids") #include <vector> class Com { public: Com() { CoInitialize(NULL); } ~Com() { CoUninitialize(); } }; class ComMovieSource { Com m_com; CComPtr<IGraphBuilder> m_graphBuilder; CComQIPtr<IMediaControl> m_mediaControl; CComPtr<ICaptureGraphBuilder2> m_captureGraphBulider; // 出力 CComPtr<IBaseFilter> m_sampleGrabberFilter; CComQIPtr<ISampleGrabber> m_sampleGrabber; // 入力 CComPtr<IBaseFilter> m_deviceFilter; int m_w; int m_h; std::vector<BYTE> m_buffer; public: ComMovieSource(); ~ComMovieSource(); HRESULT Initialize(); int GetWidth(){ return m_w; } int GetHeight(){ return m_h; } HRESULT Update(); void *GetSample(){ return m_buffer.empty() ? 0 : &m_buffer[0]; } size_t GetSampleSize(){ return m_buffer.size(); } };
ComMovie.cpp
#include "ComMovie.h" ComMovieSource::ComMovieSource() : m_w(0), m_h(0) { } ComMovieSource::~ComMovieSource() { } HRESULT ComMovieSource::Initialize() { if(m_graphBuilder){ return S_OK; } // filter graph if (FAILED(m_graphBuilder.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC))){ return E_FAIL; } // add sample grabber if(FAILED(m_sampleGrabberFilter.CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC))){ return E_FAIL; } m_sampleGrabberFilter.QueryInterface(&m_sampleGrabber); if(!m_sampleGrabber){ return E_FAIL; } AM_MEDIA_TYPE amt; ZeroMemory(&amt, sizeof(amt)); amt.majortype = MEDIATYPE_Video; amt.subtype = MEDIASUBTYPE_RGB32; amt.formattype = FORMAT_VideoInfo; m_sampleGrabber->SetMediaType(&amt); if(FAILED(m_graphBuilder->AddFilter(m_sampleGrabberFilter, L"Sample Grabber"))){ return E_FAIL; } // add capture filter if(FAILED(m_captureGraphBulider.CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC))){ return E_FAIL; } if(FAILED(m_captureGraphBulider->SetFiltergraph(m_graphBuilder))){ return E_FAIL; } // デバイスを列挙するためのCreateDevEnumを生成 CComPtr<ICreateDevEnum> createDevEnum; if(FAILED(createDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER))){ return E_FAIL; } CComPtr<IEnumMoniker> enumMoniker; createDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enumMoniker, 0); if(!enumMoniker){ // no device return E_FAIL; } enumMoniker->Reset(); while(true){ CComPtr<IMoniker> moniker ; DWORD nFetched; if(FAILED(enumMoniker->Next(1, &moniker, &nFetched))){ return E_FAIL; } if(nFetched<1){ break; } // ToDo: 条件に合うデバイスをバインドする { // 一個目のUSBカメラ moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_deviceFilter); break; } } if(FAILED(m_graphBuilder->AddFilter(m_deviceFilter, L"Video Input Device"))){ return E_FAIL; } // デバイスとグラバフィルタを連結する if(FAILED(m_captureGraphBulider->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, m_deviceFilter, NULL, m_sampleGrabberFilter))){ return E_FAIL; } // 画像サイズ if(FAILED(m_sampleGrabber->GetConnectedMediaType(&amt))){ return E_FAIL; } VIDEOINFOHEADER *pVideoInfoHeader = (VIDEOINFOHEADER *)amt.pbFormat; m_w=pVideoInfoHeader->bmiHeader.biWidth; m_h=pVideoInfoHeader->bmiHeader.biHeight; m_buffer.resize(amt.lSampleSize); // 開始 m_sampleGrabber->SetBufferSamples(TRUE); m_graphBuilder.QueryInterface(&m_mediaControl); if(!m_mediaControl){ return E_FAIL; } if(FAILED(m_mediaControl->Run())){ return E_FAIL; } return S_OK; } HRESULT ComMovieSource::Update() { if(m_buffer.empty()){ return E_FAIL; } // 現在表示されている映像を静止画として取得 long nBufferSize=m_buffer.size(); HRESULT hr=m_sampleGrabber->GetCurrentBuffer(&nBufferSize, (long*)&m_buffer[0]); if(SUCCEEDED(hr) && nBufferSize==m_buffer.size()){ return S_OK; } return E_FAIL; }