Через 10 часов ковыряясь в стоге сена, я наконец-то смог разыскать
причина, которая была определенно не банальна (по крайней мере, для меня).
Вот оно:
Для спецификации растрового изображения размер строки должен быть кратен 4 байтам!
https://upload.wikimedia.org/wikipedia/commons/c/c4/BMPfileFormat.png
Поскольку у моего colorbar-testimage была ширина линии 313 пикселей, а каждый пиксель был закодирован как rgb565, я получил 626 байт на строку.
Но 626 не является кратным 4. Вот почему я должен был добавить еще 2 "байта заполнения" в конце каждой строки. И это было причиной моих диагональных полос.
После добавления этих 2 байтов заполнения (0x00 0x00) я получил растровое изображение, в котором заголовок говорит вам: это изображение имеет ширину 313 пикселей, но реальные данные изображения состоят из 314 пикселей на строку - это немного странно, но это определяется спецификацией.
Как только я изменил свое растровое изображение, чтобы оно соответствовало этому требованию спецификации, диагональные полосы исчезли, а ожидаемая вертикальная полоса вышла из темноты.
Поскольку в 99% всех примеров кода в Интернете предполагается, что их изображения кратны 4 ширинам линии (например, форматам изображения 320x240 или 680x480), все они не сталкиваются с моей проблемой - но большинство из них будут, если вы подадите им изображения rgb565 с нечетным количеством строк-пикселей, как я должен был сделать.
Несколько дополнительных строк (помеченных "// ***") было достаточно для добавления "трюка с отступами".
(Приведенный ниже код только для пояснения, в производительном коде вы можете добавить некоторые оптимизации)
MemoryStream memoryStream = new MemoryStream(1000000);
// Read raw image into byte array
string imgpath = "rgb565_LSB-first_313x240.raw";
FileStream fs = new FileStream(imgpath, FileMode.Open);
fs.CopyTo(memoryStream);
Byte[] buffer = memoryStream.ToArray();
// Create empty Bitmep and inject byte arrays data into bitmap's data area
Bitmap bmp = new Bitmap(313, 240, PixelFormat.Format16bppRgb565);
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, 313, 240);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format16bppRgb565);
IntPtr ptrToFirstPixel = bmpData.Scan0;
// *** Attention: Bitmap specification requires, to pad row size to a multiple of 4 Bytes
// *** See: https://upload.wikimedia.org/wikipedia/commons/c/c4/BMPfileFormat.png
// *** Solution: Copy buffer[] to buffer2[] and pay attention to padding (!!) at the end of each row
Byte[] buffer2 = new Byte[240 * bmpData.Stride];
for (int y = 0; y < 240; y++)
{
Buffer.BlockCopy(buffer, y * 313 * 2, buffer2, y * bmpData.Stride, 313 * 2);
}
Marshal.Copy(buffer2, 0, ptrToFirstPixel, buffer2.Length); // *** Use padded buffer2 instead of buffer1
bmp.UnlockBits(bmpData);
// Diplay Bitmap in my PictureBox
pbImage.Image = bmp;