C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2008/09/30 13:00
マルチ TIFF を XPS ドキュメントに変換しようと思い、サンプルコードを書いたので公開します。
僕としてはマルチ TIFF の変換が目的でしたが、このコードで JPEG やら PNG やらも変換できます。

Window1.xaml.cs
using System;
using System.IO;
using System.IO.Packaging;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media.Imaging;
using System.Windows.Markup;
using System.Windows.Xps.Packaging;
using System.Windows.Xps;
using Microsoft.Win32;

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        private XpsDocument _xpsDocument;
        private readonly Uri _packageUri;
        private readonly OpenFileDialog _openImageFileDialog;

        public Window1()
        {
            InitializeComponent();

            this._xpsDocument = null;
            this._packageUri = new Uri("pack://work.xps");
            this._openImageFileDialog = new OpenFileDialog();
            this._openImageFileDialog.Filter = "Image Files|*.bmp;*.jpg;*.jpeg;*.png;*.gif;*.tif;*.tiff";
        }

        private void _openButton_Click(object sender, RoutedEventArgs e)
        {
            if (!this._openImageFileDialog.ShowDialog(this).Value)
            {
                return;
            }
            if (this._xpsDocument != null)
            {
                this.CloseDocument();
            }
            using (Stream imageStream = this._openImageFileDialog.OpenFile())
            {
                this.BuildXpsDocument(imageStream);
                this._documentViewer.Document = this._xpsDocument.GetFixedDocumentSequence();
            }
        }

        private void BuildXpsDocument(Stream imageStream)
        {
            /*** FixedDocument の作成 ***/
            FixedDocument imagesDocument = new FixedDocument();
            BitmapDecoder bitmapDecoder = BitmapDecoder.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.Default);
            foreach (BitmapFrame sourceFrame in bitmapDecoder.Frames)
            {
                // sourceFrame を直接使用してしまうと、先頭フレーム以外リソース化されない
                BitmapFrame separatedFrame = BitmapFrame.Create(sourceFrame);
                Size frameSize = new Size(separatedFrame.PixelWidth, separatedFrame.PixelHeight);

                PageContent imagePageContent = new PageContent()
                {
                    Width = frameSize.Width,
                    Height = frameSize.Height
                };
                FixedPage imagePage = new FixedPage()
                {
                    Width = frameSize.Width,
                    Height = frameSize.Height
                };
                Image image = new Image()
                {
                    Width = frameSize.Width,
                    Height = frameSize.Height,
                    Source = separatedFrame
                };
                FixedPage.SetTop(image, 0);
                FixedPage.SetLeft(image, 0);

                imagePage.Children.Add(image);
                ((IAddChild)imagePageContent).AddChild(imagePage);
                imagesDocument.Pages.Add(imagePageContent);
            }


            /*** XpsDocument の作成 ***/
            MemoryStream packageStream = new MemoryStream();
            Package package = Package.Open(packageStream, FileMode.Create, FileAccess.ReadWrite);
            // メモリ上の XPS を DocumentViewer に表示するためには Package に URI を割り当てる必要がある
            PackageStore.AddPackage(this._packageUri, package);
            this._xpsDocument = new XpsDocument(package, CompressionOption.NotCompressed, this._packageUri.AbsoluteUri);


            /*** XpsDocument に FixedDocument を書き込む ***/
            XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(this._xpsDocument);
            writer.Write(imagesDocument);
        }

        private void CloseDocument()
        {
            this._documentViewer.Document = null;
            this._xpsDocument.Close();
            Package package = PackageStore.GetPackage(this._packageUri);
            package.Close();
            PackageStore.RemovePackage(this._packageUri);
        }
    }
}

Window1.xaml
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="419" Width="648">
    <Grid>
        <ToolBar Band="1" BandIndex="1" Height="26" Name="_mainToolBar" VerticalAlignment="Top" >
            <Button Name="_openButton" Height="20" Width="40" Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" Click="_openButton_Click">開く</Button>
        </ToolBar>
        <DocumentViewer Name="_documentViewer" VerticalAlignment="Top" Margin="0,26,0,0" />
    </Grid>
</Window>

動作させるには、Visual Studio にて "WpfApplication1" という名前の WPF アプリケーションプロジェクトを作成して、各コードファイルを上書きしてください。
また、ReachFramework.dll と System.Printing.dll への参照設定が必要となります。
スポンサーサイト



タグ: .NET C# WPF XPS 画像処理
2007/09/17 21:28
けっこうややこしいのでメモ。

// using System;
// using System.Drawing;
// using System.Drawing.Imaging;
// using System.IO;

static void Main()
{
    Image page1 = new Bitmap("C:\\work\\page3.bmp");
    Image page2 = new Bitmap("C:\\work\\page3.bmp");
    Image page3 = new Bitmap("C:\\work\\page3.bmp");

    // TIFF 形式のエンコーダ。
    ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
    Predicate<ImageCodecInfo> tiffEncoderPredicate =
        delegate(ImageCodecInfo input)
        {
            return (input.FormatID == ImageFormat.Tiff.Guid);
        };
    ImageCodecInfo tiffEncoder = Array.Find(imageEncoders, tiffEncoderPredicate);

    // エンコーダのパラメータ。
    EncoderParameters tiffEncoderParameters = new EncoderParameters(2);
    tiffEncoderParameters.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.MultiFrame);
    tiffEncoderParameters.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone);

    // 作業領域となるメモリストリーム。
    MemoryStream tiffStream = new MemoryStream();
    // Save メソッドによって、1ページ目が保存され、更に Image オブジェクトとメモリストリームが関連付けられる。
    page1.Save(tiffStream, tiffEncoder, tiffEncoderParameters);

    // 2ページ目, 3ページ目の保存に使用するエンコーダのパラメータ。
    EncoderParameters pageEncoderParameters = new EncoderParameters(2);
    pageEncoderParameters.Param[0] = new EncoderParameter(Encoder.SaveFlag, (long)EncoderValue.FrameDimensionPage);
    pageEncoderParameters.Param[1] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone);

    // 先ほどの Save メソッドで関連付けられたメモリストリームに対して保存される。
    // この操作は page1 にフレームを追加するわけではない。
    page1.SaveAdd(page2, pageEncoderParameters);
    page1.SaveAdd(page3, pageEncoderParameters);

    // メモリストリームの内容をファイルに保存する。
    File.WriteAllBytes("C:\\work\\test.tif", tiffStream.ToArray());
}



EncoderParameter のインスタンスを生成する際、EncoderValue 列挙値を long にキャストして渡しています。これは int ではなく long にしなければいけません。でないと失敗します。

サンプルなんで Dispose メソッドは呼び出してません。Image, MemoryStream  以外にも、EncoderParameters や EncoderParameter も IDisposable を実装してます。
タグ: .NET C# 画像処理