https://github.com/cyberagent-jp
でサイバーエージェントがアンドロイドの写真の補正のソースコードを公開していますね
写真の補正といえばインスタグラムが有名になりすぎてしまっていますが、その他にも優秀な写真の補正アプリがどんどん出てきているので、もし興味がある人がいれば挑戦してみるといいかもしれませんね。
https://github.com/cyberagent-jp
でサイバーエージェントがアンドロイドの写真の補正のソースコードを公開していますね
写真の補正といえばインスタグラムが有名になりすぎてしまっていますが、その他にも優秀な写真の補正アプリがどんどん出てきているので、もし興味がある人がいれば挑戦してみるといいかもしれませんね。
カメラ機能を使おうと思ったのですが、一部バグが出たので、その内容と解決方法をダラっとかかせて頂きます。
カメラの内側とかサイズとかの処理が面倒くさかったので、端末のカメラアプリに任せました。カメラアプリの任せ方はちょっと前にやったみたいな。
の内容に近いのですが、前回とは異なるバグですが、カメラアプリからたまに、画像のデータが取得できない事がありました。正確には、画像のURLが取得できなかったのですが、
で、どうやら、原因としては、作ってるアプリがportrait(縦方向)でカメラアプリがlandscapee(横方向)で、カメラアプリから、戻ってくる時に画面の向きが横向きのまま帰ってくるのだけど、こっちの方で縦方向に設定しているので、縦に方向を転換してくれる。ようなのですが、画面の向きは面倒臭い事がわかるとおもうのですが、oncreateとかが走るんですよ。
画面方向、android とかでググれば出てくるとおもうのですが、これが結構面倒くさいです。
一応、解決方法としては保存が必須な値はstaticとかにしたり、初期化とかをある程度隠しつつ行う。と言う作戦にしたら、なんとかうまく出来ました。
結構はまるポイントなので、お気をつけください!!
色の調整やホワイトバランスを調整するにあたっては基本的な機能としてandroidにそなわっているようです!
APIレベル5からほぼ実装されています。
また、parameterを用いる事でよりさまざまなエフェクトや効果を実装できるようなので、まとめてみました。
個人的にはcolorをいじるのを触ってみるのが楽しいかと思います。
以前作成したカメラファイルをもとにパラメータを変更します。
まず、パラメーターの設定についてですが、
Camera.Parameters parameters = myCamera.getParameters(); parameters.set***(***); myCamera.setParameters(parameters); myCamera.startPreview();
カメラからパラメータ要素を取得後に変更をしてセットをします。
parameters.setAntibanding(Camera.Parameters.***);
と設定をします。
入る値としては
ANTIBANDING_50HZ : ANTIBANDING_60HZ : ANTIBANDING_AUTO : ANTIBANDING_OFF :
ですが、階調の落差と言う言葉でおそらくつけてもそこまで変化のあるパラメータではありませんが、色の移り変わりを滑らかにするパラメータだと思います。(間違いがあればご連絡いただけると幸いです。)
つまりは
ANTIBANDING_50HZ :境目をやわらかくする(強) ANTIBANDING_60HZ :境目をやわらかくする(弱) ANTIBANDING_AUTO :境目をやわらかくする(自動) ANTIBANDING_OFF :境目はがちがちで表示。
だと思います。境界や、顔認識を行う場合にはOFFにした方がよいかと思いますが、通常の写真撮影に関しては、AUTOをつけておくと、やわらかな写真がとれると思います。
parameters.setFlashMode(Camera.Parameters.***)
と設定をします。
入力できる値は
FLASH_MODE_AUTO:自動 FLASH_MODE_OFF:オフ FLASH_MODE_ON :オン FLASH_MODE_RED_EYE:赤め軽減 FLASH_MODE_TORCH :常に光り続ける。
上記の設定が用意されているのですが、
機種によってフラッシュが用意されているものと用意されてないものが存在する為に
特別な理由がない限りは利用しない方が無難です。
利用する場合は利用可能かどうかのチェックを行って可能であれば利用するようにバグ回避を行いましょう。
最後に記載しております。
parameters.setSceneMode(Camera.Parameters.***);
と設定をします。
入力できるのは
SCENE_MODE_ACTION:動いている対象 SCENE_MODE_AUTO:自動 SCENE_MODE_BARCODE:バーコード SCENE_MODE_BEACH:ビーチ SCENE_MODE_CANDLELIGHT:ろうそくの炎のようなあたたかい色 SCENE_MODE_FIREWORKS:花火用 SCENE_MODE_LANDSCAPE:風景・離れた対象用 SCENE_MODE_NIGHT:夜 SCENE_MODE_NIGHT_PORTRAIT:夜の人物用 SCENE_MODE_PARTY:パーティー用 SCENE_MODE_PORTRAIT:人物用 SCENE_MODE_SNOW:雪用 SCENE_MODE_SPORTS:スポーツなどのとても早く動く対象 SCENE_MODE_STEADYPHOTO:友達用・握手とかの時にぼけないような。 SCENE_MODE_SUNSET:夕暮れ用 SCENE_MODE_THEATRE:劇場・シアター用
シーンに関しては恐ろしいほどに、いろいろな場面用がありました。
カメラ内の設定で変更するのは少し面倒ですが、何かの専用のカメラを作成する場合には、設定しておくとユーザーに喜ばれるかもしれません!
parameters.setWhiteBalance(Camera.Parameters.***);
で設定をします。
入力できる値は
WHITE_BALANCE_AUTO:自動 WHITE_BALANCE_CLOUDY_DAYLIGHT:曇りの日 WHITE_BALANCE_DAYLIGHT:お昼 WHITE_BALANCE_FLUORESCENT:蛍光灯の下 WHITE_BALANCE_INCANDESCENT:白熱灯の下 WHITE_BALANCE_SHADE:影 WHITE_BALANCE_TWILIGHT:日の出前や日没後の薄明かり WHITE_BALANCE_WARM_FLUORESCENT:暖色の蛍光灯のした。
です、こちらも特に専用のカメラではない限りはAUTOが無難だと思います。
parameters.setColorEffect(Camera.Parameters.***);
で設定します。
入力できる値は
EFFECT_AQUA:青のモノクロ EFFECT_BLACKBOARD:不明 EFFECT_MONO:モノクロ EFFECT_NEGATIVE:ネガっぽく色が反転 EFFECT_NONE:通常 EFFECT_POSTERIZE:不明 EFFECT_SEPIA:セピア EFFECT_SOLARIZE:不明 EFFECT_WHITEBOARD:不明
設定値ですが、galaxy sでは上記の不明のものに関しては動作しませんでした。
基本的には、自分で作らないといけないようです。セピアなどは綺麗に表示できるのですが、
簡単なサンプルを作成する場合に、つける程度の方が無難なようです。
もし特別なカラーエフェクトが必要な場合は自分でbitmapで色の変換を行う必要があります。
各設定に関してはサポートされているかどうかと言うのが、
下記により配列で取得できます。基本的にサポートされているものは問題ありませんが、
flashなど一部のユーザーしか利用できない機能などについてはサポートで分岐させて利用をしましょう。
Camera.Parameters.getSupportedAntibanding() Camera.Parameters.getSupportedColorEffects() Camera.Parameters.getSupportedFlashModes() Camera.Parameters.getSupportedFocusModes() Camera.Parameters.getSupportedSceneModes() Camera.Parameters.getSupportedWhiteBalance()
以上です。
エフェクトをうまく使う事で作りたいアプリを簡単につくれるようになっていますので、いろいろ試してみると面白い部分だと思います。
アンドロイドのアプリで
「サイズを指定すると落ちる」
「カメラのプレビューがなぜか歪んでいる」
「プレビューと撮影した写真で画角が異なる」
という状態がおこります。(機種によって。)
この原因を考えました。
下記より仮定及び、推測です。
まず、「サイズを指定すると落ちる」という問題です。
Android: まとめ 各端末のカメラのサポート画像サイズ
でサポートされているサイズが記載されていますが、見て分かるように機種によってサイズがばらばらです。
作成側としては画面一杯のサイズで取得をしたい時に
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ Camera.Parameters parameters = myCamera.getParameters(); parameters.setPreviewSize(width, height); myCamera.setParameters(parameters); myCamera.startPreview(); }
と記載をします。これが画面一杯のサイズでプレビューが表示されます。
しかし、画面のサイズをプレビューでサポートしてない場合に落ちます。
これは、機種の設計ミスと言ってもよいかと思うのですが、いくつかのアンドロイドで起こる事象の為、画面のサイズを指定してはいけません。
画面のサイズは指定しない方が無難かもしれません。
次に「カメラのプレビューがなぜか歪んでいる」と言う問題です。
プレビューサイズは指定をした場合に、サイズは表示されるサイズでなく解像度です。
実際には、surfaceviewのサイズで表示されます。
つまり、プレビューサイズを正方形に指定をしていた場合にもsurfaceviewの形が長方形であれば、引き伸ばされた形で表示がされてしまいます。
デフォルトで設定されている、プレビューの比率が画面のサイズと異なる場合には、値を指定しない場合には歪みます。
最後に「プレビューと撮影した写真で画角が異なる」と言う問題です。
この問題が一番面倒な問題なのですが、
Android: まとめ 各端末のカメラのサポート画像サイズ
を見てもらうと分かるように、プレビューサイズに対応した画像サイズが存在しない場合があります。(比率的に)
つまり、プレビューサイズに対応した画像サイズが存在しない場合には、自分でbitmapの変換を行ってサイズを変更する必要があります。
上下が切れているのか左右が切れているのかが不明の為、サイズをどうしても変更する比率はあわせられても、厳密にプレビューの画角で撮影はできません。
どうしても、プレビューサイズと合わせたい場合は、縦横比が一致する画像サイズが存在するプレビューサイズを選んで撮影をするか、機種ごとに場合分けをするしかありません。
以上で、カメラを作成するにあたっての不具合です。
プレビューで使用できるサイズを取得する
Camera.Parameters.getSupportedPictureSizes();
画像の保存で使用できるサイズを取得する。
Camera.Parameters.getSupportedPreviewSizes();
を利用して場合わけをすれば、割と細かく設定ができますが、特に細かいところまでを考えなくてよい場合には
を利用して、マージンがあるプレビューで(ない場合もあります)撮影をすれば、
「サイズを指定すると落ちる」
「カメラのプレビューがなぜか歪んでいる」
を回避をする事ができるので、細かい設定は面倒くさいけど、比率などを合わせたい場合には最適かと思います。
プレビューのサイズができるだけ小さい方がメモリ的に有効な気もするので、一度がっつりライブラリ的なので適合できるようにできればと思います。
以上です。
写真を撮影した後にギャラリーを見て気づいたのですが、画像のデータがおかしい事に気づきました。
撮影時に指定した範囲よりも大きい写真がとれていました。カメラの解像度と、画面の解像度の違いから発生がしているようです。
今回は撮影している範囲を画面内に抑えてみようかと思います。
カメラのサイズの変更をしていると思われる部分は
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ Camera.Parameters parameters = myCamera.getParameters(); parameters.setPreviewSize(width, height); myCamera.setParameters(parameters); myCamera.startPreview(); }
でした。setPreviewSize()で値を指定しているようでしたが値を変更しても、サイズ画像が歪むなどが記載されておりました。
また。値を設定しない方がよい。ようです。(下記リンクを参照)
なので
parameters.setPreviewSize(width, height);
を消してしまいます。
そうすると、画面の大きさに合わせて、カメラのプレビューの比率が変わってしまいます。
ここで仮定をしたのですが、「カメラのプレビュー自体はSurfaceView全体に広がる仕様」なのかと思いました。
なので、surfaceViewをカメラの解像度に合わせた比率に変更をすれば、プレビューも解像度にあったサイズに変更されるのではないか。。と。
android.view.ViewGroup.LayoutParams lp = getLayoutParams(); lp.width = 100; lp.height = 100; setLayoutParams( lp );
としたら、カメラのプレビューのサイズが100×100になりました。仮定は正しかったようです。
つまりは、カメラの比率に合わせて、SurfaceViewを画面いっぱいに広がる形でに変更をしてみました。
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ Camera.Parameters parameters = myCamera.getParameters(); android.view.ViewGroup.LayoutParams lp = getLayoutParams(); int ch = parameters.getPreviewSize().height; int cw = parameters.getPreviewSize().width; if(ch/cw > height/width){ lp.width = width; lp.height = width*ch/cw; }else{ lp.width = height*cw/ch; lp.height = height; } setLayoutParams( lp ); myCamera.setParameters(parameters); myCamera.startPreview(); }
これで、画面には撮影時に取得できる構図で、表示できるようになりました。
以上です。