Drawing rudimentary graphics in text mode

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Drawing rudimentary graphics in text mode

#16 Post by Liviu » 12 Apr 2012 20:41

jeb wrote:it fails, as XP seems to use a different findstr.

Indeed. I somehow missed that in my previous post entirely. Apologies @Ed and @foxidrive.

jeb wrote:I made a special "hotfix" for XP-only
...
I echo the backspace 4 times to remove the ":. ." characters.

Works nicely. FWIW the 4 type's could be replaced with a single "set /p" with 4 %DEL% characters, or all 4 could be saved in the "DisplayChar" file and type'd once, since its contents is largely irrelevant now.

jeb wrote:One of my next goals is to use multiple threads for the mandelbrot.

Sounds crazy enough to trust it's inevitable ;-) looking forward to see it in action.

Liviu

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Drawing rudimentary graphics in text mode

#17 Post by jeb » 13 Apr 2012 01:47

Liviu wrote:Works nicely. FWIW the 4 type's could be replaced with a single "set /p" with 4 %DEL% characters, or all 4 could be saved in the "DisplayChar" file and type'd once, since its contents is largely irrelevant now.


Obviously that is better, but I wrote it at 0:50 and I was a little bit tired :)
And it should first check if the OS is XP, so the script will run at each OS

jeb

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Drawing rudimentary graphics in text mode

#18 Post by foxidrive » 13 Apr 2012 07:20

It almost works jeb: XP Pro SP3

Code: Select all

############################################################################:. .
###
############################################################################:. .
###
############################################################################:. .
###

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Drawing rudimentary graphics in text mode

#19 Post by Liviu » 13 Apr 2012 10:02

foxidrive wrote:

Code: Select all

############################################################################:. .
###
That looks like a wrap-around in an 80-chars wide console.

The best I think can work is for the "graphics" to use %columns%-3 (where columns is the console width). Jeb's XP code displays fine here in an xp.sp3 80-wide console with the following minor changes.

Code: Select all

rem <nul set /p ".=%DEL%" > "DisplayChar"
<nul set /p ".= " >"!DisplayChar!"

Code: Select all

rem set /A maxX=78, maxY=42, maxLevel=26, one=10000
set /A maxX=76, maxY=42, maxLevel=26, one=10000

Code: Select all

del "!DisplayChar!" >nul 2>&1
goto :EOF

Code: Select all

rem type #
rem type #
rem type #
rem type #
<nul set /p ".=%DEL%%DEL%"

Liviu

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Drawing rudimentary graphics in text mode

#20 Post by foxidrive » 13 Apr 2012 10:32

Yes, my console is 80 characters wide.

It looks good with the changes, though some pixels seem to be out of spec - the colours seem odd. The top left green one, and the upper right green one, and a few others. What causes those?

http://www.freeimagehosting.net/51rnk

Here's the code to save anyone else patching.


Code: Select all

@echo off
:: xp only due to findstr differences to Win7 etc
::Mandelbrot Set graphic in text mode
::Antonio Perez Ayala - Jan/03/2012

SETLOCAL EnableDelayedExpansion
set "DisplayChar=#"

for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set "DEL=%%a"
)
rem <nul set /p ".=%DEL%" > "DisplayChar"
<nul set /p ".= " >"!DisplayChar!"

setlocal EnableDelayedExpansion
REM Working values: maximum screen coordinates and iteration level
rem set /A maxX=78, maxY=42, maxLevel=26, one=10000
set /A maxX=76, maxY=42, maxLevel=26, one=10000


call :IntAsFP   xLeft=-1.0000
call :IntAsFP    yTop= 1.1250
call :IntAsFP  xRight= 2.0000
call :IntAsFP yBottom=-1.1250
set /A xStep=(xRight-xLeft)/maxX, yStep=(yBottom-yTop)/maxY, four=4*one
set showChars=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
set "showChar[0]=."
set "Xcolor=01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21"
set i=0
for %%c in (%showChars%) do (
    set /A i+=1
    set showChar[!i!]=%%c
)

