2013-01-05 31 views
17

Tôi đang tìm cách xoay bản xem trước khung YUV nhận được từ Xem trước Callblack, cho đến nay tôi đã thiết lập bài đăng này có thuật toán xoay bản xem trước khung nhưng đang làm lộn xộn hình ảnh xem trước camera pixels rotatedXoay một mảng byte YUV trên Android

cách khác để xoay hình ảnh sẽ tạo jpg ra khỏi hình ảnh YUV, tạo bitmap, xoay bitmap và lấy mảng byte của bitmap, nhưng tôi thực sự cần định dạng trong YUV (NV21).

FYI. lý do tôi hỏi điều này là vì tôi có một ứng dụng máy ảnh hỗ trợ xoay vòng, nhưng các bản xem trước khung sẽ chỉ quay lại ở chế độ ngang.

+1

Tôi đã cũng đi qua vấn đề này và kết thúc bằng cách sử dụng giải pháp bạn đề cập đến bằng cách sử dụng 'Bitmap' để xoay hình ảnh và sử dụng JPEG thay thế. Thật vậy, việc thiết lập định hướng hiển thị không ảnh hưởng đến bộ đệm nhận được bởi 'PreviewCallback' như đã đề cập trong tài liệu: _Điều này không ảnh hưởng đến thứ tự của mảng byte được truyền trong onPreviewFrame (byte [], Camera), ảnh JPEG hoặc video được ghi._ – bvidal

+0

Chào. Bạn đã quản lý để giải quyết điều này? Cảm ơn nhiều. – Paul

Trả lời

12

Phương pháp sau đây có thể xoay một mảng byte YUV420 90 độ.

private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) 
{ 
    byte [] yuv = new byte[imageWidth*imageHeight*3/2]; 
    // Rotate the Y luma 
    int i = 0; 
    for(int x = 0;x < imageWidth;x++) 
    { 
     for(int y = imageHeight-1;y >= 0;y--)        
     { 
      yuv[i] = data[y*imageWidth+x]; 
      i++; 
     } 
    } 
    // Rotate the U and V color components 
    i = imageWidth*imageHeight*3/2-1; 
    for(int x = imageWidth-1;x > 0;x=x-2) 
    { 
     for(int y = 0;y < imageHeight/2;y++)         
     { 
      yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+x]; 
      i--; 
      yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+(x-1)]; 
      i--; 
     } 
    } 
    return yuv; 
} 

(Lưu ý rằng điều này chỉ có thể làm việc nếu chiều rộng và chiều cao là một yếu tố của 4)

+0

Cảm ơn nó thực sự giúp tôi! nhưng tôi có một vấn đề nhỏ Khi tôi áp dụng đoạn mã này trên byte dữ liệu của tôi, hình ảnh của tôi xoay sang (-90). tôi muốn xoay thành +90. hoặc nói cách đơn giản cần xoay theo hướng ngược lại bạn có thể vui lòng giúp tôi không! – Usama

+0

@Usama: bạn có tìm thấy giải pháp xoay vòng theo cách khác không? Tôi cũng bị kẹt ở đây. Cảm ơn. –

+0

Có, tôi gọi cùng hàm 3 lần, chuyển dữ liệu trả về làm đối số cho cuộc gọi tiếp theo và tham số chiều cao chiều rộng trao đổi. – Usama

2

Đây là cách tôi đã làm nó

khối mã này được thiết lập ở những nơi khác

Camera.Size size 
    Rect rectangle = new Rect(); 
    rectangle.bottom = size.height; 
    rectangle.top = 0; 
    rectangle.left = 0; 
    rectangle.right = size.width; 

Đây là phương pháp thực hiện công việc

