如何转换大小为19200字节的字节数组,其中每个字节代表4个像素(每像素2位)到排列为320x240个字符的位图

我正在与仪器通信(远程控制它)和 我需要做的一件事就是绘制仪器屏幕。 为了获得屏幕,我发出命令和仪器 回复表示屏幕的字节数组。 以下是关于将响应转换为实际屏幕的仪器手册:   该命令检索用于显示的帧缓冲区数据。   它的大小为19200字节,每像素2位,每字节4个像素排列为   320x240 characteres。   数据以RLE编码形式发送。   要将此数据转换为BMP以便在Windows中使用,它需要   变成了4BPP。另请注意,BMP文件是相对颠倒的   对于该数据,即顶部显示行是BMP中的最后一行。 我设法解压缩数据,但现在我被困在如何实际上 从解压缩的字节数组转到位图。 我的背景非常接近零和我的搜索 也没有透露太多。 我正在寻找可以用来帮助我的方向和/或文章 不明白如何完成这项工作。 任何代码甚至伪代码也会有所帮助。 :-) 所以,只是总结一下:   如何转换大小为19200字节的字节数组,其中   每个字节代表4个像素(每像素2位),   以位图排列为320x240个字符。 提前致谢。     
已邀请:
要做这样的事情,你需要这样的例程:
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;        
}
基本上,我从每个字节中拉出每组两位,并将其作为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];
}
    
如果每个像素有两位,则对于每个像素,您有4种不同的可能颜色。可能是颜色被索引或只是硬编码(即0表示黑色,1表示白色等)。 不知道这是否有多大帮助(我不知道你正在使用什么位图对象,但也许它有一个常规的RGB或ARGB方案,每个通道有1个字节),但在伪动作脚本中,我认为你应该做这样的事情。
//  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
    }
}
上面的代码就足够了,只是为了给你一个想法(希望如此!)并且基于一些假设,比如这四个像素如何存储在一个字节中。 希望它有意义。     
我不知道这是否有帮助,我将它用于从稀有旧硬件获得的数据:
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

        }
    }
}
    

要回复问题请先登录注册