<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title>楓 software</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/" />
   <link rel="self" type="application/atom+xml" href="http://www.kaede-software.com/atom.xml" />
   <id>tag:www.kaede-software.com,2012://1</id>
   <updated>2012-05-16T08:01:25Z</updated>
   
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.34</generator>

<entry>
   <title>Android 版のα1 リリース</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/05/android_1_1.html" />
   <id>tag:www.kaede-software.com,2012://1.1603</id>
   
   <published>2012-05-16T07:54:17Z</published>
   <updated>2012-05-16T08:01:25Z</updated>
   
   <summary>吉里吉里Java for Android Android で実装可能な機能があら...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p><a href="http://kaede-software.com/android/tvp/" target="_blank">吉里吉里Java for Android</a><br />
Android で実装可能な機能があらかた実装できたのでα版へ。<br />
α版とは言っても、今までのリリースとは大差ない。<br />
α版からさらにいくつかの最適化やバグフィックスを行ったらβ版にする予定。<br />
β版から実際にアプリに組み込んで apk に出来るようにリリースする。</p>

<p>動画関係はかなり制約が多い。<br />
レイヤーモード実装前程度の機能になっている。<br />
詳細は<a href="http://sourceforge.jp/projects/kirikirij/wiki/VideoOverlay" target="_blank">プロジェクト Wiki</a> の方にまとめている。<br />
完全なレイヤーモードは実現が困難だが、動画の前にレイヤーを表示する事は可能なので、レイヤーモードにすると動画の前にレイヤー群が表示されるようにしている。<br />
レイヤーモードの主な使い方は動画にメッセージレイヤーを重ねて動かすことだと思うので、そのような用途は何とか出来るはず。</p>

<p>サウンドもいろいろ制約があるが、ループチューナーを使用していないのであれば、制約は比較的少ない。<br />
ただ、サンプルデータ取得が出来ないので、口パクとかする時は現状困る。<br />
事前にデータを生成して音声の再生と同期出来るような形のものを実装しないといけない。</p>

<p>最適化は主に TJS2 のコンパイルの高速化と KAG パーサーの高速化、KAG バイナリ形式のサポートを行う予定。<br />
TJS2 のバイトコードだけでなく、KAG3 もバイナリにして読み込みを早くする。<br />
他にも細々としたところで最適化してもう少し起動を速くしたい。</p>]]>
      
   </content>
</entry>
<entry>
   <title>Android のメニュー</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/04/android_5.html" />
   <id>tag:www.kaede-software.com,2012://1.1602</id>
   
   <published>2012-04-30T09:17:11Z</published>
   <updated>2012-04-30T13:32:55Z</updated>
   
   <summary>Android 3.0 以降でメニューボタンでの操作が廃止され、ActionBa...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>Android 3.0 以降でメニューボタンでの操作が廃止され、ActionBar による実装が推奨されている。<br />
Android では互換性のため、AndroidManifest.xml で targetSdkVersion に Android 3.0 未満を指定すれば、画面下部にメニューボタンが追加される。<br />
タブレット等ハードウェアボタンを全く搭載しないのであれば、他のボタンと同列に並ぶのでいいのだが、そうでない場合メニューボタンだけが表示されてずいぶん見た目が不格好になる。<br />
Android 3.0 以降でメニューボタンなしでも操作出来るようにするためには、メニューなしでも操作出来た方が良い。<br />
また、Android のメニューは、2階層までとなっているので、吉里吉里2のメニュー設定をそのまま持ってこられるようにするには、標準機能では足りない。<br />
以上の理由により、Android 版ではメニューそのものを廃止してしまう事も考えたのだが、移植性も考え独自にメニューを実装する事にした。<br />
ただ、このメニューは非推奨 ( 問題なく機能するようには作っている )。<br />
当初標準のダイアログを使って実装する事を考えたが、チェックやラジオボタンの実装がやっかいなため、描画や操作は自前で実装してある。<br />
メニューは以下のような表示になる。</p>

<p><img src="http://www.kaede-software.com/krjava_menu_00.png" width="427" height="240" /><br />
メニューボタンを押すと表示され、タップで選べる。<br />
バックボタンで階層を戻れ、メニュートップの時はメニューを閉じる。<br />
表示中メニューボタンを押すと閉じる。<br />
メニューで下位の項目がある場合は「＞」が末尾に表示される。</p>

<p>画面に対して項目が大きいのは指で押す事を考慮しているため。<br />
これより小さいと少し押しづらい。<br />
高さが 50dip 以上になるようになっている (解像度に合わせたサイズになる) 。<br />
高さを 50dip で割った数が縦方向の項目数となる。<br />
割った時の余りは各項目に分散される (上の方の項目が 1px大きくなる可能性がある) 。<br />
幅は、その階層で表示されるメニューの文字の幅によって計算される。<br />
文字数が少ないと、次の画像のように横の項目数が増える。</p>

