アーカイブ

投稿者アーカイブ

bookwormのソースコードを公開します

以前、プライベートでiOSの書籍アプリを開発していた頃があり、単独の書籍タイトル向けにライセンス販売したりしておりました。例えばコレとか。

所がAppleの方針変更があり、書籍はストアアプリと課金で購入できる書籍データに分離しろというお達しが出て単品の書籍アプリは禁止されてしまい、開発は長続きする事なく終わってしまいました。

製品寿命も尽きてますし、当時の関係者の了承も得られたので、ソースを公開する事にします。

https://github.com/marvelph/OpenBookworm

独自のマークアップ形式のテキストコンテンツを、縦書きでリフローするタイプの書籍アプリになってます。iPhoneやiPadのポートレートでも動作しますが、iPadでランドスケープ動作させると見開きになります。シークバーでページを移動させると、トランジションがちょっと面白いかもしれません。

製品のコンテンツを抜いて著作権切れの童話に差し替えたりしたので、開発中の試行錯誤の履歴は残っていない状態です。

Xcode8でビルドして動かしてみましたが、検索とかフォントサイズ変更とか、動かなくなっている機能もあるようです。

広告
カテゴリー:開発 タグ: ,

Mangaoにrarファイル対応をコミットしました

OS X用のコミックビューア、Mangaoにrarファイル対応をコミットしました。
http://ryotaminami93.appspot.com/mangao.html

中の人からtwitter経由で「Mangaoにgithubで公開しているzipファイルのライブラリを使ったよ」という連絡があったので使ってみたのですが、

  • シンプルなのでストレスが少ない
  • キーボードの操作方法がDOSのコンソールアプリみたいで好み
  • OS X 10.8で安定している(Simple ComicやcooViewerの問題点)

事が解りました。

ソースコードも公開されていますし、ちょっと手伝いたい気持ちになったのでrarファイルの対応を行って、中の人にコードレビューして頂きました。
幸い気に入って頂けたようなので、無事マージされたバージョンがリリースされています。
rar対応の部分のライブラリは切り出して、別途githubでも公開しています。
https://github.com/marvelph/RarFile

カテゴリー:開発 タグ: ,

SV600に触ってきました

先週の火曜日に株式会社PFUのイベント、「『ScanSnap SV600』タッチ&トライ Meeting」にお邪魔してきました。

川崎まで出向いてSV600を触ってみようと考えた事には理由があります。
「ひょっとして、自炊する時の面倒な裁断作業から解放されるんじゃなかろうか?」
と、考えたためです。
特に、裁断機に入れる厚みにするためにカッターで背表紙を分解する所や、ブックカバーの裁断は面倒きわまりないです。
ただ、見開き2ページをスキャンする度にページを手で捲る事を考えると逆に苦行が増すような気もしました。
結局は触らないと解らない事が多い事と、この機会に以前から感じていたScanSnapのソフトウェア周り意見を伝えられたらと考えて、参加させて頂く事にしました。

結論としては、SV600は裁断の手間を軽減するための製品では無かったです。
ページ捲りも手間ですし、台形補正があると行ってもシードフィードスキャナのようには奇麗に読み込めませんでした。

ただ、想像を超えてすごい代物でした。
少なくても従来のフラッドベッドスキャナに感じていたストレスのいくつかは無くなっています。

まず、蓋をする必要が無い事が大きいです。
フラッドベッドスキャナで見開きを取ろうとすると、かなり強く蓋を押し付けないと真ん中付近に真っ黒い領域ができます。
抑え続ける事も面倒ですが、資料を強く開いて痛める事にも抵抗があります。

次に、スキャンしてみたら曲がっていたといいう事が良くあります。
特に強く抑えている場合は位置合わせが難しく、プレスキャンするまで仕上がりは把握できません。

もちろん開放式である事やCCDから資料の距離がある事もあって、制作などに必要なきっちりした原稿を最高の品質で読み込む目的には適さないと思いますが、単に目の前の紙を電子化したいという用度だと圧倒的に使いやすいと思います。
書籍を読み込みたいという目的が無い人であれば、シードフィードスキャナよりもおすすめだと思います。

イベントにはPFUの方が居たので、カラーとグレイスケールの自動認識モードを追加して頂けるようお願いしてみました。
書籍の場合モノクロ2値は読みづらい仕上がりになるので、グレースケールが最適です。
ただ表紙や一部のページのイラストにカラーがある場合、そこはカラーになって欲しいと思います。
全部カラーは次善としてはアリなんですが、文字ばかりの場合は薄く見えて読み難かったりします。
現状SnaSnapのソフトウェアに自動認識させると、カラーとモノクロ2値の自動認識モードになってしまう事を残念に思っていたので、ここぞとばかりにアピールしておきました。

カテゴリー:ハードウェア

PoiCa Sensorについて発表してきました

Cocoa勉強会で、PoiCa Sensorについて発表してきました。

コードがほとんど出てこないアレな発表ではありましたが、退屈はされなかったようなのでほっとしました。

カテゴリー:開発 タグ:

ScanSnap iX500を試してみました

何年か前に、裁断機を買って手持ちの技術書を電子化しようとしました。
引っ越しの時に、本棚のスペースの確保にコストがかかっている事に気がついたからです。
死蔵していた、ScanSnap S510の有効利用にもなりそうでした。
当時の目論見としては、1日に一冊でも裁断を続ければ数年で電子化が完了すると考えていました。
少なくても、新しく買う分を最初から電子版にしておけば、増える事は無いハズでした。

結果としては、いよいよ本の置き場がありません。

必要な書籍が電子版にならないとか、裁断可能な厚みに本をカッターで分解する事が面倒とか、カバーは個別にカッターで切る必要があるとか、一度にスキャナに投入できる枚数が少なくて面倒とか、紙質が悪いと詰まったり重送されるとか、ページが揃っているかのチェックが大変とか、文字認識の待ち時間が鬼のように長いとか、想像よりも遥かに苦行でした。
業者にお願いするという選択肢もあったのですが、予約待ちが凄くて忘却してしまいました。

Z80のニーモニックのリファレンスとか、MSXのI/Oポートのリファレンスとか、スキャンしないで処分しても良いような気もしますが、書籍の処分は不思議と抵抗があります。
また、Win32のAPIのリファレンスとか、JavaのAPIのリファレンスとか、電話帳級の紙の薄さとページ数を誇っていて、裁断する気も起きません。

所が、唐突にScanSnapの新機種をPFUさんからモニターとしてお借りする機会が回ってきました。
PCを高速な新機種に買い替えたら、残念なゲームが遊べるようになったという事は良く有る事なので、スキャナの性能が上がれば話が変わってくるかもしれません。

とりあえず、最近買ったRaspberry Piユーザガイドを読み取ってみました。

残念ながら、ScanSnap iX500には書籍読み取りのプリセットは無いので、設定から行いました。
ScanSnapがブレイクした理由を考えると、ちょっとどうかと思います。

  • 白紙ページを自動的に削除をオフ。これがオンだと枚数による簡易チェックが不可能になる。
  • 文字列の傾きの自動補正をオン。紙質によっては斜めに吸い込まれる事もあるので。
  • 文字認識を全ページにオン。Spotlightでウマーできる。
  • 継続読み取りオン。一回で全ページがトレーには乗らないし、カバーは紙のは大きさも違う。

悩ましいのはカラーモードで、表紙はカラーに、中身はカラーかグレーになって欲しい。
自動判別でかつ、白黒の禁止モードがあれば良いんですが……

一度にトレイに乗せられる枚数は以前と大差ありませんが、スキャンは冗談みたいに早いです。
最後にページ枚数をチェックして保存を押せば、長時間の文字認識が始まるハズ………始まらない。
不思議に思ってPDFを開いてみたら、既に文字認識が完了していました。
にわかに信じられません。

当時よりも高速なPCを使っていますが、これは想像していませんでした。

モニター期間中、一日一冊の裁断を続けられるか、試してみたいと思います。

カテゴリー:ハードウェア

PythonSQLMapperのMySQLdbへの依存を除去しました

PythonSQLMapperのMySQLdbへの依存を除去しました。
https://github.com/marvelph/PythonSQLMapper

現状、下記の三種類のデータベースモジュールをサポートしています。

