python纯终端实现图片查看器(全彩)(windows)
很多人作为命令行爱好者,无法在终端内直接查看图片是无法忍受的,
那就写一个!
先直接上代码
import os
import sys
from PIL import Image
import numpy as np
import colorama
import msvcrt # Windows专用
# 初始化colorama
colorama.init()
# 更丰富的字符梯度,用于更好的放大效果
chars = [" ", "░", "▒", "▓", "█", "▀", "▄", "▌", "▐", "■", "◢", "◣", "◤", "◥", "◧", "◨", "◩", "◪", "◫"]
def clear_screen():
"""清屏"""
os.system('cls' if os.name == 'nt' else 'clear')
def image_to_ansiart(image_path, width=80, scale=1.0):
"""将图片转换为ANSI彩色字符画,支持平滑缩放"""
try:
img = Image.open(image_path)
except Exception as e:
return f"[无法加载图片: {str(e)}]"
# 应用缩放因子
width = int(width * scale)
aspect_ratio = img.height / img.width
height = int(width * aspect_ratio * 0.45) # 调整高宽比以获得更好显示效果
# 确保最小尺寸
width = max(10, width) # 最小宽度设为10
height = max(5, height) # 最小高度设为5
# 使用高质量缩放
img = img.resize((width, height), Image.Resampling.LANCZOS)
img = img.convert("RGB")
pixels = np.array(img)
ansi_lines = []
for row in pixels:
line = []
for pixel in row:
r, g, b = pixel
brightness = 0.299 * r + 0.587 * g + 0.114 * b
# 选择字符,使用更精细的亮度分级
char_idx = int(brightness / 255 * (len(chars) - 1))
char = chars[char_idx]
# 使用24位真彩色
line.append(f"\x1b[38;2;{r};{g};{b}m{char}")
ansi_lines.append("".join(line) + "\x1b[0m")
return "\n".join(ansi_lines)
def get_terminal_size():
"""获取终端大小"""
try:
from shutil import get_terminal_size as gts
return gts().columns, gts().lines
except:
return 80, 24 # 默认值
def get_image_list(start_image=None):
"""获取当前目录图片列表,并定位到指定图片"""
images = sorted([f for f in os.listdir()
if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'))])
if not images:
print("当前目录没有图片文件(支持.png/.jpg/.jpeg/.bmp/.gif/.webp)")
return None, -1
# 如果指定了初始图片,尝试定位
idx = 0
if start_image:
start_image = os.path.basename(start_image) # 只取文件名部分
try:
idx = images.index(start_image)
except ValueError:
# 如果文件不在当前目录,添加到列表并设为当前图片
if os.path.exists(start_image):
images.append(start_image)
images.sort()
idx = images.index(start_image)
else:
print(f"警告: 指定的图片文件 {start_image} 不存在")
return images, idx
def main():
# 处理命令行参数
start_image = sys.argv[1] if len(sys.argv) > 1 else None
# 获取图片列表和初始索引
images, idx = get_image_list(start_image)
if not images:
return
scale = 1.0
base_width = min(80, get_terminal_size()[0] - 10) # 根据终端宽度调整
while True:
clear_screen()
# 显示图片信息和控制说明
print(f"图片查看器: {images[idx]} ({idx+1}/{len(images)}) 缩放: {scale:.1f}x")
print("← →:切换图片 | + -:缩放(0.2x-5.0x) | Home/End:首图/末图 | Q:退出")
print("-" * min(80, get_terminal_size()[0]))
try:
# 显示图片
art = image_to_ansiart(images[idx], base_width, scale)
print(art)
except Exception as e:
print(f"渲染错误: {str(e)}")
# 获取按键
key = msvcrt.getch()
try:
key = key.decode('utf-8').lower()
except:
key = str(key)
# 处理按键
if key == 'q':
break
elif key == '+' and scale < 5.0:
scale = min(5.0, scale + 0.1) # 更精细的缩放控制
elif key == '-' and scale > 0.2:
scale = max(0.2, scale - 0.1)
elif key == '\x00' or key == '\xe0': # 功能键前缀
next_key = msvcrt.getch()
if next_key == b'M' or next_key == b'P': # 右箭头或下箭头
idx = (idx + 1) % len(images)
scale = 1.0
elif next_key == b'K' or next_key == b'H': # 左箭头或上箭头
idx = (idx - 1) % len(images)
scale = 1.0
elif next_key == b'G': # Home键
idx = 0
scale = 1.0
elif next_key == b'O': # End键
idx = len(images) - 1
scale = 1.0
elif key == '\r': # 回车键重置缩放
scale = 1.0
elif key == 'f': # 切换全屏/正常模式
base_width = get_terminal_size()[0] - 10 if base_width < 100 else 80
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass
except Exception as e:
print(f"程序出错: {str(e)}")
finally:
# 重置终端
print("\x1b[0m") # 重置所有属性
colorama.deinit()
运行:
python viewer.py myphoto.jpg
直接
python viewer.py
也可以
效果图:
-和+可以放大缩小
(提示:windows终端 ctrl + 放大字体,ctrl - 缩小字体,缩小字体效果更佳)