2017年5月31日水曜日

C# Magick.NETを使ってみる。その2

C# Magick.NETを使ってみる
目次→http://1studying.blogspot.jp/2017/07/c-magicknetmokuzi.html#kuw03


「Magick.NET」の使い方は
https://github.com/dlemstra/Magick.NET/tree/master/Documentation
に載っています

では続きを始めます。


画像の開き方1


「Magick.NET」には、様々な「Magick画像」の開き方が存在します。
ここで改めて整理してみます。

開き方の前に「設定」について先に説明しておきます。
「MagickReadSettings」インスタンスを使えば、「設定」を使って
「Magick画像」を開く事ができます。
ここでは縦横サイズと線を描画した時の太さを先に「設定」しています。
(新規キャンバス作成時、「xc:」と「設定」をセットで使う事が出来ます)
「Magick画像」を開く際の「設定」
1
2
3
4
5
var myMagickSettings = new ImageMagick.MagickReadSettings();
//「xc:」が作成するサイズ150×150
myMagickSettings.Width = 150;
myMagickSettings.Height = 150;
myMagickSettings.StrokeWidth = 10;
「myMagickSettings」の「設定」オブジェクトは新規画像を開く際に使用します。
(「MagickReadSettings」クラスは「MagickSettings」クラスを継承しています)
キャンバスを「150*150Pixel」、線の太さを「10Pixel」に「設定」しました。

色々なパターンの画像の開き方の例です。
「myMagickSettings」の「設定」オブジェクトを使い、
新規キャンバスとして「Magick画像」を開く方法も記述してあります。
色々な画像の開き方を確認してみて下さい。
「Magick画像」の開き方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//「インスタンス時に開く」(背景緑、150*150)
using (var myMagick = new ImageMagick.MagickImage(new ImageMagick.MagickColor("#00ff00"), 150, 150))
{
}
//「インスタンス時に開く」(画像読み込み)
using (var myMagick = new ImageMagick.MagickImage("./Lenna.bmp"))
{
}
//「インスタンス時に開く」(背景緑、「設定」)
using (var myMagick = new ImageMagick.MagickImage("xc:rgb(0,100%,0)", myMagickSettings))
{
}
 
//「Readで開く」(背景緑、150*150)
using (var myMagick = new ImageMagick.MagickImage())
{
    myMagick.Read(new ImageMagick.MagickColor("#00ff00"), 150, 150));
}
//「Readで開く」(画像読み込み)
using (var myMagick = new ImageMagick.MagickImage())
{
    myMagick.Read("./Lenna.bmp");
}
//「Readで開く」(背景緑、「設定」)
using (var myMagick = new ImageMagick.MagickImage())
{
    myMagick.Read("xc:rgb(0,100%,0)", myMagickSettings);
    //後から「設定」の部分変更も可能
    myMagick.Settings.StrokeWidth = 5;
}
ここでは記述していませんが、「ストリーム」や「バイト配列」等から開く事も出来ます。
また、29行目のように、
「myMagick.Settings」を使えば、後から「設定」の変更を行う事も出来ます。
あと、
10行目と27行目で「xc:」を指定していますが、
ここでは「背景色」を意味します。



画像の開き方2(PDFやEPSやAI)


「PDF」や「EPS」や「AI」を「Magick画像」として開く為には、
「Magick.NET」がベクター形式の画像をラスタライズする必要があります。
その為に「Ghostscript」が必要となります。
(「Magick画像」をファイルに保存する際は必要ないみたい。)
「Ghostscript」無しで「PDF」や「EPS」や「AI」を開こうとすると


例外が発生して開けません。

「Ghostscript」のインストール
開けるようにする為に「Ghostscript」をインストールします。
以下のリンク先へ飛びます。「Ghostscript日本語版」
http://www.khotta.org/ghost/index.html
私は2017年5月時点での最新版である、
「 GPL Ghostscript 9.21 (64bit 日本語版)」
「gs921w64full-gpl.exe」
を取得してインストールしました。


