我在 C# 中创建了一个图像服务,它采用基础层图像 (JPG),再一层透明 PNG(32 位),然后输出最终的 JPG 图像。我试图从这个函数中挤出每一毫秒,我的代码在 GDI+ 中的 DrawImage 调用中遇到瓶颈。这里的托管代码:
// Load base image and create graphics
Image image = LoadImage(renderSettings.RenderedImageDirectory + baseLayer);
Graphics graphics = Graphics.FromImage(image);
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
// Draw additional layers to final image
for (int i = 1; i < renderLayers.Count; i++) {
// SLOW -- LoadImage just a utility method that returns an Image from disk or cache
graphics.DrawImage(LoadImage(renderSettings.RenderedImageDirectory + renderLayers[i]), 0, 0, image.Width, image.Height);
}
if (graphics != null) graphics.Dispose();
现在,我阅读了通过 P/Invoke 直接调用 GDI 获得的性能提升,并尝试替换 DrawImage 调用。我创建了一个单元测试来尝试复制加载 JPG 然后在其上分层一个透明 PNG 的相同功能。
参考:http ://social.msdn.microsoft.com/Forums/en-US/winforms/thread/29582142-0068-40dd-bd99-4b3883a76350
Bitmap sourceImage = new Bitmap("c:\\base.jpg");
Bitmap overlayImage = new Bitmap("c:\\layer1.png");
// NOTE: ImageHelper is a utility class containing all the P/Invoke stuff
// Get source image in memory
Graphics sourceImageGraphics = Graphics.FromImage(sourceImage);
IntPtr sourceImageHDC = sourceImageGraphics.GetHdc();
IntPtr sourceImageCDC = ImageHelper.CreateCompatibleDC(sourceImageHDC);
IntPtr sourceImageHandle = sourceImage.GetHbitmap();
ImageHelper.SelectObject(sourceImageCDC, sourceImageHandle);
// Get overlay image in memory
Graphics overlayImageGraphics = Graphics.FromImage(overlayImage);
IntPtr overlayImageHDC = overlayImageGraphics.GetHdc();
IntPtr overlayImageCDC = ImageHelper.CreateCompatibleDC(overlayImageHDC);
IntPtr overlayImageHandle = overlayImage.GetHbitmap();
ImageHelper.SelectObject(overlayImageCDC, overlayImageHandle);
ImageHelper.BitBlt(sourceImageHDC, 0, 0, sourceImage.Width, sourceImage.Height, overlayImageCDC, 0, 0, ImageHelper.TernaryRasterOperations.SRCAND);
ImageHelper.AlphaBlend(sourceImageHDC, 0, 0, sourceImage.Width, sourceImage.Height, overlayImageCDC, 0, 0, sourceImage.Width, sourceImage.Height, new ImageHelper.BLENDFUNCTION(ImageHelper.AC_SRC_OVER, 0, 0xff, ImageHelper.AC_SRC_ALPHA));
// Release source Image memory.
ImageHelper.DeleteDC(sourceImageCDC);
ImageHelper.DeleteObject(sourceImageHandle);
sourceImageGraphics.ReleaseHdc(sourceImageHDC);
sourceImageGraphics.Dispose();
// Release overlay Image memory.
ImageHelper.DeleteDC(overlayImageCDC);
ImageHelper.DeleteObject(overlayImageHandle);
overlayImageGraphics.ReleaseHdc(overlayImageHDC);
overlayImageGraphics.Dispose();
// Save to jpg
sourceImage.Save("c:\\output.jpg", ImageFormat.Jpeg);
但这无法产生分层图像。只是没有基本 JPG 的 PNG。我应该做些什么不同的事情?当谈到直接的 GDI 时,我有点出类拔萃。