我无法在C++(Microsoft Visual C++)中将GDI+位图转换为基64



我无法在C++中将GDI+位图转换为基64

到目前为止:

  1. 已下载并包含此库:https://github.com/ReneNyffenegger/cpp-base64

  2. 编写了如下所示的函数。

  3. 调用它,传入一个我知道有数据的位图。我知道位图有数据,因为我在这个函数后面直接调用的另一个函数中使用。

问题是charPixels数组总是充满零。

第二,你能向我解释一下解锁比特的安全方法是什么吗?我担心如果我最后这么做,如果比特在那一点上没有真正锁定,我会得到一个例外。

步幅是一个正数,它是:1280。

此外,我还可以访问"finally",因为它是C++的MS扩展。

[注意:代码更新是因为我错误地粘贴了错误的代码]

std::string GdiBitmapToBase64(Gdiplus::Bitmap* gdiBitmap, int width, int height)
{
unsigned char* charPixels = nullptr;
try
{
Gdiplus::Rect rect = Gdiplus::Rect(0, 0, width, height);
Gdiplus::BitmapData gdiBitmapData;
gdiBitmap->LockBits(&rect, Gdiplus::ImageLockMode::ImageLockModeRead, PixelFormat32bppARGB, &gdiBitmapData);
auto stride = gdiBitmapData.Stride;
if (stride < 0) stride = -stride;
charPixels = new unsigned char[height * stride];
memset(charPixels, 0, height * stride);
memcpy(charPixels, gdiBitmapData.Scan0, stride);
std::string ret = base64_encode(charPixels, stride);
gdiBitmap->UnlockBits(&gdiBitmapData);
return ret;
}
finally
{
if(charPixels != nullptr)
{
delete[] charPixels;
}
}
}

这是调用此方法的代码。这可能会有所帮助:

void CLIScumm::Wrapper::ScreenUpdated(const void* buf, int pitch, int x, int y, int w, int h, PalletteColor* color)
{
const unsigned char* bufCounter = static_cast<const unsigned char*>(buf);
for (int hightCounter = 0; hightCounter < h; hightCounter++, bufCounter = bufCounter + pitch)
{
for (int widthCounter = 0; widthCounter < w; widthCounter++)
{
PalletteColor currentColor = *(color + *(bufCounter + widthCounter));
gdiBitmap->SetPixel(x + widthCounter, y + hightCounter, Gdiplus::Color(currentColor.r, currentColor.g, currentColor.b));
}
}
_screenUpdated->Invoke(gcnew System::String(GdiBitmapToBase64(gdiBitmap, DISPLAY_DEFAULT_WIDTH, DISPLAY_DEFAULT_HEIGHT).c_str()));
}

声明:

namespace CLIScumm {
public ref class Wrapper {
...
private:
...
Gdiplus::Graphics* gdiGraphics;
Gdiplus::Bitmap* gdiBitmap;
...
};

And the initialization:
void CLIScumm::Wrapper::init()
{
if (!hasStarted)
{
try
{
if (!hasStarted)
{
...
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
(malloc(sizeof(100000) * DISPLAY_DEFAULT_HEIGHT * DISPLAY_DEFAULT_WIDTH));
gdiBitmap = new Gdiplus::Bitmap(DISPLAY_DEFAULT_WIDTH, DISPLAY_DEFAULT_HEIGHT, PixelFormat32bppARGB);
gdiGraphics = new Gdiplus::Graphics(gdiBitmap);
InitImage();
...
}
}
...
}
}

感谢大家的帮助,但我解决了自己的问题。

我把位图像素数据和位图的实际字节搞混了,Scan0就是前者。我之所以只得到零分,是因为前几帧是黑色的。

我遵循了从C++gdi::Bitmap到内存中的PNG Image的示例来获得实际的位图字节。

我将示例函数修改为:

bool SavePngMemory(Gdiplus::Bitmap* gdiBitmap, std::vector<BYTE>& data)
{
//write to IStream
IStream* istream = nullptr;
CreateStreamOnHGlobal(NULL, TRUE, &istream);
CLSID clsid_bmp;
CLSIDFromString(L"{557cf400-1a04-11d3-9a73-0000f81ef32e}", &clsid_bmp);
Gdiplus::Status status = gdiBitmap->Save(istream, &clsid_bmp);
if (status != Gdiplus::Status::Ok)
return false;
//get memory handle associated with istream
HGLOBAL hg = NULL;
GetHGlobalFromStream(istream, &hg);
//copy IStream to buffer
int bufsize = GlobalSize(hg);
data.resize(bufsize);
//lock & unlock memory
LPVOID pimage = GlobalLock(hg);
memcpy(&data[0], pimage, bufsize);
GlobalUnlock(hg);
istream->Release();
return true;
}

然后我可以通过调用将数据转换为base64

base64_encode(&data[0], data.size());

我不能保证代码的质量,因为我不了解一切是如何工作的。

最新更新