C# BitmapEncoder刷新引发参数异常
我正在尝试在我的UWP应用程序中调整图像大小。大多数情况下,附加的代码都能正常工作,但有时C# BitmapEncoder刷新引发参数异常,c#,uwp,bitmapencoder,C#,Uwp,Bitmapencoder,我正在尝试在我的UWP应用程序中调整图像大小。大多数情况下,附加的代码都能正常工作,但有时会等待encoder.FlushAsync()抛出一个参数异常 我去了MSDN(),他们告诉我(在“备注”中): 如果尝试使用BitmapTransform成员缩放以索引像素格式存储的图像,FlushAsync将失败,并使用HRESULT WINCODEC_ERR_INVALIDPARAMETER。相反,必须使用GetPixelDataAsync获取缩放像素数据,然后使用SetPixelData在编码器上进
会等待encoder.FlushAsync()代码>抛出一个参数异常
我去了MSDN(),他们告诉我(在“备注”中):
如果尝试使用BitmapTransform成员缩放以索引像素格式存储的图像,FlushAsync将失败,并使用HRESULT WINCODEC_ERR_INVALIDPARAMETER。相反,必须使用GetPixelDataAsync获取缩放像素数据,然后使用SetPixelData在编码器上进行设置
我已经试着这么做了,看到了两行注释(由于重复,我觉得这两行有点不对劲)。在第二行(我尝试SetPixelData
),编码器奖励我一个缓冲区分配不足的异常
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
}
导致此问题的示例图像:。此处的单元测试:
如何避免参数异常
?如何知道图像是“索引像素格式”,如何调整此格式的大小
在第二行(我尝试设置PixelData),编码器会奖励我一个缓冲区分配不充分的异常
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
}
这是因为当您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;
}
}
如何知道图像是“索引像素格式”,如何调整此格式的大小
我找不到任何有效的方法来检测索引像素格式的图像,但因为
如果尝试使用BitmapTransform成员缩放以索引像素格式存储的图像,FlushAsync将失败,并使用HRESULT WINCODEC_ERR_INVALIDPARAMETER。相反,必须使用GetPixelDataAsync获取缩放像素数据,然后使用SetPixelData在编码器上进行设置
这是一种使用捕获异常并再次使用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;
}
}
谢谢!一旦我能测试它,我会尝试并接受你的回答。不幸的是,这并没有解决问题。GetPixelDataAsync
和SetPixelData
似乎工作正常,但是pixelencoder.FlushAsync()代码>仍然抛出一个参数异常
。我添加了一个图像的链接,导致我的问题出现此问题。@FlorianMoser,很抱歉反应太晚,我刚刚用您提供的图像测试了我的第一块代码,我无法重现问题?从你的第二个链接中,我发现你下载了那张图片,下载后可能吗?我没有测试下载图像然后对其进行转换,我只是将您的图像放入图片库并使用FileOpenPicker选择此图像,效果很好。我的操作系统版本是10586。我正在开发一个技术预览版本(14393.5),并为min&max版本10586开发。这个问题仍然发生在我的机器上,我添加了更多的单元测试来证实这一点。我认为你的例子和我的代码之间的唯一区别是使用的流,可能有问题,我会在有时间的时候再尝试一些。我再也不能重现这个错误了