🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

3回答

4805閲覧

android camera2でズーム後のtextureViewをキャプチャーする方法

sekaikan_ozaki

総合スコア65

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2019/10/07 10:19

編集2019/10/07 15:01

PCスペック
Windows10 HOME 64bit
メモリ 32GB
プロセッサ Intel Core i7-8700CPU 3.20GHz
Android Studio 3.4.1(最新ver)
デモ用端末(XPERIA OS:7.0 API 24)

camera2APIを使って,カメラアプリを開発しています.

現在の進捗

とりあえずカメラを起動させて,ボタンを押したら撮影されるところまでできました.

現在の課題

ズーム機能を実装したのですが,
撮影ボタンを押すと,もとのズームされていない方の画像が撮影されてしまうのを直したいです.

ズームの方法として,ScaleGestureDetectorを実装して,textureViewを大きくしたり,小さくしたりすることはできています.

mCamera.mTextureView.getBitmap();で,textureViewをビットマップ形式で取り出して,作成したファイルに保存する流れを取っているのですが,ズームの部分のコードでtextureViewのビットマップの値を変えてないから,もとのビットマップの値のまま取り出しているということが問題だとはわかっていますが,どう直せばよいのかが分かりません.
ScaleListenerクラスの中で,スケールに応じてbitmapを変更すればよいのでしょうか??

java

