たまりば

  パソコン・インターネット パソコン・インターネット  三鷹市 三鷹市

【訂正・加筆】
2017年04月23日 00:00

2017/04/23 2017/05/22 ゼルダの伝説ブレスオブザワイルドプレイ日記(ネタバレ有) 更新。
2016/12/06 漢点字一覧表で、別の元データとの間で不一致があったので追記。
2016/09/10 ネット契約を1Mbpsにしてみたの読み込み時間の記述が間違っていたので訂正。
2016/09/04 ファミコンの縦解像度224px説の考察 左8pxを隠す機能の用途が思っていたのと違ったので追記。
2016/06/06 Windows7でのペイントの劣化具合に新しく気づいたバグ情報を追加。
2015/08/29 ベースラインPICの注意点で、型番の間違いを訂正、OPTION2の書き込み方法の間違いを訂正。
2015/08/28 Windows7でのペイントの劣化具合に新しく気づいたバグ情報を追加。
2013/09/26 5×5 ひらがなフォント5×5フォント改 / JavaScriptフォント表示機から5×5ドットフォント完成版に、思えばリンクを貼っていなかったのでリンク。
2013/05/05 最弱のPICマイコンで電子オルガン_前編の単純ミスを1ヶ所修正。
2013/04/27 文字コード表示機が特定の環境で動かない問題を修正、RTL文字での表示崩れを修正。
2013/03/03 5×5ドットフォント完成版が紹介されていたので少々加筆しました。
2012/11/18 ハロウィー?ンの正規表現に訂正・加筆があります。