cls
set /A yPos=yTop-yStep
for /L %%y in (0,1,%maxY%) do (
   set /A yPos+=yStep, xPos=xLeft-xStep
   for /L %%x in (0,1,%maxX%) do (
      set /A xPos+=xStep, xIter=xPos, yIter=yPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
      set level=0
      for /L %%i in (1,1,%maxLevel%) do (
         if !level! == 0 (
            if !root! lss %four% (
               set /A yIter=2*xIter*yIter/one-yPos, xIter=xSquare-ySquare-xPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
            ) else (
               set level=%%i
            )
         rem noelse
         )
      )
      rem for %%l in (!level!) do set /P =!showChar[%%l]!< NUL
     set /a col=level*3
     call :ColorText !col! !DisplayChar!
   )
   echo(
)
del "!DisplayChar!" >nul 2>&1
goto :EOF


:IntAsFP Int=FP
set FP=%2
set %1=!FP:.=!
exit /B


:ColorText
echo off
set "color=!Xcolor:~%1,2!"
findstr /v /a:%color% /R "^$" "%~2" nul
rem type #
rem type #
rem type #
rem type #
<nul set /p ".=%DEL%%DEL%"
goto :eof

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Drawing rudimentary graphics in text mode

#21 Post by Liviu » 13 Apr 2012 22:38

foxidrive wrote:It looks good with the changes, though some pixels seem to be out of spec - the colours seem odd. The top left green one, and the upper right green one, and a few others. What causes those?

That's one of those good questions with no easy answer ;-)

I think the math is right in the batch code. What looks like artifacts are in fact due to discretization, aliasing and our penchant for colors.

Mandelbrot sets themselves are black and white - each point/pixel is either "in" or "out". In the batch, that would amount to remapping the "color palette" to something like...

Code: Select all

set "Xcolor=f0 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08 08"

However, the popular visualizations assign colors based on the estimated "closeness" to the "in" set. That's only an estimate, and the limited integer precision of "set /a" arithmetics doesn't do it any favors. The pretty graphics you can find elsewhere are usually calculated in double-precision-floating-point.

Furthermore, fractals such as the Mandelbrot set are, loosely speaking, "infinitely zoomable". Which means that a very low resolution graphics, such as the 76x42 in the console, can sometimes accidentally "focus" upon some "exceptional" pixel, one which may represent its own micro-island of "in" values upon closer zoom-in. This is usually "masked out" by averaging/anti-aliasing elsewhere.

Liviu

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Drawing rudimentary graphics in text mode

#22 Post by foxidrive » 14 Apr 2012 04:25

Thanks. It's a neat piece of batch anyway. :)

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

Re: Drawing rudimentary graphics in text mode

#23 Post by Aacini » 14 Apr 2012 21:43

I wrote an .EXE version of my ColorMsg program that should correctly run in 64-bits Windows versions. To get it, copy this ColorMsg.exe.hex file:

Code: Select all

4D5A7E0102[3]20[3]FFFF[3]01[4]10003E[3]0100FB306A72[734]0FB60E8000E362BF8100B020FCF3AE7458E3568A45FFE8560080
3D20740EC0E0048AE08A05E847000AC44749E33B32E450B022F2AE7532E3308BF78BD1F2AE75094A3A057504474975F32BD1
741B8BCA5BB020B409CD10B222ACB40ECD103AC275053A04750146E2F032C0B44CCD213C6172022C203C4172022C072C30C3

and then execute this command:

Code: Select all

hextobin colormsg.exe.hex
You need to get HexToBin.bat conversion program from this post first.

You may review the result generated by my version of Mandelbrot Set color text here. That image took 1 minute 42 seconds in my very old "Intel(R) Pentium(R) M processor" @ 1.20 GHz lap-top running Windows XP Pro Version 2002 SP3 (with the DOS window maximized via Alt-Enter).

Note that my program use ASCII-255 character with color 0 to display the "land" (center) area of Mandelbrot Set in black:

Code: Select all

. . . .
THIS CHARACTER IS AN ASCII-255, NOT A SPACE!
set "showChar[0]= "
. . . .
set showColor[0]=0
The same result can be obtained using ASCII-219 block character (█) with color 0:

Code: Select all

set  showChars=█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ▓ ▓ ▒ ▒ ▒ ░ ░ ░ ░
set showColors=0 1 2 3 4 5 6 7 8 9 A B C C D D D D E E E E E E E E E
set i=-1
for %%c in (%showChars%) do (
    set /A i+=1
    set showChar[!i!]=%%c
)
set i=-1
for %%c in (%showColors%) do (
    set /A i+=1
    set showColor[!i!]=%%c
)

Drawing artifacts are caused by the lost of precision when floating point operations are simulated via 32-bits integers (with just 4 decimal digits in this case). However, those artifacts appear only between green and cyan color bands at right side of the image. I want to post a graphics mode Mandelbrot Set image so you can compare both versions, but when my old Turbo-C program with BGI graphics show the image, it can NOT be copied via Shift-PrtSc key. Anybody knows how can I copy that image?

Antonio

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Drawing rudimentary graphics in text mode

#24 Post by Liviu » 15 Apr 2012 00:24

Aacini wrote:Drawing artifacts are caused by the lost of precision when floating point operations are simulated via 32-bits integers (with just 4 decimal digits in this case).
Precision-wise there is one minor improvement possible, with emphasis on minor... The "set /A" integer division truncates towards 0 in the sense that 199/100=1 and -199/100=-1. A better 4-decimals emulation would round to the nearest integer, instead. For positive values, this would mean replacing, for example

Code: Select all

set /A xSquare=xIter*xIter/one
with

Code: Select all

set /A xSquare=(xIter*xIter+one/2)/one
For values of unknown sign, there would be an additional "if" needed to choose between "+one/2" vs. "-one/2".

Aacini wrote:I want to post a graphics mode Mandelbrot Set image so you can compare both versions, but when my old Turbo-C program with BGI graphics show the image, it can NOT be copied via Shift-PrtSc key. Anybody knows how can I copy that image?
I doubt many know Borland's BGI nowadays, and those who do may be approaching the memory loss phase of life ;-) Seriously, that's badly outdated, both as an IDE and for language support. GCC or the (free and more Windows-oriented) Visual C++ express edition come to mind.

Back to your actual question, if you have any virtual environment available (such as vmware, virtualpc, virtualbox etc) you could probably run the program full screen inside a virtual machine, and take a screen snapshot from the host. There may be ways to do it directly in the host, without any virtual machine involved, but those may depend on graphics drivers, helper apps, or the phases of the moon.

Liviu

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Drawing rudimentary graphics in text mode

#25 Post by foxidrive » 15 Apr 2012 02:20

Aacini wrote:However, those artifacts appear only between green and cyan color bands at right side of the image. I want to post a graphics mode Mandelbrot Set image so you can compare both versions, but when my old Turbo-C program with BGI graphics show the image, it can NOT be copied via Shift-PrtSc key. Anybody knows how can I copy that image?


Alt+Printscreen captures the window that is in focus, or use Snagit (payware) or another screen grabber.

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Drawing rudimentary graphics in text mode

#26 Post by Liviu » 15 Apr 2012 10:43

foxidrive wrote:Alt+Printscreen captures the window that is in focus, or use Snagit (payware) or another screen grabber.

It's been a long time and I may be wrong, but I believe BGI requires "hardware full screen" (Alt+Enter, not to be confused with a maximized window) in graphics mode, and neither Shift/Alt+Printscreen work there.

Most (all?) 3rd party screen scrapers don't support this, either, including Snagit (http://techsmith.custhelp.com/app/answe ... X1dJVms%3D).

Liviu

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Drawing rudimentary graphics in text mode

#27 Post by foxidrive » 15 Apr 2012 16:30

In that case I dunno either.

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

Re: Drawing rudimentary graphics in text mode

#28 Post by Aacini » 30 Apr 2012 19:46

May someone confirm if my ColorMsg.exe program works in 64-bits Windows versions? Thanks :)

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

