Cmdgfx - draw 3d and graphic primitives (polygons,circles etc) in cmd window (now with 24-bit RGB support!)

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#31 Post by penpen » 19 Jul 2016 16:51

Well nowadays, it is much more than a simple memcpy (maybe i chbeck, if my memory doesn't play games with me...).
To be honest i couldn't understand it all... (sh.. asm... and the actual Visual Studio although more powerful, is much more unhandy than MS VS 6.0 on that point; no pleasure).

It seems the following happens (no guarantees):
The function WriteConsoleOutput calls a kind of console server with the message to display.
This server then displays the screen content line by line, row by row;
but every time the color changes an exception is thrown, restarting the whole process from the new starting position.
And the only reason (if i haven't overlooked something) of this is a single event that is thrown - i couldn't find out anything about this event;
i would guess it sets the color of the graphic context which, if that guess is true, runs in another thread.

So it seems i guessed right in my above post, although i found that hard to believe... .


penpen

Edit: I was wrong: WriteConsoleOutput never was a simple "memcopy"; Sorry @Microsoft.
Last edited by penpen on 20 Jul 2016 12:01, edited 1 time in total.

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#32 Post by misol101 » 19 Jul 2016 17:05

penpen: thanks, very ambitious going straight to the source and examining it!

According to your analysis though, I find my own statement a few posts ago hilarious:
It's like the incompetent MS developer decided that the whole text "engine" needs to be restarted every time the color changes... :)

Not too far off, actually :lol: (ok, I guess the guy had *some* reason, but nobody can convince me it couldn't have been done in another, better, much faster way)

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#33 Post by penpen » 19 Jul 2016 17:56

I think MS originally built a secure (but slow) running console version.
They never optimized it on that point, because it wasn't needed:
The console window is also a frame
=> you could use the default graphics functions, or if needed even embed an opengl panel.

Sample code to use the default color functions:

Code: Select all

// test.cpp
#include<windows.h>
#include<iostream>

using namespace std;

int main()
{
   PAINTSTRUCT ps;
   HWND hWnd = GetConsoleWindow();   // console window
   HDC hdc = GetDC(hWnd);         // device context
//      HDC hdc = ::BeginPaint(hWnd, &ps);

   for (int y = 0; y < 256; ++y)
   for (int x = 0; x < 256; ++x)
      SetPixel(hdc, x, y, RGB(x, y, 0));
   
   ReleaseDC(hWnd, hdc);
//   ::EndPaint(hWnd, &ps);
   cin.ignore();
   return 0;
}


penpen

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#34 Post by aGerman » 19 Jul 2016 18:03

I also don't understand the entire behavior. What I found is that not WriteConsoleOutput slows down the process. It's rather the way how MS updates the window (which seems to happen every time a character cell was changed).

Code: Select all

#include <windows.h>
#include <stdio.h>
#include <conio.h>

#define     COLS        160
#define     ROWS        55
#define     ITERATIONS  100

CHAR_INFO disp[ROWS][COLS];
HANDLE next, hbuffers[3];
COORD size = { COLS, ROWS };
COORD src = { 0, 0};
SMALL_RECT  dest = { 0, 0, COLS, ROWS };


void write_screen(int colrange, int charrange, int k) {
    int i, j;

    for (i = 0; i < ROWS; ++i) {
        for (j = 0; j < COLS; ++j) {
             disp[i][j].Char.AsciiChar = k % charrange+1;
             disp[i][j].Attributes = k % colrange+1;
             k++;
        }
    }
    WriteConsoleOutput(next, (CHAR_INFO *)disp, size, src, &dest);
}

void runTest(int col_range, int char_range) {
    int i, startT;

    startT = GetTickCount();

    // original test using only one screen buffer
    next = hbuffers[0];
    SetConsoleActiveScreenBuffer(next);
    for (i = 0; i < ITERATIONS; i++) {
      write_screen(col_range, char_range, i);
    }

    SetConsoleActiveScreenBuffer(hbuffers[2]);
    printf("one screen buffer  %ld s\n", (GetTickCount() - startT)/1000);
    getch();


    startT = GetTickCount();

    // new test using two screen buffers where the new content is written to an invisible buffer before it was activated
    for (i = 0; i < ITERATIONS; i++) {
      next = hbuffers[i & 1]; // next screen buffer depending if i was even or odd
      write_screen(col_range, char_range, i);
      SetConsoleActiveScreenBuffer(next);
    }

    SetConsoleActiveScreenBuffer(hbuffers[2]);
    printf("two screen buffers %ld s\n", (GetTickCount() - startT)/1000);
    getch();

}

int main(int argc, char **argv) {
    CONSOLE_SCREEN_BUFFER_INFOEX csbi;
    hbuffers[2] = GetStdHandle(STD_OUTPUT_HANDLE);

    // create 2 new screen buffers
    hbuffers[0] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
    hbuffers[1] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);

    // read the current screen buffer info and adjust the new buffers accordingly
    GetConsoleScreenBufferInfoEx(hbuffers[2], &csbi);
    SetConsoleScreenBufferInfoEx(hbuffers[0], &csbi);
    SetConsoleScreenBufferInfoEx(hbuffers[1], &csbi);

    runTest(250,200);

    return 1;
}

I used different screen buffers. Using WriteConsoleOutput to an invisible screen buffer is done in next to no time. But as soon as you activate this screen buffer to make it visible the same boring window updates are applied :evil:

Regards
aGerman

//EDIT
@penpen I already used this possibility to draw selected bitmap images to the console window. It works but the console window isn't able to save the informations. You can scroll it away and it won't appear again if you scroll back.

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#35 Post by misol101 » 19 Jul 2016 18:32

penpen wrote:The console window is also a frame
=> you could use the default graphics functions, or if needed even embed an opengl panel.

Sample code to use the default color functions:
...


Woah. Neat!

Edit: Come to think of it, it would actually be possible to fake using "text" mode, but instead just embed a screen capture of all console characters for all cmd fonts in a program and then copy/paste from that into a bitmap, then write that bitmap to the console frame, giving the illusion of using text :)

And the funny part is that it would most likely be a lot faster!

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#36 Post by Aacini » 19 Jul 2016 21:40

misol101 wrote:Come to think of it, it would actually be possible to fake using "text" mode, but instead just embed a screen capture of all console characters for all cmd fonts in a program and then copy/paste from that into a bitmap, then write that bitmap to the console frame, giving the illusion of using text :)

