写数学公式,功能最强大的当然是LaTex了。不过,强大不代表易用,驾驭LaTex绝不是一件容易的事儿。这也不难理解:毕竟数学公式不是孤立存在的,必然要作为文档、网页或者程序输出的元素,如何无缝地让LaTex关联到文档、网页或程序,的确是个棘手的难题。

既然直接使用LaTex有难度,那就退而求其次:借助于工具将数学公式转为图片,然后就可以方便地应用到文档、网页或者程序中了。这样的工具,除了在线式的,基本上都是重量级的,安装和使用极不方便。我曾经花了11个C币从CSDN买过一个数学公式转图片的工具,下载之后发现,竟然只是封装了一个http请求,图片仍然是在线生成的!一气之下,自己写了个离线的,只是功能比较简单,不能方便地设置输出图像的大小和颜色。

最近工作中又用到了LaTex,几经尝试,终于在matplotlib源码中发现了一个处理LaTex数学公式的好东西。稍加改造,增加了字体、字号、颜色和分辨率的设置,最终完美解决了LaTex数学公式转图片的问题。

1. 核心代码

先从最简单的开始吧。matplotlib有个mathtext子模块,提供了math_to_image函数可以直接将LaTex数学公式生成图片。下面的代码,仅仅两行,就将质能方程转成了图片。请注意,LaTex数学公式一定要包含在两个$符号之间。

>>> from matplotlib import mathtext
>>> mathtext.math_to_image(r'$E=mc^2$', r'd:\demo_1.png')

生成的图片宽度55个像素,高度15个像素,分辨率为100dpi。这么迷你,看上去可怜巴巴的。


虽然指定了png格式,也确实存在透明通道,其背景却是不透明的。除了png格式外,math_to_image函数还支持eps, pdf, pgf, png, ps, raw, rgba, svg, svgz等格式,但不支持jpg格式。

2. 设置字体、字号、分辨率

要设置字体字号,就得先导入matplotlib的font_manager字体管理模块。该模块的FontProperties类可以实例化一个字体对象传给math_to_image函数,用来设置family(字体)、size(字号)和weight(笔画轻重)等。

math_to_image函数的dpi参数用于设置分辨率(每英寸像素数)。如果应用于网页的话,建议分辨率设置为72dpi就可以了,如果用于印刷,请将dip设置为300。

>>> import matplotlib.font_manager as mfm
>>> prop = mfm.FontProperties(family='sans-serif', size=64, weight='normal')
>>> mathtext.math_to_image(r'$E=mc^2$', r'd:\demo_2.png', prop=prop, dpi=72)

输出结果如下。这次生成的图片终于不那么可怜了,宽度250个像素,高度59个像素。

如果不知道有哪些字体可用怎么办?不要担心,下面这一行代码就可以列出当前系统中全部的可用字体。在我的电脑上运行之后,找到了几百种可用的字体(重名的字体表示该字体有多个字体文件)。

>>> [item.name for item in mfm.fontManager.ttflist]

3. 设置颜色

要想对图片文件做颜色处理,最好的方式是先将math_to_image的输出暂存到类文件对象中,借助于PIL和NumPy完成颜色设置后,再保存为文件。为此,要先导入io模块、pillow模块和numpy模块。

在开始写代码前,先约定使用浮点型的三元组表示颜色,比如,(0.17, 0.63, 0.17)表示亮度稍暗的绿色。如果喜欢使用其他方式表示颜色,请自行转换。下面的例子换了一个复杂的数学公式(虚构的,并无实际意义)来演示如何设置颜色。

