読者です 読者をやめる 読者になる 読者になる

daiizの自由帳

フレンチフライ トリュフ塩仕立て

技術ネタに絞り込む
スポンサーリンク

NaN

雑談

NaNって何か面白い字面してると思う

NaN: Not a Number
(非数)NaN - Wikipedia

NaN: Not a Nan
(非ナン; カレー屋でナンを頼んだのにライスが渡されたときに返す)ナン - Wikipedia

NaN: ナン

NaN: Not a Nandemonai
(何でもなくない; 「どうしたの?」と聞いて「何でもない」と返答されたときに,「何でもないでは済まされない」という意を込めて返す)

NaN: Not a Neko
(猫でない; NyaNの場合は子猫でない)

【SVG ScreenShot】スクリーンショット画像ファイルをURLとして使えるようになりました

作品 tech

SVGスクリーンショットに新機能を追加しました.変なタイトルですが最強な機能です. SVGスクリーンショットウェブアプリの,スクリーンショットコンテンツをプレビューする画面で利用できます.画面左下に「PNG画像をダウンロードする」ボタンを用意しましたのでこちらからご利用ください.

何ができるのか

スクリーンショットコンテンツをPNG画像としてダウンロードできます.ダウンロードされたファイルはただの画像ファイルですのでPCでもスマホであっても,普通の画像プレビューアプリで開くことができます.これまではSVGファイルをダウンロードしていたため,一般の画像ビューワでお手軽綺麗には閲覧できませんでした.

何が凄いのか

これだと,ただのPNG形式のスクリーンショット画像ですが,ここから簡単にSVG形式のスクリーンショットをプレビューできます. 実はダウンロードされた画像ファイルのファイル名には,SVGスクリーンショットのウェブアプリでコンテンツを特定するidが含まれています.つまりこの画像ファイルをウェブアプリの画面にドロップするだけで,コンテンツのプレビューページが開きます.このプレビューページでは,従来通りのSVGコンテンツが表示されますので,スクリーンショットに埋め込まれたリンクをクリックできますし,撮影したページに移動することもできます.

この機能を使えば「 https://svgscreenshot.appspot.com/c/5743114304094208」というURLを共有する代わりに,人気記事-5743114304094208.pngと名付けた画像を共有してもOK! ということです.もちろんコンテンツの公開範囲設定も可能です.

さらに

この仕組みの特長は,画像に付けられたファイル名(に含まれたid)を保持できてさえいれば,スクリーンショットコンテンツのURLをいつでも生成できるということです*1.これを利用して,Google DriveGoogle Photos との連携を実現しました.予めSVGスクリーンショットのChrome拡張機能をインストールしておけば,これらのサービスにアップロードしたスクリーンショットPNG画像をクリックして,SVGのプレビューページを開くことができます*2.普段使い慣れたサービスで画像を管理することができます.

f:id:daiiz:20160926022051p:plain
Google Drive のファイル一覧ページからコンテンツを検出

f:id:daiiz:20160926022121p:plain:w500
Google Photos の写真詳細ページからからコンテンツを検出

Slackも投稿した画像のファイル名を保持してくれるらしいので,近いうちに同様に対応する予定です.

関連リンク

*1:ファイル名が壊れた場合は再ダウンロードすればOKです

*2:この機能については後日詳細を書きます

プログラミング系の記事を絞り込めるようにした

雑談

技術ブログと雑記ブログを分けようかと考えていたけれど,自分の性格的に上手く運用できなそうなのでやめた.これまで通りこのブログ一本でいこうと思う.
とは言っても2つに分けて読めるようにしたかったので,はてなブログの「カテゴリータグを付ける機能」を使って,主にプログラミングのことを書いている記事に対してtechのタグを付けた.http://daiiz.hatenablog.com/archive/category/tech にアクセスすると技術ブログっぽい記事リストが表示される.深夜テンションで付けたため不適当な記事があるかもしれないので,見つけ次第タグを外していく.ブログのタイトル下のスペースにも「技術ネタに絞り込む」というリンクを置いて先程のURLにジャンプするようにしておいた.なかなか良い解決策だと自画自賛してる.

