简体   繁体   English

如何在没有UI(UWP)的情况下将图像加载到内存中

[英]How to load an Image in memory without the UI (UWP)

I'm trying to open an image in memory and set it's Source property. 我正在尝试在内存中打开图像并将其设置为Source属性。 I can't use the UI for this, it's work I'd like to happen in the background. 我不能为此使用UI,这是我想在后台进行的工作。 However, the ImageOpened doesn't fire. 但是,ImageOpened不会触发。 Any other ways to achieve this? 还有其他方法可以做到这一点吗?

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 ...
};

My goal would then be to do some work on the Image and save it to a file using the RenderTargetBitmap class. 然后,我的目标是在Image上做一些工作,并使用RenderTargetBitmap类将其保存到文件中。

Here's async task you may use: 您可以使用以下异步任务:

    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;
    }

Also you should subscribe to event before loading source to Image 另外,在将源加载到Image之前,您应该先订阅事件

If you're going to be doing image editing / manipulation, you'd be better off using the Win2D library Nuget package from Microsoft, so your code would look something like this: 如果您要进行图像编辑/操作,最好使用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);
            }
        }
    }

Here's a completely standalone, off-screen render-to-file example. 这是一个完全独立的屏幕外渲染到文件的示例。 You provide an input image filename and output image filename. 您提供输入图像文件名和输出图像文件名。

It grabs the top 256 x 64 corner of your image and superimposes some ugly "Hello, world!" 它抓住了图像的顶部256 x 64角,并叠加了一些难看的“你好,世界!” text over it and saves it to a file. 在其上输入文本并将其保存到文件中。

示例输出

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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM