【问题标题】:android camera setDisplayOrientation(90) fails in different devicesandroid camera setDisplayOrientation(90) 在不同的设备上失败
【发布时间】:2012-08-18 08:31:26
【问题描述】:

我的相机应用有问题。相机活动处于纵向模式。所以我给了

camera.setDisplayOrientation(90);

根据 SO 中的不同帖子,这将在纵向模式下正常工作。

但它在不同的设备上永远无法正常工作。问题是,预览向左或向右旋转 90 度。在 Htc 中没关系。但是对于银河系列,它不起作用。

谁能帮帮我?

【问题讨论】:

    标签: android orientation android-camera


    【解决方案1】:

    按以下不同方式设置方向和预览,按要求使用:

    第一种方法:

      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
      {            
        if (isPreviewRunning)
        {
            mCamera.stopPreview();
        }
    
        Parameters parameters = mCamera.getParameters();
        Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
    
        if(display.getRotation() == Surface.ROTATION_0)
        {
            parameters.setPreviewSize(height, width);                           
            mCamera.setDisplayOrientation(90);
        }
    
        if(display.getRotation() == Surface.ROTATION_90)
        {
            parameters.setPreviewSize(width, height);                           
        }
    
        if(display.getRotation() == Surface.ROTATION_180)
        {
            parameters.setPreviewSize(height, width);               
        }
    
        if(display.getRotation() == Surface.ROTATION_270)
        {
            parameters.setPreviewSize(width, height);
            mCamera.setDisplayOrientation(180);
        }
    
        mCamera.setParameters(parameters);
        previewCamera();                      
    }
    

      public void previewCamera()
      {        
         try 
         {           
              mCamera.setPreviewDisplay(mSurfaceHolder);          
              mCamera.startPreview();
              isPreviewRunning = true;
         }
         catch(Exception e)
         {
             Log.d(APP_CLASS, "Cannot start preview", e);    
         }
     }
    

    第二种方式:

      private Camera mCamera;
      private OrientationEventListener mOrientationEventListener;
      private int mOrientation =  -1;
    
     private static final int ORIENTATION_PORTRAIT_NORMAL =  1;
     private static final int ORIENTATION_PORTRAIT_INVERTED =  2;
     private static final int ORIENTATION_LANDSCAPE_NORMAL =  3;
     private static final int ORIENTATION_LANDSCAPE_INVERTED =  4;
    
     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
             // force Landscape layout
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR |           ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
       /*
          Your other initialization code here
       */
       }
    
     @Override 
      protected void onResume() {
           super.onResume();
    
            if (mOrientationEventListener == null) {            
                  mOrientationEventListener = new OrientationEventListener(this,  SensorManager.SENSOR_DELAY_NORMAL) {
    
            @Override
            public void onOrientationChanged(int orientation) {
    
                // determine our orientation based on sensor response
                int lastOrientation = mOrientation;
    
                if (orientation >= 315 || orientation < 45) {
                    if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          
                        mOrientation = ORIENTATION_PORTRAIT_NORMAL;
                    }
                }
                else if (orientation < 315 && orientation >= 225) {
                    if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
                        mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
                    }                       
                }
                else if (orientation < 225 && orientation >= 135) {
                    if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
                        mOrientation = ORIENTATION_PORTRAIT_INVERTED;
                    }                       
                }
                else { // orientation <135 && orientation > 45
                    if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
                        mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
                    }                       
                }   
    
                if (lastOrientation != mOrientation) {
                    changeRotation(mOrientation, lastOrientation);
                }
            }
        };
    }
    if (mOrientationEventListener.canDetectOrientation()) {
        mOrientationEventListener.enable();
        }
     }
    
      @Override protected void onPause() {
           super.onPause();
           mOrientationEventListener.disable();
      }
    
        /**
         * Performs required action to accommodate new orientation
         * @param orientation
         * @param lastOrientation
        */
       private void changeRotation(int orientation, int lastOrientation) {
       switch (orientation) {
        case ORIENTATION_PORTRAIT_NORMAL:
            mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 270));
            mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 270));
            Log.v("CameraActivity", "Orientation = 90");
            break;
        case ORIENTATION_LANDSCAPE_NORMAL:
            mSnapButton.setImageResource(android.R.drawable.ic_menu_camera);
            mBackButton.setImageResource(android.R.drawable.ic_menu_revert);
            Log.v("CameraActivity", "Orientation = 0");
            break;
        case ORIENTATION_PORTRAIT_INVERTED:
            mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 90));
            mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 90));
            Log.v("CameraActivity", "Orientation = 270");
            break;
        case ORIENTATION_LANDSCAPE_INVERTED:
            mSnapButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_camera, 180));
            mBackButton.setImageDrawable(getRotatedImage(android.R.drawable.ic_menu_revert, 180));      
            Log.v("CameraActivity", "Orientation = 180");
            break;
         }
      } 
    
        /**
       * Rotates given Drawable
       * @param drawableId    Drawable Id to rotate
       * @param degrees       Rotate drawable by Degrees
       * @return              Rotated Drawable
       */
     private Drawable getRotatedImage(int drawableId, int degrees) {
        Bitmap original = BitmapFactory.decodeResource(getResources(), drawableId);
        Matrix matrix = new Matrix();
        matrix.postRotate(degrees);
    
       Bitmap rotated = Bitmap.createBitmap(original, 0, 0, original.getWidth(),  original.getHeight(),  matrix, true);
      return new BitmapDrawable(rotated);
    }
    

    然后在您的 PictureCallback 中设置元数据以指示旋转级别:

    private Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() {
    
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        try {
            // Populate image metadata
    
            ContentValues image = new ContentValues();
            // additional picture metadata
            image.put(Media.DISPLAY_NAME, [picture name]);
            image.put(Media.MIME_TYPE, "image/jpg");
            image.put(Media.TITLE, [picture title]);
            image.put(Media.DESCRIPTION, [picture description]);
            image.put(Media.DATE_ADDED, [some time]);
            image.put(Media.DATE_TAKEN, [some time]);
            image.put(Media.DATE_MODIFIED, [some time]);
    
            // do not rotate image, just put rotation info in
            switch (mOrientation) {
                case ORIENTATION_PORTRAIT_NORMAL:
                    image.put(Media.ORIENTATION, 90);
                    break;
                case ORIENTATION_LANDSCAPE_NORMAL:
                    image.put(Media.ORIENTATION, 0);
                    break;
                case ORIENTATION_PORTRAIT_INVERTED:
                    image.put(Media.ORIENTATION, 270);
                    break;
                case ORIENTATION_LANDSCAPE_INVERTED:
                    image.put(Media.ORIENTATION, 180);
                    break;
            }
    
            // store the picture
            Uri uri = getContentResolver().insert(
                    Media.EXTERNAL_CONTENT_URI, image);
    
            try {
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
                        data.length);
                OutputStream out = getContentResolver().openOutputStream(
                        uri);
                boolean success = bitmap.compress(
                        Bitmap.CompressFormat.JPEG, 75, out);
                out.close();
                if (!success) {
                    finish(); // image output failed without any error,
                                // silently finish
                }
    

    现在,当基于横向的设备出现时,需要在 OrientationEventListener 中对其进行额外检查。

      Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();                                        
     if (display.getOrientation() == Surface.ROTATION_0) { 
        // landscape oriented devices
     } else { 
         // portrait oriented device
     }
    

    完整代码(LC有点浪费,但很容易演示该方法)

     @Override
     public void onOrientationChanged(int orientation) {
    
    // determine our orientation based on sensor response
    int lastOrientation = mOrientation;
    
    Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();                                        
    
    if (display.getOrientation() == Surface.ROTATION_0) {   // landscape oriented devices
        if (orientation >= 315 || orientation < 45) {
            if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {                         
                mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
            }
        } else if (orientation < 315 && orientation >= 225) {
            if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
                mOrientation = ORIENTATION_PORTRAIT_INVERTED;
            }                       
        } else if (orientation < 225 && orientation >= 135) {
            if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
                mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
            }                       
        } else if (orientation <135 && orientation > 45) { 
            if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
                mOrientation = ORIENTATION_PORTRAIT_NORMAL;
            }                       
        }                       
    } else {  // portrait oriented devices
        if (orientation >= 315 || orientation < 45) {
            if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          
                mOrientation = ORIENTATION_PORTRAIT_NORMAL;
            }
        } else if (orientation < 315 && orientation >= 225) {
            if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
                mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
     }                       
        } else if (orientation < 225 && orientation >= 135) {
            if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
                mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
            }                       
        } else if (orientation <135 && orientation > 45) { 
            if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {
                mOrientation = ORIENTATION_PORTRAIT_NORMAL;
            }                       
        }                       
    } else {  // portrait oriented devices
        if (orientation >= 315 || orientation < 45) {
            if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          
                mOrientation = ORIENTATION_PORTRAIT_NORMAL;
            }
        } else if (orientation < 315 && orientation >= 225) {
            if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) {
                mOrientation = ORIENTATION_LANDSCAPE_NORMAL;
            }                       
        } else if (orientation < 225 && orientation >= 135) {
            if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) {
                mOrientation = ORIENTATION_PORTRAIT_INVERTED;
            }                       
        } else if (orientation <135 && orientation > 45) { 
            if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) {
                mOrientation = ORIENTATION_LANDSCAPE_INVERTED;
            }                       
        }
     }
    
      if (lastOrientation != mOrientation) {
        changeRotation(mOrientation, lastOrientation);
      }
     }
    

    第三种方式:

     private Bitmap adjustImageOrientation(Bitmap image) {
        ExifInterface exif;
        try {
            exif = new ExifInterface(picturePath);
            int exifOrientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
    
            int rotate = 0;
            switch (exifOrientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;
    
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;
    
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
            }
    
            if (rotate != 0) {
                int w = image.getWidth();
                int h = image.getHeight();
    
                // Setting pre rotate
                Matrix mtx = new Matrix();
                mtx.preRotate(rotate);
    
                // Rotating Bitmap & convert to ARGB_8888, required by tess
                image = Bitmap.createBitmap(image, 0, 0, w, h, mtx, false);
    
            }
        } catch (IOException e) {
                 return null;
        }
        return image.copy(Bitmap.Config.ARGB_8888, true);
    }
    

    【讨论】:

      【解决方案2】:

      我给这个answer 提供了一个类似的问题,但正如你所说,它是在 HTC 设备上。我建议您在旋转代码中添加断点并在物理旋转设备时检查变量 - 这可能有助于识别 Galaxy 模型的不同之处。

      【讨论】:

        【解决方案3】:

        检查是否在手机设置中选中了“自动旋转屏幕”选项(设置 > 显示或屏幕 - 取决于 android 版本)。

        【讨论】:

          【解决方案4】:

          刚刚发布了一个对我有用的新解决方案。

          基本上你可以从 Camera.CameraInfo 中获取方向值。这将告诉您需要在 setDisplayOrientation 上使用的度数,以便正确显示图像。使用后置摄像头时,您可以简单地使用 setDisplayOrientation 并检索到值,但是当使用前置摄像头时,您需要稍微调整一下,因为 Android 系统会翻转图像,使其看起来像镜子。

          以下代码对我有用,并在 4 种不同的设备上进行了测试,包括 Nexus6 和 Galaxy。

          Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
          int cameraCount = Camera.getNumberOfCameras();
          int camIdx = 0; // DO your logic to get front or back camera...or loop through all avaialable.
          Camera.getCameraInfo(camIdx, cameraInfo);
          
          try {
              mCamera = Camera.open(camIdx);
              // If using back camera then simply rotate what CameraInfo tells you.
              if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)
                  mCamera.setDisplayOrientation(cameraInfo.orientation);
              else
                  // If using front camera note that image might be flipped to give users the impresion the are looking at a mirror.
                  mCamera.setDisplayOrientation( (360 - cameraInfo.orientation) % 360);
          } catch (Exception e) {
              e.printStackTrace();
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-07-05
            • 2018-04-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-13
            • 1970-01-01
            相关资源
            最近更新 更多