5

ビットマップを8bppに変換する最速の方法を探していました。私は2つの方法を見つけました:

1.1。

        public static System.Drawing.Image ConvertTo8bpp(Bitmap oldbmp)
    {
        using (var ms = new MemoryStream())
        {
            oldbmp.Save(ms, ImageFormat.Gif);
            ms.Position = 0;
            return System.Drawing.Image.FromStream(ms);
        }
    }

2. http://www.wischik.com/lu/programmer/1bpp.html

しかし: 1。非常に低品質の結果になります(不良パレット)

2は、負のストライドのビットマップを表示します。ロックビットを使用してデータをバイト配列にコピーしようとすると、例外が発生します。保護されたメモリの読み取りまたは書き込みを試みました。これは多くの場合、他のメモリが破損していることを示しています。

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

        this.stride = bmpData.Stride;
        this.bytesPerPixel = GetBytesPerPixel(bmp.PixelFormat);
        int length = bmpData.Stride * bmp.Height;
        if (this.stride < 0)
            this.data = new byte[-length];
        else
            this.data = new byte[length];
        Marshal.Copy(bmpData.Scan0, data, 0, length);

        //Unlock the bitmap
        bmp.UnlockBits(bmpData);

どうすれば2を作ることができますか?または、負のストライドのロックビットを使用してデータをコピーするにはどうすればよいですか?

4

5 に答える 5

8

ここでの問題はScan0、データの最初のバイトの先頭ではなく、最初のスキャンラインの先頭を指していることです。ボトムアップビットマップでは、最初のスキャンラインはStrideビットマップデータの末尾からのバイトです。

Marshal.Copyからデータをコピーするために呼び出すと、位置から開始してバイトScan0をコピーしようとします。明らかに、それは雑草に流れ込むでしょう。(Height*Stride)((Height-1)*Stride)

ビットマップデータをコピーするだけの場合は、で開始アドレスを計算する必要がありますScan0 - (Height-1)*Stride。これにより、ビットマップデータの先頭から開始されます。その計算されたアドレスをに渡すことができますMarshal.Copy

スキャンラインを順番に(つまり、上、次、次、...下)コピーする場合は、一度に1行ずつコピーする必要があります。Strideからバイトをコピーしてから(負の値)をScan0追加し、その行をコピーします。 Stride、など。リックブリュースターはそこに正しい答えを持っていました:https ://stackoverflow.com/a/10360753/56778

于 2013-06-14T19:39:40.893 に答える
7

一度に1行をコピーし、行の開始ポインターをとして計算します((byte*)scan0 + (y * stride))。コードは、正または負のストライドのどちらでも同じになります。

于 2012-04-28T05:03:39.357 に答える
5

FromHbitmapメソッドによって作成されたビットマップに何か奇妙なことがある理由はわかりませんがBitmap bmpClone = (Bitmap)bmp.Clone();、bmpCloneでLockBitsを使用して実行することで修正できることは知っています。

bmp.Clone()また、を使用すると、クローンが終了するまでbmpのDispose()を実行できないことがわかりました。

これも機能し、ネガティブストライドイメージを後でではなく早く破棄しましょう。

        Bitmap bmp = null;
        using (Bitmap bmpT = CopyToBpp(bmpO, 1))
        {
            bmp = new Bitmap(bmpT);
        }
于 2012-04-26T20:58:54.500 に答える
1

BitmapDataのC#ドキュメントから:ストライドは、4バイトの境界に切り上げられたピクセルの単一行(スキャンライン)の幅です。ストライドが正の場合、ビットマップはトップダウンです。ストライドが負の場合、ビットマップはボトムアップです

于 2011-07-26T18:55:11.087 に答える
-2

私はあなたが得ている例外が原因だと思います

this.data = new byte[-length];

そして、データを負のサイズのバイト配列にコピーしようとします(それが実際にどのようにコンパイルされるかはわかりません...)。

于 2012-05-03T12:01:10.547 に答える