RGB24 To Yuv420 C语言实现
生活随笔
收集整理的這篇文章主要介紹了
RGB24 To Yuv420 C语言实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
RGB24 To Yuv420 C語言實現(非SIMD版本)
以下代碼來自 libyuv
#include <stdint.h>//下面三個函數為RGB-->>Yuv420的公式 static __inline int RGBToYJ(uint8_t r, uint8_t g, uint8_t b) {return (38 * r + 75 * g + 15 * b + 64) >> 7; } static __inline int RGBToUJ(uint8_t r, uint8_t g, uint8_t b) {return (127 * b - 84 * g - 43 * r + 0x8080) >> 8; } static __inline int RGBToVJ(uint8_t r, uint8_t g, uint8_t b) {return (127 * r - 107 * g - 20 * b + 0x8080) >> 8; }//取平均值 #define AVGB(a, b) (((a) + (b) + 1) >> 1)#define R 2 //R的順序 #define G 1 //G的順序 #define B 0 //B的順序 #define BPP 3 //BPP是一個像素占的字節數void RGB24ToYRow_C(const uint8_t* src_rgb, uint8_t* dst_y, int width) {int x;for (x = 0; x < width; ++x) {dst_y[0] = RGBToYJ(src_rgb[R], src_rgb[G], src_rgb[B]);src_rgb += BPP; /*BPP == 3*/dst_y += 1;} } void RGB24ToUVRow_C(const uint8_t* src_rgb, int src_stride_rgb, uint8_t* dst_u, uint8_t* dst_v, int width) {const uint8_t* src_rgb1 = src_rgb + src_stride_rgb;int x;for (x = 0; x < width - 1; x += 2)//一次處理兩行{//U,V采樣方式:四個像素(邊長為2像素的正方形,如下)RGB值的平均值,再計算出U,V// p1 p2 這是第一行的兩個像素// p3 p4 這是第二行的兩個像素uint8_t ab = AVGB(AVGB(src_rgb[B], src_rgb1[B]), AVGB(src_rgb[B + BPP], src_rgb1[B + BPP]));uint8_t ag = AVGB(AVGB(src_rgb[G], src_rgb1[G]), AVGB(src_rgb[G + BPP], src_rgb1[G + BPP]));uint8_t ar = AVGB(AVGB(src_rgb[R], src_rgb1[R]), AVGB(src_rgb[R + BPP], src_rgb1[R + BPP]));dst_u[0] = RGBToUJ(ar, ag, ab);dst_v[0] = RGBToVJ(ar, ag, ab);src_rgb += BPP * 2;src_rgb1 += BPP * 2;dst_u += 1;dst_v += 1;}if (width & 1)//奇數行的情況下,最后一行只對兩個像素求平均{uint8_t ab = AVGB(src_rgb[B], src_rgb1[B]);uint8_t ag = AVGB(src_rgb[G], src_rgb1[G]);uint8_t ar = AVGB(src_rgb[R], src_rgb1[R]);dst_u[0] = RGBToUJ(ar, ag, ab);dst_v[0] = RGBToVJ(ar, ag, ab);} }/* src_rgb24: rgb24數據,注意順序為BGR src_stride_rgb24: 一行像素點占用的字節數,循環的時候換行要用到(此處應該是width * 3,然后結果補成4的倍數)dst_y: 存放y平面的地址 dst_stride_y: 和src_stride_rgb24類似,只是這里應該是width..后面的參數參考前面即可width: 圖像寬度(單位:像素) height: 圖像高度 (單位:像素) */ int RGB24ToI420(const uint8_t* src_rgb24, int src_stride_rgb24, uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u, int dst_stride_u, uint8_t* dst_v, int dst_stride_v, int width, int height) {int y;void(*RGB24ToUVRow)(const uint8_t* src_rgb24, int src_stride_rgb24,uint8_t* dst_u, uint8_t* dst_v, int width) =RGB24ToUVRow_C;void(*RGB24ToYRow)(const uint8_t* src_rgb24, uint8_t* dst_y, int width) =RGB24ToYRow_C;if (!src_rgb24 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {return -1;}if (height < 0) {height = -height;src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;src_stride_rgb24 = -src_stride_rgb24;}for (y = 0; y < height - 1; y += 2) //一次處理兩行{RGB24ToUVRow(src_rgb24, src_stride_rgb24, dst_u, dst_v, width);RGB24ToYRow(src_rgb24, dst_y, width);RGB24ToYRow(src_rgb24 + src_stride_rgb24, dst_y + dst_stride_y, width);src_rgb24 += src_stride_rgb24 * 2;dst_y += dst_stride_y * 2;dst_u += dst_stride_u;dst_v += dst_stride_v;}if (height & 1) //高度為奇數的話,再單獨處理最后一行{RGB24ToUVRow(src_rgb24, 0, dst_u, dst_v, width);RGB24ToYRow(src_rgb24, dst_y, width);}return 0; }性能測試: 轉換一張1920x1080圖片用時:30ms(SIMD版本用時<1ms)
測試機器:
總結
以上是生活随笔為你收集整理的RGB24 To Yuv420 C语言实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAN\CANFD\FlexRay\LI
- 下一篇: 计算机课件制作教程ppt,电脑制作ppt