FormatConvertedBitmapで変換してみる
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace _20190315_Pixelformats.Pbgra32で色変化
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
string imagePath = "";
imagePath = @"D:\ブログ用\テスト用画像\半透明A100R30G122B224.png";
byte[] pixels;
BitmapSource bitmapPbgra32;
(pixels, bitmapPbgra32) = MakeByteArrayAndSourceFromImageFile(imagePath, PixelFormats.Pbgra32);
var Pbgra32 = Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
MyImagePbgra32.Source = bitmapPbgra32;
BitmapSource bitmapRgra32;
(pixels, bitmapRgra32) = MakeByteArrayAndSourceFromImageFile(imagePath, PixelFormats.Bgra32);
var Bgra32 = Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
MyImageBgra32.Source = bitmapRgra32;
BitmapSource source;
(pixels, source) = MakeByteArrayAndSourceFromImageFile(imagePath, PixelFormats.Bgr32);
var Bgr32 = Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
(pixels, source) = MakeByteArrayAndSourceFromImageFile(imagePath, PixelFormats.Rgb24);
var Rgb24 = Color.FromRgb(pixels[0], pixels[1], pixels[2]);
(pixels, source) = MakeByteArrayAndSourceFromImageFile(imagePath, PixelFormats.Bgr24);
var Bgr24 = Color.FromRgb(pixels[2], pixels[1], pixels[0]);
BitmapImage bitmapImage = new BitmapImage(new Uri(imagePath));
var pf = bitmapImage.Format;
int stride = pf.BitsPerPixel / 8 * bitmapImage.PixelWidth;
pixels = new byte[stride * bitmapImage.PixelHeight];
bitmapImage.CopyPixels(pixels, stride, 0);
var auto = Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]);
}
<summary>
</summary>
<param name="filePath"></param>
<param name="pixelFormat"></param>
<param name="dpiX"></param>
<param name="dpiY"></param>
<returns></returns>
private (byte[] array, BitmapSource source) MakeByteArrayAndSourceFromImageFile(string filePath, PixelFormat pixelFormat, double dpiX = 0, double dpiY = 0)
{
byte[] pixels = null;
BitmapSource source = null;
try
{
using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
var bf = BitmapFrame.Create(fs);
var convertedBitmap = new FormatConvertedBitmap(bf, pixelFormat, null, 0);
int w = convertedBitmap.PixelWidth;
int h = convertedBitmap.PixelHeight;
int stride = (w * pixelFormat.BitsPerPixel + 7) / 8;
pixels = new byte[h * stride];
convertedBitmap.CopyPixels(pixels, stride, 0);
if (dpiX == 0) { dpiX = bf.DpiX; }
if (dpiY == 0) { dpiY = bf.DpiY; }
source = BitmapSource.Create(
w, h, dpiX, dpiY,
convertedBitmap.Format,
convertedBitmap.Palette, pixels, stride);
};
}
catch (Exception)
{
}
return (pixels, source);
}
}
}
A R G B
元の色 #641E7AE0 100, 30, 122, 224
Formats 色
Pbgra32 #640C3058 100, 12, 48, 88
Bgra32 #641E7AE0 100, 30, 122, 224
Bgr32 #641E7AE0 100, 30, 122, 224
Rgb24 #FF1E7AE0 255, 30, 122, 224
Bgr24 #FF1E7AE0 255, 30, 122, 224
Pbgra32だけ変色している
Rgb24とBgr24の透明度AもFFに変化しているけど
24bitカラーはAがないので完全不透明の値FFであっている、期待通り
一覧
でも、これを表示してみると
なので半透明画像を扱うときはPbgra32じゃなくてBgra32を使ったほうが良さそう
配列の中を覗いてみる
Pbgra32
違う、その色じゃない
Bgra32
ほー、いいじゃないか
こういうのでいいんだよ、こういうので(ご満悦)
そもそもBitmapImageを使って普通に読み込めば自動でBgra32になるんだけど
今までわざわざPbgra32に変換して読み込んでいた
最初はPbgra32とBgra32どちらもARGBそれぞれに8bitずつで合計32bit(bpp)と、全く同じなんだけど、どこが違うんだろうと検索していたら、Pbgra32のほうが処理が少し速いってのが英語であって、理解できなかったけど早いに越したことはないと思って使っていた
見た目は期待通りに問題なく表示されるから気が付かなかったんだよねえ
FormatConvertedBitmapとか使ってよけいなことしないで
普通にBitmapImageにファイルパスを渡して普通に読み込んでいればよかった、44行目
これなら自動で選んでくれたのがBgra32になる、45行目
もう一回どう変化しているのか見てみると
透明度のAは変化せず、RGBの値が一律4割に減っている感じ
A R G B
元の色 #641E7AE0 100, 30, 122, 224
Formats 色
Pbgra32 #640C3058 100, 12, 48, 88
R=12/30=0.4
R=0.4、G=0.39344262、B=0.39285714
この4割ってのはAの最大値255に対するAの値と同じ割合で
100/255=0.39215686
なんだよねえ