【问题标题】:How to convert a byte array of 19200 bytes in size where each byte represents 4 pixels (2 bits per pixel) to a bitmap arranged as 320x240 characters如何将大小为 19200 字节的字节数组(每个字节代表 4 个像素(每像素 2 位))转换为排列为 320x240 字符的位图
【发布时间】:2010-06-03 19:42:33
【问题描述】:

我正在与仪器通信(远程控制它)并且
我需要做的一件事是绘制仪器屏幕。

为了获得屏幕,我发出命令和仪器
回复一个代表屏幕的字节数组。

以下是仪器手册关于将响应转换为实际屏幕的内容:

该命令检索用于显示的帧缓冲区数据。
它的大小为 19200 字节,每像素 2 位,每字节 4 像素排列为
320x240 个字符。
数据以 RLE 编码形式发送。
要将此数据转换为 BMP 以在 Windows 中使用,它需要
变成了4BPP。另请注意,BMP 文件是相对颠倒的
到此数据,即顶部显示行是 BMP 中的最后一行。

我设法解压数据,但现在我被困在如何实际解压
从解压缩的字节数组转到位图。

我在这方面的背景几乎为零,而且我的搜索量
也没有透露太多。

我正在寻找可以帮助我的方向和/或文章
不知道如何完成这项工作。

任何代码甚至伪代码也会有所帮助。 :-)

所以,总结一下:

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

提前致谢。

【问题讨论】:

    标签: c# bitmap bpp


    【解决方案1】:

    要做这样的事情,你需要这样的例程:

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

    【讨论】:

    • 感谢一堆底座。有效。我确实必须使用“反向”代码。这对我来说都是黑魔法,所以我有一些学习要做。 :-) 但是,它有效,而且非常棒。
    【解决方案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
        }
    }
    

    上面的代码,我只想说,只是给你一个想法(希望如此!)并且基于一些假设,例如这四个像素如何存储在一个字节中。

    希望它有意义。

    【讨论】:

      【解决方案3】:

      我不知道这是否有帮助,我将其用于从罕见的旧硬件获得的数据:

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

      【讨论】:

      • 他的数据是每像素 2 位,而不是每像素 4 位,所以这会失败。
      猜你喜欢
      • 2022-05-11
      • 2012-11-16
      • 1970-01-01
      • 2013-01-14
      • 2013-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多