Ошибка при использовании RenderTargetBitmap в UWP

Я пытаюсь создать растровое изображение и получить следующий код:

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(uielement);

IBuffer pixels = await renderTargetBitmap.GetPixelsAsync();

. . .

var pixelArray = pixels.ToArray();

Для того, чтобы получить ToArray() расширение, я наткнулся на этот вопрос. И я добавил:

using System.Runtime.InteropServices.WindowsRuntime; // For ToArray

К моему коду. Однако, когда я запускаю, я получаю следующую ошибку:

Возникло исключение: System.ArgumentException в System.Runtime.WindowsRuntime.dll

Дополнительная информация: указанный индекс буфера находится за пределами емкости буфера.

Когда я углубляюсь в детали, в трассировке стека говорится:

в>System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.ToArray(источник IBuffer, UInt32 sourceIndex, число Int32) в>System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.ToArray(источник IBUffer)

Этот метод извлечения массива пикселей все еще применим к UWP? Если это так, есть ли способ получить более подробную информацию из этого сообщения об ошибке?

1 ответ

Решение

Этот метод выделения массива пикселей определенно применим к UWP. Что касается ошибки, декомпилированный ToArray() выглядит так:

public static byte[] ToArray(this IBuffer source)
{
  if (source == null)
    throw new ArgumentNullException("source");
  return WindowsRuntimeBufferExtensions.ToArray(source, 0U, checked ((int) source.Length));
}

Другими словами, это вызывает ToArray перегрузка, которая принимает начальный индекс и длину:

public static byte[] ToArray(this IBuffer source, uint sourceIndex, int count)
{
  if (source == null)
    throw new ArgumentNullException("source");
  if (count < 0)
    throw new ArgumentOutOfRangeException("count");
  if (sourceIndex < 0U)
    throw new ArgumentOutOfRangeException("sourceIndex");
  if (source.Capacity <= sourceIndex)
    throw new ArgumentException(SR.GetString("Argument_BufferIndexExceedsCapacity"));
  if ((long) (source.Capacity - sourceIndex) < (long) count)
    throw new ArgumentException(SR.GetString("Argument_InsufficientSpaceInSourceBuffer"));
  byte[] destination = new byte[count];
  WindowsRuntimeBufferExtensions.CopyTo(source, sourceIndex, destination, 0, count);
  return destination;
}

Строка (и) почти наверняка вызывает вашу проблему:

  if (source.Capacity <= sourceIndex)
    throw new ArgumentException(SR.GetString("Argument_BufferIndexExceedsCapacity"));

...и с тех пор sourceIndex обязательно 0, это будет означать, что source.Capacity также 0.

Я предлагаю вам добавить некоторые инструменты в ваш код для проверки IBuffer:

RenderTargetBitmap rtb = new RenderTargetBitmap();
await rtb.RenderAsync(element);

IBuffer pixelBuffer = await rtb.GetPixelsAsync();
Debug.WriteLine($"Capacity = {pixelBuffer.Capacity}, Length={pixelBuffer.Length}");
byte[] pixels = pixelBuffer.ToArray();

Я думаю вполне вероятно, что ваша проблема возникает до ToArray вызов. Я использую ту же самую последовательность в моем собственном приложении UWP, получая отладочный вывод примерно так:

Capacity = 216720, Length=216720

Я столкнулся с той же проблемой при попытке сделать скриншот в приложении UWP.

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(uielement);

дал мне это исключение, когда uielement является Window.Current.Content,

Но когда я пытался

RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(null);

тот же код работал без исключения и дает мне скриншот окна приложения UWP.

Другие вопросы по тегам