<p><img src="http://www.kaede-software.com/krjava_menu_01.png" width="427" height="240" /><br />
横方向の項目数は、その階層のメニューの最大幅で画面幅を割った数で計算される。<br />
1未満になる時は、1になる。<br />
1になった時で、文字が幅を超える時はそのメニュー文字列はそのメニューに入るように文字が削られ末尾に「…」が付与される。<br />
1画面内にメニューが入りきらない時はメニュー末尾に「▽次へ」が挿入され、そのメニューを押下する事ではみ出てメニュー項目を表示するメニュー表示に切り替わる。<br />
2ページ以降では、最初に「△前へ」が表示され、前のメニュー項目に戻れるようになっている。<br />
セパレータは非表示で、その項目自体ないものとして扱われる。<br />
チェックがある場合は以下のように表示される。</p>

<p><img src="http://www.kaede-software.com/krjava_menu_02.png" width="427" height="240" /><br />
ラジオボタンは次のように表示される。</p>

<p><img src="http://www.kaede-software.com/krjava_menu_03.png" width="427" height="240" /><br />
文字、背景、線の色はリソースの colors.xml で指定可能になっている。<br />
文字、背景は通常、押下、無効の3種類定義してある。</p>

<p>メニューボタンを搭載しない場合、画面下部にメニューを表示しないように AndroidManifest.xml の targetSdkVersion で API Level 11 以上を指定したときのことを考慮し、Window.showMenu() を追加する。<br />
これによってメニューボタンを押してメニュー表示した時と同じ動作をする。<br />
API Level 11 以上を指定し、メニューを使用する場合は、画面内にこのメソッドを呼び出すボタン等を配置しておかないとメニューでのみ実現している機能があるのなら、その機能を呼び出す事が出来なくなってしまうので注意する必要がある。</p>

<p>なお、矢印キーでの項目選択やEnterでの選択は現状実装されていない。</p>]]>
      
   </content>
</entry>
<entry>
   <title>気になる挙動を調べてみた</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/04/post_572.html" />
   <id>tag:www.kaede-software.com,2012://1.1601</id>
   
   <published>2012-04-26T13:57:43Z</published>
   <updated>2012-04-26T14:09:10Z</updated>
   
   <summary>tjs2では特定条件で判定からはずしたブロックのdeleteが実行されるらしい？...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里 その他の開発日誌" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p><a href="http://p-lux.net/?no=1337" target="_blank">tjs2では特定条件で判定からはずしたブロックのdeleteが実行されるらしい？</a> ここに記述されている内容が気になったので調べてみた。<br />
以下スクリプトと問題点を転記。</p>

<table bgcolor="#E2EBEF"><tr><td>

<p>function test()<br />
{<br />
　var lay = new Layer(kag, kag.fore.base);<br />
　var result;<br />
　if (false)<br />
　{<br />
　　dm("run");<br />
　　result = delete lay;<br />
　}<br />
　dm("■result:"+result);<br />
　dm("■lay:"+lay);<br />
}</p>

<p></td></tr></table></p>

<p>dm("■lay:"+lay); で、lay がないと言われて例外発生。</p>

<table bgcolor="#E2EBEF"><tr><td>

<p>function test()<br />
{<br />
　var lay = new Layer(kag, kag.fore.base);<br />
　if (false)<br />
　{<br />
　　var lay;<br />
　　delete lay;<br />
　}<br />
　dm("■lay:"+lay);<br />
}</p>

<p></td></tr></table></p>

<p>このように記述すると問題なく動作する。</p>

<table bgcolor="#E2EBEF"><tr><td>

<p>function test()<br />
{<br />
　if(false)<br />
　　var p = 0;<br />
　dm(p);<br />
}</p>

<p></td></tr></table></p>

<p>dm(p); での p の値が不定。</p>

<p>3個目の変数アクセスの方は比較的簡単。<br />
中かっこのない if 文はスコープをネストしないので、var で変数宣言したら上位のスコープと思えるスコープに変数が作られる。<br />
で、dm でアクセスした時、変数はあるが初期化されていないので、未初期化変数へのアクセスとなり、値は不定。</p>

<p>1個目の挙動は少しやっかい。<br />
バイトコードを出してみると、delete は通らないし、デバッガで追ってみても通らない ( そもそも delete のコードは出力されない ) 。<br />
例外が発生するのは、dm("■lay:"+lay); で lay へのアクセスが、proxy(this or global) のメンバ lay へアクセスしようとしてメンバが見付からないところ。<br />
なぜここでローカル変数へのアクセスではなく、メンバアクセスになっているか。<br />
ローカル変数に対する delete がどのようになっているかを調べると、処理はコンパイル時に行われていた。<br />
ローカル変数に対する delete のバイトコードを作るところで、ローカル変数の lay が削除されてしまうので、dm("■lay:"+lay); ではローカル変数の lay は消えているため、メンバアクセスになっている。<br />
そして、これはコンパイル時に行われるため、if 文は関係なく、単純に前にあるか後ろにあるかによって変数があったり、なくなったりする。</p>

