2011-12-01 12 views
22

Piszę aplikację na Androida, która korzysta z aparatu. mam ustawienie kamery orientację ekranu do 90, moja działalność jest w orientacji pionowej:Obraz z kamery systemu Android powinien zostać obrócony po przechwyceniu?

camera.setDisplayOrientation(90); 

Dostaję dobrze zorientowany obraz podglądu, ale powstały obraz jest obrócony do -90 stopni (w kierunku przeciwnym do ruchu wskazówek zegara) i

exif.getAttribute(ExifInterface.TAG_ORIENTATION) 

powraca ORIENTATION_NORMAL
Czy to normalne zachowanie? Czy powinienem obrócić wynikowy obraz po przechwyceniu?

urządzenia - Nexus S API - 10

+0

To samo dzieje się ze mną; Jestem też na Nexus S API 10; dzięki za pytanie. – serkanozel

+0

Odpowiedz tutaj http://stackoverflow.com/questions/14066038/why-image-captured-using-camera-intent-gets-rotated-on-some-devices-in-android –

+1

Możliwy duplikat [Dlaczego przechwycono obraz za pomocą kamery cel jest obracany na niektórych urządzeniach w systemie Android?] (https://stackoverflow.com/questions/14066038/why-does-an-image-captured-using-camera-intent-gets-rotated-on-some-devices -on-a) – bummi

Odpowiedz

13

Problem orientacja aparatu całkowitą katastrofą (jak również uchwycenie obrazu), ponieważ producenci sprzętu nie przylegają do normy. Telefony HTC robią wszystko w jedną stronę, telefony Samsung robią to inaczej, linia Nexus wydaje się trzymać bez względu na to, który sprzedawca, ROMy oparte na CM7, myślę, że podążają za standardem bez względu na sprzęt, ale masz pomysł. W pewnym sensie musisz zdecydować, co zrobić w oparciu o telefon/ROM. Zobacz dyskusję tutaj: Android camera unexplainable rotation on capture for some devices (not in EXIF)

21

Spróbuj

try { 
     File f = new File(imagePath); 
     ExifInterface exif = new ExifInterface(f.getPath()); 
     int orientation = exif.getAttributeInt(
       ExifInterface.TAG_ORIENTATION, 
       ExifInterface.ORIENTATION_NORMAL); 

     int angle = 0; 

     if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { 
      angle = 90; 
     } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { 
      angle = 180; 
     } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { 
      angle = 270; 
     } 

     Matrix mat = new Matrix(); 
     mat.postRotate(angle); 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inSampleSize = 2; 

     Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), 
       null, options); 
     bitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), 
       bmp.getHeight(), mat, true); 
     ByteArrayOutputStream outstudentstreamOutputStream = new ByteArrayOutputStream(); 
     bitmap.compress(Bitmap.CompressFormat.PNG, 100, 
       outstudentstreamOutputStream); 
     imageView.setImageBitmap(bitmap); 

    } catch (IOException e) { 
     Log.w("TAG", "-- Error in setting image"); 
    } catch (OutOfMemoryError oom) { 
     Log.w("TAG", "-- OOM Error in setting image"); 
    } 

Będzie pracować

+2

Jakiekolwiek potwierdzenie tego działania? – JoaoFilipeClementeMartins

+2

Nie, dint działa dla mnie! – AabidMulani

+2

ciekawy jak doszedłeś do wniosku, że to zadziała dla wszystkich urządzeń. – sudocoder

1
camera.setDisplayOrientation(90); 

I zostały zakodowane app dla tylko w trybie portretowym.

Uczyni aparatu, aby obrócić do 90 stopni, a to może spowodować nie nadaje się dla wszystkich urządzeń Android W celu uzyskania prawidłowego Preview dla wszystkich urządzeń z systemem Android użyć następującego kodu, który sędziował w Twórcy.

Poniżej trzeba wysłać swoją aktywność, cameraId = powrotem wynosi 0, a dla Przednia kamera jest 1

public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { 
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
     case Surface.ROTATION_0: 
      degrees = 0; 
      break; 
     case Surface.ROTATION_90: 
      degrees = 90; 
      break; 
     case Surface.ROTATION_180: 
      degrees = 180; 
      break; 
     case Surface.ROTATION_270: 
      degrees = 270; 
      break; 
    } 

    int result; 
    //int currentapiVersion = android.os.Build.VERSION.SDK_INT; 
     // do something for phones running an SDK before lollipop 
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
      result = (info.orientation + degrees) % 360; 
      result = (360 - result) % 360; // compensate the mirror 
     } else { // back-facing 
      result = (info.orientation - degrees + 360) % 360; 
     } 

    camera.setDisplayOrientation(result); 
} 