「Generate cidfmap for Windows CJK TrueType fonts」は
チェックしたまま「Finish」

「PDF」や「EPS」や「AI」を開く
「AI」ファイルを開き、「RGB、300Dpi、Tiff」で保存してみます。
イラストレーターで使用された効果等によっては必ずしも正しい表示にならない事もあるので、
注意して下さい。(aiファイルは自前で用意して下さい)
「AI」を開く
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//PDF、EPS、AIのラスタライズ時の設定
var myMagickSettings = new ImageMagick.MagickReadSettings();
//ラスタライズ時ICCプロファイル(ICCプロファイル「sRGB.icm」を使用)
myMagickSettings.ColorSpace = ImageMagick.ColorSpace.sRGB;
//ラスタライズ時解像度
myMagickSettings.Density = new ImageMagick.Density(300);
//ラスタライズ時カラータイプ
myMagickSettings.ColorType = ImageMagick.ColorType.TrueColor;
using (var myMagick = new ImageMagick.MagickImage())
{
    //Gostscriptを使用してsRGBでラスタライズ
    myMagick.Read("test_CMYK_ai.ai", myMagickSettings);
    myMagick.Strip();//解像度変更を反映させる為「EXIF情報」削除
    //解像度を再設定
    myMagick.Density = new ImageMagick.Density(myMagick.Density.X, myMagick.Density.Y);
    //フォーマットをtifに指定
    myMagick.Format = ImageMagick.MagickFormat.Tif;
    myMagick.Write("test_out.tif"); //tifで保存
}
MessageBox.Show("処理終了");
「Ghostscript」がインストール済みの為、
問題なく「AI」ファイルを開き、保存する事ができました。


「複数頁PDF」を開く(頁指定も)
「複数頁PDF」を全て単頁「tif」へ変換して保存します。
更に、
「複数頁PDF」を1頁目のみ読み込み「jpg」保存してみます。
(pdfファイルは自前で用意して下さい)
「複数頁PDF」を開く
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//PDF、EPS、AIのラスタライズ時の設定
var myMagickSettings = new ImageMagick.MagickReadSettings();
//ラスタライズ時ICCプロファイル(ICCプロファイル「sRGB.icm」を使用)
myMagickSettings.ColorSpace = ImageMagick.ColorSpace.sRGB;
//ラスタライズ時解像度
myMagickSettings.Density = new ImageMagick.Density(300);
//ラスタライズ時カラータイプ
myMagickSettings.ColorType = ImageMagick.ColorType.TrueColor;
//「Magick画像」のコレクションを開く
using (var myMagicks = new ImageMagick.MagickImageCollection())
{
    //「Gostscript」を使用してsRGBでラスタライズ
    myMagicks.Read("./test_複数頁PDF.pdf", myMagickSettings);
    for (int i = 0; i < myMagicks.Count; i++)
    {
        //コレクションから「Magick画像」を1頁分取得
        ImageMagick.MagickImage myMagick = myMagicks[i];
        myMagick.Strip();//解像度変更を反映させる為「EXIF情報」削除
        //解像度を再設定
        myMagick.Density = new ImageMagick.Density(myMagick.Density.X, myMagick.Density.Y);
        //フォーマットをtifに指定
        myMagick.Format = ImageMagick.MagickFormat.Tif;
        //tifで保存
        myMagick.Write(string.Format(@"./test_out_{0}.tif", i + 1));
    }
}
//「複数頁PDF」の頁数が多い場合は、
//範囲指定を行いラスタライズ化する事もできます。
myMagickSettings.FrameIndex = 0;//1頁目から読み込み
myMagickSettings.FrameCount = 1;//1頁分だけ読み込み
using (var myMagicks = new ImageMagick.MagickImageCollection("./test_複数頁PDF.pdf", myMagickSettings))
{
    myMagicks[0].Strip();//解像度変更を反映させる為「EXIF情報」削除
    //解像度を再設定
    myMagicks[0].Density = new ImageMagick.Density(myMagicks[0].Density.X, myMagicks[0].Density.Y);
    myMagicks[0].Quality = 75; //品質
    //jpgで保存
    myMagicks[0].Write(@"./test_out_1.jpg");
}
MessageBox.Show("処理終了");
コレクションとしてPDFを読み込み、
そこから各頁を「Magick画像」として抽出しています。
コレクションを使わなくてもファイル名の後ろに「[]」で、開きたい頁を直接指定すれば、
PDFの指定ページをいきなり開く事も可能です。
(開く頁の指定は、[0]→1頁目、[1]→2頁目、[2]→3頁目、[3]→4頁目…となります。)
//PDFの3頁目を「Magick画像として」開く
using (var myMagick = new ImageMagick.MagickImage("./test_複数頁PDF.pdf[2]"))