private Bitmap rotateBitmap(YuvImage yuvImage, int orientation, Rect rectangle) 
    { 
    ByteArrayOutputStream os = new ByteArrayOutputStream(); 
    yuvImage.compressToJpeg(rectangle, 100, os); 

    Matrix matrix = new Matrix(); 
    matrix.postRotate(orientation); 
    byte[] bytes = os.toByteArray(); 
    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 
    return Bitmap.createBitmap(bitmap, 0 , 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
    } 

nén YUVImage thành JPEG để bitmap có thể xử lý nó. Xoay bitmap và sau đó xuất nó. Để có được nó trở lại một JPEG mà là cách tôi muốn nó tôi đã sử dụng dòng này

image.compress(Bitmap.CompressFormat.JPEG, 50, outputStream); 
+0

Điều này có thể gây ra hiện tượng và sẽ chậm do có thêm bước mã hóa/giải mã JPEG. Sẽ không đề nghị cho bất cứ điều gì khác hơn là thử nghiệm. –

4

Dưới đây là các tùy chọn để biến một góc khác nhau (90, 180, 270):

public static byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) { 
    byte[] yuv = new byte[imageWidth * imageHeight * 3/2]; 
    // Rotate the Y luma 
    int i = 0; 
    for (int x = 0; x < imageWidth; x++) { 
     for (int y = imageHeight - 1; y >= 0; y--) { 
      yuv[i] = data[y * imageWidth + x]; 
      i++; 
     } 
    } 
    // Rotate the U and V color components 
    i = imageWidth * imageHeight * 3/2 - 1; 
    for (int x = imageWidth - 1; x > 0; x = x - 2) { 
     for (int y = 0; y < imageHeight/2; y++) { 
      yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x]; 
      i--; 
      yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) 
        + (x - 1)]; 
      i--; 
     } 
    } 
    return yuv; 
} 

private static byte[] rotateYUV420Degree180(byte[] data, int imageWidth, int imageHeight) { 
    byte[] yuv = new byte[imageWidth * imageHeight * 3/2]; 
    int i = 0; 
    int count = 0; 
    for (i = imageWidth * imageHeight - 1; i >= 0; i--) { 
     yuv[count] = data[i]; 
     count++; 
    } 
    i = imageWidth * imageHeight * 3/2 - 1; 
    for (i = imageWidth * imageHeight * 3/2 - 1; i >= imageWidth 
      * imageHeight; i -= 2) { 
     yuv[count++] = data[i - 1]; 
     yuv[count++] = data[i]; 
    } 
    return yuv; 
} 

public static byte[] rotateYUV420Degree270(byte[] data, int imageWidth, 
            int imageHeight) { 
    byte[] yuv = new byte[imageWidth * imageHeight * 3/2]; 
    int nWidth = 0, nHeight = 0; 
    int wh = 0; 
    int uvHeight = 0; 
    if (imageWidth != nWidth || imageHeight != nHeight) { 
     nWidth = imageWidth; 
     nHeight = imageHeight; 
     wh = imageWidth * imageHeight; 
     uvHeight = imageHeight >> 1;// uvHeight = height/2 
    } 
    // ??Y 
    int k = 0; 
    for (int i = 0; i < imageWidth; i++) { 
     int nPos = 0; 
     for (int j = 0; j < imageHeight; j++) { 
      yuv[k] = data[nPos + i]; 
      k++; 
      nPos += imageWidth; 
     } 
    } 
    for (int i = 0; i < imageWidth; i += 2) { 
     int nPos = wh; 
     for (int j = 0; j < uvHeight; j++) { 
      yuv[k] = data[nPos + i]; 
      yuv[k + 1] = data[nPos + i + 1]; 
      k += 2; 
      nPos += imageWidth; 
     } 
    } 
    return rotateYUV420Degree180(yuv, imageWidth, imageHeight); 
} 
+0

Phương pháp của bạn để xoay 270º nó áp dụng một hiệu ứng gương trên hình ảnh. Giải pháp đúng nên là: 'return rotateYuv420Degree180 (rotateYuv420Degree180 (dữ liệu, imageWidth, imageHeight), imageWidth, imageHeight); ' Không có ý nghĩa gì để xoay 90º theo cách khác với phương thức' rotateYuv420Degree90' ban đầu của bạn –

+0

Yo man! Bạn đã cứu ngày của tôi. :) –