/// <summary>
/// 生成长图
/// </summary>
/// <param name="imageList"></param>
/// <param name="toPath"></param>
/// <returns></returns>
public async Task<bool> CreateLongGraphAsync(List<SlideImageData> imageList, string toPath)
{
var bitmapSource = await CreateLongBitmapAsync(imageList);
if (bitmapSource != null)
SaveBitmap(toPath, bitmapSource);
return true;
}
private async Task<RenderTargetBitmap> CreateLongBitmapAsync(List<SlideImageData> imageList)
{
if (imageList.Count <= 0) return null;
double sumHeight = 0;
int lineHeight = 5;
if (imageList.Count == 1)
{
sumHeight = imageList.First().Height;
}
else
{
sumHeight = imageList.Sum(img => img.Height) + lineHeight * (imageList.Count - 1);
}
double maxWidth = imageList.Max(img => img.Width);
var combineImg = new RenderTargetBitmap((int)maxWidth,
(int)sumHeight,
96d,
96d,
PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
int positionY = 0;
foreach (var image in imageList)
{
drawingContext.DrawImage(image.ImageSource, new Rect(0, positionY, image.Width, image.Height));
positionY += image.Height + lineHeight;
}
}
combineImg.Render(drawingVisual);
if (combineImg.CanFreeze)
combineImg.Freeze();
return combineImg;
}
/// <summary>
/// 保存位图
/// </summary>
/// <param name="savePath"></param>
/// <param name="getSource"></param>
private void SaveBitmap(string savePath, RenderTargetBitmap getSource)
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(getSource));
using FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Read);
encoder.Save(fs);
getSource.Clear();
getSource = null;
GC.Collect();
}
跟踪主要是RenderTargetBitmap的内存没办法释放。所以替换了另一种方式Bitmap+Graphics生成png长图
/// <summary>
/// 生成长图
/// </summary>
/// <param name="imageList"></param>
/// <param name="toPath"></param>
/// <returns></returns>
public async Task<bool> CreateLongGraphAsync(List<SlideImageData> imageList, string toPath)
{
Bitmap mergedBitmap = MergeImages(imageList.Select(t => t.ImageSource).ToList());
mergedBitmap.Save(toPath, ImageFormat.Png);
//var bitmapSource = await CreateLongBitmapAsync(imageList);
//if (bitmapSource != null)
// SaveBitmap(toPath, bitmapSource);
return true;
}
// 定义合并图片的方法
private Bitmap MergeImages(List<ImageSource> images)
{
if (images.Count <= 0) return null;
double sumHeight = 0;
int lineHeight = 5;
if (images.Count == 1)
{
sumHeight = images.First().Height;
}
else
{
sumHeight = images.Sum(img => img.Height) + lineHeight * (images.Count - 1);
}
double maxWidth = images.Max(img => img.Width);
// 创建一个位图对象
Bitmap bitmap = new Bitmap((int)maxWidth, (int)sumHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// 使用Graphics类绘制图片
using (Graphics g = Graphics.FromImage(bitmap))
{
int y = 0;
foreach (var image in images)
{
g.DrawImage(ImageSourceToBitmap(image), new System.Drawing.Rectangle(0, y, (int)image.Width, (int)image.Height));
y += (int)image.Height;
}
}
return bitmap;
}
// 定义将ImageSource转换为Bitmap的方法
private Bitmap ImageSourceToBitmap(ImageSource imageSource)
{
BitmapImage bitmapImage = (BitmapImage)imageSource;
Bitmap bitmap = new Bitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
bitmapImage.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
bitmap.UnlockBits(data);
return bitmap;
}
private BitmapImage ConvertRenderTargetBitmapToBitmapImage(RenderTargetBitmap wbm)
{
BitmapImage bmp = new BitmapImage();
using (MemoryStream stream = new MemoryStream())
{
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(wbm));
encoder.Save(stream);
bmp.BeginInit();
bmp.CacheOption = BitmapCacheOption.OnLoad;
bmp.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
bmp.StreamSource = new MemoryStream(stream.ToArray()); //stream;
bmp.EndInit();
bmp.Freeze();
}
return bmp;
}
/// <summary>
/// 保存位图
/// </summary>
/// <param name="savePath"></param>
/// <param name="getSource"></param>
private void SaveBitmap(string savePath, RenderTargetBitmap getSource)
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(getSource));
using FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Read);
encoder.Save(fs);
getSource.Clear();
getSource = null;
GC.Collect();
}