如何提高BlendEffect的质量? Lumia Imaging 3.0及更高版本超宽工作计划 [英] How to improve BlendEffect quality? Lumia Imaging 3.0 & UWP

查看:91
本文介绍了如何提高BlendEffect的质量? Lumia Imaging 3.0及更高版本超宽工作计划的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个将文本放入背景图像的应用程序.将文本块作为子元素放置在画布控件上,然后将画布渲染为PNG.然后,我使用BlendEffect将其与背景图像混合.

I am developing an app that put text into a background image. The textblocks are placed on a canvas control as children and I render the canvas to PNG. Then I use the BlendEffect to blend it with a background image.

更新 这篇文章专门讲关于Lumia Imaging SDK的链接效果.不幸的是,其中一位发表评论的人的视野很开阔,坚持认为我必须了解有损图像和无损图像之间的区别.这种观点与告诉孩子如何在我的上下文中在Microsoft Paint中保存图像一样有用.在其他注释中,

UPDATE This post is specifically about chaining effects with Lumia Imaging SDK. Unfortunately one of the person who commented was having a tunnel vision and insist that I must learn about the difference between lossy and lossless image. An opinion as useful as telling a kid how to save an image in Microsoft Paint in my context. In some other comment, he even arrogantly wish that I must be having tons of bugs in my app and am having some mental problem.

我在这里了解Lumia Imaging,显然我遇到了一个没有使用该SDK经验的人,并坚持要炫耀.然后对此文章投了反对票,以使自己感觉好些.

I am here to learn about Lumia Imaging and obviously I encountered a person who has no experience with that SDK and insisted on showing off. Then down voted this post to make himself feel better.

话虽如此,@ Martin Liversage指出它不仅仅是JPEG人工制品,这对我们很有帮助.我尝试过使用几个链接步骤和选项,同时另存为JPEG,并且图像的输出确实有所不同.虽然另存为PNG确实可以提高质量,但是这仍然不是我期望的.因此,我在这里问具有使用SDK经验的任何人我可以在我的代码中做些什么来改善我的结果.

With that said, @Martin Liversage was helpful by pointing out that it was not merely JPEG artifacts. I have tried playing with several chaining steps and options while saving as JPEG and indeed the images came out differently. While saving as PNG did improve the quality, it is still not what I expect. So I am here asking anyone with personal experience using the SDK about what I can I do in my code to improve my result.

这是我的代码

private async void saveChainedEffects(StorageFile file)
{
    var displayInformation = DisplayInformation.GetForCurrentView();
    var renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(Textify.CanvasControl);
    var width = renderTargetBitmap.PixelWidth;
    var height = renderTargetBitmap.PixelHeight;
    IBuffer textBuffer = await renderTargetBitmap.GetPixelsAsync();
    byte[] pixels = textBuffer.ToArray();

    using (InMemoryRandomAccessStream memoryRas = new InMemoryRandomAccessStream())
    {
        //Encode foregroundtext to PNG
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, memoryRas);

        encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                             BitmapAlphaMode.Straight,
                             (uint)width,
                             (uint)height,
                             displayInformation.LogicalDpi,
                             displayInformation.LogicalDpi,
                             pixels);

        await encoder.FlushAsync();

        IImageProvider effectBackground;

        if (SelectedEffect.Name == "No Effect")
        {
            effectBackground = imageProcessorRenderer.M_Source;
        }
        else
        {
            effectBackground = (SelectedEffect.GetEffectAsync(imageProcessorRenderer.M_Source, new Size(), new Size())).Result;
        }

        StreamImageSource streamForeground = new StreamImageSource(memoryRas.AsStream());

        //Sharpening the text has unintended consequences to I set to 0d
        using (SharpnessEffect sharpnessEffect = new SharpnessEffect(streamForeground, 0d) )
        using (BlendEffect blendEffect = new BlendEffect(effectBackground, sharpnessEffect, BlendFunction.Normal, 1.0f))
        {
            string errorMessage = null;
            Debug.WriteLine("M_SourceSize (Normalized) {0}", imageProcessorRenderer.M_SourceSize);
            Debug.WriteLine("PreviewSize {0}", imageProcessorRenderer.PreviewSize);

            try
            {
                using (var filestream = await file.OpenAsync(FileAccessMode.ReadWrite))
                using (var jpegRenderer = new JpegRenderer(blendEffect) { Size = imageProcessorRenderer.M_SourceSize, Quality = 1.0, RenderOptions = RenderOptions.Mixed })
                {
                    IBuffer jpegBuffer = await jpegRenderer.RenderAsync().AsTask().ConfigureAwait(false);
                    await filestream.WriteAsync(jpegBuffer);
                    await filestream.FlushAsync();
                }
            }
            catch (Exception exception)
            {
                errorMessage = exception.Message;
            }

            if (!string.IsNullOrEmpty(errorMessage))
            {
                var dialog = new MessageDialog(errorMessage);
                await dialog.ShowAsync();
            }
        }
    }
}

