Comment convertir un tableau d'octets de 19200 octets où chaque octet représente 4 pixels (2 bits par pixel) à un bitmap agencé en tant que caractères 320x240

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

  •  24-10-2019
  •  | 
  •  

Question

Je communique avec un instrument (contrôle à distance, il) et
l'une des choses que je dois faire est de dessiner l'écran de l'appareil.

Afin d'obtenir l'écran j'envoie une commande et l'instrument
les réponses avec un tableau d'octets qui représente l'écran.

Ci-dessous ce que le manuel de l'instrument doit dire au sujet de la conversion de la réponse à l'écran réel:

La commande récupère les données de mémoire vidéo utilisées pour l'affichage.
Il est de 19200 octets, 2 bits par pixel, 4 pixels par octet disposés comme
320x240 caracteres.
Les données sont envoyées sous forme codée RLE.
Pour convertir ces données dans un fichier BMP pour une utilisation dans Windows, il doit être
transformé en un 4bpp. Notez également que les fichiers BMP sont à l'envers
par rapport à ces données, à savoir la ligne d'affichage supérieure est la dernière ligne de la BMP.

J'ai réussi à décompresser les données, mais maintenant je suis coincé sur la façon de réellement
aller du tableau d'octets décompressé à un bitmap.

Mon fond sur ce point est assez proche de zéro et mes recherches
n'ont pas révélé non plus.

Je cherche des directions et / ou des articles que je pourrais utiliser pour me aider
undestand comment réaliser ce but.

Tout code ou même pseudo code serait également utile. :-)

Alors, pour résumer tout cela:

Comment convertir un tableau d'octets de 19200 octets, où
chaque octet représente 4 pixels (2 bits par pixel), France à un bitmap agencé en 320x240 caractères.

Merci à l'avance.

Était-ce utile?

La solution

Pour ce faire quelque chose comme, vous voulez une routine comme ceci:

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

d'ici, vous avez besoin ReadPixelValue et 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;        
}

Fondamentalement, je tire chaque ensemble de deux bits de chaque octet et le retourner comme un int.

En ce qui concerne la conversion de couleur qui est à vous comment faire la tête ou la queue des 4 valeurs qui reviennent. Très probablement, vous pouvez faire quelque chose comme ceci:

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

Autres conseils

Si vous avez deux bits par pixel, pour chaque pixel que vous avez 4 différentes couleurs possibles. Probablement les couleurs sont indexées ou tout simplement codés en dur (à savoir 0 signifie noir, blanc 1, etc).

Je ne sais pas si cela est d'une grande aide (je ne sais pas quel objet bitmap que vous utilisez, mais peut-être il a un schéma régulier RVB ou ARVB avec 1 octet par canal), mais en pseudo-actionscript, je pensez que vous devriez faire quelque chose comme ça.

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

Le code ci-dessus, il suffit de dire, est juste pour vous donner une idée (je l'espère!) Et repose sur certaines hypothèses comme la façon dont ces quatre pixels sont stockés dans un octet.

Hope il est logique.

I dont know if this helps, I use this for data I got from a rare old hardware:

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

        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top