Last active
October 30, 2017 11:56
-
-
Save lgyjg/c65460bc3c9f17b4fc8a9839a04753ad to your computer and use it in GitHub Desktop.
java 实现 Bitmap 转 YUV 数据
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* YUV420sp | |
* | |
* @param inputWidth | |
* @param inputHeight | |
* @param scaled | |
* @return | |
*/ | |
public static byte[] getYUV420sp(int inputWidth, int inputHeight, Bitmap scaled) { | |
Log.d(TAG, "getYUV420sp: start"); | |
int[] argb = new int[inputWidth * inputHeight]; | |
scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight); | |
scaled.recycle(); | |
byte[] yuv = new byte[inputWidth * inputHeight * 3 / 2]; | |
encodeYUV420SP(yuv, argb, inputWidth, inputHeight); | |
return yuv; | |
} | |
public static byte[] getYUV420sp(int inputWidth, int inputHeight, byte[] scaled) { | |
Log.d(TAG, "getYUV420sp: start"); | |
int[] argb = new int[inputWidth * inputHeight]; | |
scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight); | |
scaled.recycle(); | |
byte[] yuv = new byte[inputWidth * inputHeight * 3 / 2]; | |
encodeYUV420SP(yuv, argb, inputWidth, inputHeight); | |
return yuv; | |
} | |
/** | |
* RGB转YUV420sp | |
* | |
* @param yuv420sp inputWidth * inputHeight * 3 / 2 | |
* @param argb inputWidth * inputHeight | |
* @param width | |
* @param height | |
*/ | |
private static void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) { | |
// 帧图片的像素大小 | |
final int frameSize = width * height; | |
// ---YUV数据--- | |
int Y, U, V; | |
// Y的index从0开始 | |
int yIndex = 0; | |
// UV的index从frameSize开始 | |
int uvIndex = frameSize; | |
// ---颜色数据--- | |
int a, R, G, B; | |
int argbIndex = 0; | |
// ---循环所有像素点,RGB转YUV--- | |
for (int j = 0; j < height; j++) { | |
for (int i = 0; i < width; i++) { | |
// a is not used obviously | |
a = (argb[argbIndex] & 0xff000000) >> 24; | |
R = (argb[argbIndex] & 0xff0000) >> 16; | |
G = (argb[argbIndex] & 0xff00) >> 8; | |
B = (argb[argbIndex] & 0xff); | |
argbIndex++; | |
// well known RGB to YUV algorithm, 经典的转化算法,但是会导致转化后的图片灰度增加 | |
// Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16; | |
// U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128; | |
// V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128; | |
// 优化后的算法 | |
Y = (306 * R + 601 * G + 117 * B) >> 10; | |
U = ((-173 * R - 339 * G + 512 * B) >> 10) + 128; | |
V = ((512 * R - 429 * G - 83 * B) >> 10) + 128; | |
// 取最大值 | |
Y = Math.max(0, Math.min(Y, 255)); | |
U = Math.max(0, Math.min(U, 255)); | |
V = Math.max(0, Math.min(V, 255)); | |
// NV21 has a plane of Y and interleaved planes of VU each | |
// sampled by a factor of 2 | |
// meaning for every 4 Y pixels there are 1 V and 1 U. Note the | |
// sampling is every other | |
// pixel AND every other scanline. | |
// ---Y--- | |
yuv420sp[yIndex++] = (byte) Y; | |
// ---UV--- | |
if ((j % 2 == 0) && (i % 2 == 0)) { | |
yuv420sp[uvIndex++] = (byte) V; | |
yuv420sp[uvIndex++] = (byte) U; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment