So konvertieren Sie ein Byte -Array von 19200 Bytes in Größe, wobei jedes Byte 4 Pixel (2 Bit pro Pixel) in eine Bitmap repräsentiert, die als 320x240 Zeichen angeordnet ist

StackOverflow https://stackoverflow.com/questions/2969208

  •  24-10-2019
  •  | 
  •  

Frage

Ich kommuniziere mit einem Instrument (Fernbedienung es) und
Eines der Dinge, die ich tun muss, ist, den Instrumentenbildschirm zu zeichnen.

Um den Bildschirm zu erhalten, stelle ich einen Befehl und das Instrument aus
Antworten mit einer Reihe von Bytes, die den Bildschirm darstellen.

Im Folgenden finden Sie das Instrumentenhandbuch über die Konvertierung der Antwort in den tatsächlichen Bildschirm:

Der Befehl ruft die für die Anzeige verwendeten FrameBuffer -Daten ab.
Es ist 19200 Bytes Größe, 2 Bit pro Pixel, 4 Pixel pro Byte als angeordnet als
320x240 Charakter.
Die Daten werden in RLE -codiertem Formular gesendet.
Um diese Daten für die Verwendung in Windows in einen BMP umzuwandeln, muss dies sein
verwandelte sich in ein 4BPP. Beachten Sie auch, dass BMP -Dateien relativ auf dem Kopf stehen
Zu diesen Daten ist die obere Anzeigezeile die letzte Zeile im BMP.

Ich habe es geschafft, die Daten auszupacken, aber jetzt bin ich festgefahren, wie es tatsächlich zu finden ist
Gehen Sie vom ausgepackten Byte -Array zu einer Bitmap.

Mein Hintergrund dazu ist ziemlich nahe Null und meine Suchanfragen
habe auch nicht viel enthüllt.

Ich suche nach Anweisungen und/oder Artikeln, mit denen ich mir helfen könnte, mir zu helfen
Untestand, wie man das erledigt.

Jeder Code oder sogar Pseudocode würde ebenfalls helfen. :-)

Also nur um alles zusammenzufassen:

Wie man ein Byte -Array von 19200 Bytes in Größe umwandelt, wo
Jedes Byte repräsentiert 4 Pixel (2 Bit pro Pixel),
zu einer Bitmap, die als 320x240 Zeichen angeordnet ist.

Danke im Voraus.

War es hilfreich?

Lösung

Um so etwas zu tun, möchten Sie eine Routine wie diese:

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;
}

Von hier aus benötigen Sie ReadPixelValue und 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;        
}

Grundsätzlich ziehe ich jeden Satz von zwei Teilen aus jedem Byte heraus und kehre es als int zurück.

Für die Konvertierung in Farbe liegt das bei Ihnen, wie Sie Köpfe oder Schwanz der 4 zurückkommenden Werte herstellen. Höchstwahrscheinlich können Sie so etwas tun:

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];
}

Andere Tipps

Wenn Sie zwei Bits pro Pixel haben, haben Sie für jedes Pixel 4 verschiedene mögliche Farben. Wahrscheinlich sind die Farben indiziert oder nur festcodiert (dh 0 bedeutet schwarz, 1 weiß usw.).

Ich weiß nicht, ob dies viel Hilfe ist (ich weiß nicht, welches Bitmap-Objekt Sie verwenden, aber vielleicht hat es ein regelmäßiges RGB- oder ARGB Mach so etwas.

//  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
    }
}

Der obige Code genügt es zu sagen, nur eine Idee zu geben (hoffentlich!) Und basiert auf einigen Annahmen, wie diese vier Pixel in einem Byte gespeichert werden.

Hoffe es macht Sinn.

Ich weiß nicht, ob dies hilft, ich verwende dies für Daten, die ich von einer seltenen alten Hardware erhalten habe:

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

        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top