图片的每一个像素点都可以数值化,那么将构成图片的每一个像素点填充到excel的单元格中去,然后合理调整单元格长宽比便可以拼成一副画。反过来想,用一张单元格足够小的excel表格将图片蒙上一层,犹如用 一张网去切割这张图片,图片被切割成一小块一小块 ,如果网格足够细,每一小块里面的颜色几乎只有一种,这样就可以用一个三元组(RGB)来刻画 ,这样一张图片就可以由一个很大的矩阵来刻画 ,矩阵中的每一个元素都是一个 RGB三元组。不管从图片到excel还是从excel到图片,我们都可以构建一个一一映射关系,我们便可以依循这个理论在excel作画。
代码主要来自:程序员如何 10 分钟用 Python 画出蒙娜丽莎? - 知乎
直接运行会有报错,需要稍微修改:
- # 修正前
- column = col[0].column
- # 修正後
- column = col[0].column_letter
worksheet.column_dimensions[_w].width = 8
- MAX_WIDTH = 400
- MAX_HEIGHT = 400
修改后代码如下:
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- #@Time : 2023/09/10
- #@Author: Hehuyi_In
- #@File : picture_to_excel.py
-
- from PIL import Image
- import openpyxl
- from openpyxl.styles import fills
- import os
-
- MAX_WIDTH = 400
- MAX_HEIGHT = 400
-
- # excel的单元格默认是长方形,修改为正方形才不会使图片变形
- # 调整excel每个单元格大小,避免图片过大,excel无法打开
- # 过小电子画会过于模糊,太大excel可能无法打开
- def resize(img):
- w, h = img.size
- if w > MAX_WIDTH:
- h = MAX_WIDTH / w * h
- w = MAX_WIDTH
-
- if h > MAX_HEIGHT:
- w = MAX_HEIGHT / h * w
- h = MAX_HEIGHT
- return img.resize((int(w), int(h)), Image.ANTIALIAS)
-
- # 整型转16进制
- # getpixel()获取的颜色值是rgb十进制的,但fills.PatternFill 里的fgColor`参数接收到的颜色值是十六进制的值,因此需要转换
- def int_to_16(num):
- num1 = hex(num).replace('0x', '')
- # 位数只有一位时在前面补零
- num2 = num1 if len(num1) > 1 else '0' + num1
- return num2
-
- # 绘图函数
- def draw_jpg(img_path):
- # 打开图片
- img_pic = resize(Image.open(img_path))
- img_name = os.path.basename(img_path)
-
- # 输出的excel名,若已存在则删除
- out_file = img_name.split('.')[0] + '.xlsx'
- if os.path.exists(out_file):
- os.remove(out_file)
-
- # 新建一个excel文件
- workbook = openpyxl.Workbook()
- # 激活一个工作表(sheet)
- worksheet = workbook.active
-
- width, height = img_pic.size
-
- # 循环处理图片中的每个像素
- for w in range(1, width + 1):
- for h in range(1, height + 1):
- # getpixel函数用于获取像素色彩值,入参为像素坐标
- if img_pic.mode == 'RGB':
- r, g, b = img_pic.getpixel((w - 1, h - 1))
- elif img_pic.mode == 'RGBA':
- r, g, b, a = img_pic.getpixel((w - 1, h - 1))
-
- # 将rgb值转换为16进制
- hex_rgb = int_to_16(r) + int_to_16(g) + int_to_16(b)
-
- # 定位每个单元格
- cell = worksheet.cell(column=w, row=h)
-
- # 第一行
- if h == 1:
- _w = cell.column_letter
- _h = cell.col_idx
- # 调整列宽
- worksheet.column_dimensions[_w].width = 8
- # 调整行高
- worksheet.row_dimensions[h].height = 45
- # 填充颜色,fill_type是填充类型,fgColor是填充的颜色
- cell.fill = fills.PatternFill(fill_type="solid", fgColor=hex_rgb)
-
- print('saving...')
- workbook.save(out_file)
- print('success!')
-
-
- if __name__ == '__main__':
- draw_jpg('lyx.jpg')
效果图,以我这个头像为例(excel画出来的图太大了,这里截了一部分)

这要是手工画一张不得画几个月...但通过程序可以直接秒出,牛哇~
参考
https://zhuanlan.zhihu.com/p/95720761
https://blog.51cto.com/u_15255081/6164226
https://blog.csdn.net/weixin_43790276/article/details/108478270
https://qiita.com/gorimacho/items/63707223e692f7401988