今までは何も指定しないで作成していたけど圧縮(エンコード)方式をいくつか選べるみたいなので試してみた
TiffBitmapEncoder.Compression プロパティに
TiffCompressOption列挙型から選んで指定する
TiffCompressOption 列挙型 (System.Windows.Media.Imaging)
から引用
Ccitt3引用ここまで
CCITT3 圧縮スキーマが使用されます。
Ccitt4
CCITT4 圧縮スキーマが使用されます。
Default
TiffBitmapEncoder エンコーダーは、実行できる最適な圧縮スキーマで、ビットマップを保存しようとしています。
Lzw
LZW 圧縮スキーマが使用されます。
None
Tagged Image File Format (TIFF) イメージは圧縮されません。
Rle
RLE 圧縮スキーマが使用されます。
Zip
Zip 圧縮スキーマが使用されます。
何も指定しないとDefaultになる
圧縮する画像は
256x192ピクセルの24bitのbmp形式の
画像A
ファイルサイズは144KB(147510バイト)
256*192*24/8=147456
圧縮方式による見た目の違い
Tiffは可逆圧縮なので見た目は元のBitmap画像とまったく同じはず
Ccitt3と4はファクシミリに使われている方式だから白黒2値になるみたい
ファイルサイズ変化
画像A
KB
元画像144
Ccitt314.2
Ccitt414.4
Default128
Lzw170
None144
Rle145
Zip132
圧縮なのにLzwとRleは元画像よりファイルサイズが増えている
一番効率がいいのはDefaultなので何も指定しないのがいいみたい
Defaultの説明では最適な圧縮方法を採りますってあるけどなんだろうって気になる
エクスプローラーのファイルのプロパティから見ると
LZWってある
でもLzwを指定してできたファイルとはサイズが違いすぎる
ファイルのプロパティから見た圧縮方式
指定した単語とは微妙に違ったり表示がなかったり
でもDefaultとLzwはどちらもLZWだねえ
TIFFファイルの圧縮フォーマット判別法こちらを参考にして
http://robaq.info/tiffcompression.xhtml
バイナリエディタで確認してみた
検索で03 01 03 00 01 00
だけどLzwを指定したものは170KBってぜんぜん違うサイズだからなあ
LZWにも種類があるってことかしら
これ以上は難しそうなのでパス
別の画像を圧縮
png画像が得意そうな画像B
プロパティでみると
527x497ピクセルの32bitのbmp形式の画像B
ファイルサイズは990KB(1047730バイト)
527*497*32/8=1047676
ファイルサイズ変化
画像A画像B
KBKB
元画像144990
Ccitt3 14 31
Ccitt4 14 41
Default128107
Lzw170 93
None144769
Rle145575
Zip132 46
おお、スゴイ縮んだ
Defaultでも10分の1に圧縮できているし、一番効率が良かったZip形式では20分の1
可逆圧縮でこの圧縮率はスゴイ
png画像も同じくらい縮むから好きなんだけどTiff画像もいいねえ
今回参照したところ
TiffCompressOption 列挙型 (System.Windows.Media.Imaging)ありがとうございます
https://msdn.microsoft.com/ja-jp/library/system.windows.media.imaging.tiffcompressoption(v=vs.110).aspx
TIFFファイルの圧縮フォーマット判別法
http://robaq.info/tiffcompression.xhtml
CGファイル概説 第5章 第2節 その2
http://www.snap-tck.com/room03/c02/cg/cg05_03.html
TIFFのフォーマット(その1) | JProgramer
http://jprogramer.com/libtiffcate/3188
TIFF Tag Reference, Baseline TIFF Tags
https://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
TIFF - Wikipedia
https://en.wikipedia.org/wiki/TIFF
using System.Windows;
using System.Windows.Media.Imaging;
using System.IO;
//TiffBitmapEncoder クラス(System.Windows.Media.Imaging)
//https://msdn.microsoft.com/ja-jp/library/system.windows.media.imaging.tiffbitmapencoder(v=vs.110).aspx
namespace _20180115_TiffEncoder
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Title = this.ToString();
string filePath;
//filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_96dpi_Bgr32.bmp";
//filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_96dpi_BlackWhite.png";
//filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_96dpi_Gray2.png";
//filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_72dpi.jpg";
//filePath = @"D:\ブログ用\チェック用2\NEC_1259_2018_01_14_午後わてん.jpg";
//filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_96dpi_Prgba64.png";
//filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_96dpi_Bgr24.bmp";
filePath = @"D:\ブログ用\WPF\20180113_画像読み込み07_02_.bmp";
BitmapSource source = GetBitmapSource10(filePath, true, 96, 96);
TiffTest2(source, TiffCompressOption.Ccitt3);
TiffTest2(source, TiffCompressOption.Ccitt4);
TiffTest2(source, TiffCompressOption.Default);
TiffTest2(source, TiffCompressOption.Lzw);
TiffTest2(source, TiffCompressOption.None);
TiffTest2(source, TiffCompressOption.Rle);
TiffTest2(source, TiffCompressOption.Zip);
}
private void TiffTest2(BitmapSource source, TiffCompressOption compressOption)
{
TiffBitmapEncoder encoder = new TiffBitmapEncoder();
BitmapFrame frame = BitmapFrame.Create(source);
encoder.Frames.Add(frame);
encoder.Compression = compressOption;
string fileName = frame.Format.ToString() + "_" + encoder.Compression.ToString() + ".tiff";
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
encoder.Save(fs);
}
}
/// <summary>
/// ファイルパスとPixelFormatを正確にするか最適にするかを指定してBitmapSourceを取得、
/// dpiの変更は任意
/// </summary>
/// <param name="filePath">画像ファイルのフルパス</param>
/// <param name="accuratePixelFormat">Trueなら画像ファイルと同じ正確なPixelFormat、
/// Falseは今の環境で最適なものに変更される</param>
/// <param name="dpiX">無指定なら画像ファイルで指定されているdpiになる</param>
/// <param name="dpiY">無指定なら画像ファイルで指定されているdpiになる</param>
/// <returns></returns>
private BitmapSource GetBitmapSource10(
string filePath, bool accuratePixelFormat, double dpiX = 0, double dpiY = 0)
{
BitmapSource source;
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
BitmapFrame bitmapFrame;
//PixelFormatを元の画像と同じにするかパソコンの環境に合わせるか
if (accuratePixelFormat)
{//画像と同じ
bitmapFrame = BitmapFrame.Create(
fs,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
}
else
{//環境に最適なものに変更
bitmapFrame = BitmapFrame.Create(
fs,
BitmapCreateOptions.None,
BitmapCacheOption.Default);
}
int w = bitmapFrame.PixelWidth;
int h = bitmapFrame.PixelHeight;
int stride = (w * bitmapFrame.Format.BitsPerPixel) / 8;
byte[] pixels = new byte[w * stride];
bitmapFrame.CopyPixels(pixels, stride, 0);
//dpi指定がなければ元の画像と同じdpiにする
if (dpiX == 0) { dpiX = bitmapFrame.DpiX; }
if (dpiY == 0) { dpiY = bitmapFrame.DpiY; }
//dpiを指定してBitmapSource作成
source = BitmapSource.Create(
w, h, dpiX, dpiY,
bitmapFrame.Format,
bitmapFrame.Palette, pixels, stride);
};
return source;
}
}
}
画像ファイルパスからBitmapSourceを作成
TiffBitmapEncoderのFrameにそれを入れて
Compressに圧縮形式を指定してからファイルに保存しているだけ
今回はXAML必要なかった、こういう時にコンソールアプリってのがあるんだろうなあ
画像ファイルパスからBitmapSource作成の
GetBitmapSource10は前回の記事からコピペ
TiffBitmapEncoderにFrame追加は
encoder.Frames.Add(取得したBitmapSource);
これだとエラーになったので
取得したBitmapSourceからBitmapFrame.Createで作成したものを追加で
BitmapFrame frame = BitmapFrame.Create(取得したBitmapSource);
encoder.Frames.Add(frame);
こうした
前回の記事
WPF、画像ファイルを開く方法まとめ ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15325331.html