Почему мой алгоритм преобразования между индексом и x, y с помощью растровых буферов приводит к вертикальному отражению изображения? - PullRequest
11 голосов
/ 06 мая 2019

При работе с растровыми буферами, такими как:

[50, 50, 50, 255, 50, 50, 50, 255, ...]
[r,  g,  b,  a,   r,  g,  b,  a, ...]

Я часто использую математику следующим образом:

let bufferWidth = width * 4;
buffer.forEach((channel, index) => {
    let y = Math.floor(index / bufferWidth);
    let x = Math.floor((index % bufferWidth) / 4);
    let remainder = index % 4;

для вычисления x, y или наоборот для работы с плоскимибуферы растровых данных.Почти всегда я получаю перевернутые результаты и, так или иначе, переворачиваю их обратно, но, очевидно, что-то не так с моим мышлением по этому поводу.

Что не так с этой математикой, которая может привести к переворачиванию растрового изображения?

Полный код, функция для обрезки растрового изображения:

function crop(
  buffer,
  width,
  height,
  leftLimit,
  rightLimit,
  lowerLimit,
  upperLimit
) {
  let croppedWidth = rightLimit - leftLimit;
  let croppedHeight = upperLimit - lowerLimit;
  let length = croppedHeight * croppedWidth * 4;
  let bufferWidth = width * 4;
  let croppedBuffer = new Uint8Array(length);
  buffer.forEach((channel, index) => {
    let y = Math.floor(index / bufferWidth);
    let x = Math.floor((index % bufferWidth) / 4);
    let remainder = index % 4;
    let yCropped = y - lowerLimit;
    let xCropped = x - leftLimit;
    let indexCropped = yCropped * croppedWidth * 4 + xCropped * 4 + remainder;
    if (
      xCropped >= 0 &&
      xCropped <= croppedWidth &&
      yCropped >= 0 &&
      yCropped <= croppedHeight
    ) {
      croppedBuffer[indexCropped] = buffer[index];
    }
  });
  return croppedBuffer;
}

Ответы [ 2 ]

4 голосов
/ 15 мая 2019

Растровое изображение обычно начинается с нижнего левого угла и продолжается до правого верхнего угла.Но не всегда.

В заголовочном файле растрового изображения есть значение biHeight, если это значение отрицательное, то растровое изображение перевернуто, оно начинается снизу слева.И если это значение положительное, то растровое изображение начинается с верхнего левого угла.

Если у вас есть доступ к biHeight, просто переверните его значение, чтобы отобразить растровое изображение правой стороной вверх.

Чтобы сделатьвычисления проще, выберите любую действительную точку X / Y, затем найдите соответствующий source_index в буфере, как показано ниже.Скопируйте эту точку в буфер назначения.

Обратите внимание, что вам нужен дополнительный цикл для копирования 4 байтов из источника в место назначения (у вас этого нет в коде, поэтому я не уверен, как работает ваш кодвообще)

for(let i = 0; i < bytes_per_pixel; i++)
    buffer_cropped[dst_index + i] = buffer[source_index + i];

Приведенный ниже код должен работать для 32-битных изображений (4 байта на пиксель).Обратите внимание, что для 24-битных изображений потребуется заполнение.

if (height < 0) 
    height = -height;
let bytes_per_pixel = 4;
let cropped_x = 10;
let cropped_y = 10;
let cropped_width = width / 2;
let cropped_height = height / 2;

if (new_x < 0 || new_x >= new_width || 
    new_y < 0 || new_y >= new_height) { error... }
if (cropped_width < 1 || cropped_width > width || 
    cropped_height < 1 || cropped_height > height) { error... }

let dst_index = 0;
for(let y = cropped_y; y < cropped_y + cropped_height; y++)
{
    for(let x = cropped_x; x < cropped_x + cropped_width; x++)
    {
        //use for right-side up bitmap:
        //int source_index = (y * width + x) * bytes_per_pixel;
        ////

        //use for upside-down bitmap:
        let source_index = ((height - y - 1)* width + x) * bytes_per_pixel;
        ////

        for(let i = 0; i < bytes_per_pixel; i++)
            buffer_cropped[dst_index + i] = buffer[source_index + i];
        dst_index += bits_per_pixel;
    }
}
1 голос
/ 14 мая 2019

Проверьте заголовок вашего растрового изображения. В случае (сверху вниз) высота должна быть отрицательной. Документация .

biHeight Высота растрового изображения в пикселях. Если biHeight положительный, точечный рисунок - это DIB снизу вверх, а его источник - левый нижний угол. Если biHeight отрицателен, растровое изображение является нисходящим DIB и его источником это верхний левый угол.

Если biHeight отрицателен, указывая на нисходящий DIB, biCompression должен быть либо BI_RGB, либо BI_BITFIELDS. Нисходящие DIB не могут быть сжаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...