質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

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

Android

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

Q&A

解決済

1回答

1068閲覧

Androidのcamera2でズームした画像を保存したい

Begi

総合スコア56

Java

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

Android

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

0グッド

2クリップ

投稿2018/10/26 12:44

###前提・実現したいこと
androidのカメラ開発を行っています。
camera2のAPIで基本的な動作は実装済みで、ズーム機能も付加しようと思い開発していますが、ズームした状態でシャッターボタンを押してもズーム前の画像が撮影されてしまいます。
お力をお貸しいただけないでしょうか。

###仕様
・横向きで撮影。解像度は1280*960固定
・アプリ自体はwebView
・撮影→プレビュー確認→再撮影又は保存して次の画像を撮影 の連続撮影機能あり

Java

1public class TakePictureActivity extends Activity { 2 3 RelativeLayout wrapper; 4 static final String TAG = "TakePictureActivity"; 5 private Size mPreviewSize; 6 7 private TextureView mTextureView; 8 private CameraDevice mCameraDevice; 9 private CaptureRequest.Builder mPreviewBuilder; 10 private CameraCaptureSession mPreviewSession; 11 12 private Button mBtnShot; //撮影ボタン 13 Resources res; 14 private TextView mTextViewPictName; //キャプション 15 16 static final int CAM_WIDTH = 1280; 17 static final int CAM_HEIGHT = 960; 18 19 boolean zoomFlg = false; 20 private int zoomTop = 0; 21 private int zoomLeft = 0; 22 //画像の順番を管理 23 private String mCurrentImageId; 24 private String base64img; 25 26 static int camIdx = 0; 27 CameraCharacteristics characteristics; 28 29 @Override 30 protected void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.take_picture_activity); 33 res = getResources(); 34 35 this.wrapper = (RelativeLayout) findViewById(R.id.wrapper); 36 37 mTextureView = (TextureView) findViewById(R.id.takepicture_texture_view); 38 mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); 39 40 //撮影ボタンクリック時の処理 41 this.mBtnShot = (Button) findViewById(R.id.takepicture_btn_shoot); 42 this.mBtnShot.setOnClickListener(new OnClickListener() { 43 @Override 44 public void onClick(View v) { 45 takePicture(); 46 } 47 }); 48 49 this.setContentView(this.wrapper); 50 } 51 52 /** 53 * textureViewのサイズを変更 54 */ 55 private void changeTextureView(int dstWidth, int dstHeight) { 56 int tw = mTextureView.getWidth(); 57 int th = mTextureView.getHeight(); 58 { 59 int tmp = tw; 60 tw = th; 61 th = tmp; 62 } 63 double srcRatio = (double) dstHeight / dstWidth; 64 double tRatio = (double) th / tw; 65 int dw, dh; 66 if(tRatio < srcRatio) { 67 dw = (int) (th / srcRatio); 68 dh = th; 69 } 70 else { 71 dw = tw; 72 dh = (int) (dw * srcRatio); 73 } 74 mTextureView.setScaleY((float) dw / tw); 75 mTextureView.setScaleX((float) dh / th); 76 } 77 78 private void takePicture() { 79 80 if(mCameraDevice == null){ 81 Log.e(TAG, "mCameraDevice is null"); 82 return; 83 } 84 85 CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 86 try { 87 characteristics = manager.getCameraCharacteristics(mCameraDevice.getId()); 88 89 ImageReader reader = ImageReader.newInstance(CAM_WIDTH, CAM_HEIGHT, ImageFormat.JPEG, 1); 90 List<Surface> outputSurfaces = new ArrayList<>(); 91 outputSurfaces.add(reader.getSurface()); 92 outputSurfaces.add(new Surface(mTextureView.getSurfaceTexture())); 93 94 final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 95 captureBuilder.addTarget(reader.getSurface()); 96 captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 97 98 ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() { 99 @Override 100 public void onImageAvailable(ImageReader reader) { 101 Image image = reader.acquireLatestImage(); 102 103 ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 104 byte bytes[] = new byte[buffer.capacity()]; 105 buffer.get(bytes); 106 107 if (!zoomFlg) { 108 zoomTop = 0; 109 zoomLeft = 0; 110 } 111 if (zoomLeft > zoomTop) { 112 int tmp = zoomTop; 113 zoomTop = zoomLeft; 114 zoomLeft = tmp; 115 } 116 117 //TODO: メンテンス案件: Image からのクロップ 拡大率対応が必要 118 Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 119 120 // 希望するサイズを画像から得る 121 int srcWidth = image.getWidth(); 122 int srcHeight = image.getHeight(); 123 124 Bitmap rotBmp = Bitmap.createBitmap(cropMap, 0, 0, srcWidth, srcHeight, null, true); 125 126 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 127 rotBmp.compress(CompressFormat.JPEG, 90, baos); 128 byte[] dstBytes = baos.toByteArray(); 129 130 String base64Str = Base64.encodeToString(dstBytes, Base64.DEFAULT); 131 base64img = "data:image/jpeg;base64," + base64Str; 132 zoomFlg = false; 133 } 134 }; 135 136 HandlerThread thread = new HandlerThread("CameraCapture"); 137 thread.start(); 138 final Handler backgroundHandler = new Handler(thread.getLooper()); 139 reader.setOnImageAvailableListener(readerListener, backgroundHandler); 140 141 final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() { 142 @Override 143 public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 144 super.onCaptureCompleted(session, request, result); 145 Log.i(TAG, "onCaptureCompleted"); 146 mTextureView.setAlpha(1.0f); 147 closeCamera(); 148 } 149 150 }; 151 152 mCameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 153 @Override 154 public void onConfigured(CameraCaptureSession session) { 155 try { 156 session.capture(captureBuilder.build(), captureListener, backgroundHandler); 157 } catch (CameraAccessException e){ 158 e.printStackTrace(); 159 } 160 } 161 162 @Override 163 public void onConfigureFailed(CameraCaptureSession session) { 164 } 165 }, backgroundHandler); 166 } catch (CameraAccessException e){ 167 e.printStackTrace(); 168 } 169 } 170 171 private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() { 172 @Override 173 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 174 openCamera(); 175 } 176 @Override 177 public void onSurfaceTextureUpdated(SurfaceTexture surface) { } 178 @Override 179 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } 180 @Override 181 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 182 return false; 183 } 184 }; 185 186 private void setupZoomHandler(CameraCharacteristics cameraCharacteristics) { 187 ActiveArrayZoomHandlerBuilder.forView(mTextureView) 188 .setActiveArraySize(cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)) 189 .setMaxZoom(cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM ) * 10) 190 .setZoomListener(new ActiveArrayZoomHandler.IZoomHandlerListener() { 191 @Override 192 public void onZoomChanged(Rect zoom) { 193 mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom); 194 zoomTop = zoom.top; 195 zoomLeft = zoom.left; 196 zoomFlg = true; 197 updatePreview(); 198 } 199 }).build(); 200 } 201 202 private void openCamera() { 203 CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 204 try { 205 String camId = manager.getCameraIdList()[camIdx % manager.getCameraIdList().length]; 206 manager.openCamera(camId, mStateCallback, null); 207 } catch (CameraAccessException e){ 208 } catch (Exception e) { 209 closeCamera(); 210 } 211 } 212 213 /** 214 * カメラ終了時の処理 215 */ 216 private void closeCamera(){ 217 if(mCameraDevice == null) { 218 Log.e(TAG, "mCameraDevice is already closed."); 219 return; 220 } 221 mCameraDevice.close(); 222 } 223 224 private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { 225 @Override 226 public void onOpened(CameraDevice camera) { 227 mCameraDevice = camera; 228 Log.i(TAG, "mStateCallback.onOpened"); 229 startPreview(); 230 } 231 @Override 232 public void onError(CameraDevice camera, int error) { 233 Log.e(TAG, "error: " + error); 234 } 235 @Override 236 public void onDisconnected(CameraDevice camera) { } 237 }; 238 239 /** 240 * TextureViewに対しサイズを設定 241 */ 242 protected void startPreview() { 243 if(mCameraDevice == null || ! mTextureView.isAvailable()){ 244 Log.e(TAG, 245 "▼▼▼startPreview failed. mCameraDevice: " + mCameraDevice 246 + ", mTextureView.isAvailable: " + mTextureView.isAvailable() + "▼▼▼" 247 ); 248 return; 249 } 250 251 SurfaceTexture texture = mTextureView.getSurfaceTexture(); 252 if(texture == null){ 253 Log.e(TAG, "texture is null"); 254 return; 255 } 256 257 texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 258 Surface surface = new Surface(texture); 259 260 try { 261 mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 262 mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 263 } catch (CameraAccessException e){ 264 Log.e(TAG, "createCaptureRequest is failed."); 265 } 266 267 mPreviewBuilder.addTarget(surface); 268 try { 269 mCameraDevice.createCaptureSession( 270 Arrays.asList(surface), 271 new CameraCaptureSession.StateCallback() { 272 @Override 273 public void onConfigured(CameraCaptureSession session) { 274 mPreviewSession = session; 275 mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 276 updatePreview(); 277 } 278 @Override 279 public void onConfigureFailed(CameraCaptureSession session) { 280 Toast.makeText(TakePictureActivity.this, "onConfigureFailed", Toast.LENGTH_SHORT).show(); 281 } 282 }, 283 null 284 ); 285 } catch (CameraAccessException e){ 286 Log.e(TAG, "createCaptureSession is failed."); 287 } 288 } 289 290 private void updatePreview() { 291 292 if(mCameraDevice == null) { 293 Log.e(TAG, "mPreviewDevice is null"); 294 return; 295 } 296 297 //mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 298 HandlerThread thread = new HandlerThread("CameraPreview"); 299 thread.start(); 300 Handler backgroundHandler = new Handler(thread.getLooper()); 301 try { 302 mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, backgroundHandler); 303 } catch (CameraAccessException e){ 304 } 305 } 306 307} 308 309

ズーム機能自体は、別ファイルに分離しています。
BitmapFactory#decodeByteArrayでbitmapをクロップすればいい気がするのですが、うまく動作せず質問させていただきました。
よろしくお願い致します。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/10/27 05:28

「うまく動作せず」を具体的に書いてください。
Begi

2018/10/28 05:51

コメントありがとうございます。decodeByteArrayの第三引数のlengthを減らしてみたり、などてす。根本的な仕組みの理解が足りておらずすみません。
Wind

2018/11/15 06:16

ソースをざっと見ただけですので見当外れかもしれませんが、ZoomLeftやZoomTopに値を入れた後、これらの値を何も使っていないように見えますがどうでしょう?
guest

回答1

0

自己解決

takePicture()メソッドの
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
のタイミングでcaptureBuilderに対してSCALER_CROP_REGIONをセットしたら拡大した画像が保存できました。
具体的には、別メソッドで設定したRect型のzoomが設定されていればセットするという処理を行いました。
if (zoom != null) {
captureBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
}

yukke_さん、Windさんコメントありがとうございました。

投稿2018/11/27 12:39

Begi

総合スコア56

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問