気分転換に30分でこんなアプリつくってみました。


30分といってもコア部分だけで、使ってみたら色々直したいところが出てきて結局2,3時間は使ったと思いますが・・・。
鉄道唱歌を閲覧するアプリです。
好きなものに「旅」「鉄道」「ガジェット」が上位にランキングする僕にはぴったりのアプリです。
鉄道唱歌って見ているだけで込み上げる旅情が半端ないですよね。よね。
アプリにはなんと全5集を網羅。これが悲劇の始まりだ。
古い作品で漢字が難読なのでルビを表示する機能が入っています。
ルビが入っているということはそれを手入力しないといけないわけで・・・
実はそこだけまだ出来ていません。
あまりの膨大な量に永遠に出来ないかも・・・永遠はあるよ・・。という感じになっております。。
技術的興味から試しにiAD貼ってみているんですが、やっぱり鬱陶しいの苦手なのではずそうかなと思っています。
どうせ金銭的にはたいした役にも立たないでしょうし・・・。
でも一度試してみたいような気もする。
とにかく後はふりがなを入力すれば完成なのですが、如何せん量が多い。
1日10番づつくらい昼休みにでも入力する日課にすればそのうち終わるかもしれません。。。
(そう言いながら1日もやってませんが)
そのうち公開される・・・かもしれません。
僕が作るアイコンはダサいと定評があります。。
というか、アイコンにまで力をかけることが無いのですが、センスもやっぱりありません。
能力がないなら素直に人の作った物を使えばいいのですが、それはそれでライセンスとかで面倒。
そういうわけで、自分で作ります。
ところでiPhoneのツールバーアイコンはヘタに(用途に沿わない)システムアイコン使うとAppleの審査で怒られるらしいので自分で用意する必要があります。
「設定アイコン」と「HOMEアイコン」が欲しかったので作りました。
(このくらいよく使うのはAppleが用意しておいて欲しいよ・・・)
モノクロなので簡単かとおもいきや、思いのほかサイズが小さくてかなりデフォルメしないと潰れてしまいます。
センスがないのでアイデアも浮かばず、ザ定番というデザインにしてみました。
![]()
サザエさんを思い出しながら書いた。
表示してみると以下のような感じ。
うーん。まぁこんなもんか・・・。
![]()
iPhone用コミックビューアComicGlassですが、多くの方にダウンロードいただけているようで嬉しい限りです。
バージョン1.0を公開した当時は宣伝してないこともあってほとんどダウンロードされなかったのでもう止めようかと思いました。
iPhone用コミックビューアではiComicというアプリが定番なようですね。
実は開発を始めるときには存在を知りませんでした。(というか全く調べなかった)
自分は普通に写真としてiPhoneに転送して読んでて見づらい→専用アプリ作ろうという流れでした。
知ってたら開発はしなかったと思いますが、いつもの計画性の無さのなせる業です・・・。
既に在るならもう止めようかなぁとも思ったのですが、そこそこ自分では使いやすくなってきていたので公開まで進めることにしました。
現在はまだ何かと発展途上ですが、少しづつ完成度を高めて行きたいと思います。
そのためにはユーザーのみなさんのご要望が一番役立ちます。
けっこうバグがまだ多く、それの対応に全力だったのですが、その次に注力するのは画質問題ですね。
快適なページ送りと品質だけは理論的最良値にもって行きたいものです。
画質については、最後の縮小をiPhoneOSのUIScrollViewに任せているため速いけど少しボケるのだと思われます。
ズーム後に再計算して再描写すればよいと思うのでやってみます。
あとページ送りがもたつくという感想を貰ってます。
なんだろう? と思っていたのですが、どうやらタップ移動のときに一瞬遅れるということなのではないかと。
実はこれ、ダブルタップを判定するために敢えて待ち時間があるのが原因です。
画面の端ではダブルタップ無効にしてすぐにシングルタップとして判断するようにしたほうが良いのかも・・・。
もうひとつの構想はスキャンした小説ビューアとしての機能です。
全部表示するとギリギリ読めないくらいの字のつぶれ具合なので、行を画像認識して自動的に折り返しをつける機能を目玉として考えています。
iPhoneでも動く軽い画像認識アルゴリズムが出来るかどうかが鍵ですが、正直画像アルゴリズムよりもiPhoneのUI作るほうが面倒そうだったりします。
なお、ComicGlassを開発始めてたのは2ヶ月ほど前からです。
休日はあまり時間が取れないので平日仕事して子供寝かせた後の1〜2時間の細切れ時間で開発してます。あとは電車の中。
その割りにはけっこう早く形になったんじゃね? とか自画自賛しながら今後も進めて参ります。
(最初のころはもう少しまとめて開発しましたが)
まだできたてほやほやなので今後にご期待ください。
ハードウエアの制約の中で可能な限りの完成度を目指して。
(目指すだけなら簡単だぜー)
置き場所問題の解決や外出先への持ち運びのためにコミック(漫画)などの書籍をスキャンして電子化している人もいると思います。
僕も何度も読みたい本はスキャンした上でノートPCなどで読んでいたのですが、電車の中などでも気軽に読めるようiPhone/iPod touchでもスキャンしたコミックを読めるアプリを作ってみました。
既にそのような画像ビューアのようなソフトはあったのですが、自分の使い方にはちょっと物足りなかったので、無ければ作ろう! って事で作りました。
スキャンしたコミックなどはZIPなどに固めて1ファイルにすることが多いと思いますが、このアプリはZIPファイルを直接開けます。
(つまりZIPファイルを本として扱います)
アプリの名前はComic Glassです。
自分では便利に使ってますが、多くの方も使ってもらえると更に幸せ。
ComicGlassをiTunesで開く(ここからダウンロードできます)

