各バイトが320x240文字として配置されたビットマップに4ピクセル(ピクセルあたり2ビット)を表すサイズの19200バイトのバイト配列を変換する方法
質問
私は楽器と通信しています(リモート制御)と
私がしなければならないことの1つは、楽器画面を描くことです。
画面を取得するために、コマンドと楽器を発行します
画面を表すバイトの配列で応答します。
以下は、実際の画面への応答を変換することについて、機器マニュアルが言っていることです。
コマンドは、ディスプレイに使用されるFrameBufferデータを取得します。
サイズが19200バイト、ピクセルあたり2ビット、バイトあたり4ピクセルが配置されています
320x240文字。
データはRLEエンコードフォームで送信されます。
このデータをWindowsで使用するためにBMPに変換するには、
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とconvertaltocolorが必要です。
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];
}
他のヒント
ピクセルごとに2ビットがある場合、ピクセルごとに4つの異なる可能な色があります。おそらく、色はインデックス化されているか、単にハードコードされています(つまり、黒は黒、1つの白などを意味します)。
これが多くの助けがあるかどうかはわかりません(使用しているBitMapオブジェクトはわかりませんが、おそらくチャネルごとに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つのピクセルがバイトに保存される方法などのいくつかの仮定に基づいています。
それが理にかなっていることを願っています。
これが役立つかどうかはわかりません。これは、珍しい古いハードウェアから得たデータに使用します。
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
}
}
}