2

得られた画像の一部は傾いており、一部は傾いていません。

期待される結果: (529x22)

ここに画像の説明を入力

実際の結果: (529x22)

さまざまな画像サイズを気にしないでください。これらはスクリーンショットです。どちらも 529x22 です。

ここに画像の説明を入力

私が使用しているコードは、ここSOの質問に対する回答から得たものです。

// some other method
byte[] pixels = new byte[size - 16];
Array.Copy(this.data, offset, pixels, 0, pixels.Length);
this.ByteToImage(w, h, pixels);

// builds the pixels to a image
private Bitmap ByteToImage(int w, int h, byte[] pixels)
{
    var bmp = new Bitmap(w, h, PixelFormat.Format16bppRgb565);

    var BoundsRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    BitmapData bmpData = bmp.LockBits(BoundsRect,
                                    ImageLockMode.WriteOnly,
                                    bmp.PixelFormat);

    // bytes => not using this because it gives error
    // eg. pixel.Length = 16032, bytes = 16064
    int bytes = bmpData.Stride * bmp.Height;

    Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
    bmp.UnlockBits(bmpData);

    return bmp;
}

斜めではなく、うまくいくものもあるので、私は混乱しています。しかし、他の人は傾いています。私は何を取りこぼしたか?

アップデート

コメントと回答で述べたように、問題はストライドの計算方法です。私はまだそれを行う方法について混乱していますが、これを試しました:

public static void RemovePadding(this Bitmap bitmap)
{
    int bytesPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;

    BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
    var pixels = new byte[bitmapData.Width * bitmapData.Height * bytesPerPixel];

    for (int row = 0; row < bitmapData.Height; row++)
    {
        var dataBeginPointer = IntPtr.Add(bitmapData.Scan0, row * bitmapData.Stride);
        Marshal.Copy(dataBeginPointer, pixels, row * bitmapData.Width * bytesPerPixel, bitmapData.Width * bytesPerPixel);
    }

    Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);
    bitmap.UnlockBits(bitmapData);
}

しかし、結果は(より傾いています):

ここに画像の説明を入力

4

2 に答える 2

3

これはここで機能するようです:

private Bitmap ByteToImage(int w, int h, byte[] pixels)
{
    var bmp = new Bitmap(w, h, PixelFormat.Format16bppRgb565);
    byte bpp = 2;
    var BoundsRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    BitmapData bmpData = bmp.LockBits(BoundsRect,
                                    ImageLockMode.WriteOnly,
                                    bmp.PixelFormat);
    // copy line by line:
    for (int y = 0; y < h; y++ )
        Marshal.Copy(pixels, y * w * bpp, bmpData.Scan0 + bmpData.Stride * y, w * bpp);
    bmp.UnlockBits(bmpData);

    return bmp;
}

ループを使用して、データの各行を適切な場所に配置します。データにはパディングが含まれていませんが、ターゲット アドレスにはパディングが含まれている必要があります。

したがって、データ アクセスには実際のアドレスを掛ける必要がありますwidth * bytePerPixelが、ターゲット アドレスにはStride、次の 4 バイトの倍数にパディングされたスキャンラインの長さを掛ける必要があります。それwidth=300stride=300width=301それはstride=304..

すべてのピクセル データを 1 ステップで移動できるのは、パディングがない場合、つまり幅が の倍数の場合のみです4

于 2016-08-20T10:57:40.140 に答える