And the funny part is that it would most likely be a lot faster!

This description remembers me the method I used to show characters via individual pixels, that is explained at this post. 8)

Antonio

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#37 Post by misol101 » 20 Jul 2016 03:20

Aacini wrote:This description remembers me the method I used to show characters via individual pixels, that is explained at this post. 8)


Yeah pretty similar, though in a "reverse" manner. This forum is cool; for pretty much whatever I can think of it seems somebody have tried it out already in one way or the other 8)

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#38 Post by aGerman » 20 Jul 2016 03:53

I'll send you a PM with the tool for inserting a .bmp.

Regards
aGerman

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#39 Post by penpen » 20 Jul 2016 12:22

I looked into the "xp Version" (using Visual Studio 6.0) of WriteConsoleOutput and have to admit, that i was wrong:
WriteConsoleOutput never was a simple "memcopy" (Sorry @Microsoft: I've edited the above posts).

As far as i could watch, it does exactly the same, except the point that under Visual Studio 6.0
the default implementation is WriteConsoleOutputA and not WriteConsoleOutputW.

On both Windows versions the speed of colored output is slower, but under XP the speed is much higher (using the same pc).
Timing (game of life; monocolored output = "0x71"; colorized outpout = "(((i - 1)*COLS + (j - 1)) & 0xff)")

Code: Select all

win           monocolored              colorized
 10   ~4 seconds/~250 fps   ~58 seconds/~ 17 fps
 xp   ~2 seconds/~500 fps   ~ 8 seconds/~125 fps

Maybe i've missed something, but i'm out of ideas.


penpen

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#40 Post by misol101 » 22 Jul 2016 03:19

Well, it simply had to be done :mrgreen:

I embedded console font 6 into the test program, and wrote the whole thing out as a bitmap instead of calling WriteConsoleOutput!

Compiled with: gcc -o consolespeedtest3.exe consolespeedtest3.c -O2 -lgdi32

The old results (with WriteConsoleOutput) were: Test1: 0.2s, Test2: 7.0s, Test3: 7.0s

The new results are: Test1: 0.6s, Test2: 0.6s, Test3: 0.6s

So, as you can see this is good and bad. For the "worst case" (change color every char), this means this approach is about 11-12 times faster! In the "best case"(no color change) though, it's about 3 times slower...

Is there a faster way to create and blit the output to the screen than what I'm doing below?

Code: Select all

// needed for mingw to recognize GDI functions
#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <stdio.h>
#include <conio.h>

// Cmd font 6
int cmd_font6_w=8;
int cmd_font6_h=12;
int cmd_font6_data[256][12] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 126, 195, 129, 165, 129, 189, 153, 195, 126, 0, 0 },
{ 0, 126, 255, 255, 219, 255, 195, 231, 255, 126, 0, 0 },
{ 0, 0, 34, 119, 127, 127, 127, 62, 28, 8, 0, 0 },
{ 0, 8, 28, 62, 127, 127, 62, 28, 8, 0, 0, 0 },
{ 0, 24, 60, 60, 255, 231, 231, 24, 24, 126, 0, 0 },
{ 0, 24, 60, 126, 255, 255, 126, 24, 24, 126, 0, 0 },
{ 0, 0, 0, 0, 60, 126, 126, 60, 0, 0, 0, 0 },
{ 255, 255, 255, 255, 195, 129, 129, 195, 255, 255, 255, 255 },
{ 0, 0, 60, 126, 102, 66, 66, 102, 126, 60, 0, 0 },
{ 255, 255, 195, 129, 153, 189, 189, 153, 129, 195, 255, 255 },
{ 0, 124, 112, 92, 78, 31, 51, 51, 51, 30, 0, 0 },
{ 0, 60, 102, 102, 102, 60, 24, 126, 24, 24, 0, 0 },
{ 0, 248, 152, 152, 248, 24, 24, 30, 31, 14, 0, 0 },
{ 0, 254, 198, 254, 198, 198, 198, 230, 231, 103, 3, 0 },
{ 0, 0, 24, 219, 126, 231, 231, 126, 219, 24, 0, 0 },
{ 0, 1, 3, 7, 31, 127, 31, 7, 3, 1, 0, 0 },
{ 0, 64, 96, 112, 124, 127, 124, 112, 96, 64, 0, 0 },
{ 0, 24, 60, 126, 24, 24, 24, 126, 60, 24, 0, 0 },
{ 0, 102, 102, 102, 102, 102, 0, 0, 102, 102, 0, 0 },
{ 0, 254, 219, 219, 219, 222, 216, 216, 216, 216, 0, 0 },
{ 0, 126, 198, 12, 60, 102, 102, 60, 48, 99, 126, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 127, 127, 127, 0, 0 },
{ 0, 24, 60, 126, 24, 24, 24, 126, 60, 24, 126, 0 },
{ 0, 24, 60, 126, 24, 24, 24, 24, 24, 24, 0, 0 },
{ 0, 24, 24, 24, 24, 24, 24, 126, 60, 24, 0, 0 },
{ 0, 0, 0, 24, 48, 127, 48, 24, 0, 0, 0, 0 },
{ 0, 0, 0, 12, 6, 127, 6, 12, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 3, 3, 3, 127, 0, 0, 0, 0 },
{ 0, 0, 0, 36, 102, 255, 102, 36, 0, 0, 0, 0 },
{ 0, 0, 8, 8, 28, 28, 62, 62, 127, 127, 0, 0 },
{ 0, 0, 127, 127, 62, 62, 28, 28, 8, 8, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 12, 30, 30, 30, 12, 12, 0, 12, 12, 0, 0 },
{ 0, 102, 102, 102, 36, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 54, 54, 127, 54, 54, 54, 127, 54, 54, 0, 0 },
{ 12, 12, 62, 3, 3, 30, 48, 48, 31, 12, 12, 0 },
{ 0, 0, 0, 35, 51, 24, 12, 6, 51, 49, 0, 0 },
{ 0, 14, 27, 27, 14, 95, 123, 51, 59, 110, 0, 0 },
{ 0, 12, 12, 12, 6, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 48, 24, 12, 6, 6, 6, 12, 24, 48, 0, 0 },
{ 0, 6, 12, 24, 48, 48, 48, 24, 12, 6, 0, 0 },
{ 0, 0, 0, 102, 60, 255, 60, 102, 0, 0, 0, 0 },
{ 0, 0, 0, 24, 24, 126, 24, 24, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 6, 0 },
{ 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 0, 0 },
{ 0, 0, 64, 96, 48, 24, 12, 6, 3, 1, 0, 0 },
{ 0, 62, 99, 115, 123, 107, 111, 103, 99, 62, 0, 0 },
{ 0, 8, 12, 15, 12, 12, 12, 12, 12, 63, 0, 0 },
{ 0, 30, 51, 51, 48, 24, 12, 6, 51, 63, 0, 0 },
{ 0, 30, 51, 48, 48, 28, 48, 48, 51, 30, 0, 0 },
{ 0, 48, 56, 60, 54, 51, 127, 48, 48, 120, 0, 0 },
{ 0, 63, 3, 3, 3, 31, 48, 48, 51, 30, 0, 0 },
{ 0, 28, 6, 3, 3, 31, 51, 51, 51, 30, 0, 0 },
{ 0, 127, 99, 99, 96, 48, 24, 12, 12, 12, 0, 0 },
{ 0, 30, 51, 51, 51, 30, 51, 51, 51, 30, 0, 0 },
{ 0, 30, 51, 51, 51, 62, 24, 24, 12, 14, 0, 0 },
{ 0, 0, 0, 28, 28, 0, 0, 28, 28, 0, 0, 0 },
{ 0, 0, 0, 28, 28, 0, 0, 28, 28, 24, 12, 0 },
{ 0, 48, 24, 12, 6, 3, 6, 12, 24, 48, 0, 0 },
{ 0, 0, 0, 0, 126, 0, 126, 0, 0, 0, 0, 0 },
{ 0, 6, 12, 24, 48, 96, 48, 24, 12, 6, 0, 0 },
{ 0, 30, 51, 48, 24, 12, 12, 0, 12, 12, 0, 0 },
{ 0, 62, 99, 99, 123, 123, 123, 3, 3, 62, 0, 0 },
{ 0, 12, 30, 51, 51, 51, 63, 51, 51, 51, 0, 0 },
{ 0, 63, 102, 102, 102, 62, 102, 102, 102, 63, 0, 0 },
{ 0, 60, 102, 99, 3, 3, 3, 99, 102, 60, 0, 0 },
{ 0, 31, 54, 102, 102, 102, 102, 102, 54, 31, 0, 0 },
{ 0, 127, 70, 6, 38, 62, 38, 6, 70, 127, 0, 0 },
{ 0, 127, 102, 70, 38, 62, 38, 6, 6, 15, 0, 0 },
{ 0, 60, 102, 99, 3, 3, 115, 99, 102, 124, 0, 0 },
{ 0, 51, 51, 51, 51, 63, 51, 51, 51, 51, 0, 0 },
{ 0, 30, 12, 12, 12, 12, 12, 12, 12, 30, 0, 0 },
{ 0, 120, 48, 48, 48, 48, 51, 51, 51, 30, 0, 0 },
{ 0, 103, 102, 54, 54, 30, 54, 54, 102, 103, 0, 0 },
{ 0, 15, 6, 6, 6, 6, 70, 102, 102, 127, 0, 0 },
{ 0, 99, 119, 127, 127, 107, 99, 99, 99, 99, 0, 0 },
{ 0, 99, 99, 103, 111, 127, 123, 115, 99, 99, 0, 0 },
{ 0, 28, 54, 99, 99, 99, 99, 99, 54, 28, 0, 0 },
{ 0, 63, 102, 102, 102, 62, 6, 6, 6, 15, 0, 0 },
{ 0, 28, 54, 99, 99, 99, 115, 123, 62, 48, 120, 0 },
{ 0, 63, 102, 102, 102, 62, 54, 102, 102, 103, 0, 0 },
{ 0, 30, 51, 51, 3, 14, 24, 51, 51, 30, 0, 0 },
{ 0, 63, 45, 12, 12, 12, 12, 12, 12, 30, 0, 0 },
{ 0, 51, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 51, 51, 51, 51, 51, 51, 51, 30, 12, 0, 0 },
{ 0, 99, 99, 99, 99, 107, 107, 54, 54, 54, 0, 0 },
{ 0, 51, 51, 51, 30, 12, 30, 51, 51, 51, 0, 0 },
{ 0, 51, 51, 51, 51, 30, 12, 12, 12, 30, 0, 0 },
{ 0, 127, 115, 25, 24, 12, 6, 70, 99, 127, 0, 0 },
{ 0, 60, 12, 12, 12, 12, 12, 12, 12, 60, 0, 0 },
{ 0, 0, 1, 3, 6, 12, 24, 48, 96, 64, 0, 0 },
{ 0, 60, 48, 48, 48, 48, 48, 48, 48, 60, 0, 0 },
{ 8, 28, 54, 99, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0 },
{ 12, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 30, 48, 62, 51, 51, 110, 0, 0 },
{ 0, 7, 6, 6, 62, 102, 102, 102, 102, 59, 0, 0 },
{ 0, 0, 0, 0, 30, 51, 3, 3, 51, 30, 0, 0 },
{ 0, 56, 48, 48, 62, 51, 51, 51, 51, 110, 0, 0 },
{ 0, 0, 0, 0, 30, 51, 63, 3, 51, 30, 0, 0 },
{ 0, 28, 54, 6, 6, 31, 6, 6, 6, 15, 0, 0 },
{ 0, 0, 0, 0, 110, 51, 51, 51, 62, 48, 51, 30 },
{ 0, 7, 6, 6, 54, 110, 102, 102, 102, 103, 0, 0 },
{ 0, 24, 24, 0, 30, 24, 24, 24, 24, 126, 0, 0 },
{ 0, 48, 48, 0, 60, 48, 48, 48, 48, 51, 51, 30 },
{ 0, 7, 6, 6, 102, 54, 30, 54, 102, 103, 0, 0 },
{ 0, 30, 24, 24, 24, 24, 24, 24, 24, 126, 0, 0 },
{ 0, 0, 0, 0, 63, 107, 107, 107, 107, 99, 0, 0 },
{ 0, 0, 0, 0, 31, 51, 51, 51, 51, 51, 0, 0 },
{ 0, 0, 0, 0, 30, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 0, 0, 0, 59, 102, 102, 102, 102, 62, 6, 15 },
{ 0, 0, 0, 0, 110, 51, 51, 51, 51, 62, 48, 120 },
{ 0, 0, 0, 0, 55, 118, 110, 6, 6, 15, 0, 0 },
{ 0, 0, 0, 0, 30, 51, 6, 24, 51, 30, 0, 0 },
{ 0, 0, 4, 6, 63, 6, 6, 6, 54, 28, 0, 0 },
{ 0, 0, 0, 0, 51, 51, 51, 51, 51, 110, 0, 0 },
{ 0, 0, 0, 0, 51, 51, 51, 51, 30, 12, 0, 0 },
{ 0, 0, 0, 0, 99, 99, 107, 107, 54, 54, 0, 0 },
{ 0, 0, 0, 0, 99, 54, 28, 28, 54, 99, 0, 0 },
{ 0, 0, 0, 0, 102, 102, 102, 102, 60, 48, 24, 15 },
{ 0, 0, 0, 0, 63, 49, 24, 6, 35, 63, 0, 0 },
{ 0, 56, 12, 12, 6, 3, 6, 12, 12, 56, 0, 0 },
{ 0, 24, 24, 24, 24, 0, 24, 24, 24, 24, 0, 0 },
{ 0, 7, 12, 12, 24, 48, 24, 12, 12, 7, 0, 0 },
{ 0, 206, 91, 115, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 8, 28, 54, 99, 99, 127, 0, 0, 0 },
{ 0, 30, 51, 51, 3, 3, 3, 51, 51, 30, 12, 6 },
{ 0, 51, 51, 0, 51, 51, 51, 51, 51, 110, 0, 0 },
{ 48, 24, 12, 0, 30, 51, 63, 3, 51, 30, 0, 0 },
{ 12, 30, 51, 0, 30, 48, 62, 51, 51, 110, 0, 0 },
{ 0, 51, 51, 0, 30, 48, 62, 51, 51, 110, 0, 0 },
{ 3, 6, 12, 0, 30, 48, 62, 51, 51, 110, 0, 0 },
{ 28, 54, 54, 28, 31, 48, 62, 51, 51, 110, 0, 0 },
{ 0, 0, 0, 0, 30, 51, 3, 3, 51, 30, 12, 6 },
{ 12, 30, 51, 0, 30, 51, 63, 3, 3, 62, 0, 0 },
{ 0, 51, 51, 0, 30, 51, 63, 3, 3, 62, 0, 0 },
{ 3, 6, 12, 0, 30, 51, 63, 3, 3, 62, 0, 0 },
{ 0, 54, 54, 0, 30, 24, 24, 24, 24, 126, 0, 0 },
{ 8, 28, 54, 0, 30, 24, 24, 24, 24, 126, 0, 0 },
{ 6, 12, 24, 0, 30, 24, 24, 24, 24, 126, 0, 0 },
{ 0, 51, 0, 12, 30, 51, 51, 63, 51, 51, 0, 0 },
{ 30, 51, 51, 30, 30, 51, 51, 63, 51, 51, 0, 0 },
{ 48, 24, 0, 63, 35, 3, 31, 3, 35, 63, 0, 0 },
{ 0, 0, 0, 0, 127, 216, 254, 27, 27, 247, 0, 0 },
{ 0, 124, 30, 27, 27, 127, 27, 27, 27, 123, 0, 0 },
{ 12, 30, 51, 0, 30, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 51, 51, 0, 30, 51, 51, 51, 51, 30, 0, 0 },
{ 3, 6, 12, 0, 30, 51, 51, 51, 51, 30, 0, 0 },
{ 12, 30, 51, 0, 51, 51, 51, 51, 51, 110, 0, 0 },
{ 3, 6, 12, 0, 51, 51, 51, 51, 51, 110, 0, 0 },
{ 0, 102, 102, 0, 102, 102, 102, 102, 60, 48, 24, 15 },
{ 0, 51, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 51, 0, 51, 51, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 0, 0, 0, 30, 51, 59, 55, 51, 30, 0, 0 },
{ 60, 102, 6, 6, 6, 63, 6, 6, 3, 127, 0, 0 },
{ 0, 92, 54, 115, 107, 107, 107, 103, 54, 29, 0, 0 },
{ 0, 0, 0, 0, 0, 99, 54, 28, 54, 99, 0, 0 },
{ 112, 216, 24, 24, 126, 24, 24, 24, 27, 14, 0, 0 },
{ 48, 24, 12, 0, 30, 48, 62, 51, 51, 110, 0, 0 },
{ 48, 24, 12, 0, 30, 24, 24, 24, 24, 126, 0, 0 },
{ 48, 24, 12, 0, 30, 51, 51, 51, 51, 30, 0, 0 },
{ 48, 24, 12, 0, 51, 51, 51, 51, 51, 110, 0, 0 },
{ 0, 110, 59, 0, 31, 51, 51, 51, 51, 51, 0, 0 },
{ 110, 59, 0, 99, 103, 111, 123, 115, 99, 99, 0, 0 },
{ 0, 30, 51, 51, 126, 0, 127, 0, 0, 0, 0, 0 },
{ 0, 30, 51, 51, 30, 0, 127, 0, 0, 0, 0, 0 },
{ 0, 12, 12, 0, 12, 6, 3, 3, 51, 30, 0, 0 },
{ 0, 28, 34, 93, 85, 93, 77, 85, 34, 28, 0, 0 },
{ 0, 0, 0, 0, 0, 63, 48, 48, 48, 0, 0, 0 },
{ 0, 70, 103, 54, 30, 12, 118, 195, 97, 48, 248, 0 },
{ 0, 198, 103, 54, 30, 236, 246, 219, 205, 252, 192, 0 },
{ 0, 12, 12, 0, 12, 12, 30, 30, 30, 12, 0, 0 },
{ 0, 0, 0, 0, 204, 102, 51, 51, 102, 204, 0, 0 },
{ 0, 0, 0, 0, 51, 102, 204, 204, 102, 51, 0, 0 },
{ 36, 73, 146, 36, 73, 146, 36, 73, 146, 36, 73, 146 },
{ 170, 85, 170, 85, 170, 85, 170, 85, 170, 85, 170, 85 },
{ 182, 219, 109, 182, 219, 109, 182, 219, 109, 182, 219, 109 },
{ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 },
{ 24, 24, 24, 24, 24, 31, 24, 24, 24, 24, 24, 24 },
{ 48, 24, 0, 12, 30, 51, 51, 63, 51, 51, 0, 0 },
{ 30, 51, 0, 12, 30, 51, 51, 63, 51, 51, 0, 0 },
{ 6, 12, 0, 12, 30, 51, 51, 63, 51, 51, 0, 0 },
{ 0, 28, 34, 93, 69, 69, 69, 93, 34, 28, 0, 0 },
{ 102, 102, 102, 102, 103, 96, 96, 103, 102, 102, 102, 102 },
{ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102 },
{ 0, 0, 0, 0, 127, 96, 96, 103, 102, 102, 102, 102 },
{ 102, 102, 102, 102, 103, 96, 96, 127, 0, 0, 0, 0 },
{ 0, 12, 12, 30, 51, 3, 3, 51, 30, 12, 12, 0 },
{ 51, 51, 51, 51, 30, 63, 12, 63, 12, 12, 0, 0 },
{ 0, 0, 0, 0, 0, 31, 24, 24, 24, 24, 24, 24 },
{ 24, 24, 24, 24, 24, 248, 0, 0, 0, 0, 0, 0 },
{ 24, 24, 24, 24, 24, 255, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 255, 24, 24, 24, 24, 24, 24 },
{ 24, 24, 24, 24, 24, 248, 24, 24, 24, 24, 24, 24 },
{ 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0 },
{ 24, 24, 24, 24, 24, 255, 24, 24, 24, 24, 24, 24 },
{ 0, 110, 59, 0, 30, 48, 62, 51, 51, 110, 0, 0 },
{ 110, 59, 0, 12, 30, 51, 51, 63, 51, 51, 0, 0 },
{ 102, 102, 102, 102, 230, 6, 6, 254, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 254, 6, 6, 230, 102, 102, 102, 102 },
{ 102, 102, 102, 102, 231, 0, 0, 255, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 255, 0, 0, 231, 102, 102, 102, 102 },
{ 102, 102, 102, 102, 230, 6, 6, 230, 102, 102, 102, 102 },
{ 0, 0, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0 },
{ 102, 102, 102, 102, 231, 0, 0, 231, 102, 102, 102, 102 },
{ 0, 0, 0, 0, 0, 99, 62, 54, 62, 99, 0, 0 },
{ 51, 12, 27, 48, 96, 126, 99, 99, 99, 62, 0, 0 },
{ 0, 31, 54, 102, 102, 111, 102, 102, 54, 31, 0, 0 },
{ 30, 51, 0, 63, 35, 3, 31, 3, 35, 63, 0, 0 },
{ 0, 51, 0, 63, 35, 3, 31, 3, 35, 63, 0, 0 },
{ 6, 12, 0, 63, 35, 3, 31, 3, 35, 63, 0, 0 },
{ 0, 15, 12, 12, 12, 63, 0, 0, 0, 0, 0, 0 },
{ 24, 12, 0, 30, 12, 12, 12, 12, 12, 30, 0, 0 },
{ 30, 51, 0, 30, 12, 12, 12, 12, 12, 30, 0, 0 },
{ 0, 51, 0, 30, 12, 12, 12, 12, 12, 30, 0, 0 },
{ 24, 24, 24, 24, 24, 31, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 248, 24, 24, 24, 24, 24, 24 },
{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 },
{ 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255 },
{ 0, 24, 24, 24, 24, 0, 24, 24, 24, 24, 0, 0 },
{ 6, 12, 0, 30, 12, 12, 12, 12, 12, 30, 0, 0 },
{ 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0 },
{ 24, 12, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 30, 51, 51, 27, 51, 51, 51, 31, 3, 6, 0 },
{ 30, 51, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 6, 12, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 110, 59, 0, 30, 51, 51, 51, 51, 30, 0, 0 },
{ 110, 59, 0, 30, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 0, 0, 0, 0, 102, 102, 102, 102, 102, 222, 6, 3 },
{ 0, 0, 7, 6, 62, 102, 102, 62, 6, 15, 0, 0 },
{ 0, 15, 6, 62, 102, 102, 102, 62, 6, 15, 0, 0 },
{ 24, 12, 0, 51, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 30, 51, 0, 51, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 6, 12, 0, 51, 51, 51, 51, 51, 51, 30, 0, 0 },
{ 96, 48, 24, 0, 102, 102, 102, 102, 60, 48, 24, 15 },
{ 24, 12, 0, 51, 51, 51, 30, 12, 12, 30, 0, 0 },
{ 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 48, 24, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 12, 12, 63, 12, 12, 0, 63, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 31, 0, 0, 31, 0, 0, 0 },
{ 7, 204, 102, 60, 31, 236, 246, 219, 205, 252, 192, 0 },
{ 0, 254, 219, 219, 219, 222, 216, 216, 216, 216, 0, 0 },
{ 0, 126, 198, 12, 60, 102, 102, 60, 48, 99, 126, 0 },
{ 0, 0, 12, 12, 0, 63, 0, 12, 12, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 14 },
{ 0, 60, 102, 102, 102, 60, 0, 0, 0, 0, 0, 0 },
{ 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0 },
{ 0, 12, 14, 12, 12, 30, 0, 0, 0, 0, 0, 0 },
{ 0, 30, 48, 28, 48, 30, 0, 0, 0, 0, 0, 0 },
{ 0, 30, 48, 24, 12, 62, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 63, 63, 63, 63, 63, 63, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
};