>>> from io import BytesIO
>>> from PIL import Image
>>> import numpy as np
>>> text = r'$s(t) = \mathcal{A}\mathrm{sin}(2 \omega \sum_{i=0}^\infty t_i)$'
>>> color = (0.17, 0.63, 0.17) # 要使用的颜色
>>> bfo = BytesIO() # 创建二进制的类文件对象
>>> prop = mfm.FontProperties(family='Palatino Linotype', size=256, weight='normal')
>>> mathtext.math_to_image(text, bfo, prop=prop, dpi=72)
209.0
>>> im = Image.open(bfo) # 打开二进制的类文件对象,返回一个PIL图像对象
>>> r, g, b, a = im.split() # 分离出RGBA四个通道
>>> r, g, b = 255-np.array(r), 255-np.array(g), 255-np.array(b) # RGB通道反白
>>> a = r/3 + g/3 + b/3 # 生成新的alpha通道
>>> r, g, b = r*color[0], g*color[1], b*color[2] # RGB通道设置为目标颜色
>>> im = np.dstack((r,g,b,a)).astype(np.uint8) # RGBA四个通道合并为三维的numpy数组
>>> im = Image.fromarray(im) # numpy数组转PIL图像对象
>>> im.save(r'd:\demo_3.png') # PIL图像对象保存为文件

来看看最终的输出结果是什么样的呢?最终生成了2451x653的一张大图,公式内容、字体、字号、颜色等,正如期望的那样。大功告成!

4. 封装成函数

为了方便使用,将上面的代码封装成一个函数,完整代码如下。

# -*- coding: utf-8 -*-import os
from io import BytesIO
from PIL import Image
import numpy as np
import matplotlib.font_manager as mfm
from matplotlib import mathtextdef latex2img(text, size=32, color=(0.1,0.1,0.1), out=None, **kwds):"""LaTex数学公式转图片text        - 文本字符串,其中数学公式须包含在两个$符号之间size        - 字号,整型,默认32color       - 颜色,浮点型三元组,值域范围[0,1],默认深黑色out         - 文件名,仅支持后缀名为.png的文件名。若维None,则返回PIL图像对象kwds        - 关键字参数dpi         - 输出分辨率(每英寸像素数),默认72family      - 系统支持的字体,None表示当前默认的字体weight      - 笔画轻重,可选项包括:normal(默认)、light和bold"""assert out is None or os.path.splitext(out)[1].lower() == '.png', '仅支持后缀名为.png的文件名'for key in kwds:if key not in ['dpi', 'family', 'weight']:raise KeyError('不支持的关键字参数:%s'%key)dpi = kwds.get('dpi', 72)family = kwds.get('family', None)weight = kwds.get('weight', 'normal')bfo = BytesIO() # 创建二进制的类文件对象prop = mfm.FontProperties(family=family, size=size, weight=weight)mathtext.math_to_image(text, bfo, prop=prop, dpi=dpi)im = Image.open(bfo)r, g, b, a = im.split()r, g, b = 255-np.array(r), 255-np.array(g), 255-np.array(b)a = r/3 + g/3 + b/3r, g, b = r*color[0], g*color[1], b*color[2]im = np.dstack((r,g,b,a)).astype(np.uint8)im = Image.fromarray(im)if out is None:return imelse:im.save(out)print('生成的图片已保存为%s'%out)if __name__  == '__main__':text = r'$\sum_{i=0}^\infty x_i$'latex2img(text, size=48, color=(0.1,0.8,0.8), out=r'd:\demo.png')text = r'$\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}$'im = latex2img(text, size=48, color=(0.9,0.1,0.1))im.show()

