TL; DR:私はbyte[]
です。私はBgra32Pixel[]
が欲しいです。コピーしたくない。コピーが必要な場合は、できるだけ高速にコピーを最適化し、1バイトをコピーしないでください。それも可能ですか?byte []をC#のstruct FASTの配列に変換する方法は?
詳しい説明:ここでは
が構造です:
/// <summary>
/// Represents a PixelFormats.Bgra32 format pixel
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct Bgra32Pixel {
[FieldOffset(0)]
public readonly int Value;
[FieldOffset(0)]
public byte B;
[FieldOffset(1)]
public byte G;
[FieldOffset(2)]
public byte R;
[FieldOffset(3)]
public byte A;
}
私はバイト配列を持って、それdata
を呼び出すことができます。私はBgra32Pixel[]
としてアクセスしたいと思います。 メモリ内の同じバイト。そのためにバイトをコピーする必要がありますか?
var pixels = data as Bgra32Pixel[];
をしかし、それはしていません:
私はこのような何かをしたいが働きました。それを行う最速の方法は何ですか?
私の推測では、オリジナルのbyte []参照から直接Bgra32Pixelを返すインデクサーでカスタムタイプを作成することです。しかしそれはあまり速くないでしょう。コピーは必要ありませんが、各アクセスは実際には4バイトから新しい構造体を作成します。いいえ、不必要ではないようです。 C#を考えてbyte []が何らかの形でBgra32Pixel []になるようにする方法がなければなりません。
だからここで私はすべての答えを読んだ後に発見された私のソリューションです:
TLは、DR:構造体の必要はありません。
structへの変換には、安全でないコンテキストと固定ステートメントが必要です。これはパフォーマンスには悪いことです。ビットマップから背景を削除するコードは、左上隅のピクセルが背景色であることを前提としています。このコードは、各ピクセルに特別な「色アルファへの」ブードゥー教を呼び出します。
/// <summary>
/// Extensions for bitmap manipulations.
/// </summary>
static class BitmapSourceExtensions {
/// <summary>
/// Removes the background from the bitmap assuming the first pixel is background color.
/// </summary>
/// <param name="source">Opaque bitmap.</param>
/// <returns>Bitmap with background removed.</returns>
public static BitmapSource RemoveBackground(this BitmapSource source) {
if (source.Format != PixelFormats.Bgr32) throw new NotImplementedException("Pixel format not implemented.");
var target = new WriteableBitmap(source.PixelWidth, source.PixelHeight, source.DpiX, source.DpiY, PixelFormats.Bgra32, null);
var pixelSize = source.Format.BitsPerPixel/8;
var pixelCount = source.PixelWidth * source.PixelHeight;
var pixels = new uint[pixelCount];
var stride = source.PixelWidth * pixelSize;
source.CopyPixels(pixels, stride, 0);
var background = new LABColor(pixels[0]);
for (int i = 0; i < pixelCount; i++) pixels[i] &= background.ColorToAlpha(pixels[i]);
var bounds = new Int32Rect(0, 0, source.PixelWidth, source.PixelHeight);
target.WritePixels(bounds, pixels, stride, 0);
return target;
}
}
あなたは非常に興味があれば、ここでは、使用ブードゥー教のクラスです:
/// <summary>
/// CIE LAB color space structure with BGRA pixel support.
/// </summary>
public struct LABColor {
/// <summary>
/// Lightness (0..100).
/// </summary>
public readonly double L;
/// <summary>
/// A component (0..100)
/// </summary>
public readonly double A;
/// <summary>
/// B component (0..100)
/// </summary>
public readonly double B;
/// <summary>
/// Creates CIE LAB color from BGRA pixel.
/// </summary>
/// <param name="bgra">Pixel.</param>
public LABColor(uint bgra) {
const double t = 1d/3d;
double r = ((bgra & 0x00ff0000u) >> 16)/255d;
double g = ((bgra & 0x0000ff00u) >> 8)/255d;
double b = (bgra & 0x000000ffu)/255d;
r = (r > 0.04045 ? Math.Pow((r + 0.055)/1.055, 2.4) : r/12.92) * 100d;
g = (g > 0.04045 ? Math.Pow((g + 0.055)/1.055, 2.4) : g/12.92) * 100d;
b = (b > 0.04045 ? Math.Pow((b + 0.055)/1.055, 2.4) : b/12.92) * 100d;
double x = (r * 0.4124 + g * 0.3576 + b * 0.1805)/95.047;
double y = (r * 0.2126 + g * 0.7152 + b * 0.0722)/100.000;
double z = (r * 0.0193 + g * 0.1192 + b * 0.9505)/108.883;
x = x > 0.0088564516790356311 ? Math.Pow(x, t) : (903.2962962962963 * x + 16d)/116d;
y = y > 0.0088564516790356311 ? Math.Pow(y, t) : (903.2962962962963 * y + 16d)/116d;
z = z > 0.0088564516790356311 ? Math.Pow(z, t) : (903.2962962962963 * z + 16d)/116d;
L = Math.Max(0d, 116d * y - 16d);
A = 500d * (x - y);
B = 200d * (y - z);
}
/// <summary>
/// Calculates color space distance between 2 CIE LAB colors.
/// </summary>
/// <param name="c">CIE LAB color.</param>
/// <returns>A color space distance between 2 colors from 0 (same colors) to 100 (black and white)</returns>
public double Distance(LABColor c) {
double dl = L - c.L;
double da = A - c.A;
double db = B - c.B;
return Math.Sqrt(dl * dl + da * da + db * db);
}
/// <summary>
/// Calculates bit mask for alpha calculated from difference between this color and another BGRA color.
/// </summary>
/// <param name="bgra">Pixel.</param>
/// <returns>Bit mask for alpha in BGRA pixel format.</returns>
public uint ColorToAlpha(uint bgra) => 0xffffffu | ((uint)(Distance(new LABColor(bgra)) * 2.55d) << 24);
}
私は戻って与えていますコミュニティ。私はStackOverflowとGithubで必要な数学をすべて見つけました。 GIMPは "color to alpha"エフェクトと非常によく似たものを使用していると思います。
質問はまだ開かれています:それを行うより速い方法がありますか?
http://stackoverflow.com/questions/31045358/how-do-i-copy-bytes-into-a-struct-variable- in-c –
バイト配列の形式は何ですか?それはシリアル化されているBgra32Pixelですか?あるいは、特定の順序でB/G/R/Aフィールドにメッシュ化する値を持つバイトの配列ですか?または、バイト配列はBgra32Pixelデータを含むメモリ内のアドレスへのポインタですか?または...? – Abion47
サンプルデータの中には、適切な答えを得るために長い道のりがあります。 – Abion47