Re: Drawing rudimentary graphics in text mode

#29 Post by Aacini » 02 May 2012 22:48

I downloaded w w w.dosbox.com DOS emulator for Windows and run my very old Turbo-C Mandelbrot Set program in graphics mode. After that I was able to capture the image and store it in a file, here it is. The original Mandelbrot Set image in color text mode is here, if you want to compare both images.

Antonio

P.S. May someone confirm if my ColorMsg.exe program run in 64-bits Windows, please? :roll: I want to rewrite my other auxiliary programs, but I must be sure first that the conversion works! :?

neorobin
Posts: 47
Joined: 01 May 2012 12:18

Re: Drawing rudimentary graphics in text mode

#30 Post by neorobin » 03 May 2012 03:53

Draw a maze:

Code: Select all

#############################################################
# #   #         #   #         #     #         #       #     #
# # # ####### ### # # ##### # # ### # ### ##### ##### # # ###
#   #   #   #     #   #   # # #   # # # #       #     # #   #
####### # # # ######### ### ##### # # # ####### # ### # ### #
#     #   # #           #   #     #       #   # #   # # # # #
# ### ##### ########### # ### ############# # ##### # # # # #
#   #   # # #       #   #     #   #         #     # # # # # #
# # ### # # # ##### # ######### # # ############# # ### # # #
# #   #   # #     # # # #   #   # #     #           #   # # #
# ### ##### # ### ### # # # # # ####### # ########### ### # #
# # #     # #   #     # # # # #       # #   # #     #     # #
# # ##### # ### ####### # # # ##### ### ### # # ### # ##### #
# #     # # #   #     #   #   #   #   #   #   # # #   #   # #
# # ##### # # ### ### # ##### # # # # ### ##### # ##### # # #
#   #   # # # #   #   # #   # # # # #   # #   # # #     #   #
### # # # # # # ### ### # # # # # ### # # # # # # # ####### #
#   # # # # #   #     # # # # # #     # #   # #   #       # #
##### # # # ######### ### # # # # ########### ### ####### # #
#     #   #         # #   # # # # #   #       #       #   # #
# # ##### ######### # # ### ### # # # # ####### ####### ### #
# # #   # #     # # #   #       # # # # #       # #     # # #
# ### # # # ### # # ############# # # # # ####### # ##### # #
# #   # # #   #   #       # #     # #   # #     # #   # #   #
# # ### # ### # ######### # # ##### ##### # ### # ### # # ###
# # # # #     # #       # #       #         #       # #   # #
# # # # ####### # ##### # ####### ################### # ### #
#   # # #     # # # #   # #   #         #       #     #     #
# ### # # ### ### # # # # # # ######### # ##### # ######### #
# #   #   # # #     # # #   #   #       #   # #   #         #
# # # ##### # # ##### ######### ##### ##### # ##### #########
# # #       #     #   #   #     #   # #   # #     #         #
# ##### ### ####### ### # # ##### # # ### # ### # ######### #
#     # # #     #   #   # #   #   # # #   #   # #   #   #   #
##### # # # ##### ### ### ### # ### # # # ### ### # # # # ###
#   # #   #     #   # # #   # # # # #   #   #   # # # # #   #
# ### ### ##### ### # # ### # # # # ### ##### # ### # # ### #
# #   #   #   #   #   #   #   # # #   # #   # #   # # # #   #
# # ####### # # # ####### ##### # ### ### # ##### # # # # ###
#           #   #               #         #       #   #     #
#############################################################