<p>2個目がなぜ通るのかと言うと、上述の処理を見ればわかる。<br />
if 文のスコープ内にある lay 変数は削除されるが、それより外のスコープの lay は削除されず、ローカル変数へのアクセスとして解釈されて、期待通りの動作をするはず。<br />
これは実際に処理を追ってないのである程度推測。</p>

<p><br />
動作はいいとして、ローカル変数への delete はこのような仕様であると認識して使わないと意図しない記述をしてしまいそう。<br />
と言うか、ローカル変数を delete すること自体が問題の種か。<br />
まあ、ローカル変数を delete しようとした事はないが。<br />
中かっこのない if 文の方は、そんなことしないから気にする必要ないと思うけど。</p>]]>
      
   </content>
</entry>
<entry>
   <title>吉里吉里Java/KAG3 のメモリ消費量</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/04/javakag3.html" />
   <id>tag:www.kaede-software.com,2012://1.1600</id>
   
   <published>2012-04-11T08:13:30Z</published>
   <updated>2012-04-11T08:16:56Z</updated>
   
   <summary>吉里吉里Java の実際の使用量だが、吉里吉里Javaで KAG3 のバイトコー...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>吉里吉里Java の実際の使用量だが、吉里吉里Javaで KAG3 のバイトコードを読み込んで動作している段階で、Javaヒープは約10MB使われている。</p>

<p>SurfaceView のみで起動するだけでも、ネイティブヒープは約4.2MB必要。</p>

<p>トランジションや Layer.piledCopy を使用した時、そのベースとなったレイヤーと同サイズのキャッシュ領域が内部に作られる。<br />
キャッシュ領域は、一時的なもの( 設定によって毎回削除しないようにする事も可能 )ではあるが、キャッシュ領域が必要となる機能を使う場合、このサイズも考慮に入れておく必要がある。<br />
LayerManager はレイヤー合成に必要な領域を持つ。<br />
この領域は画像演算の分割処理の指定によってサイズは変わるが、現状吉里吉里Javaでは画像演算の分割処理をなしにしているので、プライマリレイヤーと同じサイズ確保される事になる( レイヤー合成は画像演算の分割処理を考慮した作りとなっているが、現状トランジションはこの辺り考慮していないため )。<br />
後、プライマリレイヤー1枚は最低必要となるだろうから、オフスクリーン、キャッシュ、合成領域、プライマリの4枚分最低限必要となる(トランジションと Layer.piledCopy を使わないのであれば、キャッシュ領域は不要)。</p>

<p>800x480 で 32bitカラーで計算すると 800x480x4x4 = 約6MB</p>

<p>ここまで合計すると約20.2MBは必要になる。<br />
アプリケーションヒープが24MBの機種で動作させるのは KAG3 を使わなくても相当きついことがわかってくる。<br />
KAG3 では、さらに最低でもヒストリーレイヤー、プライマリーレイヤーの裏 で約3MBは必要になる。<br />
これで23MB。<br />
そのままでは立ち絵やメッセージを出したらメモリが足りなくなる可能性が濃厚。<br />
追加した purgeImage で普段は必要のない ヒストリーレイヤーと裏にあるレイヤーの分を解放しておけば、この分は必要なくなる(使用時は必要になるので、その時の検討は必要)。</p>

<p>トランジションを使わないようにすれば、キャッシュ領域が作られないので、その分使用量を浮かせられる。<br />
黒一色のレイヤーにα値を変化させながら合成すれば、フェードアウト/インするトランジションが出来るので、キャッシュ領域を使わないトランジションが出来る( base に画像、その上のレイヤーに黒一色でα値を変化させるレイヤーを置く形。遅延確保によって単一色レイヤーをメモリ確保せずに実現できる )。<br />
また、完全に画面が消えた時に、バックで表に画像を読み込むことになるので裏面も不要になる。</p>

<p>メッセージレイヤーは、そのサイズ分と文字描画用のレイヤーがメッセージレイヤーの幅+8 x 高さ+8 分使われる。<br />
また、リンク等のハイライトでメッセージレイヤー幅 x 文字高さが使われる。<br />
このため無駄なメッセージレイヤーは出来るだけ作らないようにし、初期サイズも出来るだけ小さくしておいた方が使用メモリ量は少なくて済む。<br />
メッセージレイヤーにフレーム画像を使わないようにして、purgeImage して単一色で塗ればメッセージレイヤーのベース部分のメモリが浮かせられる。</p>

<p>この辺りの工夫を入れる事で、見栄えは少し劣るが 24MB で動作させることも不可能ではなくなるはず。<br />
3.0 以降は largeHeap を使って PC と遜色ない作りにして、それ未満は少メモリ版とする対応もありかもしれない。<br />
数年で 4.0 が普及する事を見込んで、largeHeap 使う前提で作るという手もあるが。</p>]]>
      
   </content>
