日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RGB24 To Yuv420 C语言实现

發(fā)布時間:2023/12/8 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RGB24 To Yuv420 C语言实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

RGB24 To Yuv420 C語言實現(xiàn)(非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是一個像素占的字節(jié)數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: 一行像素點占用的字節(jié)數,循環(huán)的時候換行要用到(此處應該是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语言实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。