c# - BitmapEncoder 刷新抛出参数异常

标签 c# uwp bitmapencoder

我正在尝试调整我的 UWP 应用程序中的图像大小。大多数情况下,附加代码都有效,但有时 await encoder.FlushAsync(); 会抛出 ArgumentException

我已经前往 MSDN ( https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmapencoder.bitmaptransform.aspx ),他们告诉我(在“备注”处):

If you try scale an image stored in an indexed pixel format using the BitmapTransform member, FlushAsync fails with HRESULT WINCODEC_ERR_INVALIDPARAMETER . Instead, you must use GetPixelDataAsync to obtain the scaled pixel data and then use SetPixelData to set it on the encoder.

我已经尝试这样做了,请参阅两条注释行(由于重复,这对我来说看起来有点不对)。在第二行(我尝试 SetPixelData),编码器用 buffer allocated not sufficient 异常奖励我。

var decoder = await BitmapDecoder.CreateAsync(streamToReadFrom.AsStream().AsRandomAccessStream());
if (decoder.OrientedPixelHeight > height ||
    decoder.OrientedPixelWidth > width)
{
    var resizedStream = new InMemoryRandomAccessStream();
    BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder);

    encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
    encoder.BitmapTransform.ScaledHeight = newHeight;
    encoder.BitmapTransform.ScaledWidth = newWidth;

    //"buffer allocated not sufficient"
    // var pd = await decoder.GetPixelDataAsync(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Ignore,
    //             encoder.BitmapTransform, ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);
    // encoder.SetPixelData(BitmapPixelFormat.Rgba16, BitmapAlphaMode.Ignore,
    //             decoder.OrientedPixelWidth, decoder.OrientedPixelHeight, decoder.DpiX, decoder.DpiY, pd.DetachPixelData());

    // write out to the stream
    // might fail cause https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmapencoder.bitmaptransform.aspx
    await encoder.FlushAsync();

    // Read out resizedStream and return
}

导致此问题的示例图像:http://www.spiegel.de/images/image-1028227-hppano-lqbn.jpg .此处进行单元测试:https://github.com/famoser/OfflineMedia/blob/master/Famoser.OfflineMedia.UnitTests/Presentation/ImageResizeTest.cs

如何避免 ArgumentException?我如何知道图像采用“索引像素格式”,以及如何调整此格式的大小?

最佳答案

On the second line (where I try to SetPixelData) the Encoder rewards me with an buffer allocated not sufficient Exception.

这是因为当您 SetPixelData 时,像素数据与来自 GetPixelDataAsync 的像素数据不匹配。例如,您可以这样编写代码:

if (file != null)
{
    BitmapImage bmp = new BitmapImage();
    using(var imageStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
    {
        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);
        InMemoryRandomAccessStream pixelras = new InMemoryRandomAccessStream();
        BitmapEncoder pixelencoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, pixelras);
        BitmapTransform transform = new BitmapTransform();
        transform.InterpolationMode = BitmapInterpolationMode.Fant;
        transform.ScaledHeight = 400;
        transform.ScaledWidth = 400;
        var provider = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8, 
            BitmapAlphaMode.Ignore, 
            transform, 
            ExifOrientationMode.RespectExifOrientation, 
            ColorManagementMode.DoNotColorManage);
        var pixels = provider.DetachPixelData();
        pixelencoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, 400, 
            400, decoder.DpiX, decoder.DpiY, pixels);

        try
        {
            await pixelencoder.FlushAsync();
        }
        catch(Exception ex)
        {

        }
        bmp.SetSource(pixelras);
        img.Source = bmp;                  
    }
}

How do I know an image is in an "indexed pixel format", and how can I resize this format too?

我找不到任何有效的方法来检测索引像素格式图像,但既然有人说

If you try scale an image stored in an indexed pixel format using the BitmapTransform member, FlushAsync fails with HRESULT WINCODEC_ERR_INVALIDPARAMETER . Instead, you must use GetPixelDataAsync to obtain the scaled pixel data and then use SetPixelData to set it on the encoder.

是使用catch the exception再使用SetPixelData的方法,例如:

if (file != null)
{
    BitmapImage bmp = new BitmapImage();
    using(var imageStream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite))
    {
        BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);
        InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
        BitmapEncoder encoder = await BitmapEncoder.CreateForTranscodingAsync(ras, decoder);

        encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
        encoder.BitmapTransform.ScaledHeight = 400;
        encoder.BitmapTransform.ScaledWidth = 400;

        try
        {
            await encoder.FlushAsync();
            bmp.SetSource(ras);
        }
        catch (Exception ex)
        {
            if (ex.HResult.ToString() == "WINCODEC_ERR_INVALIDPARAMETER")
            {
                InMemoryRandomAccessStream pixelras = new InMemoryRandomAccessStream();
                BitmapEncoder pixelencoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, pixelras)
                BitmapTransform transform = new BitmapTransform();
                transform.InterpolationMode = BitmapInterpolationMode.Fant;
                transform.ScaledHeight = 400;
                transform.ScaledWidth = 400;
                var provider = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8,
                    BitmapAlphaMode.Ignore,
                    transform,
                    ExifOrientationMode.RespectExifOrientation,
                    ColorManagementMode.DoNotColorManage);
                var pixels = provider.DetachPixelData();
                pixelencoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, 400,
                    400, decoder.DpiX, decoder.DpiY, pixels);
                try
                {
                    await pixelencoder.FlushAsync();
                    bmp.SetSource(pixelras);
                }
                catch
                {

                }
            }
        }                    
        img.Source = bmp;                  
    }
}

关于c# - BitmapEncoder 刷新抛出参数异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38617761/

相关文章:

c# - 如何为重复过程实现多线程池

c# - 是否有可能在构造函数中违反 Liskov 替换原则?

c# - 尝试使用 XHR 联系 WCF 服务时出现 400 错误请求

c# - 将可执行文件包含到 UWP 最终包中

c# - DataTemplate 中的绑定(bind)命令

c# - UWP 将图像编码为 PNG

c# - 如何从对象和变量创建 Json?

c# - ASP.Net Core 401 中的 SignalR 未经授权

c# - TiffBitmapEncoder,内存错误导致 C#/WPF 中内存不足异常