私はプレビューコールブラックから受け取ったYUVフレームプレビューを回転させたいと思っています。これまでのところ、フレームプレビューを回転させるアルゴリズムを含むこの投稿を見つけましたが、プレビュー画像を乱しています カメラピクセル回転
画像を回転させる別の方法は、YUV画像からjpgを作成し、ビットマップを作成し、ビットマップを回転して、ビットマップのバイト配列を取得することですが、実際にはYUV(NV21)の形式が必要です。
ご参考までに。これを尋ねる理由は、回転をサポートするカメラアプリがあるためですが、フレームプレビューが横向きモードでのみ戻ってきます。
次のメソッドは、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;
}
(これは、幅と高さが4倍の場合にのみ機能することに注意してください)
別のコーナー(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);
}
これが私がやった方法です
このコードブロックは他の場所で設定されています
Camera.Size size
Rect rectangle = new Rect();
rectangle.bottom = size.height;
rectangle.top = 0;
rectangle.left = 0;
rectangle.right = size.width;
これは仕事をする方法です
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);
}
yUVImageをJPEGに圧縮して、ビットマップで処理できるようにします。ビットマップを回転してエクスポートします。 JPEGに戻すには、この行を使用しました。
image.compress(Bitmap.CompressFormat.JPEG, 50, outputStream);