(ご覧のようにiPad対応も考えていたのですが、僕のミスがあってAppleの審査に落とされてしまったのでiPad対応版は修正中です)
で、何がこのアプリの特徴か、という事なのですがいくつかあります。
1.狭い画面でも快適に閲覧できる

iPhoneの最大の魅力はサクサクとした動作。それを活かせば快適に閲覧できるはずです。
フリックで画面はさーっとスムーズにスクロールします。
文字が潰れて見えない時などはダブルタップをすると自動的に最適なサイズにズームイン・ズームアウトします。
この辺の動作がぎこちないとガッカリなのでスマートな動作を目指しました。
スキャンした画像が2ページ分(見開き)の場合は自動的に分割して表示します。
2.快適なページ送り
まず縦書きを意識しています。
もちろん横書き用にも設定できますが、日本の漫画や書籍の多くは縦書きなのでページ送りの方向や、最初にページを開いた時にどの位置が開始位置になるかというのはけっこう重要です。
そしてページ先読みとページキャッシュです。
次に表示するであろうページをバックグランドで先読みし、既に読んだページのキャッシュを作ります。
これによってページ送りが非常に快適になりました。
またシークバーによるページ送りもできるので本の途中へも簡単に移動できます。

3.既にスキャンしたファイルをできるだけ活用できる
画像といっても色々、ZIPといっても色々あります。
あまりにも大きな画像はiPhoneのハードウエアの制約にひっかかりますが、かなり大きめの画像でも内部で自動的にリサイズして表示できます。
また、ZIPファイルの中にフォルダが入っていたり、ZIPファイルの中にZIPファイルが入っていてもアプリ単体でなんとかできるようになっています。

パスワード付きのZIPファイルにも次回バージョンで対応します。

4.本の転送が容易
iPhoneにファイルを転送するには何かと制約があるものです。
Appleに認められた方法でやろうとするとWiFiを使うことになります。
Comic Glassでは内蔵したファイル転送機能によりWebサーバから簡単にファイルを転送できます。
しかしWebサーバを容易するのも面倒なものです。
そこでPC用にComicGlass専用転送ソフトも用意しました。
これを使えば更にラクちんです。

なお、非公式ながらUSB経由でiPhoneにファイルを転送するソフトも存在しています。
これらで転送したファイルも閲覧できるようになっています。
(次回バージョンアップにて対応)
5.フォルダで本の管理ができる
転送したファイルはファイル一覧に表示されます。
読んでいる途中の本は一覧のアイコンで確認でき、途中から再開することができます。
長いファイル名は自動的に文字列の内容をチェックして短縮しますので、ファイル名末尾の巻数が見えなくて困った!ということも起きません。
またファイルの他にフォルダを作ることができます。
フォルダの中にフォルダを作ることも当然できます。

ちょっと会社では人に見られたくないフォルダがあるなぁという場合にはフォルダにパスコードロックをかけて自分にしか開けないようにすることもできます。

