Convert R G B values into single 0 - 255 color value?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Convert R G B values into single 0 - 255 color value?

#16 Post by IcarusLives » 16 Apr 2018 10:25

jeb wrote:
16 Apr 2018 09:46
-snip-
Your code is beautiful!!! It works so much better than mine! Excellent work, Jeb! Thank you for sharing!

I replied to your other post as well!

viewtopic.php?p=56404#p56404

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

Re: Convert R G B values into single 0 - 255 color value?

#17 Post by penpen » 16 Apr 2018 15:11

Here is an example of how i meant to use color lookup tables (tested on Windows 10):

Code: Select all

@echo off
setlocal enableExtensions disableDelayedExpansion
call :init

:: set up colortables
set "colorTable1="0;0;0","0;255;0","255;255;255","128;196;0","196;196;196""
set "colorTable2="0;0;0","255;0;0","255;255;255","255;140;64","196;196;196""
set "colorTable3="0;0;0","0;0;255","255;255;255","0;128;196","196;196;196""

set "loadColors(table)=set "i=0" & for %%a in (!table!) do (set "c!i!=%%~a" & set /a "i+=1")"

setlocal enableDelayedExpansion
mode con cols=100 lines=52
color 17
cls

:: render sprite with different colortables
%loadColors(table):table=colorTable1%
<nul set /p "=%setCursor(x;y):x;y=5;9%%sprite%"

%loadColors(table):table=colorTable2%
<nul set /p "=%setCursor(x;y):x;y=15;29%%sprite%"

%loadColors(table):table=colorTable3%
<nul set /p "=%setCursor(x;y):x;y=25;49%%sprite%"

<nul set /p "=%setCursor(x;y):x;y=50;1%"
%statement%

endlocal

pause
goto :eof


:init
::setup escape
for /F %%a in ('echo prompt $E^| cmd') do set "ESC=%%a"

::setup escape codes
set "saveCursor()=%ESC%[s"
set "unsaveCursor()=%ESC%[u"
set "restoreCursor()=%ESC%[8"
set "setCursor(x;y)=%ESC%[x;yf"
set "up(x)=%ESC%[xA"
set "down(x)=%ESC%[xB"
set "left(x)=%ESC%[xD"
set "right(x)=%ESC%[xC"
set "setColor(r;g;b)=%ESC%[38;2;r;g;bm"
set "resetAttributes()=%ESC%[0m"


::setup artwork
:: artwork also contains an image mask with " " := "not painted"
:: artwork pixels := " XG.@-"
set /a "artwork.lastRow=21, artwork.lastColumns=43"
::                         1         2         3         4
::               01234567890123456789012345678901234567890123
set  "artwork[0]=                  XXXXXXXX                  "
set  "artwork[1]=              XXXXGGGGGGGGXXXX              "
set  "artwork[2]=          XXXXGGGGGGGGGGGGGGGGXXXX          "
set  "artwork[3]=        XXGGXXGGGGGGGGGG....GGXXGGXX        "
set  "artwork[4]=      XXGGGGGGXXGGGGGGGGGGGGXXGGGGGGXX      "
set  "artwork[5]=      XXGGGGGG@@XXXXXXXXXXXXGGGGGGGGXX      "
set  "artwork[6]=    XXGGGGGGGGXX@@@@@@@@GGGGXXGGGGGGGGXX    "
set  "artwork[7]=    XXGGGGGGXX@@@@@@@@@@GGGGGGXXGGGGGGXX    "
set  "artwork[8]=    XXGGGGXX@@@@@@@@@@@@GGGGGG@@XXGGGGXX    "
set  "artwork[9]=  XXGGGGXX@@GG@@@@@@@@@@GGGGGGGG@@XXGGGGXX  "
set "artwork[10]=  XXGGXXGGXXGGGG@@@@@@GGGGGGGGGGXXGGXXGGXX  "
set "artwork[11]=  XXXX@@@@GGXXGGGGGGGGGGGGGGGGXXGG@@@@XXXX  "
set "artwork[12]=XXXXGGGGGGGGGGXXGGGGGGGGGGGGXXGGGGGGGGGGXXXX"
set "artwork[13]=XX..XXGGGGGGGGGGXXXXXXXXXXXX@@GGGGGGGGXX..XX"
set "artwork[14]=XX..XXGGGGGGGGXXGGGGGGGGGGGGXXGGGGGGGGXX..XX"
set "artwork[15]=XX--..XXXXGGXXGGGGGGGGGGGGGGGGXXGGXXXX..--XX"
set "artwork[16]=  XX......XXXXGGGGGGGGGGGGGGGGXXXX......XX  "
set "artwork[17]=  XX--........XXXXXXXXXXXXXXXX........--XX  "
set "artwork[18]=    XX----........................----XX    "
set "artwork[19]=      XXXX----................----XXXX      "
set "artwork[20]=          XXXX----------------XXXX          "
set "artwork[21]=              XXXXXXXXXXXXXXXX              "


