【问题标题】:Merging JPGs with GDI in C#在 C# 中将 JPG 与 GDI 合并
【发布时间】:2010-11-07 11:13:35
【问题描述】:

我的场景:

  • 我有一张彩色背景图片 JPG。
  • 我有一个白色背景 JPG 上的黑色文本。
  • 两张图片大小相同(高度和宽度)

我想用黑色文本和白色背景将图像覆盖在彩色背景图像上,即白色背景变为透明以查看其下方的彩色背景。

如何在 C# 中使用 GDI 做到这一点?

谢谢!

【问题讨论】:

    标签: c# transparency gdi jpeg


    【解决方案1】:

    如果图像大小相同,则对它们进行迭代并“与”每个像素的颜色。对于白色像素,您应该获得另一张图像的颜色,对于黑色像素,您应该获得黑色。

    如果它们的大小不同,请先缩放。

    我是在脑海中编造这个,但是像这样:

    Color destColor = Color.FromArgb(pixel1.ToArgb() & pixel2.ToArgb());
    

    【讨论】:

    • 这可能有效,两个图像大小相同。你能提供一个快速的代码 sn-p 或一个链接吗?
    • 您不能直接与颜色对象,您需要与组件值。
    • 谢谢,我用这个想出了一个解决方案:stackoverflow.com/questions/1071374/merging-jpgs-with-gdi-in-c/…
    • 你和一个带有 int 的 Color 对象。 FromArgb 返回一个“颜色”,ToArgb 返回一个 int。
    • @Ed - 我仍然看不到你所看到的。请阅读我的代码并确切告诉我我没有按照你说的做我需要做的事???????
    【解决方案2】:

    感谢GalacticCowboy 我能够想出这个解决方案:

    using (Bitmap background = (Bitmap)Bitmap.FromFile(backgroundPath))
    {
         using (Bitmap foreground = (Bitmap)Bitmap.FromFile(foregroundPath))
         {
              // check if heights and widths are the same
              if (background.Height == foreground.Height & background.Width == foreground.Width)
              {
                   using (Bitmap mergedImage = new Bitmap(background.Width, background.Height))
                   {
                        for (int x = 0; x < mergedImage.Width; x++)
                        {
                             for (int y = 0; y < mergedImage.Height; y++)
                             {
                                  Color backgroundPixel = background.GetPixel(x, y);
                                  Color foregroundPixel = foreground.GetPixel(x, y);
                                  Color mergedPixel = Color.FromArgb(backgroundPixel.ToArgb() & foregroundPixel.ToArgb());
                                  mergedImage.SetPixel(x, y, mergedPixel);
                              }
                        }
                        mergedImage.Save("filepath");
                   }
    
              }
         }
    }
    

    像魅力一样工作。谢谢!

    【讨论】:

      【解决方案3】:

      存在更简单快捷的方法。绘制必须部分可见的图像时应使用 ImageAttributes。

      Image BackImage = Image.FromFile(backgroundPath);
      using (Graphics g = Graphics.FromImage(BackImage))
      {
          using (ForeImage = Image.FromFile(foregroundPath))
          {   
              ImageAttributes imageAttr = new ImageAttributes();
              imageAttr.SetColorKey(Color.FromArgb(245, 245, 245), Color.FromArgb(255, 255, 255),
                  ColorAdjustType.Default);
              g.DrawImage(ForeImage, new Rectangle(0, 0, BackImage.Width, BackImage.Height),
                  0, 0, BackImage.Width, BackImage.Height, GraphicsUnit.Pixel, imageAttr);
          }
      }
      

      SetColorKey 方法将使指定范围内的颜色透明,因此您可以使白色位图像素透明,包括所有受 jpeg 压缩伪影影响的像素。

      【讨论】:

      • 我没试过这个,所以我可能是错的,但是使用像这样的透明颜色的一个典型缺点是,你会在从透明到不透明的切换处得到一个尖锐的边缘,这会如果使用其他方法,请软化。
      • 我也没试过,这个sn-p是从头写的。但我想说的是,DrawImage 有很多使用 ImageAttributes 的可能性,因此作者的任务可以正确完成(经过他身边的一些额外调查),而不会出现缓慢的逐像素合成
      • 我想这归结为预期的结果 - 处理速度与图像质量。我尝试了你的方法,它明显更快(0.1 秒对大约 2 秒,对于 800x600 图像),但是使用我的方法,文本边缘周围有很多噪音。
      猜你喜欢
      • 2014-07-31
      • 2014-10-30
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 2012-11-17
      • 2015-10-18
      • 2015-03-12
      • 2021-01-19
      相关资源
      最近更新 更多