如何在没有 UI (UWP) 的情况下在内存中加载图像
How to load an Image in memory without the UI (UWP)
我正在尝试打开内存中的图像并将其设置为来源 属性。我不能为此使用 UI,这是我希望在后台进行的工作。但是,ImageOpened 不会触发。还有其他方法可以实现吗?
var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
var scaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
var desktopSize = new Size(bounds.Width * scaleFactor, bounds.Height * scaleFactor);
var image = new Image()
{
Width = desktopSize.Width,
Height = desktopSize.Height,
};
image.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
image.Arrange(new Rect(0, 0, desktopSize.Width, desktopSize.Height));
image.UpdateLayout();
image.Source = new BitmapImage(new Uri(file.Path, UriKind.RelativeOrAbsolute));
image.ImageOpened += (sender, e) =>
{
// Currently not firing ...
};
然后我的目标是对图像进行一些处理,然后使用 RenderTargetBitmap
class.
将其保存到文件中
这是一个完全独立的离屏渲染到文件示例。
您提供输入图像文件名和输出图像文件名。
它抓取图像的顶部 256 x 64 角并在其上叠加一些难看的 "Hello, world!" 文本并将其保存到文件中。
using System;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
class OffscreenRenderer
{
public void Render(string sourceImageFilename, string outputImageFilename)
{
FontFamily fontFamily = new FontFamily("Arial");
double fontSize = 42.0;
Brush foreground = new System.Windows.Media.SolidColorBrush(Color.FromArgb(255, 255, 128, 0));
FormattedText text = new FormattedText("Hello, world!",
new CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch()),
fontSize,
foreground);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
var overlayImage = new BitmapImage(new Uri(sourceImageFilename));
drawingContext.DrawImage(overlayImage,
new Rect(0, 0, overlayImage.Width, overlayImage.Height));
drawingContext.DrawText(text, new Point(2, 2));
drawingContext.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap(256, 64, 96, 96, PixelFormats.Pbgra32);
rtb.Render(drawingVisual);
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using (Stream stream = File.Create(outputImageFilename))
{
png.Save(stream);
}
}
}
您可以使用以下异步任务:
private async Task<BitmapImage> CreateBitmapAsync(Uri uri, int decodeWidth, int decodeHeight)
{
var storageFile = await StorageFile.GetFileFromApplicationUriAsync(uri);
var bitmap = new BitmapImage { DecodePixelWidth = decodeWidth, DecodePixelHeight = decodeHeight };
using (IRandomAccessStream fileStream = await storageFile.OpenAsync(FileAccessMode.Read))
{
await bitmap.SetSourceAsync(fileStream);
}
return bitmap;
}
此外,您应该在将源加载到 Image
之前订阅事件
如果您要进行图像编辑/操作,最好使用 Microsoft 的 Win2D 库 Nuget 包,这样您的代码将如下所示:
public static async Task DoImageStuffAsync(Uri sourceUri, StorageFile outputFile)
{
using (CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), sourceUri).AsTask().ConfigureAwait(false))
using (CanvasRenderTarget target = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), (float)bitmap.Size.Width, (float)bitmap.Size.Height, bitmap.Dpi))
{
using (var ds = target.CreateDrawingSession())
{
// todo : custom drawing code - this just draws the source image
ds.DrawImage(bitmap);
}
using (var outputStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite).AsTask().ConfigureAwait(false))
{
await target.SaveAsync(outputStream, CanvasBitmapFileFormat.JpegXR).AsTask().ConfigureAwait(false);
}
}
}
我正在尝试打开内存中的图像并将其设置为来源 属性。我不能为此使用 UI,这是我希望在后台进行的工作。但是,ImageOpened 不会触发。还有其他方法可以实现吗?
var bounds = ApplicationView.GetForCurrentView().VisibleBounds;
var scaleFactor = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
var desktopSize = new Size(bounds.Width * scaleFactor, bounds.Height * scaleFactor);
var image = new Image()
{
Width = desktopSize.Width,
Height = desktopSize.Height,
};
image.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
image.Arrange(new Rect(0, 0, desktopSize.Width, desktopSize.Height));
image.UpdateLayout();
image.Source = new BitmapImage(new Uri(file.Path, UriKind.RelativeOrAbsolute));
image.ImageOpened += (sender, e) =>
{
// Currently not firing ...
};
然后我的目标是对图像进行一些处理,然后使用 RenderTargetBitmap
class.
这是一个完全独立的离屏渲染到文件示例。 您提供输入图像文件名和输出图像文件名。
它抓取图像的顶部 256 x 64 角并在其上叠加一些难看的 "Hello, world!" 文本并将其保存到文件中。
using System;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
class OffscreenRenderer
{
public void Render(string sourceImageFilename, string outputImageFilename)
{
FontFamily fontFamily = new FontFamily("Arial");
double fontSize = 42.0;
Brush foreground = new System.Windows.Media.SolidColorBrush(Color.FromArgb(255, 255, 128, 0));
FormattedText text = new FormattedText("Hello, world!",
new CultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, new FontStretch()),
fontSize,
foreground);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
var overlayImage = new BitmapImage(new Uri(sourceImageFilename));
drawingContext.DrawImage(overlayImage,
new Rect(0, 0, overlayImage.Width, overlayImage.Height));
drawingContext.DrawText(text, new Point(2, 2));
drawingContext.Close();
RenderTargetBitmap rtb = new RenderTargetBitmap(256, 64, 96, 96, PixelFormats.Pbgra32);
rtb.Render(drawingVisual);
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using (Stream stream = File.Create(outputImageFilename))
{
png.Save(stream);
}
}
}
您可以使用以下异步任务:
private async Task<BitmapImage> CreateBitmapAsync(Uri uri, int decodeWidth, int decodeHeight)
{
var storageFile = await StorageFile.GetFileFromApplicationUriAsync(uri);
var bitmap = new BitmapImage { DecodePixelWidth = decodeWidth, DecodePixelHeight = decodeHeight };
using (IRandomAccessStream fileStream = await storageFile.OpenAsync(FileAccessMode.Read))
{
await bitmap.SetSourceAsync(fileStream);
}
return bitmap;
}
此外,您应该在将源加载到 Image
如果您要进行图像编辑/操作,最好使用 Microsoft 的 Win2D 库 Nuget 包,这样您的代码将如下所示:
public static async Task DoImageStuffAsync(Uri sourceUri, StorageFile outputFile)
{
using (CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(CanvasDevice.GetSharedDevice(), sourceUri).AsTask().ConfigureAwait(false))
using (CanvasRenderTarget target = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), (float)bitmap.Size.Width, (float)bitmap.Size.Height, bitmap.Dpi))
{
using (var ds = target.CreateDrawingSession())
{
// todo : custom drawing code - this just draws the source image
ds.DrawImage(bitmap);
}
using (var outputStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite).AsTask().ConfigureAwait(false))
{
await target.SaveAsync(outputStream, CanvasBitmapFileFormat.JpegXR).AsTask().ConfigureAwait(false);
}
}
}