</entry>
<entry>
   <title>遅延確保と明示的解放</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/04/post_571.html" />
   <id>tag:www.kaede-software.com,2012://1.1599</id>
   
   <published>2012-04-06T14:46:01Z</published>
   <updated>2012-04-06T14:48:36Z</updated>
   
   <summary>使用メモリを少しでも節約できるように Android 版にいくつか機能を追加した...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>使用メモリを少しでも節約できるように Android 版にいくつか機能を追加した。</p>

<p>一つは遅延確保で、実際にそのレイヤーが描画される時、もしくは画像が読み込まれた時まで、メモリを確保しない。<br />
オリジナルでは、setImageSize 等されると、その時点でそのサイズ分のメモリが確保されるが、Android ではこの時にそのレイヤーでまだメモリ確保されていないのであれば、この時点ではまだメモリを確保しない。<br />
また、描画時も未確保のレイヤーを確保済みのレイヤーに描画する場合、単一色で塗りつぶす処理を行い、メモリ確保は行わない。<br />
一種のシェイプ、もしくはカラードポリゴンのように扱われる。<br />
ただ、状況によってはメモリ確保されるケースもある。<br />
逆に描画される側の場合は必要なので、その時点でメモリ確保される。<br />
未確保のレイヤーの全体を fill した場合、未確保のままで色を指定できる。<br />
つまり、未確保のレイヤーはサイズと色を持った矩形のように扱われる。</p>

<p>レイヤーに purgeImage というメソッドを追加して、保持している画像のメモリを明示的に解放する処理を追加した。<br />
KAG3 にある freeimage は、レイヤーと画像サイズを 32x32 に縮小するが、ピクセルデータが完全に未使用になるわけではない。<br />
32x32 であれば、4KB 程度なのであまり大きくはないが、なくせるのならなくせた方がいい。<br />
また、purgeImage はピクセルデータは解放するが、画像サイズは維持する。<br />
ただ、吉里吉里2 はCopy-On-Writeで画像を共有しているケースがあるので、共有されている場合はピクセルデータは解放しない(すると他で壊れる)。<br />
と書いたが、purgeImage が呼ばれた時に明示的に共有解除してしまった方が良いかもしれないので検討する。</p>

<p>レイヤーを非表示にした時に、内部で purgeImage をコールして、非表示にしたレイヤーのピクセルデータを破棄してしまうようにしたが、これは好ましくない状況もあると思うので、オプションで切り替えられるようにしようと思っている。</p>

<p><br />
互換性を気にしないのであれば、複数の形状のシェイプや画像のタイリング等を加えれば、使用可能な状況ではメモリ使用量を削減できるが、UI やメッセージレイヤーなど結構限定されるので、無理をしていびつな形で入れるのは避けることに。</p>]]>
      
   </content>
</entry>
<entry>
   <title>View 周りのメモリ使用量削減検討</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/04/view.html" />
   <id>tag:www.kaede-software.com,2012://1.1598</id>
   
   <published>2012-04-04T15:57:29Z</published>
   <updated>2012-04-04T16:01:53Z</updated>
   
   <summary>View 周りでどれくらい変わるのか確認してみた。 Xperia arc 854...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>View 周りでどれくらい変わるのか確認してみた。<br />
Xperia arc 854x480 で確認したところ――<br />
SurfaceView のみの場合、Java ヒープに約2.7MB、ネイティブヒープに約4.2MB と約7MB。<br />
GLSurfaceView でそのまま設定した場合、Java ヒープに約2.7MB、ネイティブヒープに約4.8MB と約7.5MB。<br />
GLSurfaceView で GLSurfaceView.setEGLConfigChooser( 8,8,8,0,0,0 ); と GLSurfaceView.Renderer を実装したクラスを GLSurfaceView に設定する前に指定して、ステンシルやデプスバッファを使わないようにすれば、SurfaceView より少し使用メモリが多い程度でほとんど同じサイズになった。<br />
約0.5MBはデプスバッファだろうか。詳しくは調べていない。<br />
GLSurfaceViewを使えば、バックバッファ等 VRAM に配置されて使用量が減るかとも思ったが、そんな事はなかった。<br />
ImageView (640x480の画像を指定) のみの場合、Java ヒープに約2.7MB、ネイティブヒープに約5.4MB と約8.1MB</p>

<p>SurfaceView を使うのが一番使用メモリ量が少なそうだ。</p>

<p>これらのサイズは画面サイズが異なると当然使用量に変化が出ると考えられる。<br />
実際、EeePad transformer TF101 (1280x800) では、SurfaceView のみの起動で 約9MB使われていた。</p>

<p>検索したところ Xperia Arc の VRAM はメインメモリと共有のようだ。<br />
GLSurfaceView にして、テクスチャに転送しても使用メモリ量が減らなかったり、GLSurfaceView でも差がないのはこの辺りが原因だろうか？ 詳しくは調べていないが、使用メモリ量が減らない機種があるのなら、GLSurfaceView に対応してもあまり意味はなさそうだ。<br />
将来的に選択可能になっていても良いとは思うが。</p>