#define     COLS        160
#define     ROWS        55
#define     ITERATIONS  100

unsigned char videoCol[ROWS*COLS];
unsigned char videoChar[ROWS*COLS];

void convertToGdiBitmap(int XRES, int YRES, unsigned char *videoCol, unsigned char *videoChar, int fontIndex) {
  HWND hWnd = NULL;
  HDC hDc = NULL, hDcBmp = NULL;
  HBITMAP hBmp1 = NULL;
  HGDIOBJ hGdiObj = NULL;
  BITMAP bmp = {0};
  LONG w = 0, h = 0;
  int iRet = EXIT_FAILURE;
  long x=0, y=0;
  unsigned char *outdata = NULL, *pcol, *outt;
  int i,j,ccol,cchar,l,m, index;
  static unsigned char cmdPalette[16][3] = { {0,0,0}, {128,0,0}, {0,128,0}, {128,128,0}, {0,0,128}, {128,0,128}, {0,128,128}, {192,192,192}, {128,128,128}, {255,0,0}, {0,255,0}, {255,255,0}, {0,0,255}, {255,0,255}, {0,255,255}, {255,255,255} };
  static int *fontData[16] = { NULL, NULL, NULL, NULL, NULL, NULL, &cmd_font6_data[0][0], NULL, NULL, NULL };
  int fontWidth[16] = { 0, 0, 0, 0, 0, 0, cmd_font6_w, 0, 0, 0 };
  int fontHeight[16] = { 0, 0, 0, 0, 0, 0, cmd_font6_h, 0, 0, 0 };
  int fw, fh, *data, val, bpp = 4;
  unsigned char *fgcol, *bgcol;
 
  fw = fontWidth[fontIndex];
  fh = fontHeight[fontIndex];
  data = fontData[fontIndex];
                     
  if ((hWnd = GetConsoleWindow()))
  {
    if ((hDc = GetDC(hWnd)))
    {
      if ((hDcBmp = CreateCompatibleDC(hDc)))
      {
        w = XRES * fw;
         h = YRES * fh;
        outdata = (unsigned char *)malloc(w*h*4);
        if (!outdata) { printf("#ERR: Could not allocate memory for output buffer\n"); ReleaseDC(hWnd, hDcBmp); ReleaseDC(hWnd, hDc); return; }
/*            
        hBmp1 = (HBITMAP)CreateBitmap(w, h, 1, 8*bpp, NULL);
        if (!hBmp1) { bpp = 3; hBmp1 = (HBITMAP)CreateBitmap(w, h, 1, 8*bpp, NULL); }
        if (!hBmp1) { printf("#ERR: Could not create 24 or 32 bpp output bitmap\n"); free(outdata); ReleaseDC(hWnd, hDcBmp); ReleaseDC(hWnd, hDc); return; }
        DeleteObject(hBmp1);
*/
        for (i = 0; i < YRES; i++) {          
            for (j = 0; j < XRES; j++) {
              cchar = videoChar[j+i*XRES];
              ccol = videoCol[j+i*XRES];
              fgcol = cmdPalette[ccol&0xf];
              bgcol = cmdPalette[ccol>>4];
              for (l = 0; l < fh; l++) {
                  index = (j*fw + (i*fh+l)*XRES*fw)*bpp;
                  val = data[cchar*fh+l];
                  outt = &outdata[index];
                  for (m = 0; m < fw; m++) {
                     pcol = val & 1 ? fgcol : bgcol;
                     *outt++ = *pcol++; // B
                     *outt++ = *pcol++; // G
                     *outt++ = *pcol++; // R
                     if (bpp == 4) *outt++ = 255;    // A?
                     val >>= 1;
                  }
              }
           }
        }

        hBmp1 = (HBITMAP)CreateBitmap(w, h, 1, 8*bpp, outdata);
        if (hBmp1)
        {
          if (GetObject(hBmp1, sizeof(bmp), &bmp))
          {
            w = bmp.bmWidth; h = bmp.bmHeight;
            if ((hGdiObj = SelectObject(hDcBmp, hBmp1)) && hGdiObj != HGDI_ERROR)
            {
             if (BitBlt(hDc, (int)x, (int)y, (int)w, (int)h, hDcBmp, 0, 0, SRCCOPY)) {
               iRet = EXIT_SUCCESS;
             }
             DeleteObject(hGdiObj);
            }
          }
          DeleteObject(hBmp1);
        }

        ReleaseDC(hWnd, hDcBmp);
      }
      ReleaseDC(hWnd, hDc);
    }
  }
 
  if (iRet == EXIT_FAILURE) printf("#ERR: Failure processing output bitmap\n");
  if (outdata) free(outdata);
}