(お願い)
このアプリは出来立てほやほやVersion1.0です。
既にわかっている不具合もありますが、多くは修正済みで次のバージョンアップで対応します。
もし上記アプリに興味がある方がいらっしゃいましたら是非使ってみてご要望やご感想などをお寄せいただけると幸いです。
そして今後に期待できるな! と思って頂けたら他の方にも紹介してくださると尚幸せです。(ここ重要)
以前の日記でデコードするコードを載せましたが、その続きです。
エンコードの方は適当に思いつきでは無理そうだったのでRFCを読んでみました。
参照元はRFC 3986になります。
Percent-Encodingのデコード関数とエンコード関数を作ってあります。
とはいえ、ナナメ読みなのであんまり信頼してもらっては困りますが。
読んで気づいたのですが、"+"の処理はPercent-Encodingの範疇ではないっぽいですね。
ただしapplication/x-www-form-urlencodedではまずスペースを"+"に置き換えます。
というわけでソースから一応外しました。
上記の用にフォームで使う用途によっては残しておいたほうが便利なのでコメントにしただけにしてます。
長くなったのでファイルでも置いてきます。
1 ://///////////////////////////
2 :///
3 :/// Percent-Encoding(RFC 3986)
4 :///
5 :/// 2010.03.08 http://Knonline.NET
6 :///
7 :
8 :
9 :#include "percentEncoding.h"
10 :
11 ://///////////Percent-Encoding/////////////////////////
12 :
13 :#define ASCII_ALPHA1_START (0x41) //A
14 :#define ASCII_ALPHA1_END (0x5A) //Z
15 :#define ASCII_ALPHA2_START (0x61) //a
16 :#define ASCII_ALPHA2_END (0x7A) //z
17 :#define ASCII_DIGIT_START (0x30) //0
18 :#define ASCII_DIGIT_END (0x39) //9
19 :#define ASCII_HYPHEN (0x2D) //-
20 :#define ASCII_PERIOD (0x2E) //.
21 :#define ASCII_UNDERSCORE (0x5F) //_
22 :#define ASCII_TILDA (0x7E) //~
23 :
24 :
25 :
26 :
27 ://16進数文字[A-F|a-f]から数値を得る
28 :int valueFromHexChar(char hex)
29 :{
30 : if('0' <= hex && hex <= '9') return hex - '0';
31 : else if('A' <= hex && hex <= 'F') return hex - 'A' +10;
32 : else if('a' <= hex && hex <= 'f') return hex - 'a' +10;
33 : else return 0;
34 :}
35 :
36 ://数値[0-15]から16進数文字を得る
37 :char hexCharFromValue(unsigned int value)
38 :{
39 : if( value <0 || 16 <= value) return '0';
40 : return "0123456789ABCDEF"[value];
41 :}
42 :
43 ://URLエンコードをデコードする
44 :void urlDecode(char* decoded
45 : ,size_t decoded_length
46 : ,const char* source)
47 :{
48 : decoded_length--; //最後の\0の分
49 : while(*source && decoded_length){
50 : if(*source == '%'){
51 : if(*(source+1) == '\0') break; //%の後2Byte続かずに
終わっている場合に備えて
52 : *(decoded++)
53 : = (valueFromHexChar( *(source+1) ) <<4 )
54 : + valueFromHexChar( *(source+2) );
55 : source += 3;
56 : }/*else if(*source == '+'){ //おまけ
57 : *(decoded++) = ' ';
58 : source++;
59 : }*/else{
60 : *(decoded++) = *(source++);
61 : }
62 : decoded_length--;
63 : }
64 : *decoded = '\0';
65 :}
66 :
67 ://URLエンコードにエンコードする
68 :void urlEncode(char* encoded
69 : ,size_t encoded_length
70 : ,const char* source)
71 :{
72 : char temp;
73 : encoded_length--;
74 : while(*source && encoded_length){
75 : temp =*source;
76 : if( ASCII_ALPHA1_START <= temp && temp<= ASCII_ALPHA1_END
77 : ||ASCII_ALPHA2_START <= temp && temp<= ASCII_ALPHA2_END
78 : ||ASCII_DIGIT_START <= temp && temp<= ASCII_DIGIT_END
79 : || temp == ASCII_HYPHEN
80 : || temp == ASCII_PERIOD
81 : || temp == ASCII_UNDERSCORE
82 : || temp == ASCII_TILDA)
83 : {
84 : //Unreserved Characters
85 : *(encoded++) = temp;
86 :
87 : }else{
88 : //Reserved Characters
89 : *(encoded++) = '%';
90 : if(!(--encoded_length)) break;
91 : *(encoded++) = hexCharFromValue((unsigned char)temp >> 4);
92 : if(!(--encoded_length)) break;
93 : *(encoded++) = hexCharFromValue(temp & 0x0F);
94 : encoded_length-=2;
95 : }
96 : source++;
97 : encoded_length--;
98 : }
99 : *encoded = '\0';
100 :}
101 :
102 :
∂ ひかりん [iPhone用なので検証できません。 時代はやはり携帯電話(SB)なんでしょうか・・・。 ]
∂ Suika [SBではないと思いますが、Appleなのかも? まあ流行病みたいなもんですよ。]
∂ ひかりん [そろそろPHSから携帯に買い換えるか。やっぱりiPhoneがいろいろと遊べていいのかな?]
∂ ひかりん [iPhone4ゲットしたのでさっそく使ってみました! 今のところ不満はないです。スタートアップガイドがめちゃめちゃ綺..]
∂ Suika [おー、うらやましいです。]