c ++在位图上绘制图像并保存

Posted

技术标签:

【中文标题】c ++在位图上绘制图像并保存【英文标题】:c++ draw images on bitmap and save 【发布时间】:2013-08-17 08:00:53 【问题描述】:

//后台可以跳过

我正在为我的 Windows 桌面背景创建一个动画时钟。基本上,我使用预先绘制的图像(时钟的数字)创建带有代码的 bmp 图像,然后保存 bmp 图像并将桌面背景设置为该图像。我尝试使用 c# 和 .Net,但为了设置桌面背景,我必须调用 WinApi 函数 (SystemParametersInfo)。从 c# 调用此函数几乎需要一秒钟。动画太长了。

所以现在我想在 c++ 中做同样的事情,我希望从非托管代码调用 SystemParametersInfo 会更快。编辑:我用c#创建bmp和c++来设置桌面背景,速度更快

//问题

我使用 Visual Studio 2012 创建了一个 Win32 控制台项目,并设法将预先绘制的图像作为资源嵌入。现在我需要将图像组合到一个位图上并将其保存到硬盘中。自从我上次用 C++ 编程已经四年了,所以我不知道如何绘制图像并保存它。

我在谷歌搜索时发现的所有代码都必须在屏幕上绘制,我显然不想这样做。

那么如何创建位图,在其上绘制资源图像(也是位图),并将其全部保存在 c++ 中?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

这个问题更多是关于 Windows API 而不是 C++。 如果要使用 Windows API,请参考 GDI+:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms533798.aspx

.NET Framework 封装了 GDI+,因此您可能只熟悉 C++ 中的类,而不是具有手动内存管理等的 C# 类。

还有一些其他的库可以处理图像。我个人喜欢 GD,一个具有多种语言绑定的 C 风格图像处理库。

https://bitbucket.org/libgd/gd-libgd/downloads

但是,与开源一样,您必须自己构建它以及依赖项。所以,可能 GDI+ 是最好的。

【讨论】:

我正忙于使用 GDI+ 编写我的 C# 程序的 c++ 版本(花了我一段时间才弄清楚)如果它有效,我将发布代码【参考方案2】:

事实证明,Win32 (c++) 代码可以快速更改桌面背景(在 i5 3.2ghz 上不到 20 毫秒),而托管 C# 代码需要 500 到 3000 毫秒。但是,非托管 c++ 代码需要永远绘制图像(300 到 1500 毫秒)。所以我所做的就是制作两个可以协同工作的程序。托管 C# 程序创建图像(在 20 毫秒内)然后保存。非托管c++将保存的图片设置为桌面背景。

C# 静态无效主要(字符串 [] 参数) //手动计算和硬编码的图像位置 //第一张图片位置 //X:532 //Y:335 位图 TheImage = new Bitmap(1366, 768);

        Graphics G = Graphics.FromImage(TheImage);

        DateTime DTNow = DateTime.Now;
        while (true)
        
            //get the time 
            DTNow = DateTime.Now;
            //draw the canvas
            G.DrawImage(Resources.canvas, 0, 0,1366,768);

            //draw the first image of the hour
            G.DrawImage(GetImage(DTNow.Hour,0),532,330,174,217);
            //draw the second image of the hour
            G.DrawImage(GetImage(DTNow.Hour, 1), 711, 330, 174, 217);
            //draw the colon
            if (DTNow.Second % 2 == 0) G.DrawImage(Resources.aColon, 890, 365,57,147);
            //draw the first digit of the minute
            G.DrawImage(GetImage(DTNow.Minute, 0), 952, 330, 174, 217);
            //draw the second digit of the minute
            G.DrawImage(GetImage(DTNow.Minute, 1), 1131, 330, 174, 217);
            //save the file
            try
            
                File.Delete("C:\\background.bmp");

                TheImage.Save("C:\\background.bmp", ImageFormat.Bmp);
            
            catch
            
            
            //calculate sleep time and sleep until next second

            DTNow = DateTime.Now.AddSeconds(1);
            DateTime NextSecond = new DateTime(DTNow.Year,DTNow.Month,DTNow.Day, DTNow.Hour,DTNow.Minute, DTNow.Second,500);
            DTNow = DateTime.Now;
      System.Threading.Thread.Sleep((int)NextSecond.Subtract(DTNow).TotalMilliseconds);

        

    
    static Bitmap GetImage(int Number, int Index)
    
        string NS = Number.ToString();
        if (NS.Length < 2) NS = "0" + NS;
        char[] digits = NS.ToCharArray();

        switch (digits[Index])
        
            case '1':  return Resources.a1;  
            case '2':  return Resources.a2; 
            case '3':  return Resources.a3;  
            case '4':  return Resources.a4;  
            case '5':  return Resources.a5;  
            case '6':  return Resources.a6; 
            case '7':  return Resources.a7; 
            case '8':  return Resources.a8; 
            case '9':  return Resources.a9;  
            default:  return Resources.a0;  
        
    

c++ int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char*, int nShowCmd) 而(真) SystemParametersInfo(SPI_SETDESKWALLPAPER,0, L"C:\background.bmp", SPIF_UPDATEINIFILE); int MS = (int)(((long)floor((long)clock()/(long)CLOCKS_PER_SEC)*1000l+1000l)-((long)clock()));

if(MS<=1000 && MS>0)
std::this_thread::sleep_for(std::chrono::milliseconds(MS));

else





return 0;

【讨论】:

以上是关于c ++在位图上绘制图像并保存的主要内容,如果未能解决你的问题,请参考以下文章

在位图图像中绘制一个圆圈并在 R 中裁剪圆圈外的像素

在位图上绘制文本失败

在位图上绘制对角线文本

如何在位图上绘制粗体文本?

Android 在位图上绘制文本

绘制在位图上以一定角度旋转的线