gpt4 book ai didi

c++ - 如何从 Scan0 创建位图/图像?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:03:27 28 4
gpt4 key购买 nike

我在将以下 C# 代码移植到 C++ 时遇到问题:

protected override void OnPaint(CefBrowser browser, CefPaintElementType type, CefRectangle[] dirtyRects
, System.IntPtr buffer, int width, int height)
{
if (isPainting == true)
return;

isPainting = true;

// Save the provided buffer (a bitmap image) as a PNG.
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(width, height, width * 4, System.Drawing.Imaging.PixelFormat.Format32bppRgb, buffer))
{
bitmap.Save(@"LastOnPaint.png", System.Drawing.Imaging.ImageFormat.Png);
} // End Using bitmap
}

它的作用:
从由最新版本的 Chromium embedded 呈现的 WebSite/SVG 创建图像并将其保存为文件。

所以这是 C++ 中相应的渲染处理程序:

void RenderHandler::OnPaint(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer, int width, int height
) {
// size_t len = sizeof(buffer) / sizeof(void*);
// printf("buffer length: %zu\n", len); // 1...
// Array size is probably: width*height * 4;
}

所以我正在研究 C# 在位图构造函数中的作用,如下所示:

public Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)
{
IntPtr bitmap = IntPtr.Zero;
int status = Gdip.GdipCreateBitmapFromScan0(width, height, stride, unchecked((int)format), new HandleRef(null, scan0), out bitmap);
Gdip.CheckStatus(status);

SetNativeImage(bitmap);
}


internal void SetNativeImage(IntPtr handle) {
if (handle == IntPtr.Zero)
throw new ArgumentException(SR.GetString(SR.NativeHandle0), "handle");

nativeImage = handle;
}

追踪到

internal const string Gdiplus = "gdiplus.dll";

[DllImport(ExternDll.Gdiplus, SetLastError=true, ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Unicode)] // 3 = Unicode
[ResourceExposure(ResourceScope.Machine)]
internal static extern int GdipCreateBitmapFromScan0(int width, int height, int stride, int format, HandleRef scan0, out IntPtr bitmap);

所以我想我可以在 gdibitmapflat 中调用 GdipCreateBitmapFromScan0快完成了

GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width
, INT height, INT stride, PixelFormat format
, BYTE* scan0, GpBitmap** bitmap)

所以我为 GDI 收集了必要的头文件,这是一次糟糕的经历

#ifndef __BITMAPHELPER_H__
#define __BITMAPHELPER_H__

// #define WIN32_LEAN_AND_MEAN

#pragma warning(disable:4458)

#include <Windows.h>
#include <ObjIdl.h>
#include <minmax.h>
#include <gdiplus.h>
#include <wingdi.h>
#include <gdiplusbitmap.h>
#include <gdiplusflat.h>
using namespace Gdiplus;
#pragma comment (lib,"gdiplus.lib")

#pragma warning(default:4458)


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <cstdbool>

#include <algorithm>
#include <memory>

并认为这会做到这一点

#include "BitmapHelper.h" 
static void Test()
{
GpBitmap *bitmap = NULL;
GdipCreateBitmapFromScan0(100, 100, 0, PixelFormat32bppARGB, NULL, &bitmap); // create a bitmap object with specified width/height/color
// GpGraphics *graph;


// Image * syntaxTest = NULL;
//syntaxTest->FromFile(TEXT("d:\\abc.jpg"), true); // create an image object
// Bitmap::FromBITMAPINFO
// GpImage *image = NULL;
// Gdiplus::Image()


Bitmap *bmp = NULL;

// GdipLoadImageFromFile(TEXT("d:\\abc.jpg"), &image); // create an image object


// GdipGetImageGraphicsContext(bitmap, &graph); // create a graphic object via bitmap object
// GdipDrawImageI(graph, image, 100, 100); // draw image to this graphic object, it can be done

}

然而,事实证明编译器不知道 GdipCreateBitmapFromScan0,尽管它肯定在 #include <gdiplusflat.h> 中...

如何从 Scan0 创建位图/图像?
注意:
当我这样做时,我不想求助于 C++.NET,最好也不要求助于 WinAPI;因为我也希望它能在 Linux 上运行。而不是像 SDL 这样的巨大依赖。

到目前为止,看起来我可能的替代方案正在使用此代码:

https://codereview.stackexchange.com/questions/196084/read-and-write-bmp-file-in-c

这意味着我必须创建 bitmap header我自己。
或者我可以使用来自 ImageIO 的一些代码.

我不敢相信即使在单个操作系统上创建一个简单的位图也这么难...

真的没有更好的(和可移植的)方法来从一个普通的像素颜色数组创建一个简单的位图吗?
为什么编译器找不到 GdipCreateBitmapFromScan0 ?
如果我使用 LoadLibrary 和 GetProcAddress 来调用它而不是 f*ing windows 头文件,我现在差不多完成了......
为什么 #include <gdiplus.h>不包括它自己的依赖项?

最佳答案

您对 .NET 内部结构的研究使您倾向于使用不属于 GDI+ 文档化公共(public)接口(interface)的一部分的函数。在我看来,这就是您大多数问题的真正原因。

我认为您可能想要做的是从您的像素创建一个 GdiPlus::Bitmap 对象开始。它有一个 constructor that looks like it'll directly accept your data .

一旦您创建了Bitmap 对象,您就可以调用它的Save 成员函数。 Bitmap 是从 Image 公开派生的,因此您基本上是在处理普通的 Image::Save 以生成 PNG。

如果你想消除对 Windows 代码的依赖,你可以考虑使用(一个明显的可能性)libpng反而。这使您可以更好地控制流程,但要付出更多的工作来使用(取决于您想要做什么,可能大约是六到十几行代码,而不是一行或两个)。

关于c++ - 如何从 Scan0 创建位图/图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55286009/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com