1public class MainActivity extends AppCompatActivity { 2 private Camera mCamera; 3 private float scale = 1f; 4 private ScaleGestureDetector detector; 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 9 setContentView(R.layout.activity_main); 10 11 detector = new ScaleGestureDetector(this,new ScaleListener()); 12 13 TextureView textureView = (TextureView) findViewById(R.id.texture_view); 14 textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { 15 @Override 16 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 17 mCamera.open(); 18 } 19 @Override 20 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {} 21 @Override 22 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 23 return false; 24 } 25 26 @Override 27 public void onSurfaceTextureUpdated(SurfaceTexture surface) {} 28 }); 29 30 mCamera = new Camera(textureView); 31 } 32 33 public boolean onTouchEvent(MotionEvent event) { 34 detector.onTouchEvent(event); 35 return super.onTouchEvent(event); 36 } 37 38 private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 39 @Override 40 public boolean onScale(ScaleGestureDetector detector) { 41 scale *= detector.getScaleFactor(); 42 mCamera.mTextureView.setScaleX(scale); 43 mCamera.mTextureView.setScaleY(scale); 44 mCamera.changeZoomLevel(2); 45 return true; 46 } 47 } 48 @Override 49 protected void onResume() { 50 super.onResume(); 51 Button button = (Button) findViewById(R.id.button); 52 button.setOnClickListener(new View.OnClickListener() { 53 @Override 54 public void onClick(View v) { 55 Bitmap bitmap = mCamera.mTextureView.getBitmap(); 56 int bitmapWidth = bitmap.getWidth(); 57 int bitmapHeight= bitmap.getHeight(); 58 Log.d("debug", "bitmapWidth:" + bitmapWidth); 59 Log.d("debug", "bitmapHeight:" + bitmapHeight); 60 try{ 61 File resultFile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/" + "capture.jpeg"); 62 resultFile.getParentFile().mkdir(); 63 String resultFilepath = resultFile.getPath(); 64 65 FileOutputStream output = new FileOutputStream(resultFilepath); 66 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output); 67 output.flush(); 68 69 } catch (IOException e) { 70 e.printStackTrace(); 71 } 72 } 73 }); 74 } 75 class Camera { 76 private CameraDevice mCamera; 77 private TextureView mTextureView; 78 private Size mCameraSize; 79 private CaptureRequest.Builder mPreviewBuilder; 80 private CameraCaptureSession mPreviewSession; 81 private int mCurrentZoomLevel = 1; 82 private Rect mCropRegion; 83 private CameraManager manager; 84 private CameraCharacteristics characteristics; 85 86 87 private CameraDevice.StateCallback mCameraDeviceCallback = new CameraDevice.StateCallback() { 88 @Override 89 public void onOpened(@NonNull CameraDevice camera) { 90 mCamera = camera; 91 createCaptureSession(); 92 } 93 94 @Override 95 public void onDisconnected(@NonNull CameraDevice camera) { 96 camera.close(); 97 mCamera = null; 98 } 99 100 @Override 101 public void onError(@NonNull CameraDevice camera, int error) { 102 camera.close(); 103 mCamera = null; 104 } 105 }; 106 107 CameraCaptureSession.StateCallback mCameraCaptureSessionCallback = new CameraCaptureSession.StateCallback() { 108 @Override 109 public void onConfigured(@NonNull CameraCaptureSession session) { 110 mPreviewSession = session; 111 updatePreview(); 112 } 113 114 @Override 115 public void onConfigureFailed(@NonNull CameraCaptureSession session) { 116 Toast.makeText(MainActivity.this, "onConfigureFailed", Toast.LENGTH_LONG).show(); 117 } 118 }; 119 public Camera(TextureView textureView) { 120 mTextureView = textureView; 121 } 122 public void open() { 123 try { 124 manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 125 for (String cameraId : manager.getCameraIdList()) { 126 characteristics = manager.getCameraCharacteristics(cameraId); 127 if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { 128 StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 129 mCameraSize = map.getOutputSizes(SurfaceTexture.class)[4]; 130 131 Log.d("debug", "cameraId:" + cameraId); 132 133 134 manager.openCamera(cameraId, mCameraDeviceCallback, null); 135 136 137 138 return; 139 } 140 } 141 } catch (CameraAccessException e) { 142 e.printStackTrace(); 143 } 144 } 145 146 private void createCaptureSession() { 147 if (!mTextureView.isAvailable()) { 148 return; 149 } 150 151 SurfaceTexture texture = mTextureView.getSurfaceTexture(); 152 texture.setDefaultBufferSize(mCameraSize.getWidth(), mCameraSize.getHeight()); 153 Surface surface = new Surface(texture); 154 155 try { 156 mPreviewBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 157 } catch (CameraAccessException e) { 158 e.printStackTrace(); 159 } 160 161 mPreviewBuilder.addTarget(surface); 162 try { 163 mCamera.createCaptureSession(Collections.singletonList(surface), mCameraCaptureSessionCallback, null); 164 } catch (CameraAccessException e) { 165 e.printStackTrace(); 166 } 167 } 168 public void changeZoomLevel(int level) { 169 // cameraId = 対象のカメラID 170 Log.d("debug", "changeZoomLevel()が呼ばれました"); 171 try { 172 manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 173 //CameraCharacteristics characteristics; 174 175 for (String cameraId : manager.getCameraIdList()) { 176 characteristics = manager.getCameraCharacteristics(cameraId); 177 if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { 178 StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 179 mCameraSize = map.getOutputSizes(SurfaceTexture.class)[4]; 180 Log.d("debug", "cameraId:" + cameraId); 181 182 } 183 } 184 185 } catch (CameraAccessException e) { 186 e.printStackTrace(); 187 } 188 189 // 最大ズームサイズ 190 float max = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); 191 if ((int) max < level || mCurrentZoomLevel == level) { 192 return; 193 } 194 Log.d("debug", "max:" + max); 195 196 mCurrentZoomLevel = level; 197 final Rect activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 198 199 if (mCurrentZoomLevel == 1) { 200 mCropRegion.set(activeArraySize); 201 Log.d("debug", "mCurrentZoomLevel:" + mCurrentZoomLevel); 202 } else { 203 Log.d("debug", "mCurrentZoomLevel:" + mCurrentZoomLevel); 204 //noinspection ConstantConditions 205 int cx = activeArraySize.centerX(); 206 int cy = activeArraySize.centerY(); 207 int hw = (activeArraySize.width() >> 1) / mCurrentZoomLevel; 208 int hh = (activeArraySize.height() >> 1) / mCurrentZoomLevel; 209 mCropRegion = new Rect(cx - hw, cy - hh, cy - hh, cy + hh); 210 } 211 } 212 213 private void updatePreview() { 214 mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 215 mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion); 216 HandlerThread thread = new HandlerThread("CameraPreview"); 217 thread.start(); 218 Handler backgroundHandler = new Handler(thread.getLooper()); 219 220 try { 221 mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, backgroundHandler); 222 } catch (CameraAccessException e) { 223 e.printStackTrace(); 224 } 225 } 226 } 227}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こちらのサイトが参考になると思います。
一応、実機でZoomの写真が撮れた事を確認できました。

https://qiita.com/ohwada/items/13c0d81b5b674474adbf
https://github.com/ohwada/Android_Samples/tree/master/Camera215

投稿2019/10/10 08:10

kamikaze.cappa

総合スコア558

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

自分なら以下を参考にします。

https://qiita.com/ikemura23/items/049e8c73edda0bf23877

投稿2019/10/08 01:46

kamikaze.cappa

総合スコア558

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sekaikan_ozaki

2019/10/10 04:15

コメントありがとうございます スクラッチではなくて,すでにあるライブラリを利用すればよいとのことですね. すべてで試してみましたが,そもそもズーム機能が実装されていないものばかりでした... また,ズーム機能が実装されていても,ピンチイン専用になっていたりと,その後の加工ができないタイプなので,今回はスクラッチ開発にもう少しだけこだわってみようと思います. ありがとうございました
guest

0

以前私が質問し、自己解決した質問がありますので参考まで。
https://teratail.com/questions/154510

投稿2019/10/07 10:31

Begi

総合スコア56

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sekaikan_ozaki

2019/10/07 14:56

コメントありがとうございます. Begi様の過去の質問を拝見させていただきました. updatePreview() のmPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);の部分の下に, mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion);を記載しました. また,https://moewe-net.com/android/camera2-zoomの方法を参考に, public void changeZoomLevel(int level) { // cameraId = 対象のカメラID Log.d("debug", "changeZoomLevel()が呼ばれました"); try { manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); //CameraCharacteristics characteristics; for (String cameraId : manager.getCameraIdList()) { characteristics = manager.getCameraCharacteristics(cameraId); if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) { StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); mCameraSize = map.getOutputSizes(SurfaceTexture.class)[4]; Log.d("debug", "cameraId:" + cameraId); //return; } } } catch (CameraAccessException e) { e.printStackTrace(); } // try { // characteristics = manager.getCameraCharacteristics(cameraId); // } catch (CameraAccessException e) { // e.printStackTrace(); // return; // } // 最大ズームサイズ float max = characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); if ((int) max < level || mCurrentZoomLevel == level) { return; } Log.d("debug", "max:" + max); mCurrentZoomLevel = level; final Rect activeArraySize = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); if (mCurrentZoomLevel == 1) { mCropRegion.set(activeArraySize); Log.d("debug", "mCurrentZoomLevel:" + mCurrentZoomLevel); } else { Log.d("debug", "mCurrentZoomLevel:" + mCurrentZoomLevel); //noinspection ConstantConditions int cx = activeArraySize.centerX(); int cy = activeArraySize.centerY(); int hw = (activeArraySize.width() >> 1) / mCurrentZoomLevel; int hh = (activeArraySize.height() >> 1) / mCurrentZoomLevel; Log.d("debug", "cx:" + cx); Log.d("debug", "cy:" + cy); Log.d("debug", "hw:" + hw); Log.d("debug", "hh:" + hh); mCropRegion = new Rect(cx - hw, cy - hh, cy - hh, cy + hh); Log.d("debug", "cx - hw:" + (cx - hw)); Log.d("debug", "cy - hh:" + (cy - hh)); Log.d("debug", "cy - hh:" + (cy - hh)); Log.d("debug", "cy + hh:" + (cy + hh)); } } のメソッドをCameraクラス内に追加し, ScaleListenerクラスの内部で,changeZoomLevelを呼ぶようにしました. しかし,何かが違うのか,撮影後の画像にズームが反映されません.. 何かアドバイスがあればいただけますでしょうか? 質問のソースコードはすでに編集しております.
Begi

2019/10/10 02:32

コメント遅くなりすみません。 ちょっと不具合のあぶり出しが難しいですね… 私のソースと違う箇所を記載してみました。 createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); を createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); に、 mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); を mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); に変更してみてもらえますでしょうか。 よろしくお願いします。
sekaikan_ozaki

2019/10/10 04:21

いえいえ,コメントしていただけるだけで大助かりです. カメラをスクラッチで記述するのも今回初めてなので,自分でもコードに関して理解が足りないところが多くて参ってます... 上記の通り,該当箇所のコードを書き換えてみたのですが,挙動は前回と変わらずでした... Begi様が解決した際のコードは, TakePictureActivity以外に別のクラスなどを設定されていましたでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問