如何从TBitmap获取像素阵列?

问题描述 投票:1回答:2

在相机应用程序中,从流式相机检索位图像素阵列。通过将像素数组写入命名管道来捕获像素阵列,在该管道的另一端,ffmpeg检索它们并创建一个AVI文件。

我将需要创建一个自定义帧(启用自定义文本),并将其像素作为结果电影的第一帧进行管道传输。

问题是我如何使用TBitmap(为了方便)到>>

  1. 从头开始创建X by Y单色(8位)位图,自定义文字。我希望背景为白色,文本为是黑色的。 (通常想出了这一步骤,请参阅下文。)

  2. 检索我可以发送/写入管道的像素数组

  3. 步骤1:以下代码创建一个TBitmap并在其上写入文本:

int w = 658;
int h = 492;
TBitmap* bm = new TBitmap();
bm->Width = w;
bm->Height = h;
bm->HandleType = bmDIB;
bm->PixelFormat = pf8bit;

bm->Canvas->Font->Name = "Tahoma";
bm->Canvas->Font->Size = 8;

int textY = 10;
string info("some Text");

bm->Canvas->TextOut(10, textY, info.c_str());

以上基本上完成了步骤1。

编写代码需要一个带有位图像素的字节数组;例如

unsigned long numWritten;
WriteFile(mPipeHandle, pImage, size, &numWritten, NULL);

其中pImage是指向无符号字符缓冲区(位图像素)的指针,大小是该缓冲区的长度。

更新:使用生成的TBitmap和TMemoryStream将数据传输到ffmpeg不会生成正确的结果。我得到了扭曲的图像,上面有3条对角线。我怀疑我只需要传递像素数据,如下面的答案所示。

我收到的相机帧缓冲区的缓冲区大小正好是323736,它等于图像中的像素数,即658x492。

将生成的位图转储到内存流后获得的缓冲区大小为325798,比预期的大小大2062字节。我怀疑这是“标题”吗?

按照示例代码here,尝试将像素作为数组获取我仍然得到一个“大”的数组,即比我从相机获得的缓冲区大2062字节。

BYTE* CustomBitmap::getPixArray()
{

HBITMAP hBitmap = this->mTheBitmap->Handle;
HDC hdc, hdcMem;
hdc = GetDC(NULL);
BITMAPINFO MyBMInfo = {0};
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

// Get the BITMAPINFO structure from the bitmap
if(0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS))
{
    return NULL;
}

// create the bitmap buffer
BYTE* mPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
//    MyBMInfo.bmiHeader.biBitCount = 8;
MyBMInfo.bmiHeader.biCompression = BI_RGB;
MyBMInfo.bmiHeader.biHeight = (MyBMInfo.bmiHeader.biHeight < 0) ? (- MyBMInfo.bmiHeader.biHeight) : (MyBMInfo.bmiHeader.biHeight);

//get the actual bitmap buffer
if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID) 
  mPixels, &MyBMInfo, DIB_RGB_COLORS))
{
    return NULL;
}

ReleaseDC(NULL, hdc);
return mPixels;

在上面的代码中,即使我选择pixelformat pf8,检查biBitCount也会得到32,而不是8。如果将TBitmapHandle类型设置为bmDDB,则会发生这种情况。有趣的是,如果我将句柄设置为bmDIB,则getPixArray()函数在退出时崩溃!显然这里有些鱼。.?

在相机应用程序中,从流式相机检索位图像素阵列。通过将像素数组写入命名管道来捕获像素阵列,在该管道的另一端,ffmpeg检索...

c++ bitmap c++builder vcl
2个回答
2
投票

[TBitmap具有PixelFormat属性来设置位深度。


0
投票

这只是现有答案的附件(在OP编辑后带有附加信息)

© www.soinside.com 2019 - 2024. All rights reserved.