Code: Select all

@echo off & setlocal enabledelayedexpansion & color f0 & chcp 437
set /a "wid=60,hei=40,wid|=1,hei|=1,iMax=wid*hei,cols=wid,row=hei+1"
title maze !wid! col X !hei! row
mode con cols=!cols! lines=!row!

set "maze="
for /l %%y in (1 1 !hei!) do for /l %%x in (1 1 !wid!) do set "maze=!maze!#"
REM {1,2,4,8} -> {17,18,20,24} <-> {Up,Left,Right,Down}
set "d17=y-=2" & set "d18=x-=2" & set "d20=x+=2" & set "d24=y+=2" & set "d=0"
set "w17=y+=1" & set "w18=x+=1" & set "w20=x-=1" & set "w24=y-=1" & set "w=0"
set "dirs=" & set "cells=." & set /a "x=2, y=2"

for /l %%* in () do (
  if defined n!x!_!y! ( rem backtrack point
    if !dirs:~-2! equ 0x1f ( rem all dirs be searched at backtrack point
      set "dirs=!dirs:~0,-2!"
      set "cells=!cells:~1!" & set "cells=!cells:*.=.!"
      if "!cells!"=="." (
        <nul set /p "=" & title Maze generation completed, any key to exit...
        >nul pause & exit
      )
      for /f "tokens=1-2 delims=.#" %%x in ("!cells!") do (set x=%%x&set y=%%y)
    ) else ( rem exist some dirs not searched at backtrack point
      for /f "tokens=1-2 delims=.#" %%x in ("!cells!") do (set x=%%x&set y=%%y)
      set "dir=!dirs:~-2!"

      set /a "visit=1, randS=!random! & 3, randE=randS | 4"
      for /l %%d in (!randS! 1 !randE!) do if !visit! neq 0 (
        set /a "dc=1<<(%%d &3), visit=dir&dc,dir|=dc, dc|=0x10"
        if !visit! equ 0 (
          for %%r in (d!dc!) do set /a "!%%r!"
          set "dirs=!dirs:~0,-2!!dir!"
    ) ) )
  ) else ( rem can pass point
    set /a "xin=x-2^x-wid,yin=y-2^y-hei,in=(xin&yin)>>31"
    if !in! equ 0 ( rem out of the region
      for /f "tokens=1-2 delims=.#" %%x in ("!cells!") do (set x=%%x&set y=%%y)
    ) else ( rem In the region
      set "cells=.!x!#!y!!cells!"
      set "n!x!_!y!=1"

      for %%r in (w!dc!) do for %%i in (1 2) do (
        set /a "ind=(x-1)+(y-1)*wid+1, lL=ind-1, lR=iMax-ind"
        for /f "tokens=1-3" %%a in ("!lL! !ind! !lR!") do (set maze=!maze:~0,%%a!+!maze:~%%b,%%c!)
        set /a "!%%r!"
      )
      for %%r in (d!dc!) do set /a "!%%r!"
      cls & <nul set /p "=!maze:+= !"

      set /a "dc=(1<<(!random!&3))|0x10"
      set "dirs=!dirs!!dc!"
      for %%r in (d!dc!) do set /a "!%%r!"
) ) )
exit

Post Reply