首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在C#中从Graphics对象中获取位图/图像?

如何在C#中从Graphics对象中获取位图/图像?
EN

Stack Overflow用户
提问于 2011-03-15 14:48:26
回答 7查看 31.6K关注 0票数 12

我想知道Graphics对象正在绘制一些东西的缓冲区的中间状态是什么。如何获取位图或它正在绘制的图像?

EN

回答 7

Stack Overflow用户

发布于 2011-03-15 14:58:50

我不太确定我是否理解你的要求,因为你的问题很不清楚。

如果您想知道如何保存Graphics对象转换为位图,那么答案是没有直接的方法可以做到这一点。在Graphics对象是单向操作。

更好的选择是创建一个新的Bitmap对象,则获取一个Graphics对象,并直接在其上绘制。下面的代码是一个示例,说明了如何做到这一点:

代码语言:javascript
运行
复制
// Create a new bitmap object
using (Bitmap bmp = new Bitmap(200, 300))
{
    // Obtain a Graphics object from that bitmap
    using (Graphics g = Graphics.FromImage(bmp))
    {
        // Draw onto the bitmap here
        // ....
        g.DrawRectangle(Pens.Red, 10, 10, 50, 50);
    }

    // Save the bitmap to a file on disk, or do whatever else with it
    // ...
    bmp.Save("C:\\MyImage.bmp");
}
票数 8
EN

Stack Overflow用户

发布于 2011-03-15 15:38:36

这段代码适用于我正在转换图像>>位图>>字节>> Base64字符串的地方。

代码语言:javascript
运行
复制
System.Drawing.Image originalImage = //your image

//Create empty bitmap image of original size

Bitmap tempBmp = new Bitmap(originalImage.Width, originalImage.Height);

Graphics g = Graphics.FromImage(tempBmp);

//draw the original image on tempBmp

g.DrawImage(originalImage, 0, 0, originalImage.Width, originalImage.Height);

//dispose originalImage and Graphics so the file is now free

g.Dispose();

originalImage.Dispose();

using (MemoryStream ms = new MemoryStream())
{
    // Convert Image to byte[]
    tempBmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
    //dpgraphic.image.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
    byte[] imageBytes = ms.ToArray();

    // Convert byte[] to Base64 String
    string strImage = Convert.ToBase64String(imageBytes);
    sb.AppendFormat(strImage);
}
票数 3
EN

Stack Overflow用户

发布于 2020-03-03 06:50:58

因为9年后没有人回答这个实际问题...

代码语言:javascript
运行
复制
// System.Windows.Forms.Internal.IntUnsafeNativeMethods
[DllImport("gdi32.dll", CharSet = CharSet.Auto, EntryPoint = "GetCurrentObject", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr IntGetCurrentObject(HandleRef hDC, int uObjectType);


IntPtr hdc = graphics.GetHdc();
// This is a HBITMAP, which is the actual buffer that is being drawn to by hdc.
IntPtr hbitmap = IntGetCurrentObject(new HandleRef(null, hdc), 7 /*OBJ_BITMAP*/);
// You can create a Gdiplus::Bitmap object from this, but it will copy all image data.
//Bitmap bitmap = Image.FromHbitmap(hbitmap);
// To manipulate the actual bitmap pixel data directly, see below.

// Put these in finally:
//bitmap.Dispose();
// NOTE: You cannot use the graphics object before ReleaseHdc is called.
graphics.ReleaseHdc(hdc);

要获取实际的位图比特,请执行以下操作,你必须先了解一些关于GDI位图的知识。有所谓的设备相关位图(DDB,或者通常只是API中的“位图”),以及与设备无关的位图(DIB)。对这种差异的完整解释超出了这个答案的范围。

如果您使用

this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

中的图形对象OnPaint将使用DIB,否则将使用DDB。

如果你的HBITMAP是一个DDB,您不能直接读/写像素数据(尽管在技术上是可行的,但Windows没有提供这样做的方法)。你必须使用GetDIBits使用特定格式将它们复制到与设备无关的缓冲区,然后SetDIBits把它们复制回去。

如果你的HBITMAP是一个DIB,然后您可以获得实际的像素位(作为指针),并使用以下命令直接在内存中读/写它们`GetObject`(请不要与GetCurrentObject):

代码语言:javascript
运行
复制
[DllImport("gdi32.dll")]
static extern unsafe int GetObject(IntPtr hobj, int cb, void* data);

[StructLayout(LayoutKind.Sequential)]
unsafe struct BITMAP
{
    int        bmType;
    int        bmWidth;
    int        bmHeight;
    int        bmWidthBytes;
    ushort     bmPlanes;
    ushort     bmBitsPixel;
    void*      bmBits;
}

BITMAP BitmapDesc = new BITMAP();
GetObject(hbitmap, sizeof(BITMAP), &BitmapDesc);

BITMAP.bmBits将会是null如果是DDB,那么它将是一个有效的内存地址;如果它是一个DIB,那么它将是一个有效的内存地址。如果您只想复制此数据,可以直接使用bmBits;总长度为bmHeight * bmWidthBytes..。

如果你真的想要操作内存中的像素数据,你需要知道DIB的确切像素格式,以便正确地操作它。像素格式有多种可能(每像素的位数为1/4/8/16/24/32、RGB与BGR、调色板等)。如果你真的想要支持所有的东西,那就需要做大量的工作..。

要做到这一点,要知道当被赋予一个HBITMAPGetObject函数将接受一个BITMAP结构(如上面的代码示例所示)或一个`DIBSECTION`结构。请注意DIBSECTION以一个BITMAP,这使得两个结构兼容。如果HBITMAP是DIB,那么GetObject将填写有效的(非空)bmBits指针,它还将填充DIBSECTION%s`BITMAPINFOHEADER`结构,然后可以使用它来检查DIB的像素格式。

检查BITMAPINFOHEADER会很痛苦。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5308363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档