PixelFormatを変更してファイルに保存
コンボボックスからPixelFormatを選ぶと変更された画像に切り替わる
Saveボタンを押すとファイルに保存する
ファイル名は元のファイル名+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
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;
namespace _20180110_PixelFormatいろいろ
{
public partial class MainWindow : Window
{
private BitmapSource OriginalBitmapSource;
private string OriginalFileName;
public MainWindow()
{
InitializeComponent();
string filePath = "";
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.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;
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();
SaveImageBmp();
SaveImagePng();
SaveImageGif();
SaveImageTiff();
SaveImageWmp();
}
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;
}
private void SaveImageJpeg()
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)(MyImage.Source)));
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;
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を変更するので
どこからでも参照できるフィールド変数?に入れておく
コンボボックスの初期化、項目を追加する
ComboBoxのItemsにPixelFormatをそのまま入れている
一個一個入れるんじゃなくて一括でできればいいんだけど、方法がわからん
でも、文字と数値しか入れられないイメージだったけど入るんだねえ、便利
コンボボックスの項目変更時にPixelFormatを変更
変更に使うのはFormatConvertedBitmapって言うクラス
これをNewで作る時
FormatConvertedBitmap(BitmapSource, PixelFormat, BitmapPalette, Double)
引数のBitmapSourceとBitmapPaletteは元画像のものを渡して、
PixelFormatはComboBoxのSelectedItem、
最後のdoubleは透明度に関係あるっぽい、0を渡しとけばいいみたい
これでできたものをImageコン
トロールのSourceに指定すると表示される
ファイルとして保存
ファイル名にPixelFormatの名前を付けたかったので
PixelFormatの名前はToStringで取得
他の形式も同じように細かい設定は何もしないで保存している
PixelFormatの中には128bitとかもあるのに、これでできているのかなあと疑問に思うので保存されたファイルを見てみると
PixelFormatがPrgba128Floatをbmp形式で保存したファイルのプロパティ
ずいぶん減っているけど64bitの
bmpって初めてみた
普通だと24とか32
次はgif画像
8bit
gifは最大で8bitみたい
最後にwdp
エクスプローラーから見る限りでは各画像形式の上限らしきbitで保存できているみたい
元の画像が24bitだしモニタも普通の液晶ディスプレイだから以上になってもきれいにはならないけどね
次は1bit
白か黒の2色の
PixelFormatはBlackWhite
単純な2値化じゃなくて誤差拡散法のディザリングみたい
結果
形式 bit
gif 8
wdp 1
gifと
jpegが8bitになっている、
jpegはなんとなく仕方がないかなあって気もするけどgifはどうなんだろう、違う気がする
その他は同じ1bitで保存されている、けど
wdpだけうまく保存できていなくて
これはEdgeで開いたところ、うまく保存できていない
ファイルサイズも
bmp形式で6KBなのにwdpは0.3KBと極端に小さくなっている
PixelFormat.BlackWhiteをWmpBitmapEncoderで
正しく保存するにはコーデックの設定を変更する必要があるのかも
2018/01/22追記ここから
wdpって今回初めて見たんだけど
今ではJEPG XRって言うみたい?
拡張子もwdpじゃなくてjxrのほうが良かったかなあ
この画像形式を開くことができるアプリは
インターネットブラウザのEdge
WindowsFormアプリのPixtack紫陽花は見られなかったけど
WPFアプリのPixtack紫陽花2ndなら見ることができた!
保存されたファイルのサイズ一覧
保存された画像ファイルのbpp一覧
wdpはこの中では一番新しい形式なだけあって128bitにも対応している
気になるのがCmyk32をjpegで保存したファイル、32bitになっている
これを
ヤフーブログも
jpegファイルは普通に投稿できるので
このファイルを載っけてみると
ペイント
でも色が変わるアプリもあるから
Cmyk32をjpeg形式で保存したファイルは、なんかおかしいんだろうねえ
色相を180度移動で反対の色にしてみたら
元が24bitだからそれ以上のフォーマットは意味ないけど一覧
面白いのは減色処理みたいになる、24未満になるものかな
Indexed1から8までの4つはパレットを持った画像になるみたい
Indexed1は1ビットなので2色
この2色は
これで
元の画像から選定してパレットに登録して使っているのかな
この色の選び方がスゴイと思う
他の画像で
この画像のPixelFormatをIndexed1にすると
Indexed2は2ビットなので4色
どうやって選んでいるのかなあ
別の画像でIndexed2
そういえば昔のプリンターは4色が普通だったなあ
Indexed4は4ビットなので16色
Indexed8は8ビットなので256色
gifはすべて8bitのファイルが出来上がったけど中身は違っているのか気になった
とくにIndexed8は8bitだからgifの最大色数256色と同じだからどうかなってみたら
アルファチャンネルを含まないRGB系と全く同じ
パレットはどんな扱いになっているんだろうねえ
Rgb101010はファイルサイズもファイルのbppも64bitや128bitのファイルと同じなのに中身は違うみたい
ファイルヘッダのbppを記録する部分が違うだけだったりして
追記
さっきの色が変わった画像を記事を投稿してからダウンロードしてみた
ビットの深さ24になっている
ヤフーブログに32bitの
jpeg画像をアップロードすると
その時点で24bitに変換されるってことかなあ
32bitの
jpeg画像はありえないってことかしらw
関連記事
前回2018/01/09は2日まえ