【问题标题】:c++ draw images on bitmap and savec ++在位图上绘制图像并保存
【发布时间】: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++ 中?

感谢您的帮助。

【问题讨论】:

    标签: c++ winapi bitmap save draw


    【解决方案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;
    

    }

    【讨论】:

      猜你喜欢
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      相关资源
      最近更新 更多