void write_screen3(int colrange, int charrange, int k) {
    int i, j;

    for (i = 1; i <= ROWS; ++i) {
        for (j = 1; j <= COLS; ++j) {
             videoChar[(i-1)*COLS+(j-1)] = k % charrange+1;
             videoCol[(i-1)*COLS+(j-1)] = k % colrange+1;
             k++;
        }
    }   
    convertToGdiBitmap(COLS, ROWS, videoCol, videoChar, 6);
}

void runTest(int col_range, int char_range) {
    int i, startT;

    startT = GetTickCount();
   
    for (i = 0; i < ITERATIONS; i++) {
      write_screen3(col_range, char_range, i);
    }

    printf("%ld s\n", (GetTickCount() - startT)/100);
    getch();
}

// 0.2, 7.0, 7.0 vs
// 0.6, 0.6, 0.6

int main(int argc, char **argv) {
    runTest(1,2);
    runTest(2,1);
    runTest(250,200);

    return 1;
}

carlos
Expert
Posts: 503
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#41 Post by carlos » 22 Jul 2016 07:32

misol101, what about use this flag on the gcc:

Code: Select all

 -fno-omit-frame-pointer


That will speed more all the functions calls.

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#42 Post by misol101 » 22 Jul 2016 10:25

carlos wrote:misol101, what about use this flag on the gcc:

Code: Select all

 -fno-omit-frame-pointer


This unfortunately did not affect the speed in a noticable way.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#43 Post by aGerman » 22 Jul 2016 13:15

Ummm ...

Imagine you have a tiled wall. You can buy wall tiles only with a limited amount of patterns and limited color variations. Every time you don't like the tiles anymore you have to chop them off and flag the wall again. Quite annoying and time-killing. Now you got the idea to paint them over. That's cheap and fast (and that's the point that reached right now). Next time you balance the reasons why you used the same limited patterns and colors of the tiles even if you already have much more possibilities with paint. You'll come to the conclusion that you would rather gild the whole wall regardless of the shape and the size of the tiles. They are still underneath your paint but completely useless and counterproductive. Their surface is too smooth and the paint doesn't hold properly. Guess what's next ... :P

I hope you understand what I tried to explain. Don't get me wrong - fiddling with the console window is fun as long as you don't try to let it behave the same as a GUI. That's foredoomed :wink:

Regards
aGerman

misol101
Posts: 475
Joined: 02 May 2016 18:20

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#44 Post by misol101 » 22 Jul 2016 13:28

aGerman wrote:Ummm ...

I hope you understand what I tried to explain. Don't get me wrong - fiddling with the console window is fun as long as you don't try to let it behave the same as a GUI. That's foredoomed :wink:


I get what you mean, I think. Of course, at some point, the question becomes: why use text at all? Why use the console at all? Why not use OpenGL instead godammit? :lol:

That is true of course, and I think I would pass that line if I started drawing actual pixels, or non-default fonts, or start alpha-blending characters, or whatnot, in the cmd window. However the approach above was simply to see if I could speed up the very slow WriteConsoleOutput by showing text as bitmaps. The result looks exactly the same in this case.

And I could! :wink: The textured world is now approximately 100% faster than before, using the above approach. However, that's where it will end...

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Cmdgfx - draw graphic primitives (polygons,circles etc) in cmd line window

#45 Post by aGerman » 22 Jul 2016 15:36

or non-default fonts

Even default fonts are already problematic. Your code works with 8x12 raster font only. Consolas font was the default setting in my Win 10. Mixing bitmap and text may fail more often as you expect. Again - I don't want to be the killjoy. Just telling you my concerns and talking about pitfalls that already ancountered to me :wink:

Post Reply