To jest jak ustawić setDisplayOrientation dla kamery

Teraz możesz mieć problemy oszczędza przechwycony obraz w prawidłowej orientacji, który jest błędem w interfejsie API aparatu, który obsługuje wszystkie urządzenia w systemie Android. można przezwyciężyć stosując poniższe kroki

PLS UWAGA EXIF ​​WARTOŚCI nie da ci poprawną wartość we wszystkich urządzeniach, więc to pomoże Ci

int CameraEyeValue = setPhotoOrientation(CameraActivity.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back 

Stosując tę ​​samą koncepcję użyliśmy wcześniej do DisplayOrientation

public int setPhotoOrientation(Activity activity, int cameraId) { 
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
     case Surface.ROTATION_0: 
      degrees = 0; 
      break; 
     case Surface.ROTATION_90: 
      degrees = 90; 
      break; 
     case Surface.ROTATION_180: 
      degrees = 180; 
      break; 
     case Surface.ROTATION_270: 
      degrees = 270; 
      break; 
    } 

    int result; 
    // do something for phones running an SDK before lollipop 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
     result = (info.orientation + degrees) % 360; 
     result = (360 - result) % 360; // compensate the mirror 
    } else { // back-facing 
     result = (info.orientation - degrees + 360) % 360; 
    } 

    return result; 
} 

Więc ostateczna metoda PictureCallBack powinien wyglądać

private PictureCallback getPictureCallback() { 
    PictureCallback picture = new PictureCallback() { 

     @Override 
     public void onPictureTaken(byte[] data, Camera camera) { 
      //make a new picture file 
      File pictureFile = getOutputMediaFile(); 

      if (pictureFile == null) { 
       return; 
      } 
      try { 
       //write the file 
       FileOutputStream fos = new FileOutputStream(pictureFile); 
       Bitmap bm=null; 

       // COnverting ByteArray to Bitmap - >Rotate and Convert back to Data 
       if (data != null) { 
        int screenWidth = getResources().getDisplayMetrics().widthPixels; 
        int screenHeight = getResources().getDisplayMetrics().heightPixels; 
        bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0); 

        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 
         // Notice that width and height are reversed 
         Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true); 
         int w = scaled.getWidth(); 
         int h = scaled.getHeight(); 
         // Setting post rotate to 90 
         Matrix mtx = new Matrix(); 

         int CameraEyeValue = setPhotoOrientation(AndroidCameraExample.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back 
         if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation 
          if (CameraEyeValue == 270) { 
           mtx.postRotate(90); 
          } else if (CameraEyeValue == 90) { 
           mtx.postRotate(270); 
          } 
         }else{ 
           mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation 
         } 

         bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true); 
        }else{// LANDSCAPE MODE 
         //No need to reverse width and height 
         Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth, screenHeight, true); 
         bm=scaled; 
        } 
       } 
       // COnverting the Die photo to Bitmap 



       ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
       bm.compress(Bitmap.CompressFormat.JPEG, 100, stream); 
       byte[] byteArray = stream.toByteArray(); 
       fos.write(byteArray); 
       //fos.write(data); 
       fos.close(); 

       Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG); 
       toast.show(); 

      } catch (FileNotFoundException e) { 
      } catch (IOException e) { 
      } 

      //refresh camera to continue preview 
      mPreview.refreshCamera(mCamera); 
      mPreview.setCameraDisplayOrientation(CameraActivity.this,GlobalCameraId,mCamera); 
     } 
    }; 
    return picture; 
} 

Ponieważ działa tylko w trybie portretu przy użyciu kamery przedniej i tylnej Obraz jest obracany tylko do portretu z prawidłową orientacją portretu we wszystkich urządzeniach z systemem Android.

Na krajobraz można zrobić to jako punkt odniesienia i wprowadzić zmiany w poniższym bloku

if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation 
     if (CameraEyeValue == 270) { 
      mtx.postRotate(90); //change Here 
      } else if (CameraEyeValue == 90) { 
      mtx.postRotate(270);//change Here 
      } 
     }else{ 
      mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation //change Here 
     } 
+0

Chcę, aby przechwytywany obraz był zawsze portretem, ale nie mogłem znaleźć kąta obrotu dla bitmapy. –

4

miałem ten sam problem jak ty, ale ja go naprawić.
Należy użyć tego samego kodu:

Camera.Parameters parameters = camera.getParameters(); 
parameters.setRotation(90); 
camera.setParameters(parameters); 

mam nadzieję, że można użyć tego kodu zbyt.

Powiązane problemy