フレンチフライ トリュフ塩仕立て

ポテト日記 ごはん

ジョナサンに行ったら必ずこれを食べます.ケチャップとマヨネーズを混ぜて使うのが最高です.ケチャップの小袋が2つ付いてくるあたりが,ポテト好きの心が分かっているなと感心します.トリュフ塩というのがなんとも贅沢ですね.ファミレスのフライドポテト部門優勝だと思います.

http://miil.me/p/9025z

目が覚めた

日記

変なタイミングで寝てしまったので,いま起きました.おはようございます.
1, 2年前に作った自前のライブラリが予想以上に良い働きをしていて嬉しい,という気持ちになったところで寝落ちした記憶があります.だいぶ古いPolymerを使ったまま放置していたので,早めに最新版に対応させたいところです.ただいまこんな感じです.ぼちぼちプログラムを書いていこうと思います.

http://miil.me/p/92mec
こういう感じです

GitHubのリポジトリリストのグラデーション波が格好いい

tech

GitHubのページデザイン,ガラッと変わりましたね!!
新しいプロフィールページも格好良いけれど,リポジトリリストの ”Past year of activity” を表す波(折れ線グラフ)がカッコよすぎる.

f:id:daiiz:20160920001655p:plain

こういうやつ↑

どうやって表示しているのか知りたかったので,ソースコードを覗いてみた.はてなブックマークのブックマーク数を表示する「50 users」のチップのように画像として配信されているのかと思いきや,SVG(Scalable Vector Graphics)を使ってその場でグラフを書いていた.

f:id:daiiz:20160920002246p:plain

idっぽいものが入っていたので少し伏せ字加工したけれど,こんな感じでrectタグが描かれている.ここでは,fill と mask を使って上手いこと値が大きいほど色が濃い折れ線が表現されている.まず,mask が参照しているのは polyline で定義している折れ線データで,以下のような値が埋め込まれている.

f:id:daiiz:20160920002709p:plain

ということで,これ単体では,次のような灰色の波が描かれる.

f:id:daiiz:20160920002754p:plain

続いて,fill では linearGradient で定義した徐々に濃くなるグラデーションの長方形を参照している.

f:id:daiiz:20160920003050p:plain

プロフィールの芝生で使われている4段階の緑色が指定されていることが分かる.これ単体では以下のようになる.

f:id:daiiz:20160920003202p:plain

この2つを組み合わせることで,グラデーション長方形から折れ線を切り出したようなデザインができている.すごい,勉強になった.SVGでの表現法の生きた例を見れたような気がして大満足.

【GAE/Python 解決済】GAEでPILをimportするのに躓いて一日悩んだ話

google app engine tech

昨日からずっと悩んでいたこれ

が解決した.結局のところプログラムの書き方が間違っていたということではなくて,どこのPIL(Python Image Library; Pillow)を呼び出すかという一点で詰まっていたらしい.まずは結論を書く.

  • Google App Engine でも普通にPILは使える.
  • Product環境(GAEサーバ上)では,GAE側で用意されているPILをロードする必要がある.
  • ローカル開発環境で使うためのPILをGAEプロジェクト内に含めてはいけない.

これだけ守り,app.yamlappengine_config.py の書き方を間違えなければ上手くいく.一つずつ振り返りメモを書いておく.

PIL のインストール

Product環境には PIL は既に用意されているので,GAEプロジェクト内にPILをインストールする必要はない.とは言っても,ローカルサーバを起動して開発するときは各自で端末にインストールする必要がある.このときは,以下のように-t lib指定した pip install をしてはいけない

# これは gcloud などを入れるときのやり方
$ pip install -t lib Pillow

これだと,プロジェクトルートのライブラリフォルダlibにインストールされてしまう.libフォルダは諸々のソースコードとともにGAEにアップロードされるのでここにPILを入れてしまうと,サーバ上で実行されるアプリケーションはこちらのPILを参照してしまう.正しくは,こうやる.

$ pip install Pillow