这是保存到JPEG之前在我的PC屏幕上看到的图像

Here's the image as seen on my PC screen before it's saved to JPEG

然后,将图像保存为JPG时,质量将明显下降,如下所示.放大图像并注意字体的边缘.

Then when the image is saved to JPG, there's a noticeable reduction in the quality as seen below. Enlarge the image and pay attention to the edges of the font.

那么,如果我想尽可能地接近原始图像质量,该怎么办?

So what are my options if I want to get as close as to the original image quality?

推荐答案

根据@Martin Liversage和@Hans Passant的反馈,我决定避免使用JPEG,而是另存为PNG.字体边缘的伪像大部分消失了.现在我来宾,我只需要玩锐化图像就可以得到想要的结果.

From @Martin Liversage and @Hans Passant feedback, I've decided to avoid JPEG and save to PNG instead. The artifacts on the edges of fonts mostly gone. I guest now I just have to play with the image sharpening to get the result I want.

更新 我仍然没有达到我想要的质量水平,因此不只是不使用JPEG而是一切都将是完美的.因此,出现了一个问题,即如何提高BlendEffect的质量.

UPDATE I still do not get the quality level that I want so it's not simply don't use JPEG and everything will be perfect. Hence the question, how to improve BlendEffect quality.

这是我的代码

private async void saveChainedEffects(StorageFile file)
{
    var displayInformation = DisplayInformation.GetForCurrentView();
    var renderTargetBitmap = new RenderTargetBitmap();
    await renderTargetBitmap.RenderAsync(Textify.CanvasControl);
    var width = renderTargetBitmap.PixelWidth;
    var height = renderTargetBitmap.PixelHeight;
    IBuffer textBuffer = await renderTargetBitmap.GetPixelsAsync();
    byte[] pixels = textBuffer.ToArray();

    using (InMemoryRandomAccessStream memoryRas = new InMemoryRandomAccessStream())
    {
        //Encode foregroundtext to PNG
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, memoryRas);

        encoder.SetPixelData(BitmapPixelFormat.Bgra8,
                             BitmapAlphaMode.Straight,
                             (uint)width,
                             (uint)height,
                             displayInformation.LogicalDpi,
                             displayInformation.LogicalDpi,
                             pixels);

        await encoder.FlushAsync(); 

        IImageProvider effectBackground;

        if (SelectedEffect.Name == "No Effect")
        {
            effectBackground = imageProcessorRenderer.M_Source;
        }
        else
        {
            effectBackground = (SelectedEffect.GetEffectAsync(imageProcessorRenderer.M_Source, new Size(), new Size())).Result;
        }

        StreamImageSource streamForeground = new StreamImageSource(memoryRas.AsStream());

        //Sharpen the text
        //using (SharpnessEffect sharpnessEffect = new SharpnessEffect(streamForeground, 0.3d) )
        using (BlendEffect blendEffect = new BlendEffect(effectBackground, streamForeground, BlendFunction.Normal, 1.0f))
        using (BitmapRenderer bitmapRenderer = new BitmapRenderer(blendEffect, ColorMode.Bgra8888))
        {


            Bitmap bitmap = await bitmapRenderer.RenderAsync();
            byte[] pixelBuffer = bitmap.Buffers[0].Buffer.ToArray();

            using (var stream = new InMemoryRandomAccessStream())
            {
                var pngEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream).AsTask().ConfigureAwait(false);

                pngEncoder.SetPixelData(BitmapPixelFormat.Bgra8, 
                    BitmapAlphaMode.Straight, 
                    (uint)bitmap.Dimensions.Width, 
                    (uint)bitmap.Dimensions.Height, 
                    displayInformation.LogicalDpi, 
                    displayInformation.LogicalDpi, 
                    pixelBuffer);

                await pngEncoder.FlushAsync().AsTask().ConfigureAwait(false);

                //Need an IBuffer, here is how to get one:
                using (var memoryStream = new MemoryStream())
                {
                    memoryStream.Capacity = (int)stream.Size;
                    var ibuffer = memoryStream.GetWindowsRuntimeBuffer();
                    await stream.ReadAsync(ibuffer, (uint)stream.Size, InputStreamOptions.None).AsTask().ConfigureAwait(false);
                    string errorMessage = null;

                    try
                    {
                        using (var filestream = await file.OpenAsync(FileAccessMode.ReadWrite))
                        {                                 
                            await filestream.WriteAsync(ibuffer);
                            await filestream.FlushAsync();
                        }
                    }
                    catch (Exception exception)
                    {
                        errorMessage = exception.Message;
                    }

                    if (!string.IsNullOrEmpty(errorMessage))
                    {
                        var dialog = new MessageDialog(errorMessage);
                        await dialog.ShowAsync();
                    }
                }
            }                
        }
    }
}