【このエントリについて】
(2012/11/18)
今まで、記事の内容にミスを見つけた場合はその記事だけ修正していたのですが、最新の記事はともかく古い記事にミスを見つけた場合は直しても気づかれないだろうと思って直すのが億劫になっていました。
これではいけないと、どうするべきか考えた結果、訂正を知らせるエントリを1つ作ることにしました。
記事を訂正した際にはこのエントリを更新して最上位に持ってくるように運用しようと思います。
(2013/03/03)
訂正だけに限らなかったので、エントリ名を【訂正】から【訂正・加筆】に変更しました。  
タグ :お知らせ

  • Windows10にフォント消されたけどまあ理解できる
    2017年04月16日 17:31

    Windows8から10にアップグレードして使っていたマシンで、先日(2016/10/12)いくつかのフォントが消えていることに気づいた。

    調べ物をしていて韓国語の字体を見たくなり、文字コード表でフォントをDotumにしようとすると、選択肢に無い。
    Gulimでもいいかと思って探すとこれも無い。BatangもGungsuhも無い。
    有効化していなかったかと思いfontsフォルダを見ると、無効ではなく存在しない。
    この辺で焦りだす。
    他の言語のフォントも怪しいと思い調べてみるとMingLiUもSimHeiも無い。なんだこれは。
    ここまではWindows付属のフォントだがOffice付属のNew Gulimは…? と見るとこれはある。
    すると消えたのはWindows付属のフォントのみなのだろうか。

    ググるとWindows10でMS明朝が無いという投稿が見つかった。→Windows10のフォントにMS明朝がありません
    「設定→システム→アプリと機能→オプション機能の管理」に「日本語補助フォント」のオプションがあるようだ。見てみると他にも各言語の「補助フォント」があり、ここからGulimやSimHeiなどをインストールできた。

    ここにきてやっと何が起こったのか理解できた。
    Windows10になって、各言語のフォントに「補助フォント」という概念ができたようだ。
    そして基本的なフォントはデフォルトで全言語のものがインストールされるが、補助フォントは使用言語のもののみがインストールされるようになったのだろう。
    その判断はまあ問題ないだろう。対応言語も多くなりフォントの容量も馬鹿にならない。

    ここで問題になるのが旧OSからのアップグレードだ。
    旧Windowsでは非使用言語の補助フォント相当も全て入っていたが、Windows10の流儀に合わせるためには存在してはいけない。だから消すと。
    理解はできる。
    消すにあたって、どのフォントを使っているかは判断のしようがないから、すべて消すことになる。
    理解はできる。

    理解はできるが、普通に使っていたファイルが消えるとなると他に何が消されたか分からないのが怖くてたまらない。
    あるはずのファイルが見つからないという経験も何度かあった。まず間違いなく気のせいだろうが、Microsoftは自分の中でもうだいぶ信用を失っているので、本当に消されてもおかしくないと思ってしまう。

    他にも、.NET2.0がWindows10へのアップデートに伴って消えるという問題もあるらしい。ああ嫌だ。
    [note] Win10アップグレード後のVisual Studio 2005起動時エラーの修正について  

  • ゼルダの伝説ブレスオブザワイルドプレイ日記(ネタバレ有)
    2017年03月12日 18:13

    1週間ちょっとプレイしてみて(というか週末だけなので累計2日3日くらい)これは感想を書き留めておきたいという気分になったので書き始める。
    主に自分が後で読み返して懐かしむために書いているが、本作は多様なルートで攻略できることが特徴のようなので、他人が変なルートをとっているを見るのも面白いかもしれない。ということで公開する。ただあまり人に読ませる文体でない部分もある。
    ネタバレについて。積極的にネタバレをしたいわけではないが、感想を書く時点ですなわちネタバレである。本作を十分にクリアした、あるいは未来永劫プレイしないと確信が持てる人以外が読むことは強く非推奨する。

    2017/04/02 エンディング到達。総プレイ時間は本体の記録によれば60:14であった。
    とりあえず日記はここまででいいかな。もしかしたらまた何か書き足したくなるかもしれないけど。→書き足したくなった。
    2017/05/22 最終更新

    ところで、本文にも書いたが、本作は(トワイライトプリンセスの時のようなことはなく)Switch版の方が全面的に優れている。
    あまり無いと思うがWiiU版とSwitch版のどちらにしようか迷っている人がここを見た時のために情報をまとめておこう。
    ・Switch版の方がTV出力時の解像度が高い。Switch本体とWiiU GamePadの比較でもSwitchの方が解像度が高い。
    ・Switch版の方が安定してフレームレートを保てる。
    ・Switch版の方が音質が良い。
    ・WiiU版は、GamePadを一切使わない。 ←これを事前に知っていたら自分はSwitch版を買っただろう
    ・Switch版は言語切替えが可能。 ←同上
    (2017/05/22追記: WiiU版も音声は切替え可能になった。文字も欲しい。)

    折角なのでWiiU版でしか見られない画面をここに載せておこう。
    タッチするとGamePadであそべます画面  続きを読む

  • JPEG圧縮を繰り返しても際限なく劣化するわけではない
    2017年02月10日 01:47

    ビデオテープのダビングやコピー機でのコピーは世代を重ねるごとに劣化が蓄積する。
    同様にJPEG画像も、保存→開く→保存…と繰り返すと、
    JPEG劣化_オリジナル
    オリジナル
    JPEG劣化_ずらし_1世代目
    保存1回目
    JPEG劣化_ずらし_9世代目
    保存9回目
    JPEG劣化_ずらし_17世代目
    保存17回目
    JPEG劣化_ずらし_49世代目
    保存49回目
    JPEG劣化_ずらし_97世代目
    保存97回目
    JPEG劣化_ずらし_201世代目
    保存201回目
    JPEG劣化_ずらし_497世代目
    保存497回目
    JPEG劣化_ずらし_1001世代目
    保存1001回目
    JPEG劣化_ずらし_2001世代目
    保存2001回目
    JPEG劣化_ずらし_5001世代目
    保存5001回目
    JPEG劣化_ずらし_10001世代目
    保存10001回目
    といった具合に劣化が蓄積して画質が際限なく落ちていき、最後には一面のノイズになってしまう…

    …と誤った認識を持っている人が多い。

    実際に試してみよう。使用するソフトは定番のImageMagick。
    magick convert -sampling-factor 1x1 -quality 95 orig.png gen1.jpg
    magick convert -sampling-factor 1x1 -quality 95 gen1.jpg gen2.jpg
    magick convert -sampling-factor 1x1 -quality 95 gen2.jpg gen3.jpg
    このようなバッチファイルをExcelとテキストエディタで作成し、実行する。
    結果は次のとおり。
    JPEG劣化_オリジナル
    オリジナル
    JPEG劣化_1世代目
    保存1回目
    JPEG劣化_17世代目
    保存17回目

    以上だ。
    3000回くらい回していたのだが、確認してみると18回目で既に前回と同一の画像が出力されていた。だいぶ時間を無駄にした。
    このように、繰り返し保存による劣化は早々に止まることが分かる。
    なお今回は1種類に収束したが、以前試した時は3種類のローテーションになったこともあった。
    また、見て分かる(分からない)とおり、1回目と17回目で差はほとんど無い。
    念のため差分をとってみよう。
    JPEG劣化_差分_1-17
    全く見えないので64倍に強調したものも置いておく。
    JPEG劣化_差分_1-17(×64)

    そもそも非可逆圧縮の原理は、元データを少々変えて「圧縮しやすいデータ」を作り、それを可逆圧縮するものと解釈できる。
    よって一度非可逆圧縮したデータを展開したデータは、既に「圧縮しやすいデータ」になっているため、同じ設定で圧縮すれば完全に可逆圧縮になってもおかしくない。
    むしろ17回まで劣化が続くことの方が不思議といえる。
    ではなぜかだが、JPEGの圧縮の根幹である離散コサイン変換(DCT)は本来は可逆なのだが、実際には有限の精度で計算するために丸め誤差が発生する。おそらくこれがJPEG再圧縮が不可逆な原因だと思う。
    またどうもJPEGの仕様はあまり厳密でないようで、エンコードでは演算の精度をソフトの自由で選べたり、デコードもソフトによって結果が違ったりする。これも一因かもしれない。
    (2/11追記)RGB→YUVの変換も丸め誤差が発生するので一因かもしれない。

    さて次にパラメータを少し変えてみる。
    JPEG劣化_オリジナル
    オリジナル
    JPEG劣化_サンプリング2×2_1世代目
    1回目
    JPEG劣化_サンプリング2×2_10世代目
    10回目
    JPEG劣化_サンプリング2×2_20世代目
    20回目
    JPEG劣化_サンプリング2×2_50世代目
    50回目
    JPEG劣化_サンプリング2×2_103世代目
    103回目

    今度は劣化が103回目まで続く。劣化の度合いも目に見えて分かる。色が褪せていて、特に赤が大幅にくすんでしまっている。
    差分をとってみる。
    JPEG劣化_サンプリング2×2_差分_1-103
    少し見にくいので4倍に強調しておこう。
    JPEG劣化_サンプリング2×2_差分_1-103(×4)
    闇夜に光る眼のようで可愛い。

    何を変えたかというと、カラーサブサンプリングだ。
    カラーサブサンプリングは、クロマサブサンプリングや色成分間引きと呼ばれたり、単にサンプリングやサンプリング比という名の設定項目で設定したりする。名前が定まっておらず面倒な概念だ。
    先の17回で劣化が止まったものは、カラーサブサンプリングがOff、別の言い方をするとサンプリングが1x1や4:4:4と呼ばれるものだ。この設定では輝度成分と色成分を元の解像度のまま処理する。この時、画像は8×8のブロックごとに処理され、隣のブロックとの間で影響を及ぼすことはない。
    一方103回の方は、カラーサブサンプリングがOn、サンプリングが2x2や4:2:0と呼ばれる設定であり、輝度成分は元解像度で、色成分は縦横1/2に縮小してから処理をする。
    この縮小で単純に2×2ピクセルを平均するのであれば16×16のブロック内に影響が留まるだろうが、どうもそうではなく線形補間か何かをされているようで、ドットの色が16×16pxの境界を越えてにじむ現象が見られる。これにより隣のブロックの色が圧縮に影響し、次回は隣の隣のブロックにまで波及し、と際限なく影響を与え合う。厳密なことは分からないがこれが劣化が長く続く理由ではないかと思う。

    なので劣化が蓄積するというのは、カラーサブサンプリングOnの設定においてはある程度正しい。
    ただしそれにしても際限なく劣化するということはないし、JPEGが全てそのように劣化するわけでもないことは上で示したとおりだ。

    さてもうひとつ、冒頭の例のように完全なノイズにまで際限なく劣化させるにはどうすればよいだろう。劣化しそうな方法をいろいろ試してみた。
    まず圧縮率を毎回変えたら量子化の閾値が変わることで劣化が続くのではないかと考えたのだが、駄目であった。1万回繰り返してもほぼ劣化が見えなかった。(同じ画像が続くことは無かったので何パターンかのローテーションになっていたようだ)
    次に90度回転を試したがこれも同様であった。今回使ったJPEGの量子化行列は縦と横で対称でないのでそれによるゆらぎを期待したのだが…。
    そこで毎回画像の位置をずらしてみることにした。7回右下へ1pxずらしたあと、1回左上に7pxずらして戻すの繰り返し。これは見事に成功、これでできたのが冒頭の画像だ。
    なぜこれが上手くいくかは、正確なことは分からないが、特定のドットに注目するとそのドットは8×8のブロック内で位置が毎回変わるようになっており、これで誤差が波及し続けるのが一因だろう。
    サンプリング2x2の時は止まってしまったのでそれ以外に何かあるのだろうが、よく分からない。何か誤差が発振するような機構があるのだろうか…。
    なお90度回転も、画像サイズが8×8の倍数でない場合はずらすのと同じことになる。

    以上、まとめると
    ・単純に同じ設定で圧縮を繰り返すだけでは際限なく劣化することはない。
    ・ただしサンプリングを落とした場合は少々劣化が続く。
    ・設定を変えても際限なく劣化はしてくれない。
    ・位置の移動を伴うと際限なく劣化した。

    JPEGの劣化は奥が深い。  

  • I2C液晶が動かない理由が分かった
    2017年01月31日 01:54

    以前、秋月で超小型のI2Cキャラクタ液晶(I2C接続小型キャラクタLCDモジュール 8x2行)を買い、PIC10F200で色々と表示していた。
    ある時思いついたネタを実装しようとしたところ10F200ではROMが足りなかったので、石をPIC12F510に変えることにした。
    移植作業はわりと楽であった。ADコンバータ関連を無効化すればあとはだいたい似たようなものである。
    しかし動かない。
    しかも不思議な事に信号線にLEDやテスターをつなぐと動く。つまり原因は単純なプログラムのミスではなくアナログ的な微妙な差異によるもののようだ。
    色々考えたが分からないのでその時はあきらめた。一昨年の5月ころだ。

    (昨年の4月に)その原因が判明したので顛末をここに書き留める。何かの参考になれば幸いだ。

    まず最初に言っておくと、このプログラムで出していた信号は正常なI2Cではない。
    第一に、本来I2CはLowとプルアップで駆動するものをHighとLowで駆動している。プログラムの簡略化と高速化の為だ。
    第二に、クロック立ち下がりからデータ変化の時間、tHD:DATはデータシートによれば最小0・最大0.9μs(後述)のところ、最小ギリギリの0にしている。10F200で可能な間隔が1μsの為だ。またデータシートによればこれでも300nsの余裕があるように読める(後述)。

    もっとまともな信号にすれば動くかもしれなかったが、それは解決にならない。
    問題は動かない事ではなく、動かない理由が分からない事である。
    規格外や規格ギリギリではあるものの、これでも動くはずだと考えてやっているのだし、実際10F200ではほぼ確実に動くのである。
    この状態で適当に変更して動くようになったとしても本当にその変更が正しかったのか分からない。何か重大な思い違いがあったら危険だ。
    またなにより、何が問題なのか分からないままというのは気持ち悪い。

    移植して動かなかった時から(覚えている限り)時系列に沿って状況を書く。

    MPLABのシミュレータで見た波形は全く同じ。
    怪しいのは実際に信号が出ているかだ。TRISの設定を間違ったり、間違って別のピンにつないでいたりすることはしょっちゅうだ。
    なので信号が出ているかどうかを確認するため、信号線に青LEDをつないだ。(LEDをつなぐと点滅具合で色々分かる。青なのは電源が電池2本の時抵抗を入れなくても大丈夫で便利だからだ)
    すると…不思議なことにほぼ確実に動作するようになった。
    最初はデータとクロック両方に付けていたが、データ線だけでも動作する。
    赤LED(+抵抗)だと駄目。電圧の問題かと思い赤LED+ダイオード1、2本で試すも駄目。また、データ線にテスターを当てるとほぼ確実に動作する。

    この時点で問題はアナログ的なものと分かった。

    アナログ的な仕様に何か違いがあるのではないかとデータシートを見る。ほとんど同じだったが、1つだけ、デバイスリセットタイマ(DRT)の時間が異なっていた。早速その分の待ちを入れてみる。
    …が、変わらず。

    もはやこれはオシロスコープを買うしかない。
    2万円の機種と迷ったが3万円のものを購入。オシロスコープで12F510で動く時(青LED付き)と動かない時を確認すると信号に違いが!
    …と思ったがよく見るとそれはACKが返っていないだけであった。
    分かったことは、最初の1バイト(アドレス)から既にACKが返っていないということだけ。
    あとはノイズだが、電源投入からI2C送信までの間に目立ったノイズは無く、電源投入時のノイズはわりと酷いがどちらも同様に酷い。

    そして10F200と12F510を比較してみると、I2C信号を送信するところは一切違いが見当たらないが、リセット直後の挙動が違っていた。
    調べてみると、デバイスリセットタイマ相当の待ちを入れた時、待ちの後にHigh-ZからHighにするつもりのところを間違って待ちの前にHighにしてしまっていた。
    …しかしこれを直しても変わらず。
    もしかしてデバイスリセットタイマ中とプログラムが走っている時では何か違いがあるのだろうか。そうなると12F510で動かすのは不可能ということに。

    この辺でできることも無くなり諦めてしばらく経った。

    ある日、なんとなくI2Cについて考えていて思った。なぜtHD:DATに上限があるのだろう。
    液晶コントローラのデータシートに上限があるように書かれていたので不審に思いながらも従っていたのだが、やはりおかしい。
    I2C液晶データシート
    I2Cのデータシートを見ると、違う書かれ方をしている。(なお後で知ったが古いデータシートでは上限0.9μsになっていた)
    I2Cデータシート
    上限はなし、その上で注釈として、
    The maximum tHD:DAT could be 3.45 μs and 0.9 μs for Standard-mode and Fast-mode, but must be less than the maximum of tVD:DAT or tVD:ACK by a transition time.
    最大のtHD:DATはスタンダードモードで3.45μs、ファースト(fast)モードで0.9μ秒になりうるが、tVD:DATまたはtVD:ACKの最大値よりトランジション時間だけ短くなくてはならない。
    This maximum must only be met if the device does not stretch the LOW period (tLOW) of the SCL signal.
    この最大値はデバイスがSCL信号のLOW期間(tLOW)をストレッチしないときのみ満たす必要がある。
    If the clock stretches the SCL, the data must be valid by the set-up time before it releases the clock.
    もしクロックがSCLをストレッチするなら(訳注: 意味が分からない。SCLはクロックだ)、データはそれ(訳注: どれ? クロック?)がクロックを解放する前にセットアップ時間だけ有効でなければならない。
    CBUSとの兼ね合いかとも思って調べようともしていたが、どうも死んだ規格らしく情報がない。その辺で当時は諦めていた気がする。
    しかしさらに考えてやっと分かった。この0.9μsという上限の値は、スレーブに対する制限なのだ。
    「マスターがクロックを生成しスレーブがデータを送信するとき、マスターがクロックをLowにしている間にスレーブはデータを変化させなければならない」という当たり前の制限について言っているだけだ。

    クロックがLowの間にデータを変化させるには、データのホールド時間(tHD:DAT)・データの立ち上がり時間(tr)または立ち下がり時間(tf)・データのセットアップ時間(tSU:DAT)の和がクロックのLow期間(tLOW)より短くなければならない。
    I2Cタイミング関係
    ファーストモードではクロックのLow期間の最小値が1.3μs、立ち上がり時間の最大値が300ns、データセットアップ時間の最小値が100nsなので、
    1.3-0.3-0.1=0.9
    となり注記の値に一致する。

    スタンダードモードでも同様に
    4.7-1-0.25=3.45
    となる。

    今回データ送信はマスター側からのみ行うため、スレーブの制限は無関係だ。よって最大0.9μsは無視してもっと長い時間とれば余裕を持った通信ができる。

    解決方法は見えた。あとは原因の方だ。10F200と12F510、LEDやテスタリードを付けた12F510で何が違うのか。

    もう一度オシロで波形を見てみよう。
    ここまでI2Cの通信内容が分かる程度の縮尺で見ていたのだが、限界までサンプリング速度を上げて拡大して見てみる。すると波形が明らかに違っていた!
    I2C_10F200/12F510比較
    10F200はシンクが強いのか立ち下がりが速い。
    これによって、SCK・SDAを同時に操作してもSCKの立ち下がりの後にSDAの立ち上がりが来てくれていたようなのだ。それが12F510では逆になっている。
    この違いで動作が分かれていたのだろう。
    なおこの3万円のオシロのサンプリング速度は250Msps(2ch時)、帯域は60MHz。迷っていた2万円の方の機種は100Msps・25MHzである。
    1/(60MHz)=17ns、1/(25MHz)=40nsであり、25MHzの帯域で今回の波形の違いを捉えられたかはかなり怪しい。
    高い方を選んで良かった。

    さて最後に、冒頭で言った300nsの余裕の件だ。

    tHD:DATの下限について、以下のように注釈がある。バージョンによって言い回しが少々変わっているが内容は同じようだ。
    ・A device must internally provide a hold time of at least 300 ns for the SDA signal (referred to the VIHmin of the SCL signal) to bridge the undefined region of the falling edge of SCL.
    ・A device must internally provide a hold time of at least 300 ns for the SDA signal (with respect to the VIH(min) of the SCL signal) to bridge the undefined region of the falling edge of SCL.
    この文章も微妙に意味が取れないのだが、精一杯の訳が以下だ。
    「SCLの立ち下がりの不定区間を橋渡しするため、デバイスはSDA信号に対して内部的に最低300nsのホールド時間を(SCL信号のVIH(min)を基準に)用意しなければならない。」
    internally・reffered・with respect to・bridgeあたりの意味がよく分からない。
    なお誤訳の可能性を考えてオランダ語の原文があるかと探したのだがどうやら英語が原文のようである。

    これを自分はこう理解した。

    受信側はSDA線の立ち下がりから300ns間内部的にHighと扱う。
    よってSCKよりSDAが(300ns-立ち下がり時間)だけ早くてもよい。
    立ち下がり時間の最大が300nsなので、都合余裕は0。

    これは12F510で動作しない現状と食い違うが、上記の文章の解釈は他に思いつかない。
    (「送信側がSDA線を300ns遅らせて駆動しなければならない」という説も見かけたが、それではinternallyでないのと、それはtHD:DATの下限が300nsと書けばよいことなので、別に注釈として書かれている説明がつかない。)
    自分の解釈が間違っているのか、このデバイスが仕様に従っていないのか分からない。
    まあどちらにせよ、諸悪の根源はI2Cの仕様書が分かりづらいせいだ。マスターの条件とスレーブの条件が混ざって書かれているし、0.9μsだの300nsだのと注釈で変な条件を追加するし、その注釈は文章の意味が取れない。

    とそんなわけで不可解な点は残ったものの、まとめると、

    ・最大値が0.9μsだと思っていたが制限は無かった。
    ・最小値が0だが300nsの余裕があると思っていたが、文の解釈はよく分からず、現に余裕は無かった。
    ・石を変えて動かなくなったのは立ち下がりの速さの差のせい。

    tHD:DATを長くしたところ、安定して動くようになった。
    12F510でI2C液晶が動いた
    (なお表示は温度計を作ろうとしていた時のダミー表示)