ghaerr / microwindows

The Nano-X Window System
Other
665 stars 91 forks source link

Load and display bitmaps at runtime #82

Open uklatt opened 10 months ago

uklatt commented 10 months ago

Hello Greg,

what is the "best" solution to load and display a BMP bitmap file with actual 0.94 version? The following code doesn't work.

  image = GdLoadImageFromFile( filename, 0 );
  hdcMem = CreateCompatibleDC( hdc );
  hbmp = CreateCompatibleBitmap( hdcMem, SCREENX, SCREENY );
  hbmpOrg = SelectObject( hdcMem, hbmp );
  DrawDIB( hdcMem, 0, 0, image );
  StretchBlt( hdc, x, y, dx, dy, hdcMem, 0, 0, image->width, image->height, MWROP_SRC_OVER );
  DeleteObject(SelectObject(hdcMem, hbmpOrg));
  DeleteDC(hdcMem);

I got the following error:

/home/root/microwindows-0.94pre/src/drivers/genmem.c:144: gen_allocatememgc: Assertion `psd == &scrdev' failed.

When I display the bitmap file (8 bit palette image) with GdDrawImageFromFile(hdc->psd, x,y,dx,dy, filename,0); only the top half of the bitmap is displayed.

ghaerr commented 10 months ago

Hello @uklatt,

hdcMem = CreateCompatibleDC( hdc );

Where is hdc initialized? Is this code part of something large in a window procedure callback function?

When I display the bitmap file (8 bit palette image) with GdDrawImageFromFile(hdc->psd, x,y,dx,dy, filename,0); only the top half of the bitmap is displayed.

In general, it isn't recommended to call Gdxxx routines directly from another (Win32 or Nano-X) API. What API are you writing programs in generally?

That said, the above GdDrawImageFromFile could be being clipped to the output window, depending on the API being used.

You might grep/look through the various demo programs in src/bin as well as demos/mwin and demos/nanox, there are a number which draw images.

Thank you!

uklatt commented 10 months ago

Hi Greg, hdccomes fromBeginPaint() in WM_PAINT of the window.

If I use the image_penguine:

extern MWIMAGEHDR image_penguin;
PMWIMAGEHDR image = &image_penguin;

the following code works.

    case WM_PAINT:
      hdc = BeginPaint(hwnd, &ps);
      GetClientRect(hwnd, &rc);
      hdcMem = CreateCompatibleDC(hdc);
      hbmp = CreateCompatibleBitmap(hdcMem, image->width, image->height);
      hbmpOrg = SelectObject(hdcMem, hbmp);
      DrawDIB(hdcMem, 0, 0, image);
      StretchBlt(ps.hdc, 0, 0, rc.right, rc.bottom, hdcMem, 0, 0, image->width, image->height, MWROP_COPY);
      DeleteObject(SelectObject(hdcMem, hbmpOrg));
      DeleteDC(hdcMem);
      EndPaint(hwnd, &ps);
      break;

But when I try to load the same bitmap it doesn't work:

    case WM_PAINT:
      hdc = BeginPaint(hwnd, &ps);
      GetClientRect(hwnd, &rc);
      image = (PMWIMAGEHDR)GdLoadImageFromFile( "./penguin.bmp", 0 );
      hdcMem = CreateCompatibleDC(hdc);
      hbmp = CreateCompatibleBitmap(hdcMem, image->width, image->height);
      hbmpOrg = SelectObject(hdcMem, hbmp);
      DrawDIB(hdcMem, 0, 0, image);
      StretchBlt(ps.hdc, 0, 0, rc.right, rc.bottom, hdcMem, 0, 0, image->width, image->height, MWROP_COPY);
      DeleteObject(SelectObject(hdcMem, hbmpOrg));
      DeleteDC(hdcMem);
      EndPaint(hwnd, &ps);
      break;

gdb-output:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".
1920x1080x32bpp pitch 7680 type 0 visual 2 colors 16777216 pixtype 8
Program received signal SIGSEGV, Segmentation fault.
0x0000aaaaaaaa10c4 in wproc (hwnd=0xaaaaaaac19e0, message=15, wParam=0, lParam=0) at main.c:65
65                              hbmp = CreateCompatibleBitmap(hdcMem, image->width, image->height);
(gdb) print image
$1 = (PMWIMAGEHDR) 0xffffffffaaac6f80
(gdb) print image->width
Cannot access memory at address 0xffffffffaaac6f84

This looks like a 32Bit/64Bit pointer problem...

==========================

I found the reason!

I missed the declaration of GdLoadImageFromFile(). Without the declaration the return value of GdLoadImageFromFile() ist truncated to int (32 bits).

uklatt commented 10 months ago

One small thing:

I use copy from memory device context to another memory device context. This triggers the assert in gen_allocatememgc I must disable this check.

PSD gen_allocatememgc(PSD psd)
{
    PSD mempsd;
    // assert(psd == &scrdev);  // triggers when copy from one memory device context to another one
...
}
ghaerr commented 10 months ago

image = (PMWIMAGEHDR)GdLoadImageFromFile( "./penguin.bmp", 0 );

In general, one can't call Gdxxx functions from the WIN32 API. The reason your program is crashing is that GdLoadImageFromtFile returns a PSD, where as a PMWIMAGEHDR is an entirely different structure. Casting from one structure pointer to another won't work.

For WIN32 API, generally you'll have to convert the image to a .c file, which the demos/mwin/mwdemo.c program does, or, you can convert the image to BMP format, then store load it from a .res resource file using resLoadBitmap. Look at demos/mwin/mwmine.c for how that can be done.

uklatt commented 10 months ago

Hi Greg, I compile the code on Linux x64 and it works ;-) Thank you for your help Uwe