Android Camera 預(yù)覽圖像被拉伸變形的解決方法

標(biāo)簽: Android 相機(jī)


最近做了一段時間的相機(jī)開發(fā),有一些感悟,所以在這里整理分享出來。在這個過程中也出現(xiàn)了一些問題,比如預(yù)覽的時候圖像是被拉伸的,預(yù)覽的時候旋轉(zhuǎn)圖片變形,把手機(jī)旋轉(zhuǎn)90的時候預(yù)覽圖片是變形的等等,很多問題。其實最后的原因都是歸因于分辨率。為什么會這么說,下面一點(diǎn)點(diǎn)分析。

自定義相機(jī),從用戶的操作的角度來看,有兩個部分。一個是看手機(jī)屏幕的圖像,一個是點(diǎn)擊拍攝照片(有特殊功能的除外,說的都是一般的相機(jī))。在這兩部中,其實都是在跟圖像打交道,手機(jī)屏幕上的圖像其實就是一幀幀硬件相機(jī)掃描出來的結(jié)果,點(diǎn)擊照相時就是把這一幀幀的圖像挑選出來某一幀。

那說道圖像,我想問個問題,“什么樣的圖像顯示是正常的呢?“可能這個問題有些人不理解,也不知道怎么回答。我有一個答案,不知道說的對不對,但是我目前是這么認(rèn)為的,如果要是有不同的意見,可以留言,大家一起討論。我認(rèn)為圖像要是顯示正常,應(yīng)該是圖像的大小跟分辨率匹配,圖像的分辨率是表述像素點(diǎn)的多少的。那假設(shè)我有一個寬3,高4的圖像,而在圖像上的像素點(diǎn)卻是,寬4個,高3個。那這種的話,像素點(diǎn)描述出來的圖片肯定不是我們想要的,是被拍扁了的一張圖片。所以自定義相機(jī)就應(yīng)該是解決如何選擇一個合適的分辨率設(shè)置給相機(jī),而且應(yīng)該是跟圖像的寬高有關(guān)。

那下面就看看如果選擇一個合適的分辨率。在android官方的demo例子里面是有相關(guān)的代碼的。

private static Camera.Size getOptimalSize(@NonNull List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) h / w;
    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    for (Camera.Size size : sizes) {
      double ratio = (double) size.width / size.height;
      if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
      if (Math.abs(size.height - targetHeight) < minDiff) {
        optimalSize = size;
        minDiff = Math.abs(size.height - targetHeight);
      }
    }

    if (optimalSize == null) {
      minDiff = Double.MAX_VALUE;
      for (Camera.Size size : sizes) {
        if (Math.abs(size.height - targetHeight) < minDiff) {
          optimalSize = size;
          minDiff = Math.abs(size.height - targetHeight);
        }
      }
    }

    return optimalSize;
  }

其實很多人會覺得,都有現(xiàn)成的代碼了,直接粘貼一些就好了,為啥上面說那么一堆。其實有這個方法在,好也好在這里,壞也壞在這里。需要注意的就是這么一行

double targetRatio = (double) h / w;

這里的代碼是h/w,但是在官方的例子里面是w/h。因為在官方的demo里相機(jī)是橫向的,但是我們一般使用的相機(jī)或者自定義的相機(jī)都是豎向的。至于設(shè)置橫豎向,其實在AndroidMainfest.xml里面設(shè)置的

    <activity android:name=".CameraActivity"
        android:screenOrientation="portrait"/>

上面設(shè)置的是豎向,如果沒有設(shè)置是橫向。繼續(xù)上面說的,為什么跟官方demo的不一樣,其實就是因為官方的例子是橫向的,所以得出來的w是大于h的,而我們的是豎向的,所以w是小于h。這樣的話,就造成了篩選分辨率錯誤。(這里的w是指用SurfaceView的寬,h指的是SurfaceView的高,SurfaceView是用來預(yù)覽的控件)

通過上面的getOptimalSize()方法就解決了挑選適合的分辨率,那圖片也就顯示正常了。只要設(shè)置分辨率的時機(jī)適當(dāng),相機(jī)就不會出現(xiàn)圖片被拉伸的問題了。

有人會說那我能不能直接拿SurfaceView的寬高當(dāng)作分辨率,我只能說有的手機(jī)是可行的,但不是所有的手機(jī)都支持自定義分比率,有的手機(jī)支持自帶的幾種分比率

Camera.Parameters cameraParameter = camera.getParameters();
cameraParameter.getSupportedPreviewSizes()

所以最好還是就在這幾個分辨率里面挑

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容