また、データベースモジュールには適切に実装されたラッパーも利用できます。
PythonSQLMapperでコネクションプルールが必要な場合は、sqlalchemy.poolの利用を推奨します。
下記のようなコードで、コネクションプルールが有効になります。

import sqlalchemy.pool as pool
import MySQLdb

MySQLdb = pool.manage(MySQLdb)

mapper = SQLMapper.Mapper(driver=MySQLdb, host='127.0.0.1', db='db', user='user', passwd='passwd', charset='utf8')
カテゴリー:開発 タグ: , , ,

PythonSQLMapperを公開しました

iBATIS風味のSQLマッピング、PythonSQLMapperをリリースしました。
https://github.com/marvelph/PythonSQLMapper

現在メインのお仕事ではバックエンド「も」担当しているのですが、データベースのアクセスにSQLAlchemyを使っています。
迷った末の選定でしたが、正直失敗したと思っています。

例えばアトミックな更新を行いたいとすると、1エンティティをロック付きでフェッチして、値を変更してコミットします。
一定条件の複数レコードを同時更新したい場合は、複数エンティティをロック付きでフェッチして、ループで値を変更してコミットです。

生成したばかりのエンティティのオートインクリメント・プライムキーを他のエンティティに保存しようとすると、一旦コミットするか再フェッチしないと値が手に入りません。

複雑なクエリ条件でエンティティを引っ張ろうとすると、フィルタをメソッドのチェーンで表現する必要があるのですが、どうみてもSQLよりも難解になります。
その上、pythonのインタープリタでしか試せません。

バッチ処理などでループ中で利用すると、マネージドエンティティが激増して、猛烈に重くなったりします。

これらはO/Rマッピング全般の傾向ではあると思うんですが、コードが複雑になるだけで良い事が無いというのが実感です。
みんな、そんなにSQLが嫌いなのかと。

iBATISのようなツールも探しまわったのですが、良い物は見つかりませんでした。
そこでCocoaSQLMapperのpythonへの移植を考えていたのですが、新サービス立ち上げのチャンスが回って来たので、土日をつぶして「ガッ」と実装しました。
その後実際に新サービスの開発に使っているのですが、良い感じに使えているので公開する事にしました。

移植と言っても、重要な部分に差異があります。
まずCocoaSQLMapperはSQLite専用であるため、テーブルのフィールド側には「型」がありません。一方、Objective-Cのクラスのプロパティには「型」があります。
そのため、オブジェクトをパラメータとし渡す場合も、クラスを結果セットの入れ物として指定する場合も、Objective-C側の型情報を使ってSQLiteにアクセスする仕組みでした。

一方PythonSQLMapperですが、現状ターゲットにしているMySQLはテーブルのフィールドに型を持ちます。
またpythonのクラスの属性の型は変化できますし、結果セットの受け取り時などに生成前であれば、属性の名前も判りません。
そのため、型情報はデータベース側を当てにする事にしました。
この考え方はパラメータとしてオブジェクトを渡す場合は問題が無いのですが、リザルトタイプにクラスを指定して結果セットを受け取る場合が問題になります。
そこで、「結果セットとクラスのコンストラクタが整合すれば良い」という事にしました。

これは次のようなSQLの結果を、

SELECT name, age FROM person;

こんなクラスであれば受け取れるという事です。

class Person(object):
    def __init__(self, name, age):
        ...

いずれにしても、データベーススキーマを解析したりして、マッピングルールを何らかの方法で与えるという事はしないという考え方は変えていません。
エンティティに対する細工も不要で、特別な親クラスなども導入していません。
マネージドエンティティという考え方を、避けているという事です。

また使い勝手を考えて、パラメータにはdictも利用可能としました。
さらにリザルトタイプは省略が可能で、匿名クラスのオブジェクトに結果セットを属性として取り付けて返します。

dictと匿名クラスだけで使う事も可能という事になりますが、エンティティクラスにはメソッドが使えますから、多くのユースケースでは従来の使い方が有効だと思います。

当面の開発目標としては、次のような事を考えています。

  • PostgreSQLのサポート
  • コネクションプールの実装
  • Flask Extensionの提供

とりあえず、コネクションプールが最優先です。

カテゴリー:開発 タグ: , ,