Xamarin.MacでNSImageをSystem.Drawing.Imageに変換する

提供: MonoBook
ナビゲーションに移動 検索に移動

Xamarin.MacにおいてAppKit.NSImageをSystem.Drawing.Imageに変換する方法を試行錯誤している。

方法1[編集 | ソースを編集]

NSImageは基本的にTIFFファイルのようなので、System.Drawing.Imageが読み込めるPNGファイルに変換を行い、ImageにStreamを食わせる。

    using System;
    using System.Drawing;
    using System.IO;
    using Foundation;
    using AppKit;

    public static class NSImageExtentions
    {
        public static Image ToImage(this NSImage image) 
        {
            using (var imageDataTiff = image.AsTiff()) 
            using (var imageRep = NSBitmapImageRep.ImageRepFromData(imageDataTiff) as NSBitmapImageRep)
            using (var imageProps = new NSDictionary())
            using (var imageDataPng = imageRep.RepresentationUsingTypeProperties(NSBitmapImageFileType.Png, imageProps))
            using (var imageStreamPng = imageDataPng.AsStream())
            { 
                return Image.FromStream(imageStreamPng);
            }
        }

なお、Xamarin.Macのクラス群はほぼDisposeメソッドを実装しておりメモリリークを防ぐためにも「using」が重要となる。 大容量のメモリを搭載している昨今のMacでは多少のメモリリークをしても大して問題にならないが、QTKitやAV Foundationを使ったビデオキャプチャなどでは1/30秒や1/60秒といった速度で1フレームごとに上記のような処理が走るため、Dispose呼出を怠ると凄い勢いでメモリリークすることになる。

これに加えてビデオキャプチャではSystem.GC.Collectメソッドの手動実行も重要な場合がある。 ビデオキャプチャなどの常時負荷が高い状況化ではガベージコレクションの自動実行だけでは処理が追いつかない場合があるようだ。 ちなみにSystem.GC.Collectをメインスレッド以外で実行しても効果がないようだ。 凄い嵌った。

関連項目[編集 | ソースを編集]

参考文献[編集 | ソースを編集]