<p><br />
吉里吉里Java では、オフスクリーンバッファを使用している。<br />
SurfaceView は、ダブルバッファリングを使って描画しているので、フリップすると1フレーム前の画像が入っているため差分描画を行う吉里吉里Java(オリジナルと同じ)だとうまく描画出来ない。<br />
Android 側のソースをざっと見たところ SurfaceHolder.lockCanvas( Rect dirty ) で、dirty を指定すると、フロントバッファから dirty 以外の領域をコピーして、Canvas の clipRect に dirty が指定された Canvas が返って来る。<br />
Surface.unlockCanvas でロック解除するとフリップを行わずにロック解除されるようだから、差分描画の1回目に dirty rect を指定しフロントバッファから変更しない部分をコピーして、差分描画し2回目以降は、dirty rect に null 指定して全体を更新する指定してコピーしないようにすることでオフスクリーンバッファを使わないように出来なくはない。<br />
( 実際にこのような挙動になるのかどうかは動作させて確認をしたわけではないので、もしかしたら違う挙動かも知れない )<br />
ただ、吉里吉里Java でゲームのサイズと画面サイズが異なり、拡大縮小が必要となった時差分描画で誤差が出て隙間が出来てしまう可能性がある。<br />
オフスクリーンバッファで画像を保持しておいた方が良い局面もあるので、結局オフスクリーンバッファを使用するのが無難な実装だと考えられる。</p>

<p>SurfaceView でオフスクリーンバッファを使うと言う、元々の実装がやはり良さそうと判断した。<br />
最終描画周りで使用メモリ量を削減できないかいろいろと検討したが、この辺り削るのは難しそうだ。</p>]]>
      
   </content>
</entry>
<entry>
   <title>メモリと OutOfMemoryError</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/04/_outofmemoryerr.html" />
   <id>tag:www.kaede-software.com,2012://1.1597</id>
   
   <published>2012-04-03T15:45:01Z</published>
   <updated>2012-04-03T15:45:55Z</updated>
   
   <summary>Androidメモ メモリ このページが Android でのメモリについてわか...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="Android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p><a href="http://www.saturn.dti.ne.jp/npaka/android/memory/index.html" target="_blank">Androidメモ メモリ</a> このページが Android でのメモリについてわかりやすくまとまっている。</p>

<p>ネイティブヒープ + Java ヒープ の合計サイズというのは、Debug.getNativeHeapAllocatedSize() + (runtime.totalMemory() - runtime.freeMemory()) で計算できるサイズのようだ。<br />
この合計値がアプリケーションヒープの最大値を超えた時 OutOfMemoryError 例外が発生する。<br />
アプリケーションヒープの最大値は ActivityManager.getMemoryClass() で得られるもののようだが、runtime.maxMemory() と同じ (単位は異なる) ようなので、runtime.maxMemory() で計算できる。<br />
ActivityManager の方は Context が必要なので、Runtime で得られる方がいろいろと扱いやすい。<br />
つまり、擬似コードで書くのなら以下のような感じ。</p>

<p>Runtime runtime = Runtime.getRuntime();<br />
if( (Debug.getNativeHeapAllocatedSize() + (runtime.totalMemory() - runtime.freeMemory())) &gt; runtime.maxMemory() ) {<br />
　throw new OutOfMemoryError();<br />
}</p>

<p>この辺りがわかるとメモリ限界付近を調査しやすくなる。</p>

<p>Android 3.0 ( APIレベル11 ) から AndroidManifest.xml の application に android:largeHeap="true" を加える事でアプリケーションで使用するHeapサイズを拡大できるが、このサイズは 256MB 辺りのようだ。<br />
上述のページや他のページ、手持ちの TF101 で調べたところ GalaxyNexus、Motorola Xoom(MZ600)、EeePad transformer TF101 で 256MB ということなので、256MB は使えるのではないかと思われる。<br />
調べた範囲では、最低どの程度なのかという仕様は見あたらなかった。</p>

<p>なお、所有端末やネットで調べた範囲だと、アプリケーションヒープは以下のサイズのようだ ( largeHeap指定がない場合 ) 。<br />
Xperia 24MB<br />
Galaxy TAB 48MB<br />
Xperia arc 32MB<br />
IS03 40MB<br />
EeePad transformer TF101 48MB<br />
Galaxy S2 70MB<br />
MEDIAS N-06C 30MB<br />
NEXUS ONE 24MB<br />
NEXUS S 32MB<br />
ATRIX 4G 32MB<br />
IS01 24MB<br />
Optimus chat (L-04C) 24MB</p>]]>
      
   </content>