:: compute sprite out of artwork
setlocal enableDelayedExpansion
rem set "ESC=^!ESC^!"
set "sprite=%saveCursor()%"
set /A "space=0"
set "lastChar= "
for /l %%r in (0, 1, %artwork.lastRow%) do (
	for /l %%c in (0, 1, %artwork.lastColumns%) do (
		for %%a in ("!artwork[%%~r]:~%%~c,1!") do (
			if "!lastChar!" == "%%~a" (
				if "%%~a" == " " ( set /a "space+=1"
				) else ( set "sprite=!sprite!Û"
				)
			) else (
				if "!lastChar!" == " " (
					if       !space! LSS 0 ( set "sprite=!sprite!%left(x):x=!space:~1!%"
					) else if !space GTR 0 ( set "sprite=!sprite!%right(x):x=!space!%"
					)
				) else (
					if "%%~a" == " " (
						set "space=1"
						if defined lastChar set "sprite=!sprite!%resetAttributes()%"
					) else (
						set "sprite=!sprite!%resetAttributes()%"
					)
				)

				if        "%%~a" == "X" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c0^!%Û"
				) else if "%%~a" == "G" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c1^!%Û"
				) else if "%%~a" == "." ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c2^!%Û"
				) else if "%%~a" == "@" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c3^!%Û"
				) else if "%%~a" == "-" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c4^!%Û"
				)
			)
			set "lastChar=%%~a"
		)
	)
	if not "!lastChar!" == " " (
		set "sprite=!sprite!%resetAttributes()%"
		set "lastChar= "
		set "space=0"
	)
	if not "%%~r" == "%artwork.lastRow%" (
		set "sprite=!sprite!%down(x):x=1%"
	)
	set /a "space-=(artwork.lastColumns+1)"
)
endlocal & set "sprite=%sprite%%restoreCursor()%%unsaveCursor()%"

goto :eof
penpen

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Convert R G B values into single 0 - 255 color value?

#18 Post by IcarusLives » 16 Apr 2018 22:31

Oh my... What a concept! I feel embarrassed I hadn't though of this. Thank you so much for this Penpen!

I also find it amazing that you ALSO managed to solve my OTHER issue viewtopic.php?p=56360#p56360

I will read this code thoroughly so I can learn from it an implement a solution into my game.

Jeb has also done something incredible!

I am so glad I joined this forum. I thought for a long time I had hit a plateau, but you all continue to inspire and teach me so much more.

Thank you for your time!

IcarusLives
Posts: 175
Joined: 17 Jan 2016 23:55

Re: Convert R G B values into single 0 - 255 color value?

#19 Post by IcarusLives » 18 Apr 2018 20:44

Penpen, I've been playing with your code, and to be honest this is really fun!

Image

Code: Select all

@echo off
setlocal enableExtensions disableDelayedExpansion
call :init

:: set up colortables
set "colorTable1="0;0;0","0;255;0","255;0;0","128;196;0","255;222;173","139;69;19""
set "colorTable2="0;0;0","255;0;0","0;0;255","255;140;64","255;222;173","139;69;19""
set "colorTable3="0;0;0","0;0;255","0;255;0","0;128;196","255;222;173","139;69;19""

set "loadColors(table)=set "i=0" & for %%a in (!table!) do (set "c!i!=%%~a" & set /a "i+=1")"

