【问题标题】:issue with image rotation on android devicesAndroid设备上的图像旋转问题
【发布时间】:2014-03-01 18:12:55
【问题描述】:

我在我的 Android 应用中创建了一个自定义相机活动,但我遇到了图像根据拍摄设备旋转 90 度的问题。这只发生在特定设备上,我似乎无法弄清楚为什么。

我在应用中所做的是

  1. 更新变量“mOrientation”,以度 (0-360) 为单位保存手机的当前方向
  2. 当用户点击快门按钮时,我会检查上次保存的方向,并在保存之前相应地旋转图像。

我在两种不同的设备上进行了测试,华为手机和三星 Galaxy S II。我发现虽然我能够确定手机的方向正在正确更新并且两者都有默认的纵向方向,但它们需要不同的“mOrientation”值,偏移 90 度,以便保存时方向正确。

这是我检查当前方向的方法:

public void onOrientationChanged(int orientation) {
if(cameraPreview.getDeviceDefaultOrientation() == Configuration.ORIENTATION_PORTRAIT){
    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;
        }                       
    }   
}else{
   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 { // orientation <135 && orientation > 45
        if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) {                          
        mOrientation = ORIENTATION_PORTRAIT_NORMAL;
    }
  }
}

这是我保存图像的方式:

private PictureCallback myPictureCallback_JPG = new PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera cam) {
        Log.d(TAG, "saving picture");
        Log.d(TAG, "portrait image? " + Boolean.toString(cameraPreview.getDeviceDefaultOrientation() == Configuration.ORIENTATION_PORTRAIT));
        Log.d(TAG, "mOrientaiton: " + mOrientation);

        //Degrees to rotate image by when saving
        int degree = 0;

        // do not rotate image, just put rotation info in
        if(cameraPreview.getDeviceDefaultOrientation() == Configuration.ORIENTATION_PORTRAIT){
            switch (mOrientation) {
            case ORIENTATION_LANDSCAPE_INVERTED:
                Log.d(TAG, "orientation landscape inverted");
                degree = 90;
                break;
            case ORIENTATION_PORTRAIT_NORMAL:
                Log.d(TAG, "orientation portrait normal");
                degree = 0;
                break;
            case ORIENTATION_LANDSCAPE_NORMAL:
                Log.d(TAG, "orientation landscape normal");
                degree = 270;
                break;
            case ORIENTATION_PORTRAIT_INVERTED:
                Log.d(TAG, "orientation portrait inverted");
                degree = 180;
                break;
            }
        }else{
            switch (mOrientation) {
            case ORIENTATION_LANDSCAPE_INVERTED:
                degree = 270;
                break;
            case ORIENTATION_PORTRAIT_NORMAL:
                degree = 180;
                break;
            case ORIENTATION_LANDSCAPE_NORMAL:
                degree = 0;
                break;
            case ORIENTATION_PORTRAIT_INVERTED:
                degree = 90;
                break;
            }
        }

        Bitmap bMap;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 6;
        options.inDither = false; // Disable Dithering mode
        options.inPurgeable = true; // Tell to gc that whether it needs free
        // memory, the Bitmap can be cleared
        options.inInputShareable = true; // Which kind of reference will be
        // used to recover the Bitmap
        // data after being clear, when
        // it will be used in the future
        options.inTempStorage = new byte[32 * 1024];
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        bMap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
        if(degree != 0){
            bMap = rotate(bMap, degree);
        }

        //Getting the picture's unique file to be added to the folder
        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);

        /*
         * This catches errors when creating the output file to put the picture in
         */
        if (pictureFile == null) {
            Log.d(TAG,"Error creating media file, check storage permissions");

            //After the camera has finished taking the picture
            handler.post(new Runnable(){

                @Override
                public void run() {
                    //Remove white border from preview
                    Log.d(TAG, "removing white background from preview");
                    cameraPreview.setBackgroundResource(0);                 
                }

            });
            //Setting the onclicklistener back on the shutter
            shutter.setOnClickListener(shutterClickListener);

            //Restarting the preview as soon as picture is done
            camera.startPreview();

            Toast.makeText(getApplicationContext(), "Error saving file. Try restarting the camera.", Toast.LENGTH_LONG).show();

            return;
        }

        FileOutputStream out = null;
        try {
            //Saving the image
            out = new FileOutputStream(pictureFile);
            bMap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            if (bMap != null) {
                bMap.recycle();
                bMap = null;
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally{
            try {
                //Assuring we always close the output stream
                if(out!=null){
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        myHorizontalLayout.add(Uri.parse(pictureFile.getPath()));

          MediaScannerConnection.scanFile(getApplicationContext(), new String[] { Environment.getExternalStorageDirectory().toString() }, null, new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) 
                  {
                      Log.i("ExternalStorage", "Scanned " + path + ":");
                      Log.i("ExternalStorage", "-> uri=" + uri);

                      camera.startPreview();

                      if(myHorizontalLayout.getItemList().size() == 1){
                          //Have added the first item to the pictures set check to green
                          MenuItem check = menu.findItem(R.id.save);
                      }

                      //After the camera has finished taking the picture
                      handler.post(new Runnable(){
                          @Override
                          public void run() {
                              //Remove white border from preview
                              Log.d(TAG, "removing white background");
                              cameraPreview.setBackgroundResource(0);                 
                          }
                      });
                      //Setting the onclicklistener back on the shutter
                      shutter.setOnClickListener(shutterClickListener);
                  }
                });


    }
};

如果有人能帮我解决这个问题,我将不胜感激。此外,如果有人对如何在无需拥有许多不同品牌的手机的情况下跨 Android 设备测试相机配置有一般性建议,我也将不胜感激。

【问题讨论】:

    标签: android camera rotation android-camera


    【解决方案1】:

    图像根据拍摄的设备旋转 90 度时遇到问题

    您的图片在技术上可能没问题。有些设备本身不旋转图像,而是设置一个 EXIF 标头告诉图像 viewer 旋转图像。并非所有图像查看器都这样做。

    另外,如果有人对如何在 Android 设备上测试摄像头配置而无需拥有许多不同品牌的手机有一般性建议,我也将不胜感激。

    依靠somebody else 为您完成这项工作。 :-)

    【讨论】:

    • 感谢您的帮助!我最终通过检查设备是否是华为设备并基于此偏移图像旋转来解决问题(我非正式地看到该应用程序在其他设备上运行,而华为设备是我见过的唯一一个有有问题)。
    • @scientiffic:哦,相信我,更多设备设置 EXIF 标头而不是实际旋转图像。
    • 在我应用轮换之前有什么方法可以让我检查一下吗?
    • @scientiffic:欢迎您检查 EXIF 方向标头是否存在并据此采取措施。
    • 感谢您的帮助。如何在保存文件之前检索 exif 方向?您是否建议保存图像,然后根据 exif 方向标头应用旋转?
    猜你喜欢
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    相关资源
    最近更新 更多