更新2

我已解决此问题,并希望在遇到任何类似情况时分享我的发现.事实证明,保存为JPEG或PNG并不是那么重要.虽然PNG确实可以改善最终图像,但您必须注意以下几点

UPDATE 2

I've fixed the issue and would like to share my findings in case anyone is in similar situation. It turned out that it's not so much about saving to JPEG or PNG. While PNG does improve the final image, you have to pay attention to the followings

  1. 确保前景和背景图像具有相似的尺寸.默认情况下,Lumia Imaging将拉伸前景以覆盖背景,并且宽高比将不受尊重.

  1. Make sure that the foreground and background image has similar dimensions. Lumia Imaging will stretch the foreground by default to cover the background and the aspect ratio won't be respected.

如果需要调整前景的大小,请在renderTargetBitmap.RenderAsync中使用允许您指定大小的重载进行操作.

If you need to resize your foreground, do it in renderTargetBitmap.RenderAsync use the overload that allows you to specify the size.

避免使用SoftwareBitmapRenderer调整前景大小,尤其是在混合之前使用透明图像时.对我来说,这影响了我的图像保真度,并由于某种原因缩小了颜色范围.

Avoid resizing your foreground using SoftwareBitmapRenderer especially when you are working with transparent image before blending. For me this affected my image fidelity and reduced the color range for some reason.

这是预先渲染与背景完美融合的前景的方式.

This is how rendered the foreground beforehand which blends perfectly with the background.

private async Task<SoftwareBitmap> renderForeground()
{
    RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();

    await renderTargetBitmap.RenderAsync(gridToRender, (int)imageProcessorRenderer.M_SourceSize.Width, (int)imageProcessorRenderer.M_SourceSize.Height);
    var width = renderTargetBitmap.PixelWidth;
    var height = renderTargetBitmap.PixelHeight;
    IBuffer textBuffer = await renderTargetBitmap.GetPixelsAsync();

    //Get the output into a software bitmap.
     var outputBitmap = new SoftwareBitmap(
         BitmapPixelFormat.Bgra8,
         width,
         height,
         BitmapAlphaMode.Premultiplied);

    outputBitmap.CopyFromBuffer(textBuffer);

    return outputBitmap;
}

这篇关于如何提高BlendEffect的质量? Lumia Imaging 3.0及更高版本超宽工作计划的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