setlocal enableDelayedExpansion
mode con cols=100 lines=52
color 17
cls
timeout /t 5

:: render sprite with different colortables
set x=19
for /l %%b in (1,1,300) do (
	
	set /a "a+=1", "b=a %% 5"
	if !b! equ 0 set /a "x+=1"
	%loadColors(table):table=colorTable1%
	set "screen=!screen!!ESC![5;19H%sprite%"
	
	%loadColors(table):table=colorTable2%
	set "screen=!screen!!ESC![15;!x!H%sprite%"
	
	<nul set /p "=!esc![2J!screen!" & <nul set /p "=!screen!" & set "screen="
	
	%loadColors(table):table=colorTable3%
	<nul set /p "=%ESC%[25;49f%sprite%"
)

<nul set /p "=%setCursor(x;y):x;y=50;1%"

endlocal

pause
goto :eof


:init
::setup escape
for /F %%a in ('echo prompt $E^| cmd') do set "ESC=%%a"

::setup escape codes
set "saveCursor()=%ESC%[s"
set "unsaveCursor()=%ESC%[u"
set "restoreCursor()=%ESC%[8"
set "setCursor(x;y)=%ESC%[x;yf"
set "up(x)=%ESC%[xA"
set "down(x)=%ESC%[xB"
set "left(x)=%ESC%[xD"
set "right(x)=%ESC%[xC"
set "setColor(r;g;b)=%ESC%[38;2;r;g;bm"
set "resetAttributes()=%ESC%[0m"


::setup artwork
:: artwork also contains an image mask with " " := "not painted"
:: artwork pixels := " XG.@-"
set /a "artwork.lastRow=16, artwork.lastColumns=11"
::                         1         2         3         4
REM ::               01234567890123456789012345678901234567890123
REM set  "artwork[0]=                  XXXXXXXX                  "
REM set  "artwork[1]=              XXXXGGGGGGGGXXXX              "
REM set  "artwork[2]=          XXXXGGGGGGGGGGGGGGGGXXXX          "
REM set  "artwork[3]=        XXGGXXGGGGGGGGGG....GGXXGGXX        "
REM set  "artwork[4]=      XXGGGGGGXXGGGGGGGGGGGGXXGGGGGGXX      "
REM set  "artwork[5]=      XXGGGGGG@@XXXXXXXXXXXXGGGGGGGGXX      "
REM set  "artwork[6]=    XXGGGGGGGGXX@@@@@@@@GGGGXXGGGGGGGGXX    "
REM set  "artwork[7]=    XXGGGGGGXX@@@@@@@@@@GGGGGGXXGGGGGGXX    "
REM set  "artwork[8]=    XXGGGGXX@@@@@@@@@@@@GGGGGG@@XXGGGGXX    "
REM set  "artwork[9]=  XXGGGGXX@@GG@@@@@@@@@@GGGGGGGG@@XXGGGGXX  "
REM set "artwork[10]=  XXGGXXGGXXGGGG@@@@@@GGGGGGGGGGXXGGXXGGXX  "
REM set "artwork[11]=  XXXX@@@@GGXXGGGGGGGGGGGGGGGGXXGG@@@@XXXX  "
REM set "artwork[12]=XXXXGGGGGGGGGGXXGGGGGGGGGGGGXXGGGGGGGGGGXXXX"
REM set "artwork[13]=XX..XXGGGGGGGGGGXXXXXXXXXXXX@@GGGGGGGGXX..XX"
REM set "artwork[14]=XX..XXGGGGGGGGXXGGGGGGGGGGGGXXGGGGGGGGXX..XX"
REM set "artwork[15]=XX--..XXXXGGXXGGGGGGGGGGGGGGGGXXGGXXXX..--XX"
REM set "artwork[16]=  XX......XXXXGGGGGGGGGGGGGGGGXXXX......XX  "
REM set "artwork[17]=  XX--........XXXXXXXXXXXXXXXX........--XX  "
REM set "artwork[18]=    XX----........................----XX    "
REM set "artwork[19]=      XXXX----................----XXXX      "
REM set "artwork[20]=          XXXX----------------XXXX          "
REM set "artwork[21]=              XXXXXXXXXXXXXXXX              "