最完美的数学公式转图片:纯Python实现,可设置字体、字号、颜色和分辨率相关推荐

  1. QT打印窗口、退出、设置字体及颜色、设置时间、控件实现系统函数、添加资源文件(菜单图片)、工具栏添加图片

    打印窗口 #include <QPrintDialog> 退出 QObject::connect(ui->exitAction, SIGNAL(triggerd()), this, ...

  2. python修改ppt的字体和颜色_使用python-pptx包批量修改ppt格式的实现

    最近实习需要对若干ppt进行格式上的调整,主要就是将标题的位置.对齐方式.字体等统一,人工修改又麻烦又容易错. 因此结合网上的pptx包资料,使用python脚本完成处理. 主要的坑点在于,shape ...

  3. python修改ppt的字体和颜色_python pptx教程:python 怎么设置ppt图表区的颜色以及给图表区加上边框...

    python 中 pptx 库 可以画组合图么? 我知道PPT可以组合画出,但是Python就不知道啦. python 怎么设置ppt图表区的颜色以及给图表区加上边框 Python Code:from ...

  4. Python+tkinter+Treeview模拟表格并设置字体和颜色

    清华大学出版社-第10届高等学校计算机程序设计课程论坛 中国大学MOOC"Python程序设计基础"免费学习地址 2020年秋季学期Python教材推荐与选用参考 推荐图书: &l ...

  5. python write函数输出字体有颜色_跪求response.write输出字体颜色解决方法

    测试结果 测试结果 您的答案: on error resume next dim strsqa,ra strsqa="select * from topic2" set ra=db ...

  6. python matplotlib searbon 设置画版颜色 热力图固定颜色等级 固定比例尺寸大小

    参数vmax.vmin cmap 设置颜色等级,参考:https://blog.csdn.net/pary__for/article/details/104971632 sns.heatmap(glo ...

  7. Python print函数设置字体效果和背景色

    实现过程: 终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关. 转义序列是以ESC开头,即用\033来完成(ESC的ASCII码用十进制表示是27,用八进制表示就是033 ...

  8. python读excel字体颜色_python操作excel之设置字体颜色及格式

    原博文 2020-06-03 13:46 − xlwings如何设置字体.颜色等属性 # coding: utf-8 import xlwings as xw app=xw.App(visible=F ...

  9. java页面字体设置颜色_java 设置字体颜色字体 窗体设置图片背景

    packageqq;importjavax.swing.*;importjava.awt.*;importjava.awt.event.WindowEvent;publicclassQ1{JWindo ...

最新文章

  1. 2019.7.9 校内测试题 史密斯数
  2. 关于git经常忘记的:远程仓库关联。
  3. 渗透学习笔记--基础篇--sql注入(数字型)
  4. 元胞自动机交通流模型c++_MATLAB——含出入匝道的交织区快速路元胞自动机模型...
  5. 要读顶级会议上的论文
  6. 电脑硬盘数据不小心格式化后,恢复数据的方法介绍
  7. U8普及版在win7系统中,UFO报表一点打印或预览就报错
  8. 连接共享打印机时,弹出无法安装打印机,打印处理器不存在!!
  9. selenium模拟刷百度流量源码
  10. 简一论币:8.14 BTC回撤介入多单谨防延续回撤,11600短多尝试
  11. 并发请求:统计数据收集模式
  12. Python二进制数据处理
  13. 增加 swap 空间
  14. 从人工客服到人机协同,容联云用AI重塑联络中心
  15. 腾讯、阿里开始正面交锋新零售,双寡头就代表未来吗?
  16. NVIDIA编码器和解码器
  17. 用OpenCv中Mat进行水平投影与垂直投影并实现字符切分
  18. 数控机床联网知识普及
  19. vue 项目启动失败 ‘webpack-dev-server‘ 不是内部或外部命令,也不是可运行的程序
  20. php用户注册自动生成邀请码,PHP如何实现根据用户id生成一个唯一邀请码

热门文章

  1. 【vue-treeselect】数据量大的时候懒加载并且可以搜索,树懒加载+搜索
  2. 读书笔记:《浮生六记》
  3. 基于 Golang 构建高可扩展的云原生 PaaS(附 PPT 下载)
  4. 广发基金2011年投资策略交流会[转]
  5. 从敏捷团队看CoP实践社团七要素
  6. 《未来呼啸而来》概览
  7. jq添加数组_jquery中push()的用法(数组添加元素)
  8. 漫画 | 啊哈,给我一碗孟婆汤
  9. Java Swing音乐播放器
  10. 女孩子也可以入手的小米MIX FOLD,有什么不一样?