草庐IT

android camera setDisplayOrientation(90) 在不同的设备上失败

coder 2023-11-24 原文

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

camera.setDisplayOrientation(90);

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

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

谁能帮帮我?

最佳答案

通过以下不同方式设置方向和预览,按需使用:

第一种方法:

  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);
}

关于android camera setDisplayOrientation(90) 在不同的设备上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12017148/

有关android camera setDisplayOrientation(90) 在不同的设备上失败的更多相关文章

  1. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  2. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  3. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  4. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

  5. ruby - 正则表达式在哪个位置失败? - 2

    我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束

  6. ruby - 使用 rbenv 和 ruby​​-build 构建 ruby​​ 失败,出现 undefined symbol : SSLv2_method - 2

    我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby​​2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby​​-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm

  7. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

  8. ruby-on-rails - 禁用设备的 :confirmable on-the-fly to batch-generate users - 2

    Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation

  9. ruby-on-rails - Ruby 的 'open_uri' 是否在读取或失败后可靠地关闭套接字? - 2

    一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我

  10. ruby-on-rails - Ruby 流量控制 : throw an exception, 返回 nil 还是让它失败? - 2

    我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id

随机推荐