set  "artwork[1]=   GGGGG    "
set  "artwork[2]=  GGGGGGGGG "
set  "artwork[3]=  EEE--X-   "
set  "artwork[4]= E-E---X--  "
set  "artwork[5]= E-EE---X---"
set  "artwork[6]= EE----XXXX "
set  "artwork[7]=   -------  "
set  "artwork[8]=  GG.GGG    "
set  "artwork[9]= GGG.GG.GGG "
set "artwork[10]=GGGG....GGGG"
set "artwork[11]=--G.@..@.G--"
set "artwork[12]=---......---"
set "artwork[13]=--........--"
set "artwork[14]=  ...  ...  "
set "artwork[15]= EEE    EEE "
set "artwork[16]=EEEE    EEEE"

:: compute sprite out of artwork
setlocal enableDelayedExpansion
rem set "ESC=^!ESC^!"
set "sprite=%saveCursor()%"
set /A "space=0"
set "lastChar= "
for /l %%r in (0, 1, %artwork.lastRow%) do (
	for /l %%c in (0, 1, %artwork.lastColumns%) do (
		for %%a in ("!artwork[%%~r]:~%%~c,1!") do (
			if "!lastChar!" == "%%~a" (
				if "%%~a" == " " ( set /a "space+=1"
				) else ( set "sprite=!sprite!Û"
				)
			) else (
				if "!lastChar!" == " " (
					if        !space! LSS 0 ( set "sprite=!sprite!%left(x):x=!space:~1!%"
					) else if !space! GTR 0 ( set "sprite=!sprite!%right(x):x=!space!%"
					)
				) else (
					if "%%~a" == " " (
						set "space=1"
						if defined lastChar set "sprite=!sprite!%resetAttributes()%"
					) else (
						set "sprite=!sprite!%resetAttributes()%"
					)
				)

				if        "%%~a" == "X" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c0^!%Û"
				) else if "%%~a" == "G" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c1^!%Û"
				) else if "%%~a" == "." ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c2^!%Û"
				) else if "%%~a" == "@" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c3^!%Û"
				) else if "%%~a" == "-" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c4^!%Û"
				) else if "%%~a" == "E" ( set "sprite=!sprite!%setColor(r;g;b):r;g;b=^!c5^!%Û"
				)
			)
			set "lastChar=%%~a"
		)
	)
	if not "!lastChar!" == " " (
		set "sprite=!sprite!%resetAttributes()%"
		set "lastChar= "
		set "space=0"
	)
	if not "%%~r" == "%artwork.lastRow%" (
		set "sprite=!sprite!%down(x):x=1%"
	)
	set /a "space-=(artwork.lastColumns+1)"
)
endlocal & set "sprite=%sprite%%restoreCursor()%%unsaveCursor()%"

goto :eof

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Convert R G B values into single 0 - 255 color value?

#20 Post by einstein1969 » 22 Apr 2023 04:30

jeb wrote:
16 Apr 2018 09:46
Hi,

I played a bit with your code.
I tried to optimize the display function, I precompute all escape sequences before the display function is called.
I used the tip of Dave to use certutil.

This should be fast enough for a game.
Only the RGB-converting time is slow (takes 7seconds on my pc)
Now the functions take arguments for the ppm file and for the output picture array.

Code: Select all

@echo off & setlocal enableDelayedExpansion

REM INIT
for /F %%a in ('echo prompt $E^| cmd') do set "ESC=%%a"

REM *** bytesPerLine must be a multiple of 6, and bytesPerLine*20 must be less then 8191
set bytesPerLine=402

REM *** Clear Screen
<nul set /p ".=%ESC%[2J"

set t1=!time!
call :readImage "pinkFloyd.ppm"
set t2=!time!
call :RGB24bitTo8bit pinkFloyd
set t3=!time!