「複数頁PDF」への保存
「jpg」を「複数頁PDF」へ保存してみます。
「複数頁PDF」への保存
1
2
3
4
5
6
7
8
9
10
//「Magick画像」のコレクションを開く
using (var myMagicks = new ImageMagick.MagickImageCollection())
{
    myMagicks.Add(new ImageMagick.MagickImage("./test_in_1.jpg"));
    myMagicks.Add(new ImageMagick.MagickImage("./test_in_2.jpg"));
    //「Magick画像」コレクションをそのままPDFへ書き出すと
    //「複数頁PDF」として書き出されます。
    myMagicks.Write("./test_out1.pdf");
}
MessageBox.Show("処理終了");


ラスタライズ時のアンチエイリアス設定
1
2
3
4
var myMagickSettings = new ImageMagick.MagickReadSettings();
//ラスタライズ時のアンチエイリアスOFF
myMagickSettings.StrokeAntiAlias = false;
myMagickSettings.TextAntiAlias = false;




画像の開き方3(PSDとレイヤー)


フォトショップ側で使用されている効果などによって、
必ずしも正しく表示される訳ではない事に注意して下さい。

PSDを開く(レイヤー含む)
コレクションで開く
「PSD」をレイヤー毎に保存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//レイヤー付きPSD画像を
//「Magick画像」のコレクションで開く
using (var myMagicks = new ImageMagick.MagickImageCollection("./test_CMYKレイヤー付.psd"))
{
    for (int i = 0; i < myMagicks.Count; i++)
    {
        //コレクションから「Magick画像」を1レイヤー分取得
        ImageMagick.MagickImage myMagick = myMagicks[i];
        //「背景」にする(アルファを白くします)
        myMagick.ColorAlpha(ImageMagick.MagickColors.White);
        //tifで保存
        myMagick.Write(string.Format(@"./test_out_{0}.tif", i));
    }
}
MessageBox.Show("処理終了");
「psd」をコレクションで開いた場合、
・「Magick画像」コレクションの1枚目は、
 「psd」内の「表示レイヤー」全てが統合化されて「Magick画像」化された物、
 が取得できます。
・「Magick画像」コレクションの2枚目以降は、
 「psd」内の「レイヤー」が下から順に「Magick画像」化された物、
 が取得できます。
 (フォルダ内レイヤーの場合も関係なく、下のレイヤーから順に取得)

指定レイヤーを開く
「PSD」内指定レイヤーを開く
1
2
3
4
5
6
7
8
9
10
//レイヤー付きPSD画像の
//表示レイヤーを統合した「Magick画像」を取得
using (var myMagick = new ImageMagick.MagickImage("./test_CMYKレイヤー付.psd[0]"))
{
    //「背景」にする(アルファを白くします)
    myMagick.ColorAlpha(ImageMagick.MagickColors.White);
    //tifで保存
    myMagick.Write(string.Format(@"./test_out_psd.tif", i));
}
MessageBox.Show("処理終了");
ファイル名の後ろに「[]」で、開きたいレイヤーを直接指定すれば、
指定レイヤーをいきなり開く事が可能です。
・「[0]」は、
 「psd」内の「表示レイヤー」全てが統合化した「Magick画像」を取得できます。
