2016-05-10 4 views
3

Я пытаюсь использовать камеру в своем приложении, и я хочу использовать ее в ландшафтном и портретном режимах. Мне не сложно создавать картинки в ландшафтном режиме, но я не нашел хороший способ сохранить фотографии в портретном режиме.Android-камера Сохранение изображений в портретном режиме

Когда я хочу, чтобы сделать снимок в портретном режиме Мне нужно установить displayorientation к портрету первой, как это:

switch (windowManager.getDefaultDisplay().getRotation()) { 
    case android.view.Surface.ROTATION_0: 
     mCamera.setDisplayOrientation(90); 
     break; 
    case android.view.Surface.ROTATION_90: 
     mCamera.setDisplayOrientation(0); 
     break; 
    case android.view.Surface.ROTATION_180: 
     mCamera.setDisplayOrientation(270); 
     break; 
    case android.view.Surface.ROTATION_270: 
     mCamera.setDisplayOrientation(180); 
     break; 
} 

Но картина все еще сохраняется в ландшафтном режиме. Одно решение, которое я нашел в том, чтобы изменить параметр вращения камеры, как это:

public void onOrientationChanged(int orientation) { 
    if (orientation == ORIENTATION_UNKNOWN) return; 
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    orientation = (orientation + 45)/90 * 90; 
    int rotation = 0; 
    if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { 
     rotation = (info.orientation - orientation + 360) % 360; 
    } else { // back-facing camera 
     rotation = (info.orientation + orientation) % 360; 
    } 
    mParameters.setRotation(rotation); 
} 

Проблема такого подхода заключается в том, что он может просто установить ориентацию в заголовке EXIF ​​и на самом деле не повернуть изображение (которое является с устройством, которое я использую).

Другой подход вращался фактические данные после того, как снимок сделан так:

Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length); 
int w = bitmap.getWidth(); 
int h = bitmap.getHeight(); 
Matrix mtx = new Matrix(); 
mtx.postRotate(rotate); 
bitmap= Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); 
ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); 
currentData = stream.toByteArray(); 

Но этот подход занимает 10 секунд (что слишком долго), и в то время как я мог бы поставить этот код в AsyncTask, я нужны данные через несколько секунд, поэтому мне все равно придется ждать.

До сих пор я не нашел лучшего решения.

+0

Напишите код NDK для выполнения поворота изображения. – CommonsWare

+0

@CommonsWare Я никогда не использовал NDK, и, когда я его просматривал, было рекомендовано не использовать его, если вы не делаете действительно интенсивный материал, или если вы хорошо знакомы с C/C++ (я их никогда не использовал). И хотя моя проблема связана с производительностью, я чувствую, что должен быть другой (лучший) способ сделать это. Я также опасаюсь, что NDK может испортить некоторые из моих приложений. –

+1

«вы делаете действительно интенсивный материал» - вращение мультимегапиксельного изображения, где вам «нужны данные сразу после», будет квалифицироваться как «действительно интенсивный материал». – CommonsWare

ответ

2

Я нашел решение, которое заставляет меня по-прежнему ждать второй или две, но это достаточно быстро для меня. Это довольно легко исправить, просто использовать метод Matrix.postRotate, но изменить:

bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); 

к:

bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); 

Для меня это очень хорошее решение, особенно потому, что везде я уже использовал .jpg, поэтому в любом случае это не сильно сжимало Bitmap .png.