convert.c 27 KB

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