・「[1]」以降は、
 「psd」内の「レイヤー」を下から数えた指定数値の場所にある「レイヤー」を、
 「Magick画像」として取得します。
 (フォルダ内レイヤーの場合も、関係なく下のレイヤーから順に数えます)


PSDでの保存
・普通のレイヤー画像を保存した場合。
 「L1」という名前の「通常レイヤー」が作られます。
 (PSD内の1つのレイヤーや表示画像をMagick画像」として開いた場合でも、
  PSD保存される画像は、
  「Magick画像」が1つのレイヤー画像として展開された画像となります。)
・統合された画像を保存した場合。
 「L1」と言う名前の「統合画像」になってしまいます。
 通常は「背景」という名前が正しいのですが、
 名前を「背景」に変更する方法が分かりませんでした。
 (tif形式等で保存すれば「背景」という正しい名前になります)



画像の開き方4(-define jpeg)


開く画像が「Jpeg」形式で、なおかつ半分以下のPixelサイズに縮小したい場合のみ、
処理を高速化する方法。
(ImageMagickコマンドの「-define jpeg:size」オプションと同じです。)
Jpeg画像を高速に開く
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var myMagickSettings = new ImageMagick.MagickReadSettings();
//「-define jpeg:size」オプション同じ
//必ずソースとなる「Jpeg画像」より、縮小予定のPixel数がが半分以下である事
myMagickSettings.SetDefine(ImageMagick.MagickFormat.Jpg, "size", "50x50");
//「Magick画像」として「Jpeg画像」を開きます
using (var myMagick = new ImageMagick.MagickImage("./test_RGB.jpg", myMagickSettings))
{
    //「2分の1」「4分の1」「8分の1」等、
    //指定Pixelの近似値のPixel数で「Magick画像」が開かれます。
    MessageBox.Show(myMagick.Width.ToString() + "\n" + myMagick.Height.ToString());
    //予定通りのPixel数へ縮小します
    myMagick.Resize(new ImageMagick.MagickGeometry(50,50));
    pictureBox1.Image = myMagick.ToBitmap();
 
    MessageBox.Show(myMagick.Width.ToString() + "\n" + myMagick.Height.ToString());
}
ソースとなる「Jpeg画像」より低い画素で開く事によって処理を高速化しています。



画像の情報を取得


画像の情報には、「画像情報」と「Exif情報」と「Magick画像」情報があります。
「Exif情報」は付加情報の為、付いていない画像も存在します。
それぞれの情報取得方法を記述します。

「画像情報」取得
「画像情報」取得
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//「画像情報」取得準備
//(ストリームやバイト配列も引数にできます)
ImageMagick.MagickImageInfo myMagickInfo = new ImageMagick.MagickImageInfo("./Lenna.bmp");
//インスタンスから「Read」を使って取得も出来ます。
//(ストリームやバイト配列も引数にできます)
var myMagickInfo2 = new ImageMagick.MagickImageInfo();
myMagickInfo2.Read("./Lenna.bmp");
 
//「画像情報」取得
string msg = "";
msg += "ファイル名:" + myMagickInfo.FileName + "\n";
msg += "色空間:" + myMagickInfo.ColorSpace + "\n";
msg += "横pixel:" + myMagickInfo.Width + "\n";
msg += "縦pixel:" + myMagickInfo.Height + "\n";
msg += "画像形式:" + myMagickInfo.Format + "\n";
msg += "横解像度:" + myMagickInfo.Density.X + "\n";
msg += "縦解像度:" + myMagickInfo.Density.Y + "\n";
msg += "解像度の単位:" + myMagickInfo.Density.Units + "\n";
MessageBox.Show(msg);
解像度の単位は「PixelsPerInch」がよく使われますが、違う場合があります。
ここが「PixelsPerCentimeter」の場合は「解像度」の数値に対して、
「×2.54倍」する必要があります。
↓結果表示

