- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在将以下 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/
我是一名优秀的程序员,十分优秀!