なぜ自前で用意したこちらのPIL*1を参照させてはいけないのか?
これはおそらく PIL/Image.py 内でGAEが禁止している関数が呼び出されているからだと思われる.実際のところ,GAEプラグインが入ったPyCharmなどのIDEでこのファイルを開くと,幾つかの行において「System calls are not allowed by Google App Engine sandbox」のような警告が出る. GAE側で提供されているPILはこれらのシステムコールの部分を上手いこと解決してくれているのだろう.

PILに限らず,このページに挙げられているような,既にGAEに組み込まれている Third-party Libraries を手元の環境にインストールするときは気を付けたい.

import文

正解な書き方はこちら(もちろん lib/ には PIL を入れない!)

from PIL import Image

これを書いておくだけで,

  • Product環境では GAEが用意した PIL/Image.pyc
  • ローカル環境では .pyenv/versions/2.7.10/lib/python2.7/site-packages/PIL/Image.pyc

が読み込まれる.

以下は,少々厄介な話になるが,一応書いておく.ローカルでは動くけどデプロイしたら動かないという現象の表. ここまでで書いたようにしていれば何の問題もないので,全部僕の勘違いが悪いのけれど,折角なのでまとめてみた.

「O」は正常に動く,「X」はエラーで失敗することを表す.マス内の上段はProduct環境での結果,下段はローカル開発環境での結果を記している.

lib/PIL あり lib/PIL なし(正解)
from PIL import Image(正解) X
O
O
O
from lib.PIL import Image X
X
-
-

ちなみにサーバでのエラーはすべて ImportError: dynamic module does not define init function (init_imaging) となる.

作業中のメモ

こういうふうに詰まると辛いけれど,ある瞬間を越えて,徐々に全貌が垣間見えてくると楽しくなってくる. f:id:daiiz:20160918231756j:plain

参考ドキュメント

*1:/base/data/home/s~[project-id]/[version].[数字列]/lib/PIL/Image.py

【GAE/Python 解決済】IOError: cannot identify image file ...

google app engine python tech

Google App Engine(Python)のローカル開発環境で,Base64エンコードされたJPEGファイルをPIL(Python Image Library)にロードしようとしている. IOError: cannot identify image file というエラーが出て進めない.ぐぐったらcStringIOあるいはBytesIOを使う方法が出てきたので両方試してみたけどダメだった.

一昨日の作業終了時は普通に動いていたのが一番の謎.

とりあえず,GAEのローカル開発環境問題なのかPythonのコードが間違ってるのかを突き止めるために,GAEでない環境で動かしてみる.

追記

# coding: utf-8
from PIL import Image
import StringIO
import cStringIO
from io import BytesIO

if __name__ == '__main__':
    img_str = "data:image/jpeg;base64,/9j/..."
    img0 = StringIO.StringIO(img_str)
    img1 = cStringIO.StringIO(img_str)
    img2 = BytesIO(img_str)
    im = Image.open(img0)

最後の行の引数をimg0, img1, img2 として試したところ全部似たようなIOエラー

img0 => IOError: cannot identify image file <StringIO.StringIO instance at 0x...>
img1 => IOError: cannot identify image file <cStringIO.StringI object at 0x...>
img2 => IOError: cannot identify image file <_io.BytesIO object at 0x...>

img_strの接頭辞data:image/jpeg;base64,を外しても結果は同じ

追記

a2b_base64という関数を使ってimg_strをバイナリにする方法でPythonスクリプトを書いたところ動いた.

from PIL import Image
import StringIO
import cStringIO
from io import BytesIO
from binascii import a2b_base64

if __name__ == '__main__':
    img_str = "data:image/jpeg;base64,/9j/...".split("data:image/jpeg;base64,")[1]
    img3 = a2b_base64(img_str)
    a = StringIO.StringIO(img3)
    im = Image.open(a)

しかし,これをGAE環境に移植すると相変わらずエラーが出る.aに代入しているところまでは動いていて,imの行で落ちていることは確認できている.

cannot identify image file <StringIO.StringIO instance at 0x...>

一体どうすればいいんだ

解決報