「./Lenna.bmp」は解像度情報が無い為、解像度が「0」と表示されています。
他に、
2値1200dpiのpsd画像を読み込んでみたら、
「色空間:Gray」、
「横解像度:1200」「縦解像度1200」「解像度の単位:PixelPerInch」
と表示されました。


「Exif情報」取得
「Exif情報」を確認する為には「Magick画像」として一度開く必要があります。
Photoshopで作成したpsdファイルは必ず「Exif情報」が付きます。
今回は「./Lenna.psd」にpsdファイルが存在する前提で処理を記述します。
「Exif情報」取得
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//「Magick画像」を開く
using (var myMagick= new ImageMagick.MagickImage("./Lenna.psd"))
{
    //「Exif情報」取得
    ImageMagick.ExifProfile myMagickExif = myMagick.GetExifProfile();
    //「Exif情報」が存在すれば
    if (myMagickExif != null)
    {
        string str = "";
        foreach (var exifValue in myMagickExif.Values)
        {
            str += exifValue.Tag + "(";
            str += exifValue.DataType + "):";
            str += exifValue.ToString() + "\n";
        }
        MessageBox.Show(str); //表示
    }
}
↓結果表示

72×72dpi、256×256pixelのファイルである事が分かります。



「Exif情報」から「サムネイル画像」の取得
「Exif情報」を確認する為には「Magick画像」として一度開く必要があります。
Photoshopで作成したjpgファイルの「Exif情報」内に「サムネイル画像」が付きます。
今回は「./Lenna.jpg」にjpgファイルが存在する前提で処理を記述します。
「Exif情報」から「サムネイル画像」の取得
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//「Magick画像」を開く
using (var myMagick= new ImageMagick.MagickImage("./Lenna.jpg"))
{
    //「Exif情報」取得
    ImageMagick.ExifProfile myMagickExif = myMagick.GetExifProfile();
    //「Exif情報」が存在すれば
    if (myMagickExif != null)
    {
        //「サムネイル画像」取得
        using (var myMagickThumbnail = myMagickExif.CreateThumbnail())
        {
            // 「Exif情報」に「サムネイル画像」が存在すれば
            if (myMagickThumbnail != null)
            {
                pictureBox1.Image = myMagickThumbnail.ToBitmap();//表示
                //myMagickThumbnail.Write("サムネ.jpg");
            }
        }
    }
}


「Magick画像」情報取得
「Magick画像」として開いて、プロパティを通して画像の細かい情報を取得できます。
以下のリンク先に取得例が載せてあります。
「C# Magick.NETを使ってみる。補足 画像情報取得」
http://1studying.blogspot.jp/2017/07/c-magicknet_12.html
メモ:
 「Magick画像」の情報(プロパティ)が取得したいだけの為に、
 一度「Magick画像」としてファイルを開かなくてはならない。
 開くファイルが大きい時「Magick画像」の情報取得に時間が掛かってしまう。
 今のところ、解決方法がみつからない。



その3へ続きます…



「C# Magick.NETを使ってみる。その3」へ続きます…



「標準画像/サンプルデータ」は「神奈川工科大学」のサイトを利用しました。
http://www.ess.ic.kanagawa-it.ac.jp/app_images_j.html
「ImageMagick コマンドリファレンス」
http://image-magick.com/


「ImageMagickのメモ」
Imagemagickの「convert」コマンドの様々な使い方が書いてある。
http://sharp-bang.jp/prog/im.html


「ImageMagick」の
「対応画像フォーマット」、「仮想画像」、「内蔵画像」、「内蔵パターン」
http://www.imagemagick.org/script/formats.php


0 件のコメント:

コメントを投稿

↑Topへ