Board logo

标题: [特效代码] [求助][已解决]请各位批处理高手解释这段代码显示图片的原理 [打印本页]

作者: HOPE2021    时间: 2021-8-9 13:18     标题: [求助][已解决]请各位批处理高手解释这段代码显示图片的原理

本帖最后由 HOPE2021 于 2021-8-9 16:16 编辑

以下这段代码是我从Dostips论坛找到的,它可以在不使用任何第三方的情况下以RGB显示图片(仅支持Win10)。
使用方法:在此批处理目录下放置一个宽120,高160像素的.bmp图片,重命名为123.bmp。再打开此批处理文件。
问题:此代码是如何做的显示图片的?原理是什么?可不可以更改分辨率?可不可以兼容Win7?
帖子标题:Display .BMP files in RGB colors - WIN 10 ONLY
来源:https://www.dostips.com/
原作者:aGerman

代码:
  1. @echo off &setlocal
  2. rem Name of the bitmap file without extension
  3. set "filename=123"
  4. rem Window title necessary to identify it for the updated registry values
  5. set "title=BMP Test"
  6. if "%~1"=="" (
  7.   rem If the .ansi file was not yet created, we will call :make_ansi to convert the .bmp content
  8.   if not exist "%filename%.ansi" call :make_ansi || (pause&goto :eof)
  9.   rem Update the size of the character cells which represent the pixels of the image
  10.   >nul reg add "HKCU\Console\%title:\=_%" /f /v "FaceName"   /t REG_SZ    /d "Terminal"
  11.   >nul reg add "HKCU\Console\%title:\=_%" /f /v "FontFamily" /t REG_DWORD /d 0x00000030
  12.   >nul reg add "HKCU\Console\%title:\=_%" /f /v "FontSize"   /t REG_DWORD /d 0x00030005
  13.   rem Restart the script to get the new settings applied
  14.   start "%title%" /max "%comspec%" /c "%~fs0" #
  15.   goto :eof
  16. ) else >nul reg delete "HKCU\Console\%title:\=_%" /f
  17. rem Print the image
  18. type "%filename%.ansi"
  19. pause
  20. goto :eof
  21. rem Subroutine to convert the pixel array of the bitmap file into a file containing "true color" ANSI escape sequences
  22. :make_ansi
  23. setlocal EnableDelayedExpansion
  24. set "outfile=!filename!.ansi"
  25. 2>nul del "!outfile!.raw.hex"
  26. rem Batch isn't able to work with the binary data of a BMP file. Thus, we use certutil to create a HEX dump.
  27. >nul certutil -encodehex "!filename!.bmp" "!outfile!.raw.hex" 4||(echo Unable to dump the bitmap&goto err)
  28. rem rn is CR + LF
  29. set "rn="&for /f "skip=1" %%i in ('echo(^|replace ? . /u /w') do if not defined rn (set rn=%%i^
  30. %= don't alter =%
  31. )
  32. rem Certutil wrote 16 space-separated byte values per line. This is inconvenient because we have to reassemble them into sequences of 2, 4, or 3 bytes later on.
  33. rem This will get easier if we write every value into a separate line first.
  34. >"!outfile!.separate.hex" (for /f "usebackq tokens=1-16" %%a in ("!outfile!.raw.hex") do echo %%a!rn!%%b!rn!%%c!rn!%%d!rn!%%e!rn!%%f!rn!%%g!rn!%%h!rn!%%i!rn!%%j!rn!%%k!rn!%%l!rn!%%m!rn!%%n!rn!%%o!rn!%%p)
  35. del "!outfile!.raw.hex"
  36. rem Control Sequence Introducer
  37. for /f %%e in ('echo prompt $E^|cmd') do set "csi=%%e["
  38. rem We use SET /P to read one byte value at once. Sequences that represent numeric values are in little endian byte order.
  39. rem For the variable naming refer to the structure documentations linked in the remarks.
  40. <"!outfile!.separate.hex" (
  41.   rem BITMAPFILEHEADER https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader
  42.   set /p "bfType_1="&set /p "bfType_2="
  43.   if "!bfType_1!!bfType_2!" neq "424d" (echo Wrong file type. Magic number must be 424d (ASCII "BM"^)&goto err)
  44.   set /p "b4="&set /p "b3="&set /p "b2="&set /p "b1="
  45.   set /a "bfSize=0x!b1!!b2!!b3!!b4!"
  46.   for %%i in ("!filename!.bmp") do if !bfSize! neq %%~zi (echo File size doesn't match (!bfSize! vs. %%~zi^)&goto err)
  47.   set /p "="&set /p "="&set /p "="&set /p "=" &rem bfReserved1 and bfReserved2 with two unused bytes each
  48.   set /p "b4="&set /p "b3="&set /p "b2="&set /p "b1="
  49.   set /a "bfOffBits=0x!b1!!b2!!b3!!b4!" &rem Offset in bytes between the beginning of the file and the pixel array
  50.   rem BITMAPINFOHEADER https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader
  51.   set /p "b4="&set /p "b3="&set /p "b2="&set /p "b1="
  52.   set /a "biSize=0x!b1!!b2!!b3!!b4!"
  53.   if !biSize! neq 40 (echo Wrong DIB header&goto err)
  54.   set /p "b4="&set /p "b3="&set /p "b2="&set /p "b1="
  55.   set /a "biWidth=0x!b1!!b2!!b3!!b4!" &rem Width of the bitmap in pixels
  56.   set /p "b4="&set /p "b3="&set /p "b2="&set /p "b1="
  57.   set /a "biHeight=0x!b1!!b2!!b3!!b4!" &rem Height of the bitmap in pixels
  58.   set /a "chk=((biWidth>>31)&1)+((biHeight>>31)&1)"
  59.   if !chk! neq 0 (echo Negative image size not supported&goto err)
  60.   set /p "b2="&set /p "b1="
  61.   set /a "biPlanes=0x!b1!!b2!"
  62.   if !biPlanes! neq 1 (echo Number of planes must be 1&goto err)
  63.   set /p "b2="&set /p "b1="
  64.   set /a "biBitCount=0x!b1!!b2!"
  65.   if !biBitCount! neq 24 (echo Only 24 bits color depth supported&goto err)
  66.   set /p "b4="&set /p "b3="&set /p "b2="&set /p "b1="
  67.   set /a "biCompression=0x!b1!!b2!!b3!!b4!"
  68.   if !biCompression! neq 0 (echo Only uncompressed bitmaps supported&goto err)
  69.   set /a "skip=bfOffBits-34" &rem We already read 34 bytes. Some further bytes are not of interest. We ignore them to get to the begin of the pixel array.
  70.   for /l %%i in (1 1 !skip!) do set /p "="
  71.   
  72.   set /a "pad=(biWidth*3)%%4" &rem The pixel rows might be padded because the number of bytes has to be a multiple of 4
  73.   if !pad! neq 0 set /a "pad=4-pad"
  74.   rem A pixel consists of 3 bytes which represent the color in BGR order.
  75.   rem The first 3 bytes belong to the lower left corner of the image. This means the order of the pixel array is bottom-up.
  76.   rem Since we need both the colors in RGB order and the upper left corner first, we have to reorder literally everything.
  77.   rem After these nested loops we got a file containing the "true color" ANSI sequences.
  78.   echo The BMP file will be converted for you. This may take a while ...
  79.   >"!outfile!" type nul
  80.   for /l %%Y in (1 1 !biHeight!) do (
  81.     >"!outfile!.~tmp" (
  82.       set "row="
  83.       for /l %%X in (1 1 !biWidth!) do (
  84.         set /p "b="&set /p "g="&set /p "r="
  85.         set /a "r=0x!r!,g=0x!g!,b=0x!b!"
  86.         set "row=!row!%csi%38;2;!r!;!g!;!b!m%csi%48;2;!r!;!g!;!b!m#"
  87.       )
  88.       echo !row!%csi%0m
  89.     )
  90.     for /l %%i in (1 1 !pad!) do set /p "="
  91.     >nul copy /b "!outfile!.~tmp" + "!outfile!"
  92.     >nul move /y "!outfile!.~tmp" "!outfile!"
  93.   )
  94. )
  95. 2>nul del "!outfile!.separate.hex"
  96. endlocal&exit /b 0
  97. :err
  98. 2>nul del "!outfile!.separate.hex"
  99. endlocal&exit /b 1
复制代码
谢谢。
作者: a20150604    时间: 2021-8-9 13:47

只有  WIN 10 支持 VT100 转义序列, 可以直接在任意位置显示任意色彩的字符,   Certutil  先把 BMP 文件转为字节编码, 再用 VT100 转义序列 显示出来(每个像素都是字符, 而不是实际的屏幕像素点)
作者: slimay    时间: 2021-8-9 14:04

  1. %ESC%[38;2;!r!;!g!;!b!mÛ%ESC%[0m"
复制代码
并不是真正意义上的显示图片. 而且他也用了第三方certutil
你要显示图片批处理第三方有一堆都能实现, 还能显示三维立体图片
作者: HOPE2021    时间: 2021-8-9 14:06

谢谢各位。^_^
作者: a20150604    时间: 2021-8-9 14:07

certutil 是微软系统自带的, 不算第三方, 第三方: 一般应指微软系统不自带, 也不是微软出品的程序
作者: slimay    时间: 2021-8-9 14:22

回复 5# a20150604
抱歉, 才查清你是neorobin, 你小号太多了




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2