PixelFormatを変更してファイルに保存
PixelFormatを変更している様子
コンボボックスからPixelFormatを選ぶと変更された画像に切り替わる
Saveボタンを押すとファイルに保存する
保存形式はbmp、jpeg、gif、png、tiff、wdp
ファイル名は元のファイル名+PixelFormatの名前
PixelFormatは25種類
Bgr555
Bgr565
Bgr24
Bgr32
Bgr101010
Bgra32
Pbgra32
Cmyk32
BlackWhite
Gray2
Gray4
Gray8
Gray16
Gray32Float
Indexed1
Indexed2
Indexed4
Indexed8
Rgb24
Rgb48
Rgb128Float
Rgba64
Rgba128Float
Prgba64
Prgba128Float
XAMLデザイン画面
C#のコード
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;
//PixelFormats クラス(System.Windows.Media)
namespace _20180110_PixelFormatいろいろ
{
public partial class MainWindow : Window
{
private BitmapSource OriginalBitmapSource;//元画像を入れておく
private string OriginalFileName;//元画像のファイル名
public MainWindow()
{
InitializeComponent();
string filePath = "";
//filePath = @"D:\ブログ用\テスト用画像\青空とトマトの花.jpg";
filePath = @"D:\ブログ用\テスト用画像\NEC_8041_2017_05_09_午後わてん_72dpi.jpg";
SetSource(filePath);
OriginalFileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
DisplayOriginal();
ButtonSave.Click += ButtonSave_Click;
ComboBoxPixelFormats.SelectionChanged += ComboBoxPixelFormats_SelectionChanged;
AddComboBoxItem();
}
//コンボボックスの初期化、項目追加
private void AddComboBoxItem()
{
ComboBoxPixelFormats.Items.Add(PixelFormats.Bgr555);
ComboBoxPixelFormats.Items.Add(PixelFormats.Bgr565);
ComboBoxPixelFormats.Items.Add(PixelFormats.Bgr24);
ComboBoxPixelFormats.Items.Add(PixelFormats.Bgr32);
ComboBoxPixelFormats.Items.Add(PixelFormats.Bgr101010);
ComboBoxPixelFormats.Items.Add(PixelFormats.Bgra32);
ComboBoxPixelFormats.Items.Add(PixelFormats.Pbgra32);
ComboBoxPixelFormats.Items.Add(PixelFormats.Cmyk32);
ComboBoxPixelFormats.Items.Add(PixelFormats.BlackWhite);
//ComboBoxPixelFormats.Items.Add(PixelFormats.Default);
ComboBoxPixelFormats.Items.Add(PixelFormats.Gray2);
ComboBoxPixelFormats.Items.Add(PixelFormats.Gray4);
ComboBoxPixelFormats.Items.Add(PixelFormats.Gray8);
ComboBoxPixelFormats.Items.Add(PixelFormats.Gray16);
ComboBoxPixelFormats.Items.Add(PixelFormats.Gray32Float);
ComboBoxPixelFormats.Items.Add(PixelFormats.Indexed1);
ComboBoxPixelFormats.Items.Add(PixelFormats.Indexed2);
ComboBoxPixelFormats.Items.Add(PixelFormats.Indexed4);
ComboBoxPixelFormats.Items.Add(PixelFormats.Indexed8);
ComboBoxPixelFormats.Items.Add(PixelFormats.Rgb24);
ComboBoxPixelFormats.Items.Add(PixelFormats.Rgb48);
ComboBoxPixelFormats.Items.Add(PixelFormats.Rgb128Float);
ComboBoxPixelFormats.Items.Add(PixelFormats.Rgba64);
ComboBoxPixelFormats.Items.Add(PixelFormats.Rgba128Float);
ComboBoxPixelFormats.Items.Add(PixelFormats.Prgba64);
ComboBoxPixelFormats.Items.Add(PixelFormats.Prgba128Float);
}
//コンボボックスの項目変更時
private void ComboBoxPixelFormats_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox comboBox = (ComboBox)sender;
//var neko = comboBox.SelectedItem;
//PixelFormatの変換
PixelFormat pixelFormat = (PixelFormat)comboBox.SelectedItem;
var convertedBitmap = new FormatConvertedBitmap( OriginalBitmapSource, pixelFormat, OriginalBitmapSource.Palette, 0);
MyImage.Source = convertedBitmap;
TextBlockBpp.Text = "ビットの深さ(bpp) = " + pixelFormat.BitsPerPixel.ToString();
}
//保存ボタン押した時
private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
SaveImageJpeg();//jpeg形式でファイルに保存
SaveImageBmp();
SaveImagePng();
SaveImageGif();
SaveImageTiff();
SaveImageWmp();
}
//画像ファイルをdpi96に変換したものを取得
private void SetSource(string filePath)
{
WriteableBitmap wb;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
wb = new WriteableBitmap(BitmapFrame.Create(fs));
}
int w = wb.PixelWidth;
int h = wb.PixelHeight;
int stride = wb.BackBufferStride;
byte[] pixels = new byte[h * stride];
wb.CopyPixels(pixels, stride, 0);
var bs = BitmapSource.Create(w, h, 96, 96, wb.Format, wb.Palette, pixels, stride);
OriginalBitmapSource = bs;
TextBlockPixelFormat.Text = " = " + bs.Format.ToString();
}
private void DisplayOriginal()
{
MyImage.Source = OriginalBitmapSource;
}
//jpeg形式でファイルに保存
private void SaveImageJpeg()
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
//MessageBox.Show(encoder.QualityLevel.ToString());//75
string fileName = OriginalFileName + "_" + GetPixelFormatName() + ".jpg";
using (var fs = new FileStream(fileName, FileMode.Create))
{
encoder.Save(fs);
}
}
private void SaveImageBmp()
{
var encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
string fileName = OriginalFileName + "_" + GetPixelFormatName() + ".bmp";
using (var fs = new FileStream(fileName, FileMode.Create))
{
encoder.Save(fs);
}
}
private void SaveImagePng()
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
string fileName = OriginalFileName + "_" + GetPixelFormatName() + ".png";
using (var fs = new FileStream(fileName, FileMode.Create))
{
encoder.Save(fs);
}
}
private void SaveImageGif()
{
var encoder = new GifBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
string fileName = OriginalFileName + "_" + GetPixelFormatName() + ".gif";
using (var fs = new FileStream(fileName, FileMode.Create))
{
encoder.Save(fs);
}
}
private void SaveImageTiff()
{
var encoder = new TiffBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
string fileName = OriginalFileName + "_" + GetPixelFormatName() + ".tiff";
var neko = encoder.Compression;
//encoder.Compression = TiffCompressOption.Ccitt3;
using (var fs = new FileStream(fileName, FileMode.Create))
{
encoder.Save(fs);
}
}
private void SaveImageWmp()
{
var encoder = new WmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
string fileName = OriginalFileName + "_" + GetPixelFormatName() + ".wdp";
var neko = encoder.CodecInfo.FileExtensions;
using (var fs = new FileStream(fileName, FileMode.Create))
{
encoder.Save(fs);
}
}
private string GetPixelFormatName()
{
BitmapSource bitmapSource = (BitmapSource)MyImage.Source;
return bitmapSource.Format.ToString();
}
}
}
ファイルパスから画像取得
作成したBitmapSourceはあとでPixelFormatを変更するので
どこからでも参照できるフィールド変数?に入れておく
コンボボックスの初期化、項目を追加する
一個一個入れるんじゃなくて一括でできればいいんだけど、方法がわからん
でも、文字と数値しか入れられないイメージだったけど入るんだねえ、便利
コンボボックスの項目変更時にPixelFormatを変更
これをNewで作る時
FormatConvertedBitmap(BitmapSource, PixelFormat, BitmapPalette, Double)
引数のBitmapSourceとBitmapPaletteは元画像のものを渡して、
PixelFormatはComboBoxのSelectedItem、
最後のdoubleは透明度に関係あるっぽい、0を渡しとけばいいみたい
これでできたものをImageコントロールのSourceに指定すると表示される
ファイルとして保存
ファイル名にPixelFormatの名前を付けたかったので
PixelFormatの名前はToStringで取得
jpeg形式で保存の場合
bmp形式の場合
他の形式も同じように細かい設定は何もしないで保存している
PixelFormatの中には128bitとかもあるのに、これでできているのかなあと疑問に思うので保存されたファイルを見てみると
PixelFormatがPrgba128Floatをbmp形式で保存したファイルのプロパティ
ビットの深さは64になっている
ずいぶん減っているけど64bitのbmpって初めてみた
普通だと24とか32
次はgif画像
8bit
gifは最大で8bitみたい
jpeg
これもjpeg形式の最大値だと思う
png
tiff
tiff画像は馴染みがないから、よくわからん
最後にwdp
エクスプローラーから見る限りでは各画像形式の上限らしきbitで保存できているみたい
元の画像が24bitだしモニタも普通の液晶ディスプレイだから以上になってもきれいにはならないけどね
次は1bit
単純な2値化じゃなくて誤差拡散法のディザリングみたい
結果
形式bit
bmp1
gif8
jpeg8
png1
tiff1
wdp1
gifとjpegが8bitになっている、jpegはなんとなく仕方がないかなあって気もするけどgifはどうなんだろう、違う気がする
その他は同じ1bitで保存されている、けど
wdpだけうまく保存できていなくて
これはEdgeで開いたところ、うまく保存できていない
ファイルサイズもbmp形式で6KBなのにwdpは0.3KBと極端に小さくなっている
PixelFormat.BlackWhiteをWmpBitmapEncoderで
正しく保存するにはコーデックの設定を変更する必要があるのかも
wdpって今回初めて見たんだけど
HD Photo - Wikipediaマイクロソフトが作ったもので
https://ja.wikipedia.org/wiki/HD_Photo
JPEG XR - Wikipedia
https://ja.wikipedia.org/wiki/JPEG_XR
今ではJEPG XRって言うみたい?
拡張子もwdpじゃなくてjxrのほうが良かったかなあ
この画像形式を開くことができるアプリは
Windowsのフォト
Windows フォトビューワー
インターネットブラウザのEdge
エクスプローラーで表示形式を大きなアイコンとかにする
などWindows標準のアプリなら見ることができた
WindowsFormアプリのPixtack紫陽花は見られなかったけど
WPFアプリのPixtack紫陽花2ndなら見ることができた!
保存されたファイルのサイズ一覧
コーデックの設定は全く変更していないので
jpegとwdpは参考程度
jpegのQualityは75だった
保存された画像ファイルのbpp一覧
wdpはこの中では一番新しい形式なだけあって128bitにも対応している
気になるのがCmyk32をjpegで保存したファイル、32bitになっている
jpegで32bitなんてあるのかな
エクスプローラーで見ると
これを
ヤフーブログもjpegファイルは普通に投稿できるので
このファイルを載っけてみると
google Chromeで表示
ペイント
でも色が変わるアプリもあるから
Cmyk32をjpeg形式で保存したファイルは、なんかおかしいんだろうねえ
色相を180度移動で反対の色にしてみたら
面白いのは減色処理みたいになる、24未満になるものかな
Indexed1から8までの4つはパレットを持った画像になるみたい
Indexed1は1ビットなので2色
この2色は
これで
元の画像から選定してパレットに登録して使っているのかなこの色の選び方がスゴイと思う
他の画像で
Indexed2は2ビットなので4色
これがたった4色で表現されている
どうやって選んでいるのかなあ
別の画像でIndexed2
そういえば昔のプリンターは4色が普通だったなあ
Indexed4は4ビットなので16色
Indexed8は8ビットなので256色
gifファイルのハッシュ値一覧
とくにIndexed8は8bitだからgifの最大色数256色と同じだからどうかなってみたら
アルファチャンネルを含まないRGB系と全く同じ
パレットはどんな扱いになっているんだろうねえ
bmp
ファイルヘッダのbppを記録する部分が違うだけだったりして
追記
さっきの色が変わった画像を記事を投稿してからダウンロードしてみた
ビットの深さ24になっている
ヤフーブログに32bitのjpeg画像をアップロードすると
その時点で24bitに変換されるってことかなあ
32bitのjpeg画像はありえないってことかしらw