当前位置: 首页 > article >正文

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 - 缩小字体,缩小字体效果更佳)

 


http://www.kler.cn/a/614881.html

相关文章:

  • 数据化管理(一)---什么是数据化管理
  • 【Linux】常见信号 + 进程和作业
  • 【弹性计算】异构计算云服务和 AI 加速器(五):EAIS AI 加速器
  • Apache Iceberg 解析,一文了解Iceberg定义、应用及未来发展
  • 【SDMs分析1】基于ENMTools R包的生态位分化分析和图像绘制(identity.test())
  • 全局思维与系统思考
  • Vue学习笔记集--computed
  • Jenkins插件安装失败如何解决
  • Spring Cloud Consul使用指南
  • 【现代深度学习技术】现代卷积神经网络04:含并行连接的网络(GoogLeNet)
  • 指针和引用
  • 通过一个led点灯的demo来熟悉openharmony驱动编写的过程(附带hdf详细调用过程)
  • 聚合根的特性
  • JavaScript基础-navigator 对象
  • Docker 的实质作用是什么
  • 蓝桥杯省模拟赛 质因数之和
  • 视频AI赋能水利行业生态治理,水电站大坝漂浮物实时监测与智能预警方案
  • 【C++标准IO库】文件的输入输出
  • 机器视觉基础—高斯滤波
  • Pod 网络与 CNI 的作用