REM *** Draw the image and move the start line between 0 to 6
set "dir=1"
set /a "offset=0"
for /L %%n in (1 1 100) do (
    if defined dir (
        set /a offset+=1
        if !offset! GEQ 6 (
            set "dir="
        )
    ) else (
        set /a offset-=1
        if !offset! EQU 0 (
            set "dir=1"
        )
    )

    call :display pinkFloyd !offset!
)
echo(
echo time1=!t1!
echo time2=!t2!
echo time3=!t3!
echo time4=!time!
exit /b

:readImage
REM Parse height and width from PPM, and obtain headerSize
set "image=%~1"
for %%a in (%image%) do set "imageFileSize=%%~za"
if exist %image% ( if /i "%image:~-3%" equ "ppm" ( for /f "tokens=*" %%a in (%image%) do (
	set "str=X%%~a" & set "length=0"
	for /l %%b in (5,-1,0) do ( set /a "length|=1<<%%b"
		for /f "tokens=*" %%c in ("!length!") do if "!str:~%%c,1!" equ "" set /a "length&=~1<<%%b" )
	set /a "headerSize+=length + 1"
	if !i! equ 1 for /f "tokens=1,2" %%b in ("%%a") do ( set "o=%%b"
		if "!o:~0,1!" neq "#" set /a "width=%%b", "height=%%c" )
	if !i! equ 2 goto :break
	set /a "i+=1"
)) else ( echo Format not supported & timeout /t 2 > nul & exit )
) else ( echo File not found & timeout /t 2 > nul & exit )

:break
REM Parse all data from %image% and collect in hex[] up to <maxChars> characters (divisible by 6)
mode %width%,%height%
set /a height+=10
REM *** Set window dimension to height * width
<nul set /p ".=%ESC%[8;%height%;%width%t"

certutil -f -encodehex %image% ppm.hex.tmp > nul

set /a hex_max=0

set /a headerSize=headerSize*2 %= ignore this amount of hex values =%
set /a maxChars=bytesPerLine*2
for /f "tokens=1,*" %%a in (ppm.hex.tmp) do (
    set "line=%%b"
    set "line=!line:~0,48!"
    set "hex=!hex!!line: =!"
    if defined headerSize (
        if "!hex:~%headerSize%,1!" NEQ "" (
            set "hex=!hex:~%headerSize%!"
            set "headerSize="
        )
    )
    if "!hex:~%maxChars%,1!" NEQ "" (
        set "hex[!hex_max!]=!hex:~0,%maxChars%!"
        set /a hex_max+=1
        set "hex=!hex:~%maxChars%!"
    )
    <nul set /p ".=%ESC%[HLoading (!hex_max!)"
)
if "!hex!" == "" (
    set /a hex_max-=1
) ELSE (
    set "hex[!hex_max!]=!hex:~0,990!"
)
exit /b

REM *** Build the out[] array with color escape sequences for every pixel
:RGB24bitTo8bit <pictureName>
echo(
set /a maxCount=bytesPerLine*2-6
for /L %%a in (0,1,%hex_max%) do (
    <nul set /p ".=%ESC%7Converting RGB (%%a)%ESC%8" %= Save/restore cursor position =%
    set "out="
	for /L %%b in (0,6,%maxCount%) do (
        set "c=!hex[%%a]:~%%b,6!"
        if defined c (
            set /a "r=0x!c:~0,2!", "g=0x!c:~2,2!", "b=0x!c:~4,2!"
            set "out=!out!#!r!;!g!;!b!m "
        )
    )
    set "%1[%%a]=!out!"
)
exit /b

:display <pictureName> <offset>
REM *** Hide cursor, Set cursor to line %1
<nul set /p ".=%ESC%[?25l%ESC%[%2H"

for /L %%a in (0,1,%hex_max%) do (
    <nul set /p ".=!%1[%%a]:#=%ESC%[48;2;!"
)

REM *** Show cursor, Reset color to default
<nul set /p ".=%ESC%[?25h%ESC%[0m"
exit /b
Hi Jeb,

where you found the ESC [ 8 ; <height>; <width>t" sequence ?

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Convert R G B values into single 0 - 255 color value?

#21 Post by ShadowThief » 22 Apr 2023 07:40

Interesting, it seems that more sequences are supported than just the ones that are listed on https://learn.microsoft.com/en-us/windo ... -sequences

I'm going to have to do more research into this.

Post Reply