JellyBeanの新しいAPIを試してみる(MediaCodecと外部ディスプレイ) #AndroidAdvent2012 16日目裏
このエントリは [twitter:@ytRino] による、 Android Advent Calendar (#AndroidAdvent2012) の16日目 裏 のエントリです。
MediaCodex API
API16でなんとメディアを自分でエンコードしたデコードしたりできるらしいぞーと聞いて、これは気になると思い調べてみました。
特にエンコードは個人的に夢が広がりんぐなのでやってみたくなりました。
まずはmp3をデコードしながら再生
GoogleIOのビデオSessions | Google I/O 2012 | Google Developers
喋ってる人がどうみてDave Burkeさんの写真と別人ですが何があったんでしょうか
基本的にはMediaCodecに書いてある手順でやれば行けます。
InputBufferに元となる音データをqueueしていくと変換されたデータがOuputBufferからdequeueで取れるという流れです。
MediaCodec | Android Developers
MediaCodec codec = MediaCodec.createDecoderByType(type); codec.configure(format, ...); codec.start(); ByteBuffer[] inputBuffers = codec.getInputBuffers(); ByteBuffer[] outputBuffers = codec.getOutputBuffers(); for (;;) { int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs); if (inputBufferIndex >= 0) { // fill inputBuffers[inputBufferIndex] with valid data ... codec.queueInputBuffer(inputBufferIndex, ...); } int outputBufferIndex = codec.dequeueOutputBuffer(timeoutUs); if (outputBufferIndex >= 0) { // outputBuffer is ready to be processed or rendered. ... codec.releaseOutputBuffer(outputBufferIndex, ...); } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { outputBuffers = codec.getOutputBuffers(); } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { // Subsequent data will conform to new format. MediaFormat format = codec.getOutputFormat(); ... } } codec.stop(); codec.release(); codec = null;
ctsのとかも参考に割りと簡単にmp3をデコードできました。
ソースをMediaExtractorに突っ込む -> MediaCodecに情報を渡す -> どんどんデータを流す -> どんどんデコードされたデータが出てくる -> 再生
こんな感じ
エンコードもこの調子で楽々! と行きたかったのですが…
flacにエンコードしてみる
デコードの時はデコーダ用のMediaFormatはextractorからとれましたが、エンコードはそうはいかないので出力側のMediaFormatは入力側のMediaFormatをもとに自分で作ることにします。
String mime = "audio/flac"; MediaFormat outFormat = MediaFormat.createAudioFormat(mime, inFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE), inFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT)); // flac用のkeyがあったのでつけてみた outFormat.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, 0); final MediaCodec codec = MediaCodec.createEncoderByType(mime); codec.configure(outFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE /* encoder flag */); codec.start(); extractor.selectTrack(0);
がこれでデコードと同じようにエンコードしようと、WAVファイルを入力としたMediaExtractor#readSampleData()したところ、
IllegalArgumentExceptionで落ちました。謎に思いつつも入力をmp3にしたところ、ファイル自体はエラーなく無事にできました。
てっきりエンコーダにはPCMを突っ込むものだと思ってたのですがそれ以前のエラーに…
ひとまずPC側にpullして(端末がflacのデコードに対応してないので)みたものの再生できず…
入力がmp3だから?
用意したwavが悪いのか?
ともかくwavのextractorがエラーになってしまうので、FileInputStreamで自前でバイナリを読み込んでqueueしてみる方法も試してみましたが、mp3のデコードはなんとかできそうな感じではあるもののやはりエンコードがびみょい。
残念。
データの中身を見てみよう
ここでmp3->wav(pcm)で、流れていくデータを覗いてみると、デコードされて出てきたデータにはWAVヘッダがなく(ってPCMそのままAudioTrackなどに流して再生できるという点からは当たり前か)音データ本体のみのようです。
とりあえずエンコードされたように見えるmp3->flacのパターンではflacのフレーム(ヘッダ+データ)らしきものが出てきてるので、(果たしてmp3を入力するのはどうなんだということを抜きにして)やはりflacヘッダはないもののエンコード自体は一応できてることになります。というわけでフレーム本体しかないのでファイルに書き出しても正しく認識されないのも当然です。
ちなみに入力のmp3もフレーム区切りでextractorから流れてくるぽいです。
FLAC - format たとえば流れてきた各outputBufferの先頭(=フレームの先頭)がff f8 39という並びで始まるとき、sample rateは44.1kHzであるみたいな。
ためしに
MediaFormat format = MediaFormat.createAudioFormat(mime, 44100, 1);
の44100を22050にしてみると、ff f8 36で出力されるようになったので多分あってるはずです。
エンコーダから流れてきたデータにヘッダつければいける?
とりあえずわからないところを飛ばしつつ最低限のヘッダをつける
//flacのヘッダを付加したい public void addHeader(MediaFormat format) throws IOException { FileInputStream in; FileOutputStream out; ... // marker String marker = "fLaC"; out.write(marker.getBytes()); // meta data byte[] metaHeader; byte[] metaData; metaHeader = new byte[] { 0x1 << 3 | 0, 0, 0, 34 // last metadata flag and stream-info header }; // stream info のデータを作る metaData = metaDataStreamInfo(format); dump(metaData); out.write(metaHeader); out.write(metaData); byte[] buf = new byte[1024]; int r; while ((r = in.read(buf)) > 0) { out.write(buf, 0, r); } in.close(); out.close(); } private byte[] metaDataStreamInfo(MediaFormat format) { Log.v(TAG, format.toString()); int hz = format.getInteger(MediaFormat.KEY_SAMPLE_RATE); int ch = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT) - 1; /* ch -1 */ int total = 0; /* 0->unknownのようだが… */ int bit = 16 - 1; /* 16bits per sample -1 */ return new byte[] { 0x01, 0x00, /* min block size (?) */ 0x10, 0x00, /* max block size (?) */ 0x00, 0x00, 0x01, /* min frame size, unknown */ 0x10, 0x00, 0x00, /* max frame size, unknown */ (byte) ((hz >> 12) & 0xff), /* sample rate (hz) 20bits */ (byte) ((hz >> 4) & 0xff), (byte) (((hz << 4) & 0xff) /* 4bits */| ((ch << 1) & 0xff) /* 3bits */| ((bit >> 4) & 0xff) /* 1bit */), (byte) ((bit << 4) & 0xff | 0), /* bits(low 4bit) + total samples in stream(first 4bit...?) */ (byte) ((total >> 24) & 0xff), (byte) ((total >> 16) & 0xff), (byte) ((total >> 8) & 0xff), (byte) (total & 0xff), /* 32bit, 0 -> unknown */ 0, 0, 0, 0, 0, 0, 0, 0, /* md5 signature of unencoded audio data */ 0, 0, 0, 0, 0, 0, 0, 0, }; }
やけくそです。全然埋まってないし。 しかしこれが正しいのか確認する手段もないのでひとまず実行。
バイナリ確認してそれっぽい形になっているがやっぱり再生できずタイムアップ
total sizeやmd5をちゃんとしないとダメなのかもっと他の原因なのか…
flacの情報をさらに探していたところ、flacのgitに、wavのヘッダからトータルサイズを計算しているところがありました。wavのヘッダから読み取った値をそのまま4分の1してるだけのようだけど…
(16bit 2ch固定だから変える必要あるかも)しかしこのあとさらにflac側で処理をしていなければ自前ヘッダのサイズにも使えそう?
Xiph.org - flac.git/blob - examples/c/encode/file/main.c
82 total_samples = (((((((unsigned)buffer[43] << 8) | buffer[42]) << 8) | buffer[41]) << 8) | buffer[40]) / 4;
しかしここでタイムアップです。あれですね、もうちょっと知識がないと辛いですね。
…ていうかflacエンコードっている? いる?
せめてmp3欲しいよね、うん。 だめなのわかってるけどさ!
ああ、jniでやれってことですよね!!
一応作ったものを公開しておきます… 整理されてないですが。 GitHub - ytRino/MediaCodecSample: MediaCodecAPIをつかってエンコードしてみたかった...
このアプリではついでにMediaCodecListを使って対応しているエンコーダ・デコーダ一覧を表示させています。
MediaCodec etc 参考サイトまとめ
Sessions | Google I/O 2012 | Google Developers
Android MediaCodec “Decoded” | David Marques' Blog
oesf.biz - このウェブサイトは販売用です! - oesf リソースおよび情報
https://android-review.googlesource.com/#/c/43410/1/tests/tests/media/src/android/media/cts/DecoderTest.java
いならの住処: [Android]MediaCodecAPIを使って動画の音声のみを再生
FLAC - format
Xiph.org - flac.git/blob - examples/c/encode/file/main.c
http://www.kk.iij4u.or.jp/~kondo/wave/
MediaCodec | Android Developers
MediaFormat | Android Developers
MediaExtractor | Android Developers
MediaCodecList | Android Developers
以上です。
Presentation(とmiracast(Wifi Display))
android4.2から、外部デイスプレイがサポートされ、外部ディスプレイ用のコンテンツを簡単に作ることができます。やったね!
概要はhttp://greety.sakura.ne.jp/awiki/index.php?Android%204.2#k9ceb062の日本語訳がお勧めです。
とりあえず試してみる
MediaCodecに時間を取られてしまったので簡単にApiDemosで試してみます。
外部ディスプレイ機能は、実物がなくてもシミュレートすることができます。開発者向けオプションを有効にして、「2次画面シミュレート」から適当なのを選びます。とりあえず2つ出して見ます。
画面上にちっちゃいディスプレイが2つオーバーレイされ、開発者向けオプションの画面が3つになりました。外部ディスプレイが接続された体です。
ApiDemosからApp>ActivityのPresentationとPresentation with Media Routerで試すことができます。
Presentationではリストされたディスプレイの中から好きなだけ選択してそれぞれ別の内容を表示することができます。with Media RouterではMediaRouterクラスを使用して、適当なディスプレイにコンテンツを表示してくれます。
外部ディスプレイ用のコンテンツを表示するには
外部ディスプレイ用に別のコンテンツを表示するにはPresentationクラスを使います。今まで画面のサイズをとったりするのぐらいしか出番のなかった地味なDisplayクラスですが、これまた新しく加わったDisplayManagerから外部ディスプレイ一覧がDisplayとして取得できます。これをPresentationのコンストラクタに渡してshow()することで外部デイスプレイに表示させることができます。地味だったDisplayが大活躍
PresentationはonCreate()でsetContentView()するという馴染みある手順で簡単に実装できるます。やったね!
private void showPresentation(Display display, PresentationContents contents) { final int displayId = display.getDisplayId(); if (mActivePresentations.get(displayId) != null) { return; } Log.d(TAG, "Showing presentation photo #" + contents.photo + " on display #" + displayId + "."); // ここ DemoPresentation presentation = new DemoPresentation(this, display, contents); presentation.show(); presentation.setOnDismissListener(mOnDismissListener); mActivePresentations.put(displayId, presentation); }
private final class DemoPresentation extends Presentation { ... public DemoPresentation(Context context, Display display, PresentationContents contents) { super(context, display); mContents = contents; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.presentation_content); ...
miracast - Wifi Display
android4.2からmiracastとよばれるwifi通信による外部ディスプレイ表示ができるようになりました。GalaxyS3なんかは独自に同じようなことをやってるみたいですが。
miracastでの接続もDisplayManagerで同様に扱えるとのことで一安心ですね。
…まあそれだけなんですが。ついでにちょっと調べたところ、
Settingsも新たにSettings.Globalとして編成されていて、例によって「システム設定画面経由でかえさせてね ☆(ゝω・)vキャピ」とのことです。Specialized APIってどれのことだろう…
Global system settings, containing preferences that always apply identically to all defined users. Applications can read these but are not allowed to write; like the "Secure" settings, these are for preferences that the user must explicitly modify through the system UI or specialized APIs for those values.
というわけで手元に4.2がある方はぜひやってみてください。(ぇ
oesf.biz - このウェブサイトは販売用です! - oesf リソースおよび情報
340 @Override 341 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 342 mWifiDisplayOnSetting = isChecked; 343 Settings.Global.putInt(getContentResolver(), 344 Settings.Global.WIFI_DISPLAY_ON, isChecked ? 1 : 0); 345 }
oesf.biz - このウェブサイトは販売用です! - oesf リソースおよび情報
4725 /** 4726 * Whether Wifi display is enabled/disabled 4727 * 0=disabled. 1=enabled. 4728 * @hide 4729 */ 4730 public static final String WIFI_DISPLAY_ON = "wifi_display_on";
参考サイトまとめ
http://greety.sakura.ne.jp/awiki/index.php?Android%204.2#k9ceb062
oesf.biz - このウェブサイトは販売用です! - oesf リソースおよび情報
oesf.biz - このウェブサイトは販売用です! - oesf リソースおよび情報
Presentation | Android Developers
DisplayManager | Android Developers
MediaRouter | Android Developers
Settings.Global | Android Developers
以上です。
最後に
「今年もAndroidアドベントカレンダー参加してみようかな 中頃がいいな」と募集開始からタイミングを伺っていたところ半日たたずに表が埋まっていたのを見て嬉しいやら悲しいやらだったytRinoです。最近はありがたいことにアルバイトでandroidのコードばっか書いているので個人で書く時間があまり無いです。なんかもう大学よりバイトの時間のほうが長いという話があるとかないとか。
そして12月といえば…シューカツですね。
「在学年数の差が、戦力の決定的差ではないことを教えてやる!」
…就職先は随時募集しております。
ということで、グダグダな上に中途半端感あふれるエントリになってしまいましたが少しでも参考になるところがあればいいなというとこで16日裏のエントリとさせて頂きます。あなたもレッツニューエーピーアイ!
chrome拡張触ってみたログ
入門
chrome-extensionが全くわからないのではじめの一歩から。
Loading...でとりあえずFlickrの写真を表示させる。
でも拡張機能の画面では「マニフェストv2にしないとダメ」と警告されるのでmanifest.json
に
"manifest_version" : 2,
と書いてリロード。 何も出なくなった。
まりぽさんによると
browser_action.popupは廃止され、default_popupになった。
らしいのでmanifest.json
を
"browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" },
としてみる。ポップアップは出てるようだが写真が出ない。
Loading...によりとchrome-extension://
で拡張内のファイルが開けるらしいので試しにpopup.html
を開いて⌥⌘I(C-S-I)あたりでデベロッパーツール出してみると、<script>
の下に「実行しませーん」みたいなエラーが出てた。便利ですねありがたいですね。再びまりぽさんのページによると
バージョン2からは、セキュリティ強化のため、インラインJavaScriptは実行されなくなった。拡張内のHTMLにJavaScriptがベタ書きされていたら、外部ファイルに切り出すなどの処置が必要になる。
とのこと。なのでscript要素の中身削除して別ファイルにそのまま貼り付けてload_image.js
とか適当なファイルに保存。script要素は
<script type="text/javascript" src="load_image.js"></script>
としてリロード。動いた。
本題へ
本題「twitterのTLのアイコンを全部入れ替える」
僕はよくわかんないんだけどuserscriptとかでもできるのかな。twitterで「js初心者だけどjsしたい」的なことを言ったらわかめせんせーtwitter:@vvakameに「chrome拡張でもやれば」「アイコン総理大臣にするとか」みたいなことを言ってもらったからという理由です。
ページを書き換えるには…
twitterTLのhtmlのアイコンを全部書き換えるだけっぽいのだけど、先の入門の例ではページの内容とか全く関係ないので、htmlが取得できるのかもよくわからない。せっかくなのでAPIを眺めながらのんびり探すことに。サンプルも結構あるぽい。
なにやらLoading...これを使えばいけそうな雰囲気がする。というわけでこれを真似てcontent_scripts
を書き足す。matches
をtwitterにして、アイコンを書き換える(予定)のjsファイルを作る。アラート出すだけ。ていうかjsのお作法的にこれでいいのかよくわからないけどとりあえずアラートが出るようになった。
ここまでの状態GitHub - ytRino/chrome-ext-biginner at 78afa1bd859f37faf8d71ca474cc0ded161b563f
DOM監視
で、肝心の書き換えに入っていくわけだけど。twitterのTLって新しいツイートがくると「新しいツイート4件」みたいな感じで通知が来て、クリックすると読み込まれるってことは最初にページ読み込んだ時だけ書き換えてもダメだなという(jsぬーぶ的には)めんどくさそうなことに気づいてしまった。最初の書き換えもまだできないうちにそんな心配をして調べていたせいで、alertから次までにだいぶ時間がかかってしまった。あとから振り返ってみてもこれが良かったのか、後回しにしたほうが良かったのかはよくわからない。結局その変化、要はDOMの変化というやつはDOM MutationObserver - reacting to DOM changes without killing browser performance. - Mozilla Hacks - the Web developer blogでそういうものが元から用意されてるみたいな情報があったのでこれを使うことに。最新ブラウザさまさまですね。これなかったらtimerで回すみたいなことを考えてた。
これでもう終わったなと思ったんだけど、実際ちゃんと出るまでにはもう少しつづくんじゃよ。
タイポ
とにかくしょうもないミスが多い。eclipseでandroid(java)という環境でC-Spaceを連打しながら開発してる自分には優秀なSublime Text2と言えどもよく知らない言語+補完も即時文法チェックもないのはわりと辛いものがあった。ゆとりっていうな。
それでもChromeのデベロッパーツールのお陰でとりあえずTLのアイコンを仮で用意した自分のアイコンに書き換えるところまで出来た。ノードの指定も視覚的にわかりやすいお陰ですぐに分かったしjsのエラーもちゃんと出るしマニフェスト足りてないのも指摘してくれたしデベロッパーツールさまさまですね。
こんどこそ書き換える
デベロッパーツールが親切に教えてくれた通り、仮で用意したアイコン、エクステンション内部で持ってるのを読みこませるにはmanifest.json
に宣言。
"web_accessible_resources": ["icon.png"]
これをjsで本来のアイコンURLの代わりのアイコンとして設定する。拡張内のファイルを取得するにはLoading...ということで
var icon = chrome.extension.getURL('icon.png');
DOMは上の通り監視してるから良きタイミングで
// avatarなclass属性がついたimg要素のsrc属性をiconに差し替える $('img.avatar').attr('src', icon);
…なぜここだけjQueryを使ってるんだというツッコミはなしでお願いします。使ってみたかったんです。
これで無事新着ツイートも含めアイコンを書き換えられた。やったね
現在の状態:GitHub - ytRino/chrome-ext-biginner at 15129c4743537a8398ce53f9b1f7eeb759c289aa
メイドさんとハッカソンしてきた #androidtao
昨日(9/29)の【UEC】Android道ハッカソン【Android】 #AndroidTao : ATNDに行ってきた感想とか。
当日までの話
twitter:@numa08*1にandroid初心者向け勉強会とか開くんだけどどーすか、的な誘いをもらい、4月ぐらいから一応サポート役として計5回ほど参加してた。
ノートPC持ってなかったのでコードは書いてなかったけど。
その頃から「そのうちハッカソンやるか」とか「アキバ支部とやる」みたいなことを言っていて、ふーんまあ俺ノートとかないしって感じだったんだけど、*2結局参加することにした。
ハッカソンとか初めてだったけど緩そうだし元あるアプリの改造ならなんとかなるかな、っていうノリだった。
当日
atnd側にも知らない人が多かったけどそれ以上にアキバ支部+メイド側の構成が謎だったのでビビりながら会場へ。
会場ついたらメイドさんがプレゼンの練習してた。謎光景。最初にメイドの方々がベースとなるお絵かきアプリで作ったことをプレゼン。美白とかモザイクとか。あれ…普通にすごくね?
適当に座った席でそのままチーム分けされ、埼玉支部長でもある進藤さんや上の勉強会のとき知り合ったtwitter:@kamedon39 、コンサルなどしているというダンディな雰囲気ただよう入野さん、遅れてtwitter:@7aguchiにメイドのきりさん というチーム。
僕は、色が赤青しか変更できないみたいだしカラーピッカー乗っけるかーとかスタンプ機能とかかなーと凡アイデアしか持ってなかったので、きりさん中心に案を色々出してもらって、最終的に端末振り振りして福笑い的に顔が崩れる、という楽しげな機能を作ることに。
顔検出に加速度センサーに、もちろん画像操作と、あまり使ったことがない分野のオンパレードでかなりヒヤヒヤしながら進めていった。
自分が担当したのは撮影した画像から顔検出して各顔パーツを切り出す部分。ところが
「え…顔検出って顔全体の範囲や各パーツの位置を取れるわけじゃないの…?」
という割とショッキングな事実に、ひとまず目の位置関連は取れるようなので目の位置を動かすのを目指すことにした。
まず目の位置を検出->適当な範囲を目として囲う->範囲の画像コピー->動かす というながれ。
って書くと簡単だけどやってる時は結構必死系だった。
顔検出のテストと称してメイドさんの写真を撮りまくった。そうか今日はこのために(
完成
目を切り抜く(ぇ とこまで作ったらtwitter:@kamedon39担当のセンサー部分とマージ。振り方によって上下に目を動かす。端末を持って縦に振ると下に落ち、奥に振ると上がっていくという仕様になった。コピーした目画像動かす部分担当は、環境的に厳しい感じだったしマージだるそうだしということで、ぐぐっていた情報を参考に僕がでっち上げた。
画像は、写真もその上のお絵かきもCanvasに描画してあって、動かした目もこの上に描画したんだけど、このへんは顔検出とかよりもむしろ大変だったかもしれない。
このへんは理解不足でかなり無駄が多くなったんじゃないかと思う。ともかく完成したので良かった。
プレゼン資料は完全に進藤さんに任せてしまっていて、他にも進行、実装方法の提案、とサポートに徹して頂いて、さすがの役回りという感じで本当に助かった。進藤さん本当にありがとうございました!
プレゼンとか
プレゼンの順番を決めている 左からしおんさん、numa08、きりさん、エリカさん
このへんはたぶんアキバ支部の方で記事に上がるのではないかと思うので軽く。
- 主催チーム
カメラでとった人がニュータイプかわかるらしい。俺はニュータイプだったのだ… - きりチーム
我々チーム。 なぜかプレゼンで俺が被写体になり謎のゾンビ写真を晒される。 こういう時のメイドさんではぇ… - しおんチーム
最近話題の添い寝に乗っかり、アラームで添い寝とかできるらしいアプリ。お絵かきはどこへ - エリカチーム
メイド喫茶でサインしてもらいスタンプがわりになる(予定)。スライドのタイトルはすごいこってた。完成してたら普通によさそうだった。
あとはそれぞれ感想とか言ってひとまず締め。その後片付けながら一緒に撮影的な何かとかしたあとメイドさんは帰って行きましたとさ。
その後体育館前で暗い中ピザという不思議な打ち上げをしてお疲れ様でした。
まとめ
他の人も言っていたけど、やはり自分でやってると「(簡単に)できそうかどうか」って基準で考えちゃったりするのあるの気をつけたいですね。
今回こういう場で大変そうだなーって実装を時間制限の中で他の人と一緒にやっていくっていうのは新鮮で良かった。
初心者マカーのハッカソンデビューとしては上出来だったと思う。またこういうのでてみたいなーっと。
主催numa08とアキバ支部の方々、メイドのお3方そして各チームもみなさんおつかれさんでしたー!
余談
メイドさんって普通は撮影NGらしい、知らなかった。当日は特別オッケーだったそうで。でも触らないでください、連絡先とか聞かないでくださいとか物騒な世の中だなあと思いましたまる
あとテストと称してメイドさんの写真を撮りまくったと書きましたが、お絵かきアプリ経由でとったこれらの写真はどうもうまく端末に保存されていなようで、呼び出したカメラも行儀の良いアプリだったのか、端末に2重保存等されていないようでした。残念ですね。ちゃんと写真選べばtwitterにあげてもいいという話だったんですがあんまり取れませんでした。
メイドと聞いてビビっていたけどいい意味で普通でとても良かったです
っていうかメイドさんとあんまり交流してないですねはい。きりさん->http://ameblo.jp/kiri-kiririn/page-3.html
技術的なメモ
- FaceDetectorは目関連しか取れない。ICS以上だともっと出来るらしい。Cameraプレビューの顔検出はいろいろ取れる(今回は使えない)
- 目を切り取った(正確にはコピーした)あとにその位置を福笑い的に塗りつぶしたかった。今回は単純に
canvas.drawBitmap(mBackBmp, src, dst, null);
とした。dstは目の範囲の矩形で、srcはその一番下の一列。つまりmBackBmp(顔画像)の目の範囲一番下の一列を引き伸ばして目の部分全部埋める。目が綺麗に取れてると良い感じにのっぺらぼう的になる。Canvas,Rect,Bitmapあたりはもうちょっとちゃんと知っておきたいなー。ごちゃっとしか書けなかった。
- やんざむさんのColorPickerためしに入れてみたらちっちゃく左によったピッカーが出てきたけど何が問題なのかよくわからなかった。
- githubにおいておきましたので欲しい方はどうぞ。
MBA到着して最初にやってたことメモ
mac素人の僕のところにMBAが到着したので一日ほどたったのでやったことメモ。
- 設定を色々いじる : 全くわからないので適当によさそうなところがあればいじる。とりあえず右下クリックでwinの右クリ的なのとかタップでクリックとか
- 結局クリックしなきゃいけないこと多いので微妙かも
- chromeいれる : 拡張やらもろもろ同期されててすぐいつもの感じで使えて改めて便利だなーと。 あ、同期する内容には気を付けましょう
- Eclipse, ADT, AndroidSDK入れる : メインイベント(?) 各バージョンのSDK落とすのに時間がかかったぐらいで特に何事も無く終了
- Github for macいれる : ぐぐったら出てきたのでとりあえず入れてみた。 自分みたいな初心者に便利っぽい。
- GithubにWindowsのデスクトップで作ってたandroidアプリのプロジェクトをprivateやらpublicであげる。 : 学生アカウントが有効になったのでprivateが。
- Gitいれる : 上の入れてもコマンドじゃ出来ないようなのでできるように。若干めんどかった。
- 隠しフォルダを表示 : defaults write com.apple.finder AppleShowAllFiles true して killall Finder
あとは何やったらいいんだろう。バックアップとかかな。しばらくはググる日が続きそうです。
ノリで株式会社ウサギィについていった
ぱぶろふさんとたろーくんがウサギィ行く感じだったので、ミーハーな僕としては乗るしか無いと思い、噂のウサギィ訪問へついて行かせてもらいました。
ついったーに投げた軽い感想など。
ウサギィの理想だとか歴史だとかオフィスの紹介とかそういうのはないです。
かずー氏クラスタと呼ばれる人達のこともほとんどしらないニワカです。あしからず。
かずーしさんのTLはやいなーて見てる
— いいの(P-Body) (@ytRino) August 10, 2012
ウサギィがステマしろって
— いいの(P-Body) (@ytRino) August 10, 2012
かずーし愛妻弁当たべてた
— いいの(P-Body) (@ytRino) August 10, 2012
最初「あ、かずーしか」ってならずにワンテンポおくれて「つまりこの方がかずーしか」ってなった
— いいの(P-Body) (@ytRino) August 10, 2012#ウサギィ
「一応学生ですけどたぶん同い年ですよ」「つまりクズか」
— いいの(P-Body) (@ytRino) August 10, 2012#ウサギィ
.
— いいの(P-Body) (@ytRino) August 10, 2012@ngsw_taro ナンパし過ぎて名刺切れ疑惑 kotlinをディスられる#ウサギィ
ぱぶさんまさかの2時間遅れも歓迎される
— いいの(P-Body) (@ytRino) August 10, 2012#ウサギィ#ホワイト#ステマ
かずーしは愛妻弁当を食べながらTLを監視している
— いいの(P-Body) (@ytRino) August 10, 2012#ウサギィ
謎のエナジードリンク系炭酸飲料ライジン 2本飲むと死ぬ
— いいの(P-Body) (@ytRino) August 10, 2012#ウサギィ
↑ぜひググって下さい
ま、オヒスゆったりでしたとかは今更だと思うのでこんな軽めな感じで
— いいの(P-Body) (@ytRino) August 10, 2012
何枚か取らせてもらったけどボケすぎてて残念だったのでちょっとだけ。
正直よくウサギィの事知らないのにいろいろ有り難うございました
俺もあんなちょっとシャレオツ照明のあるゆったりしたとこでコード書きたいですね #ステマ
Android用「坂本真綾 from everywhere.」専用アプリ公開しました。
まだ公開状態になってねーよ!!!
無事見えました->https://play.google.com/store/apps/details?id=net.nessness.android.maaya.fromeverywhere
アプリの説明はこちらで。ふろむえぶりうぇー. : 坂本真綾Podcast - ちりもつ::android と言ってもポッドキャストを聴くだけです。
今回も使ってみたいAPI基準でつくってます。
今回使った今までのアプリで使ってなかったやつ↓
- Fragment
- Pager
- ついでに分割2ペイン
- ContentProvider
- CursorLoader
とまあ主にSupportLibraryな感じです。
機能としては単純だけど意外と頑張ってるところもある(たぶん)
「まあやの結婚記念日が8月8日だ!」ということで8月入ってからこの日目標と勝手に決めて作ってました。(作り始めたのはだいぶ前だけど)
紙婚式とかいうらしいです。
おめでとう真綾
ついでにytrinoの誕生日らしいです
おめでとう俺(ぇ