</entry>
<entry>
   <title>とりあえずソースコード等を貼り付けるサービス</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/03/post_570.html" />
   <id>tag:www.kaede-software.com,2012://1.1596</id>
   
   <published>2012-03-25T06:38:30Z</published>
   <updated>2012-03-25T06:42:02Z</updated>
   
   <summary>Pastie よく忘れてしまうのでメモしておく。 twitter などでソースコ...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="日常の備忘録" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p><a href="http://pastie.org/pastes/new" target="_blank">Pastie</a><br />
よく忘れてしまうのでメモしておく。<br />
twitter などでソースコードの断片やログなどを貼って知らせたり、例を見せたりしたい時に便利に使える。<br />
テキストを貼り付けると固有のURLが生成されるので、それをツイートするだけ。<br />
ソースコードの予約語のハイライト等も行ってくれるので見やすい。</p>]]>
      
   </content>
</entry>
<entry>
   <title>SD インストールに対応する時の注意点</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/03/sd.html" />
   <id>tag:www.kaede-software.com,2012://1.1595</id>
   
   <published>2012-03-23T09:44:50Z</published>
   <updated>2012-03-23T12:43:44Z</updated>
   
   <summary>SD インストールに対応する場合、AndroidManifest.xml の m...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="Android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>SD インストールに対応する場合、AndroidManifest.xml の manifest タグの属性に android:installLocation="auto" か android:installLocation="preferExternal" を追加する。<br />
auto はどちらか自動的に判断されてインストールされる。<br />
preferExternal は、SD優先だけど、SDがいっぱいなどの時本体側にインストールされる。<br />
このどちらかを指定した場合、ユーザーが本体とSDでアプリを移動できる。</p>

<p>使用する Project Build Target を Android 2.2 API Level 8 以上にする。<br />
古いバージョンでも動作させたい場合は、AndroidManifest.xml に &lt;uses-sdk android:minSdkVersion="4" /&gt; 等指定する。<br />
また、使用している API がここで指定したもの以下であるようにする。<br />
Project Build Target で新しいバージョンを指定すると新しいAPIを使用していてもビルド自体は問題なく通るが、古いバージョンの Android マシンで動かした時に落ちるので注意が必要。</p>

<p>デベロッパーコンソールでアプリをアップロードする時、公開設定のオプションのコピー防止をオフにする。<br />
ここをオンにしているとSDにインストール出来ない。</p>

<p>ある程度サイズが大きいアプリはアンインストールされやすいが、SDインストールに対応していると消されづらいようなので、対応して問題なアプリは対応しておいた方が良さそう。<br />
サイズが大きいと言っても5MBでも大きいと思われたりするから、積極的に対応した方がいい。</p>]]>
      
   </content>
</entry>
<entry>
   <title>getPixels と copyPixelsToBuffer</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/03/getpixels_copyp.html" />
   <id>tag:www.kaede-software.com,2012://1.1594</id>
   
   <published>2012-03-14T15:59:25Z</published>
   <updated>2012-03-14T16:00:06Z</updated>
   
   <summary>Bitmap.getPixels でピクセル情報を取得し、Bitmap.setP...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="Android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>Bitmap.getPixels でピクセル情報を取得し、Bitmap.setPixels で書き戻すのと、Bitmap.copyPixelsToBuffer でピクセル情報を取得し、Bitmap.copyPixelsFromBuffer で書き戻すのはどちらが早いか計測した。<br />
Xperia arc で 800x600 32bitカラーのBitmap で計測すると、<br />
1. Bitmap.getPixels/setPixels は、33msec 程度。<br />
2. Bitmap.copyPixelsToBuffer/copyPixelsFromBuffer (array) は、6～7msec程度。<br />
3. Bitmap.copyPixelsToBuffer/copyPixelsFromBuffer (direct) は、11～29msec程度。<br />
array は、int[] pixels = new int[w*h]; IntBuffer buff = IntBuffer.wrap(pixels); としたもの。<br />
direct は、ByteBuffer b = ByteBuffer.allocateDirect(w*h*4); IntBuffer buff = b.asIntBuffer(); としたもの。<br />
array を wrap した、IntBuffer で、copyPixelsToBuffer を使うのが一番早い様子。<br />
ByteBuffer.allocate を使ってもたぶん同じ結果になると思われる。</p>

<p>取得後、各ピクセルにグレースケール化処理を行い、書き戻した場合はそれぞれ以下のようになった。<br />
1. 56～59msec ( 343～674msec )<br />
2. 29～34msec ( 280～321msec )<br />
3. 1107～1248msec ( 1718～2143msec )<br />
括弧内の数値は初回で、それ以外は２回目以降の数値。<br />
JIT 等の効果により、２回目以降は速度が上がっていると思われる。<br />
3 が異様に遅いのは、IntBuffer.get/put によってピクセル値の取得と書き戻しを行っているせいだと思われる。<br />
他は、配列で処理している。</p>

<p>array を wrap した Buffer で取得設定し、array で処理するのが一番か。</p>

<p>Canvas.drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, Paint paint) を使って、書き戻した場合はどうかも計測した。<br />
1. Bitmap.copyPixelsFromBuffer 3 ～ 4msec<br />
2. Canvas.drawBitmap 31 ～ 33msec<br />
この場合も Bitmap.copyPixelsFromBuffer が大幅に早い様子。</p>

<p>自前でピクセル処理する場合、Bitmap.copyPixelsToBuffer/copyPixelsFromBuffer (array) を使うのが良さそう。</p>]]>
      
   </content>
</entry>
<entry>
   <title>Android での動画再生</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/03/android_4.html" />
   <id>tag:www.kaede-software.com,2012://1.1593</id>
   
   <published>2012-03-02T07:25:11Z</published>
   <updated>2012-03-02T07:30:03Z</updated>
   
   <summary>Android で共通にサポートされている動画形式は、このページに書かれている。...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>Android で共通にサポートされている動画形式は、<a href="http://developer.android.com/intl/ja/guide/appendix/media-formats.html" target="_blank">このページ</a>に書かれている。<br />
MPEG-4系とVP8 ( Android 2.3.3以降 ) となっている。<br />
端末によっては WMV もサポートされているが、全端末でサポートされているわけではない。</p>

<p>H.264 のライセンスは、<a href="http://av.watch.impress.co.jp/docs/20031118/mpegla.htm" target="_blank">MPEG LA、H.264の共同ライセンス体系を発表－エンコーダ/デコーダは0.20ドル。無料放送は1万ドル/年 </a> では、「12分以下のものにはライセンス徴収を行なわない。」というのと、「搭載製品の総数が年間10万個/以下の場合は、ライセンス料を支払う必要は無く」という記述があるが、「初期のライセンス期間は2010年の12月31日まで」となっていて、その後どのようになったのかはっきりしない。<br />
無料のインターネット配信の場合は、2015年まで無料で、その後さらに永久的に無料という発表はあったが、その他は不明。<br />
5年ごとにライセンスは見直されるらしいが……<br />
「デコーダ搭載製品」に当たるのかどうかも不明。</p>

<p>VP8 ( WebM ) は、現時点ではライセンス料は発生していないが、Android 2.3.3以降となっているので、それ以前のバージョンでの再生に問題が残る。</p>

<p>Android 版では、初回リリースは OS の機能をそのまま使う予定なので、これらの問題はそのまま発生する。<br />
動画についてのライセンスについてはよく調べて対処してもらう必要がある。<br />
NDK で <a href="http://wss.co.uk/pinknoise/theorarm/" target="_blank">Theorarm</a> を使って Theroa を再生すると言う手もあるが、NDK を使うとそれはそれで再生できない機種が出る問題がある。</p>

<p>ちなみに、VC-1 ( WMV ) も、ライセンス料が発生しうる。<br />
WMV3 ( WMV9 ) は、グレー。<br />
昔、<a href="http://www.kaede-software.com/2008/01/wmv_9.html" target="_blank">WMV のライセンスまとめ</a> にまとめている。</p>]]>
      
   </content>
</entry>
<entry>
   <title>メッシュ</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/02/post_569.html" />
   <id>tag:www.kaede-software.com,2012://1.1592</id>
   
   <published>2012-02-29T14:32:03Z</published>
   <updated>2012-02-29T14:32:59Z</updated>
   
   <summary>Canvas.drawBitmapMesh がメッシュワープの用途でどれくらい使...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="Android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>Canvas.drawBitmapMesh がメッシュワープの用途でどれくらい使えるか少し見てみた。<br />
タッチしたところにぎゅっと収縮するようなものをテスト用に作った。<br />
<a href="http://kaede-software.com/android/MeshTest.apk">MeshTest.apk</a><br />
Android でインストールして実行できる。<br />
20x36分割して、Canvas.drawBitmapMesh で描画している。</p>

<p>FPS を見てみると……</p>

<p>初代Xperia Android 1.6 - 6fps ～ 4fps<br />
初代Xperia Android 2.1 - 23fps ～ 16fps<br />
IS03 - 23fps ～ 16fps<br />
Xperia arc - 27fps ～ 16fps<br />
Galaxy tab - 21fps ～ 16fps<br />
Eee Pad Transformer TF101 - 27fps ～ 16fps</p>

<p>Android 1.6 の Xperia は異様に遅いが、それ以外は 20FPS以上出ている。<br />
Paint.setFilterBitmap を true にしているが、これを false にすると数FPS上がる。<br />
分割数を減らしたり、面積を減らせばもっと早くなる。<br />
そこそこ使えそうな速度で動くようだ。</p>]]>
      
   </content>
</entry>
<entry>
   <title>多言語対応で出る Lint のエラー</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/02/_lint.html" />
   <id>tag:www.kaede-software.com,2012://1.1591</id>
   
   <published>2012-02-28T13:00:48Z</published>
   <updated>2012-02-28T13:00:58Z</updated>
   
   <summary>strings.xml や array.xml で、values と value...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="Android" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>strings.xml や array.xml で、values と values-ja 等複数言語対応用のリソースを置いた時、文字列リソースが片方にしかない時 Lint がエラーを出してパッケージ化出来ない。<br />
数値や英語でも意味が通る物など、別に日本語リソースを用意する必要のないものもある。<br />
これらのリソースには「translatable="false"」をつけてやる事で、別言語のリソースを用意していなくてもエラーにならない。<br />
&lt;string name="text_resource" translatable="false"&gt; と言うように追加する。</p>]]>
      
   </content>
</entry>
<entry>
   <title>レンダリング済みフォント</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/02/post_568.html" />
   <id>tag:www.kaede-software.com,2012://1.1590</id>
   
   <published>2012-02-02T14:35:20Z</published>
   <updated>2012-02-02T14:35:49Z</updated>
   
   <summary>レンダリング済みフォントのサポートをどうするか悩んでいたけど対応した。 Java...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>レンダリング済みフォントのサポートをどうするか悩んでいたけど対応した。<br />
Java では縦書きフォントが読めない。<br />
Android も調べた範囲では読めない。<br />
後、フォントを共通化する為にもレンダリング済みフォントは有用と言うことで対応した。</p>

<p>FreeType の Java 版があるか探したが見付からず。<br />
自力で FreeType を Java に移植することも考えたが、かなり労力がかかりそう。<br />
FreeType があれば、共通化や縦書きも出来るようになると思うが、対応は大変。<br />
と言うことで、自前でのフォント関係の処理をすることは諦めた。</p>

<p><br />
少メモリ環境下では、ディスク容量やメモリ容量節約のため使用する文字のフォントデータのみ出力したいが、オリジナルのレンダリング済みフォント作成ツールでは指定した文字のフォントデータのみ出力する機能はない。<br />
ツールのソースを読んでもそれっぽい機能はない。<br />
機能追加するのはそれほど難しくなさそう。<br />
作るかどうか悩んでいたら、既にあることを教えてもらった。</p>

<p><a href="http://ruriko.denpa.org/201003b.html" target="_blank">吉里吉里レンダリング済みフォント作成ツール改</a></p>]]>
      
   </content>
</entry>
<entry>
   <title>Layer.affine 系</title>
   <link rel="alternate" type="text/html" href="http://www.kaede-software.com/2012/01/layeraffine.html" />
   <id>tag:www.kaede-software.com,2012://1.1589</id>
   
   <published>2012-01-28T08:28:43Z</published>
   <updated>2012-01-28T08:32:51Z</updated>
   
   <summary>吉里吉里2の Layer.affine 系のメソッドは、matrix 指定と頂点...</summary>
   <author>
      <name>Takenori</name>
      <uri>http://www.kaede-software.com/</uri>
   </author>
         <category term="吉里吉里Java" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="ja" xml:base="http://www.kaede-software.com/">
      <![CDATA[<p>吉里吉里2の Layer.affine 系のメソッドは、matrix 指定と頂点指定のどちらかを選べる。<br />
吉里吉里2では、matrix で指定された場合、頂点に変換して、頂点を使って描画する。</p>

<p>吉里吉里Java の場合は、常に matrix を指定して描画する。<br />
そのため頂点指定の場合は、頂点から matrix を割り出す必要がある。<br />
matrix から頂点を求めるのは簡単 (普通の行列演算) だけど、逆は手間がかかる。<br />
最初は幾何学的に求められるかと思ったが、いろいろ検討するも難しい。<br />
と言うことで方程式を解くことに。<br />
吉里吉里2では3つの頂点が与えられるので、2つの連立三元一次方程式を作ることができる。<br />
これは matrix から頂点を求める式そのまま。</p>

<p>連立三元一次方程式1<br />
x0 = (-0.5)*a + (-0.5)*c + tx<br />
x1 = (width-0.5)*a + (-0.5)*c + tx<br />
x2 = (-0.5)*a + (height-0.5)*c + tx</p>

<p>連立三元一次方程式2<br />
y0 = (-0.5)*b + (-0.5)*d + ty<br />
y1 = (width-0.5)*b + (-0.5)*d + ty<br />
y2 = (-0.5)*b + (height-0.5)*d + ty</p>

<p>このうち a, b, c, d, tx, ty が求める値。<br />
それ以外は事前にわかっている。<br />
連立方程式は、ガウス=ザイデル法やガウスの消去法等いくつか数値演算で求める方法がある。<br />
効率を考えてガウス=ザイデル法を用いて上式を解くようにしたら、解が収束せずに求められず、ガウスの消去法を用いることにした。<br />
期待通り matrix が求められている。</p>

<p>ただ、オリジナルとは異なり頂点を与える方が方程式を求める分効率が悪い。<br />
直後の描画処理に比べたらそれほどでもないかも知れないが。</p>]]>
      
   </content>
</entry>

</feed>

