convert.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2021 StarFive Technology Co., Ltd.
  4. */
  5. #include "common.h"
  6. static int g_screen_width = 0;
  7. static int g_screen_height = 0;
  8. static int g_screen_bpp = 0;
  9. static int g_screen_size = 0;
  10. static int g_screen_distype = 0; // STF_DISP_FB or STF_DISP_DRM
  11. void update_videocvt_param(int distype, int scr_width, int scr_height,
  12. int scr_bpp, int scr_size)
  13. {
  14. g_screen_distype = distype;
  15. g_screen_width = scr_width;
  16. g_screen_height = scr_height;
  17. g_screen_bpp = scr_bpp;
  18. g_screen_size = scr_size;
  19. }
  20. int yuyv_resize(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight)
  21. {
  22. int rows;
  23. const uint8_t *YUVindata;
  24. uint8_t *YUVoutdata; /* YUV and RGB pointer */
  25. int YUVinpos; /* Y U V offset */
  26. int width, height;
  27. int x_offset, y_offset;
  28. uint8_t *tmp = malloc(g_screen_size);
  29. uint32_t start_timems;
  30. uint32_t end_timems;
  31. struct timeval ts_start, ts_end;
  32. if (!tmp)
  33. return -1;
  34. gettimeofday(&ts_start, NULL);
  35. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  36. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  37. x_offset = (g_screen_width - width) / 2;
  38. y_offset = (g_screen_height - height) / 2;
  39. YUVindata = inBuf;
  40. YUVoutdata = tmp;
  41. if (imgWidth == g_screen_width) {
  42. YUVinpos = (y_offset * g_screen_width + x_offset) * 2;
  43. memcpy(&tmp[YUVinpos], inBuf, imgWidth * height * 2);
  44. memcpy(&outBuf[YUVinpos], &tmp[YUVinpos], imgWidth * height * 2);
  45. // memcpy(&outBuf[YUVinpos], inBuf, imgWidth * height * 2);
  46. gettimeofday(&ts_end, NULL);
  47. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_usec/1000;
  48. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_usec/1000;
  49. // printf("%s: copy use %dms, sizeof(int) = %d\n", __func__, end_timems - start_timems, sizeof(int));
  50. free(tmp);
  51. return 0;
  52. }
  53. /* two bytes for one pixels */
  54. for(rows = 0; rows < height; rows++)
  55. {
  56. // g_screen_width, g_screen_height g_screen_bpp
  57. YUVoutdata = tmp + ((rows + y_offset) * g_screen_width + x_offset) * 2;
  58. YUVinpos = rows * imgWidth * 2;
  59. memcpy(YUVoutdata, &YUVindata[YUVinpos], imgWidth * 2);
  60. }
  61. gettimeofday(&ts_end, NULL);
  62. start_timems = ts_start.tv_sec * 1000000 + ts_start.tv_usec;
  63. end_timems = ts_end.tv_sec * 1000000 + ts_end.tv_usec;
  64. // printf("%s: convert use %dus\n", __func__, end_timems - start_timems);
  65. gettimeofday(&ts_start, NULL);
  66. memcpy(outBuf, tmp, g_screen_size);
  67. gettimeofday(&ts_end, NULL);
  68. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_usec/1000;
  69. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_usec/1000;
  70. // printf("%s: copy use %dms, sizeof(int) = %d\n", __func__, end_timems - start_timems, sizeof(int));
  71. free(tmp);
  72. return 0;
  73. }
  74. int convert_yuyv_to_nv12(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int is_yuyv)
  75. {
  76. int rows, cols;
  77. const uint8_t *YUVdata;
  78. uint8_t *nv12data;
  79. int Ypos;
  80. int fb_Ypos, fb_Upos, fb_Vpos;
  81. int width, height;
  82. int x_offset, y_offset;
  83. uint8_t *tmp = malloc(g_screen_size);
  84. uint32_t start_timems;
  85. uint32_t end_timems;
  86. struct timeval ts_start, ts_end;
  87. if (!tmp)
  88. return -1;
  89. gettimeofday(&ts_start, NULL);
  90. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  91. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  92. x_offset = (g_screen_width - width) / 2;
  93. y_offset = (g_screen_height - height) / 2;
  94. YUVdata = inBuf;
  95. nv12data = tmp;
  96. /* two bytes for every pixels */
  97. for(rows = 0; rows < height; rows++)
  98. {
  99. // g_screen_width, g_screen_height g_screen_bpp
  100. fb_Ypos = ((rows + y_offset) * g_screen_width + x_offset);
  101. fb_Upos = ((rows + y_offset) / 2 * g_screen_width / 2 + x_offset / 2) * 2;
  102. fb_Upos = g_screen_width * g_screen_height + fb_Upos;
  103. fb_Vpos = fb_Upos + 1;
  104. Ypos = rows * imgWidth * 2;
  105. for (cols = 0; cols < width; cols += 2) {
  106. nv12data[fb_Ypos+cols] = YUVdata[Ypos+cols*2];
  107. nv12data[fb_Ypos+cols+1] = YUVdata[Ypos+cols*2+2];
  108. nv12data[fb_Upos+cols] = YUVdata[Ypos+cols*2+1];
  109. nv12data[fb_Vpos+cols] = YUVdata[Ypos+cols*2+3];
  110. }
  111. }
  112. gettimeofday(&ts_end, NULL);
  113. start_timems = ts_start.tv_sec * 1000000 + ts_start.tv_usec;
  114. end_timems = ts_end.tv_sec * 1000000 + ts_end.tv_usec;
  115. // printf("%s: convert use %dus\n", __func__, end_timems - start_timems);
  116. gettimeofday(&ts_start, NULL);
  117. memcpy(outBuf, tmp, g_screen_size);
  118. gettimeofday(&ts_end, NULL);
  119. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_usec/1000;
  120. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_usec/1000;
  121. // printf("%s: copy use %dms, sizeof(int) = %d\n", __func__, end_timems - start_timems, sizeof(int));
  122. free(tmp);
  123. return 0;
  124. }
  125. int convert_nv21_to_nv12(const uint8_t *inBuf, uint8_t *outBuf,
  126. int imgWidth, int imgHeight, int uv_changed)
  127. {
  128. int rows, cols;
  129. const uint8_t *nv21data;
  130. uint8_t *nv12data;
  131. int Ypos, Upos, Vpos;
  132. int fb_Ypos, fb_Upos, fb_Vpos;
  133. int width, height;
  134. int x_offset, y_offset;
  135. uint8_t *tmp = malloc(g_screen_size);
  136. uint32_t start_timems;
  137. uint32_t end_timems;
  138. struct timeval ts_start, ts_end;
  139. assert(tmp);
  140. gettimeofday(&ts_start, NULL);
  141. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  142. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  143. x_offset = (g_screen_width - width) / 2;
  144. y_offset = (g_screen_height - height) / 2;
  145. nv21data = inBuf;
  146. nv12data = tmp;
  147. // printf("[%s,%d]:imgWidth=%d, imgHeight=%d, g_screen_width=%d g_screen_height=%d g_screen_bpp=%d\n",__FUNCTION__,__LINE__,
  148. // imgWidth, imgHeight, g_screen_width, g_screen_height, g_screen_bpp);
  149. // below for same image size and not uv changed
  150. if (imgWidth == g_screen_width && !uv_changed) {
  151. fb_Ypos = y_offset * g_screen_width + x_offset;
  152. fb_Upos = (y_offset / 2 * g_screen_width / 2 + x_offset / 2) * 2;
  153. fb_Upos = g_screen_width * g_screen_height + fb_Upos;
  154. Upos = imgWidth * imgHeight;
  155. if (STF_DISP_FB == g_screen_distype) {
  156. // TODO: it is strange that with tmp buffer will more faster for framebuf
  157. memcpy(&tmp[fb_Ypos], inBuf, imgWidth * height);
  158. memcpy(&tmp[fb_Upos], &inBuf[Upos], imgWidth * height / 2);
  159. memcpy(&outBuf[fb_Ypos], &tmp[fb_Ypos], imgWidth * height);
  160. memcpy(&outBuf[fb_Upos], &tmp[fb_Upos], imgWidth * height / 2);
  161. } else {
  162. memcpy(&outBuf[fb_Ypos], inBuf, imgWidth * height);
  163. memcpy(&outBuf[fb_Upos], &inBuf[Upos], imgWidth * height / 2);
  164. }
  165. free(tmp);
  166. return 0;
  167. }
  168. /* two bytes for every pixels */
  169. for(rows = 0; rows < height; rows+=2)
  170. {
  171. // g_screen_width, g_screen_height g_screen_bpp
  172. fb_Ypos = ((rows + y_offset) * g_screen_width + x_offset);
  173. fb_Upos = ((rows + y_offset) / 2 * g_screen_width / 2 + x_offset / 2) * 2;
  174. fb_Upos = g_screen_width * g_screen_height + fb_Upos;
  175. fb_Vpos = fb_Upos + 1;
  176. Ypos = rows * imgWidth;
  177. Upos = imgWidth * imgHeight + Ypos / 2;
  178. Vpos = Upos + 1;
  179. memcpy(&nv12data[fb_Ypos], &nv21data[Ypos], width);
  180. memcpy(&nv12data[fb_Ypos+g_screen_width], &nv21data[Ypos+imgWidth], width);
  181. if (uv_changed) {
  182. for (cols = 0; cols < width; cols += 2) {
  183. nv12data[fb_Upos+cols] = nv21data[Vpos+cols];
  184. nv12data[fb_Vpos+cols] = nv21data[Upos+cols];
  185. }
  186. } else {
  187. memcpy(&nv12data[fb_Upos], &nv21data[Upos], width);
  188. }
  189. }
  190. gettimeofday(&ts_end, NULL);
  191. start_timems = ts_start.tv_sec * 1000000 + ts_start.tv_usec;
  192. end_timems = ts_end.tv_sec * 1000000 + ts_end.tv_usec;
  193. // printf("%s: convert use %dus\n", __func__, end_timems - start_timems);
  194. gettimeofday(&ts_start, NULL);
  195. memcpy(outBuf, tmp, g_screen_size);
  196. gettimeofday(&ts_end, NULL);
  197. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_usec/1000;
  198. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_usec/1000;
  199. // printf("%s: copy use %dms, sizeof(int) = %d\n", __func__, end_timems - start_timems, sizeof(int));
  200. free(tmp);
  201. return 0;
  202. }
  203. int convert_nv21_to_rgb(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int is_nv21)
  204. {
  205. int rows ,cols;
  206. int y, u, v, r, g, b;
  207. const uint8_t *YUVdata;
  208. uint8_t *RGBdata;
  209. int Ypos, Upos, Vpos;
  210. uint32_t i = 0;
  211. int width, height;
  212. int x_offset, y_offset;
  213. uint8_t *tmp = malloc(g_screen_size);
  214. uint32_t start_timems;
  215. uint32_t end_timems;
  216. struct timeval ts_start, ts_end;
  217. if (!tmp)
  218. return -1;
  219. gettimeofday(&ts_start, NULL);
  220. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  221. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  222. x_offset = (g_screen_width - width) / 2;
  223. y_offset = (g_screen_height - height) / 2;
  224. YUVdata = inBuf;
  225. RGBdata = tmp;
  226. /* two bytes for every pixels */
  227. for(rows = 0; rows < height; rows++)
  228. {
  229. // g_screen_width, g_screen_height g_screen_bpp
  230. RGBdata = tmp + ((rows + y_offset) * g_screen_width + x_offset) * g_screen_bpp / 8;
  231. Ypos = rows * imgWidth;
  232. Vpos = Upos = imgWidth * imgHeight + Ypos / 2;
  233. if (is_nv21)
  234. Vpos = Upos + 1;
  235. else
  236. Upos = Vpos + 1;
  237. i = 0;
  238. for (cols = 0; cols < width; cols++)
  239. {
  240. y = YUVdata[Ypos];
  241. u = YUVdata[Upos] - 128;
  242. v = YUVdata[Vpos] - 128;
  243. r = y + v + ((v * 103) >> 8);
  244. g = y - ((u * 88) >> 8) - ((v * 183) >> 8);
  245. b = y + u + ((u * 198) >> 8);
  246. r = r > 255 ? 255 : (r < 0 ? 0 : r);
  247. g = g > 255 ? 255 : (g < 0 ? 0 : g);
  248. b = b > 255 ? 255 : (b < 0 ? 0 : b);
  249. /* low -> high r g b */
  250. if (g_screen_bpp == 16) { // RGB565
  251. *(RGBdata ++) = (((g & 0x1c) << 3) | (b >> 3)); /* g low 5bit,b high 5bit */
  252. *(RGBdata ++) = ((r & 0xf8) | (g >> 5)); /* r high 5bit,g high 3bit */
  253. } else if (g_screen_bpp == 24) { // RGB888
  254. *(RGBdata ++) = b;
  255. *(RGBdata ++) = g;
  256. *(RGBdata ++) = r;
  257. } else { // RGB8888
  258. *(RGBdata ++) = b;
  259. *(RGBdata ++) = g;
  260. *(RGBdata ++) = r;
  261. *(RGBdata ++) = 0xFF;
  262. }
  263. Ypos++;
  264. i++;
  265. /* every 4 time y to update 1 time uv */
  266. if(!(i & 0x03))
  267. {
  268. Vpos = Upos = imgWidth * imgHeight + Ypos/2;
  269. if (is_nv21)
  270. Vpos = Upos + 1;
  271. else
  272. Upos = Vpos + 1;
  273. }
  274. }
  275. }
  276. gettimeofday(&ts_end, NULL);
  277. start_timems = ts_start.tv_sec * 1000000 + ts_start.tv_usec;
  278. end_timems = ts_end.tv_sec * 1000000 + ts_end.tv_usec;
  279. // printf("%s: convert use %dus\n", __func__, end_timems - start_timems);
  280. gettimeofday(&ts_start, NULL);
  281. #if 1
  282. memcpy(outBuf, tmp, g_screen_size);
  283. #else
  284. int *p_outBuf, *p_tmp;
  285. int size = g_screen_size/4;
  286. p_outBuf = outBuf;
  287. p_tmp = tmp;
  288. for (i = 0; i < size; i++)
  289. p_outBuf[i] = p_tmp[i];
  290. #endif
  291. gettimeofday(&ts_end, NULL);
  292. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_usec/1000;
  293. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_usec/1000;
  294. // printf("%s: copy use %dms, sizeof(int) = %d\n", __func__, end_timems - start_timems, sizeof(int));
  295. free(tmp);
  296. return 0;
  297. }
  298. //Y' = 0.257*R' + 0.504*G' + 0.098*B' + 16
  299. static int Rgb2Y(int r0, int g0, int b0)
  300. {
  301. // float y0 = 0.257f*r0 + 0.504f*g0 + 0.098f*b0 + 16.0f;
  302. // int y0 = (257*r0 + 504*g0 + 98*b0)/1000 + 16;
  303. // Y = (77*R + 150*G + 29*B)>>8;
  304. int y0 = (77*r0+150*g0+29*b0) >> 8;
  305. return y0;
  306. }
  307. //U equals Cb'
  308. //Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
  309. static int Rgb2U(int r0, int g0, int b0)
  310. {
  311. // float u0 = -0.148f*r0 - 0.291f*g0 + 0.439f*b0 + 128.0f;
  312. // int u0 = (-148*r0 - 291*g0 + 439*b0)/1000 + 128;
  313. // U = ((-44*R - 87*G + 131*B)>>8) + 128;
  314. int u0 = ((-44*r0 - 87*g0 + 131*b0)>>8) + 128;
  315. return u0;
  316. }
  317. //V equals Cr'
  318. //Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
  319. static int Rgb2V(int r0, int g0, int b0)
  320. {
  321. // float v0 = 0.439f*r0 - 0.368f*g0 - 0.071f*b0 + 128.0f;
  322. // int v0 = (439*r0 - 368*g0 - 71*b0)/1000 + 128;
  323. // V = ((131*R - 110*G - 21*B)>>8) + 128 ;
  324. int v0 = ((131*r0 - 110*g0 - 21*b0)>>8) + 128;
  325. return v0;
  326. }
  327. //Convert two rows from RGB to two Y rows, and one row of interleaved U,V.
  328. //I0 and I1 points two sequential source rows.
  329. //I0 -> rgbrgbrgbrgbrgbrgb...
  330. //I1 -> rgbrgbrgbrgbrgbrgb...
  331. //Y0 and Y1 points two sequential destination rows of Y plane.
  332. //Y0 -> yyyyyy
  333. //Y1 -> yyyyyy
  334. //UV0 points destination rows of interleaved UV plane.
  335. //UV0 -> uvuvuv
  336. static void Rgb2NV12TwoRows(const uint8_t I0[],
  337. const uint8_t I1[],
  338. int step,
  339. const int image_width,
  340. uint8_t Y0[],
  341. uint8_t Y1[],
  342. uint8_t UV0[])
  343. {
  344. int x; //Column index
  345. //Process 4 source pixels per iteration (2 pixels of row I0 and 2 pixels of row I1).
  346. for (x = 0; x < image_width; x += 2)
  347. {
  348. //Load R,G,B elements from first row (and convert to int).
  349. uint8_t b00 = (I0[x*step + 0] & 0x1F) << 3;
  350. uint8_t g00 = ((I0[x*step + 1] & 0x7) << 3 | I0[x*step + 0] >> 5) << 2;
  351. uint8_t r00 = I0[x*step + 1] & (~0x7);
  352. //Load next R,G,B elements from first row (and convert to int).
  353. uint8_t b01 = (I0[x*step + step+0] & 0x1F) << 3;
  354. uint8_t g01 = ((I0[x*step + step+1] & 0x7) << 3 | I0[x*step + step+0] >> 5) << 2;
  355. uint8_t r01 = I0[x*step + step+1] & (~0x7);
  356. //Load R,G,B elements from second row (and convert to int).
  357. uint8_t b10 = (I1[x*step + 0] & 0x1F) << 3;
  358. uint8_t g10 = ((I1[x*step + 1] & 0x7) << 3 | I1[x*step + 0] >> 5) << 2;
  359. uint8_t r10 = I1[x*step + 1] & (~0x7);
  360. //Load next R,G,B elements from second row (and convert to int).
  361. uint8_t b11 = (I1[x*step + step+0] & 0x1F) << 3;
  362. uint8_t g11 = ((I1[x*step + step+1] & 0x7) << 3 | I1[x*step + step+0] >> 5) << 2;
  363. uint8_t r11 = I1[x*step + step+1] & (~0x7);
  364. //Calculate 4 Y elements.
  365. uint8_t y00 = Rgb2Y(r00, g00, b00);
  366. uint8_t y01 = Rgb2Y(r01, g01, b01);
  367. uint8_t y10 = Rgb2Y(r10, g10, b10);
  368. uint8_t y11 = Rgb2Y(r11, g11, b11);
  369. //Calculate 4 U elements.
  370. uint8_t u00 = Rgb2U(r00, g00, b00);
  371. uint8_t u01 = Rgb2U(r01, g01, b01);
  372. uint8_t u10 = Rgb2U(r10, g10, b10);
  373. uint8_t u11 = Rgb2U(r11, g11, b11);
  374. //Calculate 4 V elements.
  375. uint8_t v00 = Rgb2V(r00, g00, b00);
  376. uint8_t v01 = Rgb2V(r01, g01, b01);
  377. uint8_t v10 = Rgb2V(r10, g10, b10);
  378. uint8_t v11 = Rgb2V(r11, g11, b11);
  379. //Calculate destination U element: average of 2x2 "original" U elements.
  380. uint8_t u0 = (u00 + u01 + u10 + u11)/4;
  381. //Calculate destination V element: average of 2x2 "original" V elements.
  382. uint8_t v0 = (v00 + v01 + v10 + v11)/4;
  383. //Store 4 Y elements (two in first row and two in second row).
  384. Y0[x + 0] = y00;
  385. Y0[x + 1] = y01;
  386. Y1[x + 0] = y10;
  387. Y1[x + 1] = y11;
  388. // //Store destination U element.
  389. UV0[x + 0] = u0;
  390. // //Store destination V element (next to stored U element).
  391. UV0[x + 1] = v0;
  392. }
  393. }
  394. //Convert image I from pixel ordered RGB to NV12 format.
  395. //I - Input image in pixel ordered RGB format
  396. //image_width - Number of columns of I
  397. //image_height - Number of rows of I
  398. //J - Destination "image" in NV12 format.
  399. //I is pixel ordered RGB color format (size in bytes is image_width*image_height*3):
  400. //RGBRGBRGBRGBRGBRGB
  401. //RGBRGBRGBRGBRGBRGB
  402. //RGBRGBRGBRGBRGBRGB
  403. //RGBRGBRGBRGBRGBRGB
  404. //
  405. //J is in NV12 format (size in bytes is image_width*image_height*3/2):
  406. //YYYYYY
  407. //YYYYYY
  408. //UVUVUV
  409. //Each element of destination U is average of 2x2 "original" U elements
  410. //Each element of destination V is average of 2x2 "original" V elements
  411. //
  412. //Limitations:
  413. //1. image_width must be a multiple of 2.
  414. //2. image_height must be a multiple of 2.
  415. //3. I and J must be two separate arrays (in place computation is not supported).
  416. void Rgb2NV12(const uint8_t I[], int step,
  417. const int image_width,
  418. const int image_height,
  419. uint8_t J[])
  420. {
  421. //In NV12 format, UV plane starts below Y plane.
  422. // uint8_t *UV = &J[image_width*image_height];
  423. uint8_t *UV = J;
  424. //I0 and I1 points two sequential source rows.
  425. const uint8_t *I0; //I0 -> rgbrgbrgbrgbrgbrgb...
  426. const uint8_t *I1; //I1 -> rgbrgbrgbrgbrgbrgb...
  427. //Y0 and Y1 points two sequential destination rows of Y plane.
  428. uint8_t *Y0; //Y0 -> yyyyyy
  429. uint8_t *Y1; //Y1 -> yyyyyy
  430. //UV0 points destination rows of interleaved UV plane.
  431. uint8_t *UV0; //UV0 -> uvuvuv
  432. int y; //Row index
  433. int width, height;
  434. int x_offset, y_offset;
  435. width = image_width > g_screen_width ? g_screen_width : image_width;
  436. height = image_height > g_screen_height ? g_screen_height : image_height;
  437. x_offset = (g_screen_width - width) / 2;
  438. y_offset = (g_screen_height - height) / 2;
  439. //In each iteration: process two rows of Y plane, and one row of interleaved UV plane.
  440. for (y = 0; y < height; y += 2)
  441. {
  442. I0 = &I[y*image_width*step]; //Input row width is image_width*3 bytes (each pixel is R,G,B).
  443. I1 = &I[(y+1)*image_width*step];
  444. Y0 = &J[(y+y_offset)*g_screen_width+x_offset]; //Output Y row width is image_width bytes (one Y element per pixel).
  445. Y1 = &J[(y+1+y_offset)*g_screen_width+x_offset];
  446. UV0 = &UV[g_screen_width*g_screen_height+((y+y_offset)/2*g_screen_width/2+x_offset/2)*2]; //Output UV row - width is same as Y row width.
  447. //Process two source rows into: Two Y destination row, and one destination interleaved U,V row.
  448. Rgb2NV12TwoRows(I0,
  449. I1,
  450. step,
  451. width,
  452. Y0,
  453. Y1,
  454. UV0);
  455. }
  456. }
  457. int convert_rgb565_to_nv12(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int is_nv21)
  458. {
  459. uint8_t *tmp = malloc(g_screen_size);
  460. uint32_t start_timems;
  461. uint32_t end_timems;
  462. struct timespec ts_start, ts_end;
  463. clock_gettime(CLOCK_MONOTONIC, &ts_start);
  464. Rgb2NV12(inBuf, 2, imgWidth, imgHeight, tmp);
  465. clock_gettime(CLOCK_MONOTONIC, &ts_end);
  466. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_nsec/1000000;
  467. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_nsec/1000000;
  468. // printf("%s: convert use %dms\n", __func__, end_timems - start_timems);
  469. clock_gettime(CLOCK_MONOTONIC, &ts_start);
  470. memcpy(outBuf, tmp, g_screen_size);
  471. clock_gettime(CLOCK_MONOTONIC, &ts_end);
  472. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_nsec/1000000;
  473. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_nsec/1000000;
  474. // printf("%s: use %dms\n", __func__, end_timems - start_timems);
  475. free(tmp);
  476. return 0;
  477. }
  478. int convert_yuyv_to_rgb(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int cvtMethod)
  479. {
  480. int rows ,cols;
  481. int y, u, v, r, g, b;
  482. const uint8_t *YUVdata;
  483. uint8_t *RGBdata;
  484. int Ypos, Upos, Vpos;
  485. uint32_t i = 0;
  486. int width, height;
  487. int x_offset, y_offset;
  488. uint8_t *tmp = malloc(g_screen_size);
  489. uint32_t start_timems;
  490. uint32_t end_timems;
  491. struct timespec ts_start, ts_end;
  492. clock_gettime(CLOCK_MONOTONIC, &ts_start);
  493. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  494. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  495. x_offset = (g_screen_width - width) / 2;
  496. y_offset = (g_screen_height - height) / 2;
  497. YUVdata = inBuf;
  498. RGBdata = tmp;
  499. /* two bytes for every pixels */
  500. for(rows = 0; rows < height; rows++)
  501. {
  502. // g_screen_width, g_screen_height g_screen_bpp
  503. RGBdata = tmp + ((rows + y_offset) * g_screen_width + x_offset) * g_screen_bpp / 8;
  504. Ypos = rows * imgWidth * 2;
  505. Upos = Ypos + 1;
  506. Vpos = Upos + 2;
  507. i = 0;
  508. for(cols = 0; cols < width; cols++)
  509. {
  510. y = YUVdata[Ypos];
  511. u = YUVdata[Upos] - 128;
  512. v = YUVdata[Vpos] - 128;
  513. r = y + v + ((v * 103) >> 8);
  514. g = y - ((u * 88) >> 8) - ((v * 183) >> 8);
  515. b = y + u + ((u * 198) >> 8);
  516. r = r > 255 ? 255 : (r < 0 ? 0 : r);
  517. g = g > 255 ? 255 : (g < 0 ? 0 : g);
  518. b = b > 255 ? 255 : (b < 0 ? 0 : b);
  519. /* low -> high r g b */
  520. if (g_screen_bpp == 16) { // RGB565
  521. *(RGBdata ++) = (((g & 0x1c) << 3) | (b >> 3)); /* g low 5bits,b high 5bits */
  522. *(RGBdata ++) = ((r & 0xf8) | (g >> 5)); /* r high 5bits, g high 3bits */
  523. } else if (g_screen_bpp == 24) { // RGB888
  524. *(RGBdata ++) = b;
  525. *(RGBdata ++) = g;
  526. *(RGBdata ++) = r;
  527. } else { // RGB8888
  528. *(RGBdata ++) = b;
  529. *(RGBdata ++) = g;
  530. *(RGBdata ++) = r;
  531. *(RGBdata ++) = 0xFF;
  532. }
  533. /* two bytes contain 1 y */
  534. Ypos += 2;
  535. //Ypos++;
  536. i++;
  537. /* every 2 y to update 1 uv */
  538. if(!(i & 0x01))
  539. {
  540. Upos = Ypos + 1;
  541. Vpos = Upos + 2;
  542. }
  543. }
  544. }
  545. clock_gettime(CLOCK_MONOTONIC, &ts_end);
  546. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_nsec/1000000;
  547. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_nsec/1000000;
  548. // printf("%s: convert use %dms\n", __func__, end_timems - start_timems);
  549. clock_gettime(CLOCK_MONOTONIC, &ts_start);
  550. memcpy(outBuf, tmp, g_screen_size);
  551. clock_gettime(CLOCK_MONOTONIC, &ts_end);
  552. start_timems = ts_start.tv_sec * 1000 + ts_start.tv_nsec/1000000;
  553. end_timems = ts_end.tv_sec * 1000 + ts_end.tv_nsec/1000000;
  554. // printf("%s: use %dms\n", __func__, end_timems - start_timems);
  555. free(tmp);
  556. return 0;
  557. }
  558. int convert_yuv444_to_rgb(uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int cvtMethod)
  559. {
  560. int rows ,cols;
  561. int y, u, v, r, g, b;
  562. uint8_t *YUVdata, *RGBdata;
  563. int Ypos;
  564. uint8_t *tmp = malloc(g_screen_size);
  565. YUVdata = inBuf;
  566. RGBdata = tmp;
  567. /* YUV */
  568. Ypos = 0;
  569. for(rows = 0; rows < imgHeight; rows++)
  570. {
  571. for(cols = 0; cols < imgWidth; cols++)
  572. {
  573. y = YUVdata[Ypos];
  574. u = YUVdata[Ypos + 1] - 128;
  575. v = YUVdata[Ypos + 2] - 128;
  576. r = y + v + ((v * 103) >> 8);
  577. g = y - ((u * 88) >> 8) - ((v * 183) >> 8);
  578. b = y + u + ((u * 198) >> 8);
  579. r = r > 255 ? 255 : (r < 0 ? 0 : r);
  580. g = g > 255 ? 255 : (g < 0 ? 0 : g);
  581. b = b > 255 ? 255 : (b < 0 ? 0 : b);
  582. /* low -> high r g b */
  583. if (g_screen_bpp == 16) { // RGB565
  584. *(RGBdata ++) = (((g & 0x1c) << 3) | (b >> 3)); /* g low 5bits,b high 5bits */
  585. *(RGBdata ++) = ((r & 0xf8) | (g >> 5)); /* r high 5bits,g high 3bits */
  586. } else if (g_screen_bpp == 24) { // RGB888
  587. *(RGBdata ++) = b;
  588. *(RGBdata ++) = g;
  589. *(RGBdata ++) = r;
  590. } else { // RGB8888
  591. *(RGBdata ++) = b;
  592. *(RGBdata ++) = g;
  593. *(RGBdata ++) = r;
  594. *(RGBdata ++) = 0xFF;
  595. }
  596. Ypos += 3;
  597. }
  598. }
  599. memcpy(outBuf, tmp, g_screen_size);
  600. free(tmp);
  601. return 0;
  602. }
  603. int convert_rgb565_to_rgb(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int cvtMethod)
  604. {
  605. int rows ,cols;
  606. const uint8_t *RGB565data;
  607. uint8_t *RGBdata;
  608. int RGBpos;
  609. int width, height;
  610. int x_offset, y_offset;
  611. uint8_t *tmp = malloc(g_screen_size);
  612. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  613. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  614. x_offset = (g_screen_width - width) / 2;
  615. y_offset = (g_screen_height - height) / 2;
  616. RGB565data = inBuf;
  617. RGBdata = tmp;
  618. if (imgWidth == g_screen_width) {
  619. RGBpos = (y_offset * g_screen_width + x_offset) * 2;
  620. memcpy(&tmp[RGBpos], inBuf, imgWidth * height * 2);
  621. memcpy(&outBuf[RGBpos], &tmp[RGBpos], imgWidth * height * 2);
  622. // memcpy(&outBuf[RGBpos], inBuf, imgWidth * height * 2);
  623. free(tmp);
  624. return 0;
  625. }
  626. RGBpos = 0;
  627. for(rows = 0; rows < imgHeight; rows++)
  628. {
  629. RGBdata = tmp + ((rows + y_offset) * g_screen_width + x_offset) * g_screen_bpp / 8;
  630. RGBpos = rows * imgWidth * 2;
  631. if (g_screen_bpp == 16) { // RGB565
  632. memcpy(RGBdata, &RGB565data[RGBpos], imgWidth * 2);
  633. } else {
  634. for(cols = 0; cols < imgWidth; cols++)
  635. {
  636. *(RGBdata ++) = RGB565data[RGBpos] & 0x1F;
  637. *(RGBdata ++) = (RGB565data[RGBpos + 1] & 0x7) << 3 | RGB565data[RGBpos] >> 5;
  638. *(RGBdata ++) = RGB565data[RGBpos + 1] >> 3;
  639. if (g_screen_bpp == 32) { // RGB888
  640. *(RGBdata ++) = 0xFF;
  641. }
  642. RGBpos += 2;
  643. }
  644. }
  645. }
  646. memcpy(outBuf, tmp, g_screen_size);
  647. free(tmp);
  648. return 0;
  649. }
  650. int convert_rgb888_to_rgb(const uint8_t *inBuf, uint8_t *outBuf, int imgWidth, int imgHeight, int cvtMethod)
  651. {
  652. int rows ,cols;
  653. const uint8_t *RGB888data;
  654. uint8_t *RGBdata;
  655. int RGBpos;
  656. int width, height;
  657. int x_offset, y_offset;
  658. uint8_t *tmp = malloc(g_screen_size);
  659. uint8_t r, g, b;
  660. width = imgWidth > g_screen_width ? g_screen_width : imgWidth;
  661. height = imgHeight > g_screen_height ? g_screen_height : imgHeight;
  662. x_offset = (g_screen_width - width) / 2;
  663. y_offset = (g_screen_height - height) / 2;
  664. RGB888data = inBuf;
  665. RGBdata = tmp;
  666. RGBpos = 0;
  667. for(rows = 0; rows < imgHeight; rows++)
  668. {
  669. RGBdata = tmp + ((rows + y_offset) * g_screen_width + x_offset) * g_screen_bpp / 8;
  670. RGBpos = rows * imgWidth * 3;
  671. if (g_screen_bpp == 24) { // RGB888
  672. memcpy(RGBdata, &RGB888data[RGBpos], imgWidth * 3);
  673. } else {
  674. for(cols = 0; cols < imgWidth; cols++)
  675. {
  676. if (g_screen_bpp == 16) { // RGB565
  677. b = RGB888data[RGBpos];
  678. g = RGB888data[RGBpos + 1];
  679. r = RGB888data[RGBpos + 2];
  680. *(RGBdata ++) = (((g & 0x1c) << 3) | (b >> 3)); /* g low 5bits,b high 5bits */
  681. *(RGBdata ++) = ((r & 0xf8) | (g >> 5)); /* r high 5bits,g high 3bits */
  682. } else { // RGB8888
  683. *(RGBdata ++) = RGB888data[RGBpos];
  684. *(RGBdata ++) = RGB888data[RGBpos + 1];
  685. *(RGBdata ++) = RGB888data[RGBpos + 2];
  686. *(RGBdata ++) = 0xFF;
  687. }
  688. RGBpos += 3;
  689. }
  690. }
  691. }
  692. memcpy(outBuf, tmp, g_screen_size);
  693. free(tmp);
  694. return 0;
  695. }