フォントやコードを拝借して。
成果物
情報源
圧倒的感謝っ!
概要
ttf
ファイルを入手するttf
ファイルからPNG画像ファイルを出力する
2の画像ファイルがビットマップフォントである。
手順
1. ttf
ファイルを入手する
フォントめっちゃカッコイイ! 感謝メッセージ送りたいが、Twitterアカウント作れない……。と思ったらマシュマロとかいうサービスで匿名メッセ送れた! こんなのあるのか。参考記事にも感謝メッセしたいのだが、マシュマロってない。
wget http://www17.plala.or.jp/xxxxxxx/00ff/x12y16pxLineLinker.ttf wget http://www17.plala.or.jp/xxxxxxx/00ff/x16y32pxGridGazer.ttf wget http://www17.plala.or.jp/xxxxxxx/00ff/x12y20pxScanLine.ttf wget http://www17.plala.or.jp/xxxxxxx/00ff/x14y20pxScoreDozer.ttf wget http://www17.plala.or.jp/xxxxxxx/00ff/x14y24pxHeadUpDaisy.ttf wget http://www17.plala.or.jp/xxxxxxx/00ff/x8y12pxTheStrongGamer.ttf
2. ttf
ファイルからPNG画像ファイルを出力する
2-1. 環境構築
上記にあるとおり、pillow
とnumpy
が必要。こいつでttfからPNGに変換する。
$ pyenv global system $ python3 -V Python 3.7.3 $ pip3 install pillow Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple Requirement already satisfied: pillow in /usr/lib/python3/dist-packages (5.4.1) $ pip3 install numpy Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple Requirement already satisfied: numpy in /usr/lib/python3/dist-packages (1.16.2)
git clone https://github.com/kitao/pyxel.git cd pyxel make -C pyxel/core clean all sudo pip3 install .
Python 3.8.2 だと Pillow がインストールできなかった……。エラーログ。
$ pyenv global 3.8.2 $ python -V Python 3.8.2 $ pip install Pillow Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple Collecting Pillow Using cached Pillow-7.0.0.tar.gz (38.2 MB) Installing collected packages: Pillow Running setup.py install for Pillow ... error ERROR: Command errored out with exit status 1: command: /home/pi/.pyenv/versions/3.8.2/bin/python3.8 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-dbfv3n9v/Pillow/setup.py'"'"'; __file__='"'"'/tmp/pip-install-dbfv3n9v/Pillow/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-3ukhynwd/install-record.txt --single-version-externally-managed --compile --install-headers /home/pi/.pyenv/versions/3.8.2/include/python3.8/Pillow cwd: /tmp/pip-install-dbfv3n9v/Pillow/ Complete output (174 lines): running install running build running build_py creating build creating build/lib.linux-armv7l-3.8 creating build/lib.linux-armv7l-3.8/PIL copying src/PIL/FtexImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PpmImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageFont.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/JpegImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PsdImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/SgiImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/XVThumbImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/__main__.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/Image.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/_binary.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PyAccess.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageSequence.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/DdsImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/XpmImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/McIdasImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/IcnsImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageTransform.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/BmpImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImagePalette.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/IptcImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/TiffImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/GdImageFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/_util.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/CurImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/TiffTags.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/FliImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/WebPImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageGrab.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/WmfImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageEnhance.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageShow.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PdfImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageOps.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/GbrImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageTk.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/BlpImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PcfFontFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/WalImageFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/Jpeg2KImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageMorph.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/TgaImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/EpsImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/_tkinter_finder.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/IcoImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageWin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/GimpGradientFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageDraw.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/features.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/Hdf5StubImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/JpegPresets.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/__init__.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/DcxImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImagePath.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageDraw2.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageFilter.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PcdImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PSDraw.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/BufrStubImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageChops.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/FpxImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageCms.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ExifTags.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PdfParser.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/FontFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PaletteFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageMath.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageQt.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PalmImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/GifImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImtImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/_version.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/MicImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/MspImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ContainerIO.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageColor.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/GimpPaletteFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PixarImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageStat.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/GribStubImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/BdfFontFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/MpegImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/FitsStubImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/TarIO.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/SpiderImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageFile.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/SunImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PcxImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/XbmImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/PngImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/ImageMode.py -> build/lib.linux-armv7l-3.8/PIL copying src/PIL/MpoImagePlugin.py -> build/lib.linux-armv7l-3.8/PIL running egg_info writing src/Pillow.egg-info/PKG-INFO writing dependency_links to src/Pillow.egg-info/dependency_links.txt writing top-level names to src/Pillow.egg-info/top_level.txt reading manifest file 'src/Pillow.egg-info/SOURCES.txt' reading manifest template 'MANIFEST.in' warning: no files found matching '*.c' warning: no files found matching '*.h' warning: no files found matching '*.sh' warning: no previously-included files found matching '.appveyor.yml' warning: no previously-included files found matching '.coveragerc' warning: no previously-included files found matching '.codecov.yml' warning: no previously-included files found matching '.editorconfig' warning: no previously-included files found matching '.readthedocs.yml' warning: no previously-included files found matching 'azure-pipelines.yml' warning: no previously-included files matching '.git*' found anywhere in distribution warning: no previously-included files matching '*.pyc' found anywhere in distribution warning: no previously-included files matching '*.so' found anywhere in distribution no previously-included directories found matching '.azure-pipelines' no previously-included directories found matching '.travis' writing manifest file 'src/Pillow.egg-info/SOURCES.txt' running build_ext The headers or library files could not be found for jpeg, a required dependency when compiling Pillow from source. Please see the install instructions at: https://pillow.readthedocs.io/en/latest/installation.html Traceback (most recent call last): File "/tmp/pip-install-dbfv3n9v/Pillow/setup.py", line 852, in <module> setup( File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/site-packages/setuptools/__init__.py", line 145, in setup return distutils.core.setup(**attrs) File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/core.py", line 148, in setup dist.run_commands() File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/dist.py", line 966, in run_commands self.run_command(cmd) File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/dist.py", line 985, in run_command cmd_obj.run() File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/site-packages/setuptools/command/install.py", line 61, in run return orig.install.run(self) File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/command/install.py", line 545, in run self.run_command('build') File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/cmd.py", line 313, in run_command self.distribution.run_command(command) File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/dist.py", line 985, in run_command cmd_obj.run() File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/command/build.py", line 135, in run self.run_command(cmd_name) File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/cmd.py", line 313, in run_command self.distribution.run_command(command) File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/dist.py", line 985, in run_command cmd_obj.run() File "/home/pi/.pyenv/versions/3.8.2/lib/python3.8/distutils/command/build_ext.py", line 340, in run self.build_extensions() File "/tmp/pip-install-dbfv3n9v/Pillow/setup.py", line 687, in build_extensions raise RequiredDependencyException(f) __main__.RequiredDependencyException: jpeg During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<string>", line 1, in <module> File "/tmp/pip-install-dbfv3n9v/Pillow/setup.py", line 907, in <module> raise RequiredDependencyException(msg) __main__.RequiredDependencyException: The headers or library files could not be found for jpeg, a required dependency when compiling Pillow from source. Please see the install instructions at: https://pillow.readthedocs.io/en/latest/installation.html ---------------------------------------- ERROR: Command errored out with exit status 1: /home/pi/.pyenv/versions/3.8.2/bin/python3.8 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-dbfv3n9v/Pillow/setup.py'"'"'; __file__='"'"'/tmp/pip-install-dbfv3n9v/Pillow/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /tmp/pip-record-3ukhynwd/install-record.txt --single-version-externally-managed --compile --install-headers /home/pi/.pyenv/versions/3.8.2/include/python3.8/Pillow Check the logs for full command output.
2-2. コード作成
こちらのを少し手直しして動くようにした。
example.py
#!/usr/bin/env python3 # coding: utf8 from PIL import Image, ImageFont, ImageDraw import pyxel import string class Font: def __init__(self, file, size, alphabet): import numpy as np self.file = file self.size = size self.alphabet = alphabet px_w, px_h = size # pt_w, pt_h = (int(n * 0.75) for n in meta['size']) # 96 dpi ## load custom font font = ImageFont.truetype(file, size=px_h) # it must be pt_h, but px_h brings better result img = Image.new('1', size=(256, 256)) draw = ImageDraw.Draw(img) coords = {} x, y = 0, 0 for c in alphabet: if x + px_w > 256: x = 0 y += px_h draw.text((x, y), c, font=font, fill=1) coords[c] = (x, y) x += px_w self.coords = coords self.img = img self.data = np.array(img.getdata()).reshape(256, 256) def draw_font(img, font, col=7): img_bank = pyxel.image(img) for y in range(256): for x in range(256): img_bank.set(x, y, col if font.data[y][x] else 0) def text(font, x, y, s): w, h = font.size left = x for ch in s: if ch == '\n': x = left y += h continue if ch == ' ': x += w continue if ch in font.coords.keys(): u, v = font.coords[ch] pyxel.blt(x, y, 0, u, v, w, h, 0) # for y_ in range(h): # for x_ in range(w): # if font.data[v+y_, u+x_]: # pyxel.pix(x+x_, y+y_, col) x += w def update(): pass def draw(): pyxel.cls(0) text(font, 0, 0, """ The Zen of Python, by Tim Peters Beautiful is better than ugly. みにくいよりうつくしいほうがいい。 Explicit is better than implicit. あんじするよりめいじするほうがいい。 Simple is better than complex. ふくざつであるよりはへいいであるほうがいい。 Complex is better than complicated. それでも、こみいっているよりはふくざつであるほうがまし。 Flat is better than nested. ネストはあさいほうがいい。 Sparse is better than dense. みっしゅうしているよりはすきまがあるほうがいい。 Readability counts. よみやすいことはぜんである。 Special cases aren't special enough to break the rules. とくしゅであることはルールをやぶるりゆうにならない。 Although practicality beats purity. しかし、じつようせいをもとめるとじゅんすいさがうしなわれることが ある。""".strip()) pyxel.init(255, 255, caption="よくある手法で外部フォント") fontfile = 'x8y12pxTheStrongGamer.ttf' letter_size = (8, 12) ascii_chars = string.punctuation + string.digits + string.ascii_letters ひらがな = "".join(chr(c) for c in range(ord('ぁ'), ord('ゔ')+1))+"ー" カタカナ = "".join(chr(c) for c in range(ord('ァ'), ord('ヶ')+1))+"ー" # 半角カタカナ = "".join(chr(c) for c in range(ord('ァ')-6, ord('゙')+2)) alphabet = ascii_chars + ひらがな + カタカナ + "、。「」" font = Font(fontfile, letter_size, alphabet) draw_font(0, font) font.img.save('x8y12pxTheStrongGamer.png') pyxel.run(update, draw)
上記のうち、以下のコードでビットマップフォント画像ファイルを出力する。
font.img.save('x8y12pxTheStrongGamer.png')
2-3. 実行
python3 example.py
x8y12pxTheStrongGamer.png
ファイルが出力された- 画面は以下のようになった
素敵すぎる! レトロ感パない!
課題
漢字が使えない
同じ手法を使えば漢字もできる。だが、pyxelの仕様に収まらない。漢字は6355
字ある。pyxelの.pyxresは256*256ピクセルを3枚しか持てないため2016
文字までしか収まらない。
- 漢字: 6355字
- JIS第1水準漢字 : 2965字
- JIS第2水準漢字 : 3390字
画像1枚あたり672
文字入る。今回の文字サイズは幅8
, 高さ12
ピクセル。これは256
*256
ピクセルの画像に何文字入るか算出すると以下。
256/8 = 32 256/12 = 21.333 32 * 21 = 672
pyxelにおいて1ゲームあたり最大2016
文字のビットマップフォントが使える。
672 * 3 = 2016
JIS第1水準漢字すら満たせずに上限。
そもそも、メモリの無駄遣いに思える。もうttfで描画できるシステム使いたいレベル。
文言を厳選せねばならない
平仮名と片仮名だけだとポケモンみたいに「分かち書き」っぽく書かねば読みづらいのでは?
かがくの ちからって すげー !
レトロだわ。読みづらいけど、それゆえに言葉を厳選することになるからクオリティの高いものになる傾向がある。だからレトロゲーは強い。逆にいえば、レトロゲーの作者には崇高なセンスが求められる。
使いやすくしたい。
今のコードはフォントファイルがないとpyxel
に読み込めない。PNG画像だけでも読み込めるようにしたい。
所感
これで平仮名と片仮名だけだが日本語が使えるようになった!
あとはコードを使いやすくしたい。次回、やってみる。
前回まで
- ラズパイ4Bにpyenvをインストールする(python 3.8.2)
- pyxelをインストールする(pyenv python3.8.2)
- pyxeleditorにおけるImageエディタの使い方
- pyxeleditorにおけるTileMapエディタの使い方
- pyxeleditorにおけるSoundエディタの使い方
- pyxeleditorにおけるMusicエディタの使い方
- pyxelのリソースにおける概念・制限まとめ
- pyxeleditorにおけるpyxresファイル形式まとめ
- pyxelのAPI調査
- pyxelで最小コード 窓を出す
- Pyxelで窓の境界線を消す
- 携帯ゲーム機の解像度
- pyxelで矩形を描画する
- pyxelで荒ぶる矩形
- pyxelでキーに応じて動く矩形
- pyxelで画像を描画する
- pyxelで画像をアニメーションする(スプライト。パラパラ漫画)
- pyxelで左右反転した画像を使ってアニメーションする
- pyxelでテキストを表示する
対象環境
- Raspbierry pi 4 Model B
- Raspbian buster 10.0 2019-09-26 ※
- bash 5.0.3(1)-release
- pyxel 1.3.1
$ uname -a Linux raspberrypi 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux