Menu

putpixel() C function

2026-04-03
2 days ago
  • Eugenio Di Lorenzo

    I'd like to use the putpixel() C function from a GnuCOBOL program.
    To draw geometric shapes on the screen: a circle, a rosette, etc. See:
    https://www.geeksforgeeks.org/c/putpixel-function-c/

    Possibly without using a C wrapper but using something like this in the GnuCOBOL program:

           >>SOURCE FREE
    IDENTIFICATION DIVISION.
    PROGRAM-ID. PIXELC.
    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 wX  BINARY-SHORT.
    01 wY  BINARY-SHORT.
    01 wC  BINARY-SHORT.
    PROCEDURE DIVISION.
    move 04 to wX wY wC
    *> void putpixel(int x, int y, int color);
    *> where, (x, y) is the location at which pixel is to be put and color specifies the color of the pixel.
    call static "putpixel" using by value wX wY wC returning omitted end-call
    ACCEPT OMITTED
    STOP RUN.
    

    Compiling this program gives "undefined reference to `putpixel' "

    Can someone explain to me in detail if it is possible and how / what I should do ?

     
  • Simon Sobisch

    Simon Sobisch - 2026-04-03

    As far as I see:

    • you want an int, so BINARY-LONG
    • that function seems to be a header-implementation, so you'd add --include graphics.h
     
  • Chuck Haatvedt

    Chuck Haatvedt - 6 days ago

    I believe that you will be required to use the pdcurses-wingui.dll and copy it to pdcurses.dll

        Chuck Haatvedt
    
     
  • Anonymous

    Anonymous - 6 days ago

    There are prerequisites to calling putpixel
    Initialization: You must initialize the graphics system using initgraph(&gd, &gm, ""); before calling putpixel.

    Where:
    gd = Graphics Driver ->
    A pointer to an integer specifying the driver.
    Using the macro DETECT (set to 0) allows the system to automatically pick the best driver for your hardware.

    gm = Graphics Mode -> resolution

    "" (Path to Driver):
    Windows:

    EasyX
    SDL_BGI

     
  • Eugenio Di Lorenzo

    Yes, of course, looking at
    https://www.geeksforgeeks.org/c/putpixel-function-c/
    I can see that there are some calls that need to be made before using the function.
    But the problem is something else.
    These calls, however, seem to look for a library that I don't know what it is and where to find.

    Replacing pdcurses-wingui.dll and copying it to pdcurses.dll is also impossible because I'm using the AIO compiler available in SuperBOL and VSCode.
    This compiler doesn't use pdcurses, but libncursesw.dll.a and libncursesw6.dll.

     
  • Michael Del Solio

    Some hints I found to this topic:

    putpixel() is part of the Borland BGI Graphics emulation (based on https://en.wikipedia.org/wiki/Borland_Graphics_Interface ):

    https://winbgim.codecutter.org/

    But unfortunately this is just für MinGW-32 and so it does not work with the SuperBOL-distribution which is shipped with MinGW-64.

    It should work with the distribution of Arnold because this is based on MinGW-32 but this comes without g++ (C++ compiler). But g++ ist needed because in the graphics.h the file sstream.h is referenced and this is related to C++.

    A 64-bit version is available here:
    https://github.com/ahmedshakill/WinBGIm-64
    But it has to be compiled by one self and there is no ready to use binary version - so far I see.

    PS: Maybe there are binary 64-bit versions of this lib in the internet. But these files should always watched twice because of security issues. A good practise is to check them on virustotal.com ...

     
    • Eugenio Di Lorenzo

      Sincere thanks for this answer, which I think is exhaustive, even if it doesn't meet my goals.
      Thank you.

      At this point, I'd say I have to abandon this approach.
      I remember that the older BASIC had some simple statements to draw, for example, a circle, a square or a line etc. in a graphical way.

      10 SCREEN 1                     ' set graphic mode
      20 XC = 160 : YC = 100 : R = 50 'Center and Radius
      30 FOR A = 0 TO 6.28 STEP 0.1
      40   X = XC + R * COS(A)
      50   Y = YC + R * SIN(A)
      60   PSET (X,Y)                  ' draw a pixel
      70 NEXT A
      

      If anyone has an alternative idea, I'd be very grateful.
      The goal is to draw a pixel on the screen using GnuCOBOL and, for example, a CALL to a function in a C library.

       
      • Michael Del Solio

        Thank you very much.

        I searched now for a 64-bit version and found this one for MinGW:
        https://github.com/dbautsch/winbgim/releases/tag/6.0a

        The binary libbgi64.a looks ok while checked with virustotal (please recheck if you want to use it). We need to extract the graphics.h from the file "Source code (zip)" and put it into include folder of the SuperBOL-installation ... and we need to put ibbgi64.a into the libs folder...

        Tomorrow (or within the next days) I will try to compile the example from https://www.geeksforgeeks.org/c/putpixel-function-c/ If this works we can go a step further with calling functions from GnuCOBOL. I think because GnuCOBOL uses gcc internally we need to write a wrapper in C which calls the g++ code from winbgim.

        Seems to be a longer way with some challenges ahead :-)

        Another approach we could give a view is:
        https://sourceforge.net/projects/sdl-bgi/ which is already mentioned by Anonymous above.

        Or SDL2/SDL3 directly. But we probably need wrapper routines to call it in a comfortable way from GnuCOBOL. The benefit would that this could work in Windows and Linux both.

        But maybe there are some other good solutions, ideas and howtos out there in the community right now :-)

         
        • Michael Del Solio

          Ok, I think we are on the good way with winbgm/putpixel() on SuperBOL-AIO-distribution :-)

          1) Library (always check it with virustotal.com) and graphics.h from:
          https://github.com/dbautsch/winbgim/releases/tag/6.0a

          2) Rename libbgi64.a to libbgi.a and put it into:
          C:\Users\YOURUSER\AppData\Local\GnuCOBOL\mingw64\lib\gcc\x86_64-w64-mingw32\13.2.0

          3) Put graphics.h (from the Source Code ZIP file) into:
          C:\Users\YOURUSER\AppData\Local\GnuCOBOL\mingw64\lib\gcc\x86_64-w64-mingw32\13.2.0\include

          4) Compile wrapper.cpp and circle.cob from Windows Terminal (CMD):

          g++ -c wrapper.cpp -o wrapper.o
          cobc -x circle.cob wrapper.o -lbgi -lstdc++ -lgdi32 -lcomdlg32 -luuid -loleaut32 -lole32
          

          5) Call the demo:
          circle.exe

          wrapper.cpp:

          // wrapper.cpp
          #include <graphics.h>
          
          extern "C" {
          
              void init_graph() {
                  initwindow(320, 200, "COBOL Circle");
              }
          
              void my_putpixel(int x, int y, int color) {
                  putpixel(x, y, color);
              }
          
              void wait_key() {
                  getch();
              }
          
              void close_graph() {
                  closegraph();
              }
          
          }
          

          circle.cob (from the BASIC example above):

                 >>SOURCE FREE
          IDENTIFICATION DIVISION.
          PROGRAM-ID. CIRCLE.
          
          DATA DIVISION.
          WORKING-STORAGE SECTION.
          
          01 XC    COMP-2 VALUE 160.
          01 YC    COMP-2 VALUE 100.
          01 R     COMP-2 VALUE 50.
          
          01 A     COMP-2 VALUE 0.
          01 STEP  COMP-2 VALUE 0.1.
          
          01 X     COMP-2.
          01 Y     COMP-2.
          
          01 XI    BINARY-LONG.
          01 YI    BINARY-LONG.
          
          01 WS-COLOR     BINARY-LONG VALUE 15.
          
          PROCEDURE DIVISION.
          
              CALL "init_graph"
          
              MOVE 0 TO A
          
              PERFORM UNTIL A > 6.28
          
                *>DISPLAY "A=" A " X=" X " Y=" Y
          
                COMPUTE X = XC + R * FUNCTION COS(A)
                COMPUTE Y = YC + R * FUNCTION SIN(A)
          
                COMPUTE XI = X
                COMPUTE YI = Y
          
                CALL "my_putpixel" USING BY VALUE XI YI WS-COLOR
          
                ADD STEP TO A
          
              END-PERFORM
          
              CALL "wait_key"
              CALL "close_graph"
          
              STOP RUN.
          

          PS: Colors and other constants are from graphics.h:

          // The standard Borland 16 colors
          enum colors {
          BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY, DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE };
          
           

          Last edit: Michael Del Solio 2 days ago
          • Michael Del Solio

            Now, we have some more functions available:

                   >>SOURCE FREE
            IDENTIFICATION DIVISION.
            PROGRAM-ID. GFXDEMO.
            
            DATA DIVISION.
            WORKING-STORAGE SECTION.
            
            78 C-BLACK VALUE 0.
            78 C-BLUE VALUE 1.
            78 C-GREEN VALUE 2.
            78 C-CYAN VALUE 3.
            78 C-RED VALUE 4.
            78 C-MAGENTA VALUE 5.
            78 C-BROWN VALUE 6.
            78 C-LIGHTGRAY VALUE 7.
            78 C-DARKGRAY VALUE 8.
            78 C-LIGHTBLUE VALUE 9.
            78 C-LIGHTGREEN VALUE 10.
            78 C-LIGHTCYAN VALUE 11.
            78 C-LIGHTRED VALUE 12.
            78 C-LIGHTMAGENTA VALUE 13.
            78 C-YELLOW VALUE 14.
            78 C-WHITE VALUE 15.
            
            01 X  BINARY-LONG VALUE 100.
            01 Y  BINARY-LONG VALUE 100.
            01 WS-TEXT PIC X(20) VALUE "HELLO COBOL!".
            
            PROCEDURE DIVISION.
            
                DISPLAY "START COBOL Graphics Demo"
            
                CALL "gfx_init"
            
                CALL "gfx_circle" USING BY VALUE 200 150 50 C-WHITE
                CALL "gfx_line" USING BY VALUE 0 0 300 200 C-LIGHTGREEN
                CALL "gfx_pixel" USING BY VALUE X Y C-LIGHTRED
                CALL "gfx_rect" USING BY VALUE 80 70 180 160 C-LIGHTMAGENTA
            
                *> maybe unsafe because string termination ?!
                *> CALL "gfx_text" USING BY VALUE 10 10 BY CONTENT "HELLO COBOL!"
            
                CALL "gfx_text_safe" USING
                BY VALUE 10
                BY VALUE 10
                BY CONTENT WS-TEXT
                BY VALUE LENGTH OF WS-TEXT
                BY VALUE C-YELLOW
            
                CALL "gfx_wait"
                CALL "gfx_close"
            
                DISPLAY "END COBOL Graphics Demo"
            
                STOP RUN.
            

            gfxdemo.bat:

            g++ -c gfx_wrapper.cpp -o gfx_wrapper.o
            cobc -x gfxdemo.cob gfx_wrapper.o -lbgi -lstdc++ -lgdi32 -lcomdlg32 -luuid -loleaut32 -lole32
            
            gfxdemo.exe
            

            New gfxwrapper.cpp attached ...

             
  • Chuck Haatvedt

    Chuck Haatvedt - 3 days ago

    PDCursesMOD does provide a Windows graphic version called WINGUI. With this you should be able to access individual pixels using the setpixel function. There are some serious considerations

    How to Access Pixels in WinGUI
    To draw or manipulate individual pixels, you must bypass the curses abstraction and use the underlying Windows API:

    Get the Device Context (HDC): You need a handle to the window's device context to perform graphical operations. In the WinGUI port, you can often obtain the relevant HWND (window handle) or HDC.
    Use SetPixel(): The standard Win32 API function SetPixel(hdc, x, y, color) allows you to change the color of a specific pixel at coordinates
    .
    Coordinate Systems: Remember that curses uses character-based coordinates (rows/cols), while GDI uses absolute pixel coordinates. You may need to calculate the pixel position based on the current font width and height.
    

    Key Considerations

    Redrawing: Curses manages its own internal buffer. If you draw pixels directly to the window using GDI, they may be overwritten or erased the next time curses calls refresh() or wrefresh(), as it redraws the text grid over the window.
    Portability: Using pixel-level GDI calls breaks the portability of your code. Your application will only work with the WinGUI port of PDCursesMod and won't function on standard terminal-based curses or other ports like X11 without significant changes.
    Performance: Drawing pixel-by-pixel with SetPixel() is generally slow. For complex graphics, it is better to draw to an off-screen bitmap and then copy that bitmap to the screen in one operation using BitBlt().
    

    In my opinion, if you want to do graphic's then you should consider not using curses as it is a text user interface.

    could pixels be accessed using ncursesw ?
    No,
    ncursesw (the wide-character version of ncurses) cannot access individual hardware pixels. Unlike the WinGUI port of PDCursesMod, which can interact with the Windows GDI, ncursesw is designed strictly for character-cell terminals where the smallest addressable unit is a single character cell.

    Chuck Haatvedt

     

Anonymous
Anonymous

Add attachments
Cancel





MongoDB Logo MongoDB