こんにちは。きりみんちゃんです。
このエントリはVTuber Tech#1 アドベントカレンダー4日目の代打です。 VTuberの配信システムに関するネタじゃなくてすみません。 でも代打なので許してください。
VTuberの写真が取れるアプリをつくりました
さて、きりみんちゃんカメラというAndroidアプリをつくりました。 ひさしぶりの趣味アプリです。
きりみんちゃん((バーチャル幼女プログラマー(VTuber)))のお写真が撮れます。
こんな感じの写真を生成することができます。
実装について
小さいアプリを愚直に作ったのでそれほど実装について語ることはありませんが、画像処理を久しぶりにやってちょっとがんばりました。
実装方法としては、取得した写真の画像ときりみんちゃん(フレーム)の画像をそれぞれUI上ではImageViewで表示し、保存時にImageViewからBitmap化し、Canvasを使い2つのBitmapを合成しています。
ImageViewから取得した素のBitmapをそのまま合成してもサイズがレイアウト上での表示サイズと異なるため正しく合成できません。 そこでレイアウト上での表示サイズを計算しリサイズしてあげることで、ユーザーが見た通りの画像を出力することができます。
だいたいこんな感じの処理です。
val baseBitmap = Bitmap.createBitmap(photoImageView.width, photoImageView.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(baseBitmap) val photoBitmap = (photoImageView.drawable as BitmapDrawable).bitmap val photoSize = computeBitmapSizeFromDynamicImageLayer(photoImageView) val scaledPhotoBitmap = Bitmap.createScaledBitmap(photoBitmap, photoSize.x, photoSize.y, true) canvas.drawBitmap( scaledPhotoBitmap, computeCenter(baseBitmap.width, scaledPhotoBitmap.width), computeCenter(baseBitmap.height, scaledPhotoBitmap.height), null ) if (frameImageVIew.drawable != null) { val frameBitmap = (frameImageVIew.drawable as BitmapDrawable).bitmap val frameSize = computeBitmapSizeFromDynamicImageLayer(frameImageVIew) val scaledFrameBitmap = Bitmap.createScaledBitmap(frameBitmap, frameSize.x, frameSize.y, true) scaledFrameBitmap.density = photoBitmap.density canvas.drawBitmap(scaledFrameBitmap, frameImageVIew.left.toFloat(), frameImageVIew.top.toFloat(), null) }
いろいろとハマりどころがあったのですが、その知見はまたQiitaなどに書こうかなと思います。
ViewやCanvasの座標計算はむずかしいですがやりはじめると結構たのしいです。
リンクなど
このアプリはGitHubでソースコードを公開しているので、Androidプロジェクトの構成が多少読める人(リソースの位置など)であれば、フォークして自分のオリジナルカメラアプリを作ることが出来ると思います。きりみんちゃんは権利を主張しませんが、きりみんちゃんに言及してくれたらうれしいです。 github.com
きりみんちゃんはVTuberとして技術系の動画や雑談配信、ゲーム配信などを行っています。興味がありましたらぜひ見てみてください。