36404


RTF形式の画像コード（{\pict中にある連続したとても長い半角英数字）を画像として保存するにはどうすれば良いのでしょうか？

visual studio express 2015 (windows 10 64bit)


CC BY-SA 3.0
2017-07-15T20:19:09.630
36401
2017-07-16T01:14:15.050
12778
question
c# visual-studio
RTF形式の画像コードを画像として保存したい


.NET Framework内のクラスだと`FlowDocument`が`.rtf`形式の読み込みに対応しています。

[code]

    var fd = new FlowDocument();
    var tr = new TextRange(fd.ContentStart, fd.ContentEnd);
    tr.Load(new FileStream(@"C:\temp\test.rtf", FileMode.Open), DataFormats.Rtf);
    
[/code]

読込後に`FlowDocument.Blocks`の中を探せばどこかに画像があるはずです。

ですが`FlowDocument`は`System.Windows.Controls.Image`型で画像をデコードするため、上記のコードはWPFアプリケーションのUIスレッドでしか実行できません。

ですのでWindows Formsなどでは裏でWPFアプリを起動する必要があります。

[code]

    private static void Main(string[] args)
    {
        try
        {
            // WPFアプリをバックグラウンドで起動する
            if (Application.Current == null)
            {
                var th = new Thread(() => new Application()
                {
                    ShutdownMode = ShutdownMode.OnExplicitShutdown
                }.Run());
    
                th.SetApartmentState(ApartmentState.STA);
                th.Start();
    
                while (Application.Current == null)
                {
                    Thread.Sleep(0);
                }
            }
    
            // WPFスレッドで処理を行う
            Application.Current.Dispatcher.Invoke(() =>
            {
                var fd = new FlowDocument();
                var tr = new TextRange(fd.ContentStart, fd.ContentEnd);
                tr.Load(new FileStream(@"C:\temp\test.rtf", FileMode.Open), DataFormats.Rtf);
    
                foreach (var b in fd.Blocks)
                {
                    FindImage(b);
                }
            });
    
            Console.ReadKey();
        }
        finally
        {
            // プログラム終了時にWPFアプリケーションを終了しておく
            Application.Current?.Dispatcher.Invoke(Application.Current.Shutdown);
        }
    }
    
    private static void FindImage(TextElement e)
    {
        // FlowDocumentに含まれる型ごとに内部を走査する
    
        var para = e as Paragraph;
        if (para != null)
        {
            foreach (var i in para.Inlines)
            {
                FindImage(i);
            }
            return;
        }
    
        // 画像はInlineUIContainer→Image
        var uic = e as InlineUIContainer;
        if (uic != null)
        {
            var img = uic.Child as Image;
            if (img != null)
            {
                var bmp = img.Source as BitmapSource;
    
                if (bmp != null)
                {
                    // TODO: ここで画像に対する処理を行う 表示サイズとデコード語のサイズが違うのでリサイズが必要
    
                    // ファイルに書き出す場合
                    var fn = bmp.GetHashCode() + ".png";
                    var pbe = new PngBitmapEncoder();
                    pbe.Frames.Add(BitmapFrame.Create(bmp));
                    using (var fs = new FileStream(fn, FileMode.Create))
                    {
                        pbe.Save(fs);
                    }
    
                    Console.WriteLine("{0}, {1}*{2}, {3}*{4}", fn, img.Width, img.Height, bmp.PixelWidth, bmp.PixelHeight);
                }
            }
            return;
        }
    
        // TODO: 他の要素にも対応する
    
        throw new NotImplementedException();
    }
    
[/code]


CC BY-SA 3.0
2017-07-16T01:14:15.050
36404
2017-07-16T01:14:15.050
5750
36401
answer