Вычисление необходимого размера буфера для метода WriteableBitmap.WritePixels - программирование
Подтвердить что ты не робот

Вычисление необходимого размера буфера для метода WriteableBitmap.WritePixels

Как вычислить необходимый размер буфера для метода WriteableBitmap.WritePixels?

Я использую перегрузку с четырьмя параметрами, первый - Int32Rect, следующий - массив байтов, содержащий номера RGBA для цвета, третий - это шаг (который является шириной моей записываемой растровой карты, умноженной на биты на пиксель, деленный на 8), а последний - это буфер (называемый смещением в Intellisense).

Я получаю Размер буфера не достаточен Ошибка выполнения в приведенном ниже коде:

byte[] colourData = { 0, 0, 0, 0 };

var xCoordinate = 1;
var yCoordinate = 1;

var width = 2;
var height = 2;

var rect = new Int32Rect(xCoordinate, yCoordinate, width, height);

var writeableBitmap = new WriteableBitmap(MyImage.Source as BitmapSource);

var stride = width*writeableBitmap.Format.BitsPerPixel/8;

writeableBitmap.WritePixels(rect, colourData, stride,0);

Какую формулу мне нужно использовать для вычисления значения буфера, необходимого в приведенном выше коде?

4b9b3361

Ответ 1

Значение шага вычисляется как количество байтов на "линию пикселя" в прямоугольнике записи:

var stride = (rect.Width * bitmap.Format.BitsPerPixel + 7) / 8;

Требуемый размер буфера - это количество байтов на строку, умноженное на количество строк:

var bufferSize = rect.Height * stride;

При условии, что у вас есть прямоугольник записи 2x2 и формат 32 бит на пиксель, например. PixelFormats.Pbgra32, вы получаете stride как 8 и bufferSize как 16.

Ответ 2

Шаг - это просто ширина в байтах вашего входного буфера. Это называется шагом, потому что иногда за каждой линией изображения добавляется дополнительная память, что делает невозможным использование ширины изображения для чтения каждой строки изображения.

Итак, в вашем примере это 2. Вам не нужно ничего рассчитать с битами на пиксель растрового изображения, метод WritePixels знает всю эту информацию. Вам необходимо предоставить информацию о том, как структурированы ваши входные данные.

Однако, как упоминалось в другом ответе, ваш пример не будет работать, если битмап также равен 2x2. Тогда начальная координата будет 0,0.

EDIT:

Когда я присмотрюсь к вашему примеру, я вижу ошибку. Вы говорите, что colourData является цветом ввода. Но это вводится на пиксель. Поэтому, если вы хотите изменить прямоугольник 2x2, вам понадобятся следующие входные данные:

byte[] colourData = { 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 0 };

И затем байты на пиксель равны байтам, поэтому он равен 4, умноженному на ширину каждой строки (2), составляет всего 8.

Ответ 3

Здесь Microsoft отображает код, который выполняет проверку внутри CopyPixels

        int num = ((sourceRect.Width * this.Format.BitsPerPixel) + 7) / 8;
        if (stride < num)
        {
            throw new ArgumentOutOfRangeException("stride", MS.Internal.PresentationCore.SR.Get("ParameterCannotBeLessThan", new object[] { num }));
        }
        int num2 = (stride * (sourceRect.Height - 1)) + num;
        if (bufferSize < num2)
        {
            throw new ArgumentOutOfRangeException("buffer", MS.Internal.PresentationCore.SR.Get("ParameterCannotBeLessThan", new object[] { num2 }));
        }

Ответ 4

Я работаю с этим. 60z fs

   this.playerOpacityMaskImage.WritePixels(
                new Int32Rect(0, 0, this.depthWidth, this.depthHeight),
                this.greenScreenPixelData,
                this.depthWidth * ((this.playerOpacityMaskImage.Format.BitsPerPixel + 7) / 8),
                0);

Ответ 5

Хотя пользователь Clemens ответил на вопрос о размере буфера, вопросник не знал, что он рассчитал размер буфера уже правильно, и проблема была где-то еще.

Пока детали даны и обсуждаются в комментариях, отсутствует один полный фрагмент (и полный пример использования .WritePixels(без .CopyPixels)). Вот он (я просмотрел похожие вопросы, но это было лучшее место):

var dpiX = 96;

var writeableBitmap = new WriteableBitmap(width, height, dpiX, dpiX, PixelFormats.Bgra32, null); // Pixelformat of Bgra32 results always in 4 bytes per pixel
int bytesPerPixel = (writeableBitmap.Format.BitsPerPixel + 7) / 8; // general formula
int stride = bytesPerPixel * width; // general formula valid for all PixelFormats

byte[] pixelByteArrayOfColors = new byte[stride * height]; // General calculation of buffer size

// The numbers in the array are indices to the used BitmapPalette, 
//     since we initialized it with null in the writeableBitmap init, they refer directly to RGBA, but only in this case.
// Choose a light green color for whole bitmap (for not easy to find commented MSDN example with random colors, see https://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap(VS.85).aspx
for (int pixel = 0; pixel < pixelByteArrayOfColors.Length; pixel += bytesPerPixel)
{
    pixelByteArrayOfColors[pixel] = 0;        // blue (depends normally on BitmapPalette)
    pixelByteArrayOfColors[pixel + 1] = 255;  // green (depends normally on BitmapPalette)
    pixelByteArrayOfColors[pixel + 2] = 0;    // red (depends normally on BitmapPalette)
    pixelByteArrayOfColors[pixel + 3] = 50;   // alpha (depends normally on BitmapPalette)
}

writeableBitmap.WritePixels(new Int32Rect(0, 0, width, height), pixelByteArrayOfColors, stride, 0);

Ответ 6

Я не уверен, но попробуйте это для 24-битного rgb

  {
     //your code
       var stride = width * 3;
       WriteableBitmap bmp = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr24, null);
       bmp.WritePixels(new System.Windows.Int32Rect(0, 0, width , height),byte[],stride,0));

   }