9

ビットベースの B/W/Greyscale Pre-Compiled フォント形式に取り組んでおり、形式の読み取りまたは書き込みに問題がありました (問題がどこにあるのか特定できませんでした。白黒のビットベースのバージョンは動作しますが、ご想像のとおり、特に 320x200 ピクセルの画面で作業する場合、Aliased フォントは見栄えがよくありません) ) しかし、BinaryWriter を使用するだけで、画像データをプルしたときのbool[]。

ファイル内のピクセルの基本的な形式は次のようになります。

1 - ホワイト ピクセル (これがほとんどのピクセルになるため、最も短い)

00 - 黒ピクセル (妥当な数の純粋な黒ピクセルに 10 ビットを書き込む理由はありません)

01 - グレースケール ピクセル。ピクセルの色合いを表す 1 バイトが続きます。

これで、必要な情報を書き込むことですべてがうまくいきます。これはすべてフル バイトですが、デフォルトの .Net 4.0 BinaryWriter はブール値をフル バイトとして書き込みます。フォーマット。それで、ビットベースのBinaryWriter(およびBinaryReader)の実装があるのだろうかと思っていました

編集:私は自分自身を作成することになりました。(コードについては、回答を参照してください。)

4

4 に答える 4

7

このフレームワークには何もないと思います。基本的に、(または単にストリーム) と「これまでに書き込まれたバイト」と書き込まれたビット数をラップするクラスを作成する必要があります。BinaryWriterビット数が 8 になったら、基になるストリームにバイトを書き込み、クリアします。

編集:OPは、上記の提案の可能な実装と機能する実装を以下に投稿しました。

于 2011-08-13T17:20:40.940 に答える
7

私は自分で書くことになったので、ここにそれらがあります。

BinaryWriter (必要なものだけをオーバーライドしました)

private class BinaryWriter : System.IO.BinaryWriter
{
    private bool[] curByte = new bool[8];
    private byte curBitIndx = 0;
    private System.Collections.BitArray ba;

    public BinaryWriter(Stream s) : base(s) { }

    public override void Flush()
    {
        base.Write(ConvertToByte(curByte));
        base.Flush();
    }

    public override void Write(bool value)
    {
        curByte[curBitIndx] = value;
        curBitIndx++;

        if (curBitIndx == 8)
        {
            base.Write(ConvertToByte(curByte));
            this.curBitIndx = 0;
            this.curByte = new bool[8];
        }
    }

    public override void Write(byte value)
    {
        ba = new BitArray(new byte[] { value });
        for (byte i = 0; i < 8; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    public override void Write(byte[] buffer)
    {
        for (int i = 0; i < buffer.Length; i++)
        {
            this.Write((byte)buffer[i]);
        }
    }

    public override void Write(uint value)
    {
        ba = new BitArray(BitConverter.GetBytes(value));
        for (byte i = 0; i < 32; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    public override void Write(ulong value)
    {
        ba = new BitArray(BitConverter.GetBytes(value));
        for (byte i = 0; i < 64; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    public override void Write(ushort value)
    {
        ba = new BitArray(BitConverter.GetBytes(value));
        for (byte i = 0; i < 16; i++)
        {
            this.Write(ba[i]);
        }
        ba = null;
    }

    private static byte ConvertToByte(bool[] bools)
    {
        byte b = 0;

        byte bitIndex = 0;
        for (int i = 0; i < 8; i++)
        {
            if (bools[i])
            {
                b |= (byte)(((byte)1) << bitIndex);
            }
            bitIndex++;
        }

        return b;
    }
}

また、BinaryReader についても、必要なメソッドのみをオーバーライドしました。

private class BinaryReader : System.IO.BinaryReader
{
    private bool[] curByte = new bool[8];
    private byte curBitIndx = 0;
    private BitArray ba;

    public BinaryReader(Stream s) : base(s)
    {
        ba = new BitArray(new byte[] { base.ReadByte() });
        ba.CopyTo(curByte, 0);
        ba = null;
    }

    public override bool ReadBoolean()
    {
        if (curBitIndx == 8)
        {
            ba = new BitArray(new byte[] { base.ReadByte() });
            ba.CopyTo(curByte, 0);
            ba = null;
            this.curBitIndx = 0;
        }

        bool b = curByte[curBitIndx];
        curBitIndx++;
        return b;
    }

    public override byte ReadByte()
    {
        bool[] bar = new bool[8];
        byte i;
        for (i = 0; i < 8; i++)
        {
            bar[i] = this.ReadBoolean();
        }

        byte b = 0;
        byte bitIndex = 0;
        for (i = 0; i < 8; i++)
        {
            if (bar[i])
            {
                b |= (byte)(((byte)1) << bitIndex);
            }
            bitIndex++;
        }
        return b;
    }

    public override byte[] ReadBytes(int count)
    {
        byte[] bytes = new byte[count];
        for (int i = 0; i < count; i++)
        {
            bytes[i] = this.ReadByte();
        }
        return bytes;
    }

    public override ushort ReadUInt16()
    {
        byte[] bytes = ReadBytes(2);
        return BitConverter.ToUInt16(bytes, 0);
    }

    public override uint ReadUInt32()
    {
        byte[] bytes = ReadBytes(4);
        return BitConverter.ToUInt32(bytes, 0);
    }

    public override ulong ReadUInt64()
    {
        byte[] bytes = ReadBytes(8);
        return BitConverter.ToUInt64(bytes, 0);
    }
}
于 2011-08-15T16:31:29.283 に答える
3

データをバイト配列(ブール値は役に立たず、スペースを取りすぎます。ビットに使用すると、メモリ内のバイトを占有します)またはstructデータ形式に合った特定の配列にデータを保持する場合。

内部メモリ表現を取得したら、ビットベースのバイナリ ライターはもう必要ありません。データを BinaryWriter に書き込むだけで完了です。

...しかし、デフォルトの.Net 4.0 BinaryWriterはブール値をフルバイトとして書き込みます。ご想像のとおり、ビットベースのフォーマットの使用を無効にします....

その理由は次のとおりです。C# では、bool は定義により 1 バイト サイズです。BinaryWriter は、与えられたものを単純に書き込みます。

于 2011-08-13T17:28:47.450 に答える