簡體   English   中英

縱向模式下的相機風景預覽

[英]Camera landscape preview in portrait mode

我有一個對話框設計,其中相機預覽應該在人像模式下為橫向(請參見圖片)。 我通過getOptimalPreviewSize()正確選擇了預覽大小,當我不使用setDisplayOrientation(90)時,我得到了:

在此處輸入圖片說明

當我使用setDisplayOrientation(90)時,我得到了:

在此處輸入圖片說明

有人有任何解決辦法的想法嗎? android可以做這種事情嗎?

答案(感謝Eddy Talvala):
由於當您在xml中的cam視圖為水平時無法以縱向方式處理整個cam圖片,因此應進行裁剪。 我決定水平放置並在底部裁剪所有內容:

|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | ^-^  |||  |  |  |    
|| |_\_/_ |||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

您應該使用TextureView為擬合和裁剪指定矩陣。 像這樣的東西(kotlin):

fun camInit() {
    val camParam = camera.parameters
    val optimalSize = getOptimalPortraitPreviewSize(camParam.supportedPreviewSizes, width, height)

    camParam.setPreviewSize(optimalSize.width, optimalSize.height)
    camera.parameters = camParam

    camera.setPreviewTexture(surface)

    val scaleDelta = optimalSize.height - preview.width // for portrait
    val scaleY: Float = (optimalSize.width.toFloat() - scaleDelta) / preview.height // for portrait

    val matrix = Matrix()
    matrix.setScale(1f, scaleY)    // 1f cause we fit horizontally

    preview.setTransform(matrix)

    camera.startPreview()
}

請注意,對於人像模式,您應該使用特定的getOptimalProtraitPreviewSize(),因為每個人都可以使用標准功能來獲得相機預覽的最佳尺寸(使用ASPECT_TOLERANCE等),可以返回具有較小分辨率的尺寸。 嘗試這樣的事情:

fun getOptimalPortraitPreviewSize(sizes: List<Camera.Size>, previewWidth: Int) {

    var selectedSize: Camera.Size = sizes[0]

    for (size in sizes) {
        // use size's height cause of portrait
        val currentSizeWidthDelta = abs(size.height - previewWidth)
        val selectedSizeWidthDelta = abs(selectedSize.height - previewWidth)
        if (currentSizeWidthDelta < selectedSizeWidthDelta) selectedSize = size
    }

    return selectedSize
}

圖像傳感器的長邊與設備的長邊對齊。

(bad ascii art):
____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  |     |
||         ||  |     |
||         ||  |     |
||         ||  |_____|
||         ||   sensor
||         ||   physical 
||         ||   orientation
||_________||
||  < O [] ||
|___________|
    device

鑒於此,您無法像這樣繪制圖像:

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  |     |
||  ______ ||  |     |
|| |      |||  |     |
|| |______|||  |_____|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

除非您旋轉圖像(在這種情況下不向上旋轉):

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | <-\__|||  |  |  |    
|| |_<-/__|||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

或者您水平拉伸圖像,看起來很糟糕:

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | ^___^|||  |  |  |    
|| |___|__|||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

或裁剪圖像的一部分,從而大大降低了FOV:

_____________
|           |
| _________ |   _____
||         ||  |     |
||         ||  | ^-^ |
||  ______ ||  | \_/ |
|| | ^-^  |||  |  |  |    
|| |_\_/__|||  |__|__|
||   image ||   sensor
||         ||
||         ||
||_________||
||  < O [] ||
|___________|
    device

因為當手機處於橫向時圖像傳感器是橫向的,所以如果沒有這三種情況之一,就無法在縱向UI中放置橫向預覽。 您可能需要在肖像UI中進行肖像預覽,或者需要裁剪圖像。 這不是Android的限制,只是幾何的限制。

如果要裁剪,則可能需要將相機數據發送到SurfaceTexture,然后如果要實時預覽,則要在OpenGL中裁剪。

如果您正在使用Camera2 API。 當通過ChooseOptimalSize獲得mPreviewSize時,可以交換寬度和高度。 (寬度和高度從您的角度來看)。 接着

textureView.setAspectRatio(mPreviewSize.Height, mPreviewSize.Width);

創建預覽會話時

texture.SetDefaultBufferSize(mPreviewSize.Width, mPreviewSize.Height);

然后您將預覽普通圖像

感謝@Eddy Talvala和@blinker! 我帶上我的功能可以在任何方向正確更新尺寸:

  public void invalidateSize(TextureView textureView) {
        Point cameraResolution = getCameraResolution();
        int previewRotation = getPreviewRotation();

        // Camera and preview on screen in the opposite orientation
        if (previewRotation == 90 || previewRotation == 270) {
            //noinspection SuspiciousNameCombination
            cameraResolution = new Point(cameraResolution.y, cameraResolution.x);
        }

        float cameraAspectRatio = cameraResolution.x / (float) cameraResolution.y;
        float textureAspectRatio = textureView.getWidth() / (float) textureView.getHeight();

        float scaleX = cameraAspectRatio / textureAspectRatio;
        float scaleY = textureAspectRatio / cameraAspectRatio;

        if (scaleX > scaleY) {
            scaleY = 1;
        } else {
            scaleX = 1;
        }

        Matrix matrix = new Matrix();
        matrix.setScale(scaleX, scaleY,
                textureView.getWidth() / 2f, textureView.getHeight() / 2f);

        textureView.setTransform(matrix);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM