使用Python生成Excel格式的图片

以前曾看到过 一篇报道,说有个日本人利用Excel做画。他把每一个单元格填充上颜色,缩小显示比例,就展示出一幅画。记者采访他,他说由于买不起正版的Photoshop,才委曲求全用Excel将就。

当时看着几百乘几百的单元格里,填满眼花缭乱的的颜色,心想这得花多大的精力啊?

后来想一想,要是用编程来实现,普通人几分钟以内也能够完成几幅,甚至能够达到照片级,呵呵~

先看个效果图,Excel格式的图片,够Geek吧。 python


用Python来实现,是很简单的,个人平台是:
Python 2.7.5;
PIL 1.1.7;
XlsxWriter 0.3.5;

须要说明的是,之因此选择XlsxWriter,而不是经常使用的xlwt,是由于前者能够操做Excel2007版本的xlsx文件。它拥有更多的行和列。

主要思路,就是使用PIL打开图片文件,读出每一个像素点的RGB值,再填充Excel文件。

须要注意的是,Excel2007对于单元格样式的种类也是有要求的,貌似最多65536种。所以有可能须要对颜色进行圆整。我也曾想使用PIL预先将图片的颜色转为65536色(16 bit),可是貌似PIL对65536色不太支持,因此只能出此下策。 编程

# coding: utf-8

from PIL import Image
from xlsxwriter.workbook import Workbook

class ExcelPicture(object):
    FORMAT_CONSTRAINT = 65536
    
    def __init__(self, pic_file, ratio = 1.0):
        self.__pic_file = pic_file
        
        self.__ratio = ratio
        self.__zoomed_out = False
        
        self.__formats = dict()
        
        
    # 缩小图片    
    def zoom_out(self, _img):
        _size = _img.size
        _img.thumbnail((int(_img.size[0] * self.__ratio), int(_img.size[1] * self.__ratio)))
        
        self.__zoomed_out = True
        
        
    # 对颜色进行圆整    
    def round_rgb(self, rgb, model):
        return tuple([int(round(x / model) * model) for x in rgb])
    
    
    # 查找颜色样式,去重    
    def get_format(self, color):
        _format = self.__formats.get(color, None)
        
        if _format is None:
            _format = self.__wb.add_format({'bg_color': color})
            self.__formats[color] = _format
            
        return _format
    
    
    # 操做流程
    def process(self, output_file = '_pic.xlsx', color_rounding = False, color_rounding_model = 5.0):
        # 建立xlsx文件,并调整行列属性
        self.__wb = Workbook(output_file)
        self.__sht = self.__wb.add_worksheet()
        self.__sht.set_default_row(height = 9)
        self.__sht.set_column(0, 5000, width = 1)
        
        # 打开须要进行转换的图片
        _img = Image.open(self.__pic_file)
        print 'Picture filename:', self.__pic_file
        
        # 判断是否须要缩小图片尺寸
        if self.__ratio < 1: self.zoom_out(_img)
        
        # 遍历每个像素点,并填充对应的颜色到对应的Excel单元格
        _size = _img.size
        print 'Picture size:', _size
        for (x, y) in [(x, y) for x in xrange(_size[0]) for y in xrange(_size[1])]:
            _clr = _img.getpixel((x, y))
            
            # 若是颜色种类过多,则须要将颜色圆整到近似的颜色上,以减小颜色种类
            if color_rounding: _clr = self.round_rgb(_clr, color_rounding_model)
            
            _color = '#%02X%02X%02X' % _clr
            self.__sht.write(y, x, '', self.get_format(_color))
        
        self.__wb.close()
        
        # 检查颜色样式种类是否超出限制,Excel2007对样式数量有最大限制
        format_size = len(self.__formats.keys())
        if format_size >= ExcelPicture.FORMAT_CONSTRAINT:
            print 'Failed! Color size overflow: %s.' % format_size
        else:
            print 'Success!'
            print 'Color: %s' % format_size
            print 'Color_rounding:', color_rounding
            if color_rounding: print 'Color_rounding_model:', color_rounding_model
        
        
if __name__ == '__main__':
    r = ExcelPicture('cw.jpg', ratio = 0.5)
    r.process('cw.xlsx', color_rounding = True, color_rounding_model = 5.0)
相关文章
相关标签/搜索