arwasairl
Resource contributor
- Messages
- 98
- Country

Yes, I am aware of this but there are actually 2 different factors when it comes to FS9 and our panel:Aaron: I don't know whether this will help, but could I suggest downloading the sd2gau42 documentation from here: Creating C Gauges and reading the section titled 'Understanding how P3D treats Bitmaps and Colours in Gauges'; specifically the sub-section 'This is Where it all Goes Wrong'. I have some suggestions in there on how to defeat the night banding.
I am using GDI+ and not the older MAKE macros, which means that the sim itself never touches our actual bitmaps. Each frame's presenter instead rasterizes the bitmaps with the CPU, but in terms of unconditional compression, it does not happen in the load stage but in the rendering stage.
FS9's panels are limited to 5 bits per color channel, though I noticed while reading the texture's pixel rasterizer that they include dithering, which I didn't include in my render code which can improve the appearance at the cost of noise
C++:
void ConvertBackToImg(Gdiplus::Bitmap* back, PIMAGE img,
int rx, int ry, int rw, int rh)
{
if (back == NULL || img == NULL || img->image == NULL)
{ return; }
const int dimX = (int)back->GetWidth();
const int dimY = (int)back->GetHeight();
int x0 = (rx > 0) ? rx : 0;
int y0 = (ry > 0) ? ry : 0;
int x1 = rx + rw;
int y1 = ry + rh;
if (x1 > dimX) { x1 = dimX; }
if (y1 > dimY) { y1 = dimY; }
if (x1 > img->dim.x) { x1 = img->dim.x; }
if (y1 > img->dim.y) { y1 = img->dim.y; }
if (x0 >= x1 || y0 >= y1) { return; }
Gdiplus::BitmapData bd;
Gdiplus::Rect rc(0, 0, dimX, dimY);
if (back->LockBits(&rc, Gdiplus::ImageLockModeRead,
PixelFormat32bppARGB, &bd) != Gdiplus::Ok)
{ return; }
for (int y = y0; y < y1; ++y)
{
const unsigned int* src = (const unsigned int*)
((char*)bd.Scan0 + y * bd.Stride);
char* dstRow = img->image + (UINT32)y * img->pitch;
const unsigned int* bayer = kBayer4[y & 3];
if (img->format == IMG_15_BIT)
{
unsigned short* dst = (unsigned short*)dstRow;
for (int x = x0; x < x1; ++x)
{
const unsigned int p = src[x];
if ((p >> 24) < 128) { dst[x] = 0; continue; }
const unsigned int r = (p >> 16) & 0xFF;
const unsigned int gg = (p >> 8) & 0xFF;
const unsigned int b = p & 0xFF;
const unsigned int d = bayer[x & 3];
dst[x] = (unsigned short)
(0x8000 | (Dither5(r, d) << 10) |
(Dither5(gg, d) << 5) | Dither5(b, d));
}
}
else if (img->format == IMG_32_BIT ||
img->format == IMG_32A_BIT)
{
unsigned int* dst = (unsigned int*)dstRow;
for (int x = x0; x < x1; ++x)
{
dst[x] = src[x];
}
}
else if (img->format == IMG_16_BIT)
{
unsigned short* dst = (unsigned short*)dstRow;
for (int x = x0; x < x1; ++x)
{
const unsigned int p = src[x];
if ((p >> 24) < 128) { dst[x] = 0; continue; }
const unsigned int r = (p >> 16) & 0xFF;
const unsigned int gg = (p >> 8) & 0xFF;
const unsigned int b = p & 0xFF;
const unsigned int d = bayer[x & 3];
unsigned short v = (unsigned short)
((Dither5(r, d) << 11) | (Dither6(gg, d) << 5) |
Dither5(b, d));
if (v == 0) { v = 0x0821; } // near-black
dst[x] = v;
}
}
}
back->UnlockBits(&bd);
}


