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

提供: MonoBook
2015年1月24日 (土) 06:47時点における126.213.5.102 (トーク)による版 (→‎関連項目)
ナビゲーションに移動 検索に移動

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

方法1

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

    using System;
    using System.Drawing;
    using System.IO;
    using MonoMac.Foundation;
    using MonoMac.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);
            }
        }

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

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

ちなみにSystem.GC.Collectをメインスレッド以外で実行しても効果がないようだ。 凄い嵌った。

関連項目

参考文献