WPF中控件保存成图片加强版

    WPF中将控件保存成图片,主要利用了RenderTargetBitmap方法。但是,通过测试发现这种方法有个问题,即图片是从目标UI上一级的左上角作为起点计算长宽的,也就是说,如果目标UI居中显示,那么极有可能导出的图片是不完整的,居左置顶则能导出完整图片。

    为了解决这个问题,我们可以先将包含目标UI在内的部分保存成一张大图,然后从大图中提取目标UI部分,主要利用CroppedBitmap函数。

    以下两个函数的即实现了这个功能:第一个函数是将ImageSource转换成Bitmap,第二个函数是将指定的UI保存成图片。

// ImageSource --> Bitmap
        public static Bitmap ImageSourceToBitmap(ImageSource imageSource)
        {
            BitmapSource bitmapSource = (BitmapSource)imageSource;
            Bitmap bmp = new Bitmap(bitmapSource.PixelWidth, bitmapSource.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
            BitmapData data = bmp.LockBits(
                new Rectangle(System.Drawing.Point.Empty, bmp.Size), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
                bitmapSource.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
                bmp.UnlockBits(data);
            return bmp;
        }

// UI --> Image
        public static void UISaveToImage(FrameworkElement ui, string fileName, int bigX, int BigY, int width, int height)
        {
            RenderTargetBitmap bmp = new RenderTargetBitmap(bigX, BigY, 96d, 96d, PixelFormats.Pbgra32);
            bmp.Render(ui);
            int offsetX = Math.Max((int)(0.5 * (bigX - width)), 0);
            int offsetY = Math.Max((int)(0.5 * (BigY - height)), 0);
            BitmapSource bmpSource = new CroppedBitmap(BitmapFrame.Create(bmp), new Int32Rect(offsetX, offsetY, width, height));
            ImageSourceToBitmap(bmpSource).Save(fileName);
        }

    补充说明:bigX和bigY为目标UI、目标UI上一级中较大宽和较大高;

    比如以下代码:

<ScrollViewer Grid.Column="2" Name="svProcess" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" BorderBrush="BlueViolet" BorderThickness="1">
    <Image Name="imgProcess" Stretch="Uniform" RenderOptions.BitmapScalingMode="HighQuality" IsHitTestVisible="False"/>
</ScrollViewer>

    调用方式:

int offsetX = Math.Max((int)(0.5 * (svProcess.ActualWidth - imgProcess.ActualWidth)), 0);
int offsetY = Math.Max((int)(0.5 * (svProcess.ActualHeight - imgProcess.ActualHeight)), 0);
int bigX = Math.Max((int)svProcess.ActualWidth, (int)imgProcess.ActualWidth);
int bigY = Math.Max((int)svProcess.ActualHeight, (int)imgProcess.ActualHeight);
CImageProcess.UISaveToImage(imgProcess, filename, bigX, bigY, (int)imgProcess.ActualWidth, (int)imgProcess.ActualHeight);

猜你喜欢

转载自blog.csdn.net/u012366767/article/details/81483919
今日推荐