1

私は計測器と通信しています (遠隔操作)
が必要で、計測器の画面を描画する必要があります。

画面を取得するためにコマンドを発行すると、計測器
は画面を表すバイト配列を返します。

以下は、応答を実際の画面に変換することについて、機器のマニュアルに記載されている内容です。

このコマンドは、表示に使用されるフレーム バッファ データを取得します。
サイズは 19200 バイト、ピクセルあたり 2 ビット、バイトあたり 4 ピクセルで、
320x240 文字として配置されます。
データは RLE エンコード形式で送信されます。
このデータを Windows で使用できるように BMP に変換するには
、4BPP に変換する必要があります。また、BMP ファイルはこのデータに対して上下が逆になっていることに注意してください
。つまり、一番上の表示行が BMP の最後の行です。

データを解凍することができましたが、実際
に解凍されたバイト配列からビットマップに移動する方法に行き詰まっています。

これに関する私のバックグラウンドはほぼゼロに近く、検索し
てもあまり明らかになりませんでした。


これを行う方法を理解 するのに役立つ指示や記事を探しています。

任意のコードまたは疑似コードも役立ちます。:-)

したがって、すべてを要約すると、次のようになります。


各バイトが 4 ピクセル (1 ピクセルあたり 2 ビット) を表す、サイズが 19200 バイトのバイト配列を、
320x240 文字として配置されたビットマップに変換する方法。

前もって感謝します。

4

3 に答える 3

2

このようなことを行うには、次のようなルーチンが必要になります。

Bitmap ConvertToBitmap(byte[] data, int width, int height)
{
    Bitmap bm = new Bitmap(width, height, PixelFormat.Format24bppRgb);
    for (int y=0; y < height; y++) {
        for (int x=0; x < width; x++) {
            int value = ReadPixelValue(data, x, y, width);
            Color c = ConvertValToColor(value);
            bm.SetPixel(x, y, c);
        }
    }
    return bm;
}

ここから、ReadPixelValue と ConvertValToColor が必要になります。

static int ReadPixelValue(byte[] data, int x, int y, width)
{
    int pixelsPerByte = 4;
    // added the % pixelsPerByte to deal with width not being a multiple of pixelsPerByte,
    // which won't happen in your case, but will in the general case
    int bytesPerLine = width / pixelsPerByte + (width % pixelsPerByte != 0 ? 1 : 0);
    int index = y * bytesPerLine + (x / pixelsPerByte);
    byte b = data[index];

    int pixelIndex = (x % pixelsPerByte) * 2;
    // if every 4 pixels are reversed, try this:
    // int pixelIndex = 8 - (x % pixelsPerByte) * 2;
    return ((int b) >> pixelIndex) & 0x3;        
}

基本的に、各バイトから 2 ビットの各セットを取り出して、int として返します。

色への変換に関しては、返された 4 つの値の先頭または末尾を作成する方法はあなた次第です。ほとんどの場合、次のようなことができます。

static Color[] _colors = new Color[] { Color.Black, Color.Red, Color.Blue, Color.White };
static Color ConvertValToColor(int val)
{
    if (val < 0 || val > _colors.Length)
        throw new ArgumentOutOfRangeException("val");
    return _colors[val];
}
于 2010-06-03T20:02:52.577 に答える
1

ピクセルあたり 2 ビットの場合、各ピクセルには 4 つの異なる色があります。おそらく、色はインデックス化されているか、ハードコードされているだけです (つまり、0 は黒、1 は白などを意味します)。

これが役立つかどうかはわかりません (使用しているビットマップ オブジェクトはわかりませんが、おそらくチャンネルごとに 1 バイトの通常の RGB または ARGB スキームを使用しています)。このようなことをしてください。

//  80 -> 320 / 4
for(var x:int = 0; x < 80; x++) {
    for(var y:int = 0; y < 240; y++) {
        var byteVal:int = readByte();

        var px_1:int = (byteVal >> 6) & 0x03;
        var px_2:int = (byteVal >> 4) & 0x03;
        var px_3:int = (byteVal >> 2) & 0x03;
        var px_4:int = (byteVal) & 0x03;

        //  map your pixel value to ARGB 
        px_1 = getPixelValue(px_1);
        px_2 = getPixelValue(px_2);
        px_3 = getPixelValue(px_3);
        px_4 = getPixelValue(px_4);     
        //  assuming setPixel(x,y,pixelValue)
        setPixel((x * 4), y, px_1);
        setPixel((x * 4) + 1, y, px_2);
        setPixel((x * 4) + 2, y, px_3);
        setPixel((x * 4) + 3, y, px_4);


    }
}

function getPixelValue(idx:int):uint {
    //   just an example...
    switch(idx) {
        case 0:     return 0xff000000;  //  black
        case 1:     return 0xffffffff;  //  white
        case 2:     return 0xffff0000;  //  red
        case 3:     return 0xff0000ff;  //  blue
    }
}

上記のコードは、アイデアを提供するためのものであり (願わくば!)、これらの 4 つのピクセルが 1 バイトにどのように格納されるかなどのいくつかの仮定に基づいています。

それが理にかなっていることを願っています。

于 2010-06-03T20:01:44.903 に答える
0

これが役立つかどうかはわかりません。まれな古いハードウェアから取得したデータにこれを使用します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] imageBytes = new byte[19201];
            //(Fill it with the data from the unit before doing the rest).
            Bitmap bmp_workarea = new Bitmap(320, 240, System.Drawing.Imaging.PixelFormat.Format4bppIndexed);
            Image newImage = Image.FromStream(new MemoryStream(imageBytes));
            using (Graphics gr = Graphics.FromImage(bmp_workarea))
            {
                gr.DrawImage(newImage, new Rectangle(0, 0, bmp_workarea.Width, bmp_workarea.Height));
            }
            //now you can use newImage, for example picturebox1.image=newimage

        }
    }
}
于 2010-06-03T20:11:13.053 に答える