因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作。

网上找了很久也没找到格式转换工具,最后放弃了,觉得还是写个转换工具比较快。抄写了部分libv4lconvert的代码, 我只验证了

V4L2_PIX_FMT_SGBRG8到V4L2_PIX_FMT_YUV420的转换。

 

bayer.c

##################################################################################

  1. /*
  2. * lib4lconvert, video4linux2 format conversion lib
  3. *             (C) 2008 Hans de Goede <hdegoede@redhat.com>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335  USA
  18. *
  19. * Note: original bayer_to_bgr24 code from :
  20. * 1394-Based Digital Camera Control Library
  21. *
  22. * Bayer pattern decoding functions
  23. *
  24. * Written by Damien Douxchamps and Frederic Devernay
  25. *
  26. * Note that the original bayer.c in libdc1394 supports many different
  27. * bayer decode algorithms, for lib4lconvert the one in this file has been
  28. * chosen (and optimized a bit) and the other algorithm's have been removed,
  29. * see bayer.c from libdc1394 for all supported algorithms
  30. */
  31. #include <string.h>
  32. #include <linux/videodev2.h>
  33. #include <stdio.h>
  34. #include "convert.h"
  35. /**************************************************************
  36. *     Color conversion functions for cameras that can        *
  37. * output raw-Bayer pattern images, such as some Basler and   *
  38. * Point Grey camera. Most of the algos presented here come   *
  39. * from http://www-ise.stanford.edu/~tingchen/ and have been  *
  40. * converted from Matlab to C and extended to all elementary  *
  41. * patterns.                                                  *
  42. **************************************************************/
  43. /* inspired by OpenCV's Bayer decoding */
  44. static void v4lconvert_border_bayer_line_to_bgr24(
  45. const unsigned char *bayer, const unsigned char *adjacent_bayer,
  46. unsigned char *bgr, int width, int start_with_green, int blue_line)
  47. {
  48. int t0, t1;
  49. if (start_with_green) {
  50. /* First pixel */
  51. if (blue_line) {
  52. *bgr++ = bayer[1];
  53. *bgr++ = bayer[0];
  54. *bgr++ = adjacent_bayer[0];
  55. } else {
  56. *bgr++ = adjacent_bayer[0];
  57. *bgr++ = bayer[0];
  58. *bgr++ = bayer[1];
  59. }
  60. /* Second pixel */
  61. t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
  62. t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
  63. if (blue_line) {
  64. *bgr++ = bayer[1];
  65. *bgr++ = t0;
  66. *bgr++ = t1;
  67. } else {
  68. *bgr++ = t1;
  69. *bgr++ = t0;
  70. *bgr++ = bayer[1];
  71. }
  72. bayer++;
  73. adjacent_bayer++;
  74. width -= 2;
  75. } else {
  76. /* First pixel */
  77. t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1;
  78. if (blue_line) {
  79. *bgr++ = bayer[0];
  80. *bgr++ = t0;
  81. *bgr++ = adjacent_bayer[1];
  82. } else {
  83. *bgr++ = adjacent_bayer[1];
  84. *bgr++ = t0;
  85. *bgr++ = bayer[0];
  86. }
  87. width--;
  88. }
  89. if (blue_line) {
  90. for ( ; width > 2; width -= 2) {
  91. t0 = (bayer[0] + bayer[2] + 1) >> 1;
  92. *bgr++ = t0;
  93. *bgr++ = bayer[1];
  94. *bgr++ = adjacent_bayer[1];
  95. bayer++;
  96. adjacent_bayer++;
  97. t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
  98. t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
  99. *bgr++ = bayer[1];
  100. *bgr++ = t0;
  101. *bgr++ = t1;
  102. bayer++;
  103. adjacent_bayer++;
  104. }
  105. } else {
  106. for ( ; width > 2; width -= 2) {
  107. t0 = (bayer[0] + bayer[2] + 1) >> 1;
  108. *bgr++ = adjacent_bayer[1];
  109. *bgr++ = bayer[1];
  110. *bgr++ = t0;
  111. bayer++;
  112. adjacent_bayer++;
  113. t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3;
  114. t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1;
  115. *bgr++ = t1;
  116. *bgr++ = t0;
  117. *bgr++ = bayer[1];
  118. bayer++;
  119. adjacent_bayer++;
  120. }
  121. }
  122. if (width == 2) {
  123. /* Second to last pixel */
  124. t0 = (bayer[0] + bayer[2] + 1) >> 1;
  125. if (blue_line) {
  126. *bgr++ = t0;
  127. *bgr++ = bayer[1];
  128. *bgr++ = adjacent_bayer[1];
  129. } else {
  130. *bgr++ = adjacent_bayer[1];
  131. *bgr++ = bayer[1];
  132. *bgr++ = t0;
  133. }
  134. /* Last pixel */
  135. t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1;
  136. if (blue_line) {
  137. *bgr++ = bayer[2];
  138. *bgr++ = t0;
  139. *bgr++ = adjacent_bayer[1];
  140. } else {
  141. *bgr++ = adjacent_bayer[1];
  142. *bgr++ = t0;
  143. *bgr++ = bayer[2];
  144. }
  145. } else {
  146. /* Last pixel */
  147. if (blue_line) {
  148. *bgr++ = bayer[0];
  149. *bgr++ = bayer[1];
  150. *bgr++ = adjacent_bayer[1];
  151. } else {
  152. *bgr++ = adjacent_bayer[1];
  153. *bgr++ = bayer[1];
  154. *bgr++ = bayer[0];
  155. }
  156. }
  157. }
  158. /* From libdc1394, which on turn was based on OpenCV's Bayer decoding */
  159. static void bayer_to_rgbbgr24(const unsigned char *bayer,
  160. unsigned char *bgr, int width, int height, unsigned int pixfmt,
  161. int start_with_green, int blue_line)
  162. {
  163. /* render the first line */
  164. v4lconvert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width,
  165. start_with_green, blue_line);
  166. bgr += width * 3;
  167. return;
  168. /* reduce height by 2 because of the special case top/bottom line */
  169. for (height -= 2; height; height--) {
  170. int t0, t1;
  171. /* (width - 2) because of the border */
  172. const unsigned char *bayer_end = bayer + (width - 2);
  173. if (start_with_green) {
  174. /* OpenCV has a bug in the next line, which was
  175. t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */
  176. t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1;
  177. /* Write first pixel */
  178. t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3;
  179. if (blue_line) {
  180. *bgr++ = t0;
  181. *bgr++ = t1;
  182. *bgr++ = bayer[width];
  183. } else {
  184. *bgr++ = bayer[width];
  185. *bgr++ = t1;
  186. *bgr++ = t0;
  187. }
  188. /* Write second pixel */
  189. t1 = (bayer[width] + bayer[width + 2] + 1) >> 1;
  190. if (blue_line) {
  191. *bgr++ = t0;
  192. *bgr++ = bayer[width + 1];
  193. *bgr++ = t1;
  194. } else {
  195. *bgr++ = t1;
  196. *bgr++ = bayer[width + 1];
  197. *bgr++ = t0;
  198. }
  199. bayer++;
  200. } else {
  201. /* Write first pixel */
  202. t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
  203. if (blue_line) {
  204. *bgr++ = t0;
  205. *bgr++ = bayer[width];
  206. *bgr++ = bayer[width + 1];
  207. } else {
  208. *bgr++ = bayer[width + 1];
  209. *bgr++ = bayer[width];
  210. *bgr++ = t0;
  211. }
  212. }
  213. if (blue_line) {
  214. for (; bayer <= bayer_end - 2; bayer += 2) {
  215. t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
  216. bayer[width * 2 + 2] + 2) >> 2;
  217. t1 = (bayer[1] + bayer[width] + bayer[width + 2] +
  218. bayer[width * 2 + 1] + 2) >> 2;
  219. *bgr++ = t0;
  220. *bgr++ = t1;
  221. *bgr++ = bayer[width + 1];
  222. t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
  223. t1 = (bayer[width + 1] + bayer[width + 3] + 1) >> 1;
  224. *bgr++ = t0;
  225. *bgr++ = bayer[width + 2];
  226. *bgr++ = t1;
  227. }
  228. } else {
  229. for (; bayer <= bayer_end - 2; bayer += 2) {
  230. t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
  231. bayer[width * 2 + 2] + 2) >> 2;
  232. t1 = (bayer[1] + bayer[width] + bayer[width + 2] +
  233. bayer[width * 2 + 1] + 2) >> 2;
  234. *bgr++ = bayer[width + 1];
  235. *bgr++ = t1;
  236. *bgr++ = t0;
  237. t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
  238. t1 = (bayer[width + 1] + bayer[width + 3] + 1) >> 1;
  239. *bgr++ = t1;
  240. *bgr++ = bayer[width + 2];
  241. *bgr++ = t0;
  242. }
  243. }
  244. if (bayer < bayer_end) {
  245. /* write second to last pixel */
  246. t0 = (bayer[0] + bayer[2] + bayer[width * 2] +
  247. bayer[width * 2 + 2] + 2) >> 2;
  248. t1 = (bayer[1] + bayer[width] + bayer[width + 2] +
  249. bayer[width * 2 + 1] + 2) >> 2;
  250. if (blue_line) {
  251. *bgr++ = t0;
  252. *bgr++ = t1;
  253. *bgr++ = bayer[width + 1];
  254. } else {
  255. *bgr++ = bayer[width + 1];
  256. *bgr++ = t1;
  257. *bgr++ = t0;
  258. }
  259. /* write last pixel */
  260. t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1;
  261. if (blue_line) {
  262. *bgr++ = t0;
  263. *bgr++ = bayer[width + 2];
  264. *bgr++ = bayer[width + 1];
  265. } else {
  266. *bgr++ = bayer[width + 1];
  267. *bgr++ = bayer[width + 2];
  268. *bgr++ = t0;
  269. }
  270. bayer++;
  271. } else {
  272. /* write last pixel */
  273. t0 = (bayer[0] + bayer[width * 2] + 1) >> 1;
  274. t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3;
  275. if (blue_line) {
  276. *bgr++ = t0;
  277. *bgr++ = t1;
  278. *bgr++ = bayer[width + 1];
  279. } else {
  280. *bgr++ = bayer[width + 1];
  281. *bgr++ = t1;
  282. *bgr++ = t0;
  283. }
  284. }
  285. /* skip 2 border pixels */
  286. bayer += 2;
  287. blue_line = !blue_line;
  288. start_with_green = !start_with_green;
  289. }
  290. /* render the last line */
  291. v4lconvert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width,
  292. !start_with_green, !blue_line);
  293. }
  294. void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
  295. unsigned char *bgr, int width, int height, unsigned int pixfmt)
  296. {
  297. bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt,
  298. pixfmt == V4L2_PIX_FMT_SGBRG8        /* start with green */
  299. || pixfmt == V4L2_PIX_FMT_SGRBG8,
  300. pixfmt != V4L2_PIX_FMT_SBGGR8        /* blue line */
  301. && pixfmt != V4L2_PIX_FMT_SGBRG8);
  302. }
  303. void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
  304. unsigned char *bgr, int width, int height, unsigned int pixfmt)
  305. {
  306. bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt,
  307. pixfmt == V4L2_PIX_FMT_SGBRG8        /* start with green */
  308. || pixfmt == V4L2_PIX_FMT_SGRBG8,
  309. pixfmt == V4L2_PIX_FMT_SBGGR8        /* blue line */
  310. || pixfmt == V4L2_PIX_FMT_SGBRG8);
  311. }
  312. static void v4lconvert_border_bayer_line_to_y(
  313. const unsigned char *bayer, const unsigned char *adjacent_bayer,
  314. unsigned char *y, int width, int start_with_green, int blue_line)
  315. {
  316. int t0, t1;
  317. if (start_with_green) {
  318. /* First pixel */
  319. if (blue_line) {
  320. *y++ = (8453 * adjacent_bayer[0] + 16594 * bayer[0] +
  321. 3223 * bayer[1] + 524288) >> 15;
  322. } else {
  323. *y++ = (8453 * bayer[1] + 16594 * bayer[0] +
  324. 3223 * adjacent_bayer[0] + 524288) >> 15;
  325. }
  326. /* Second pixel */
  327. t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
  328. t1 = adjacent_bayer[0] + adjacent_bayer[2];
  329. if (blue_line)
  330. *y++ = (4226 * t1 + 5531 * t0 + 3223 * bayer[1] + 524288) >> 15;
  331. else
  332. *y++ = (8453 * bayer[1] + 5531 * t0 + 1611 * t1 + 524288) >> 15;
  333. bayer++;
  334. adjacent_bayer++;
  335. width -= 2;
  336. } else {
  337. /* First pixel */
  338. t0 = bayer[1] + adjacent_bayer[0];
  339. if (blue_line) {
  340. *y++ = (8453 * adjacent_bayer[1] + 8297 * t0 +
  341. 3223 * bayer[0] + 524288) >> 15;
  342. } else {
  343. *y++ = (8453 * bayer[0] + 8297 * t0 +
  344. 3223 * adjacent_bayer[1] + 524288) >> 15;
  345. }
  346. width--;
  347. }
  348. if (blue_line) {
  349. for ( ; width > 2; width -= 2) {
  350. t0 = bayer[0] + bayer[2];
  351. *y++ = (8453 * adjacent_bayer[1] + 16594 * bayer[1] +
  352. 1611 * t0 + 524288) >> 15;
  353. bayer++;
  354. adjacent_bayer++;
  355. t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
  356. t1 = adjacent_bayer[0] + adjacent_bayer[2];
  357. *y++ = (4226 * t1 + 5531 * t0 + 3223 * bayer[1] + 524288) >> 15;
  358. bayer++;
  359. adjacent_bayer++;
  360. }
  361. } else {
  362. for ( ; width > 2; width -= 2) {
  363. t0 = bayer[0] + bayer[2];
  364. *y++ = (4226 * t0 + 16594 * bayer[1] +
  365. 3223 * adjacent_bayer[1] + 524288) >> 15;
  366. bayer++;
  367. adjacent_bayer++;
  368. t0 = bayer[0] + bayer[2] + adjacent_bayer[1];
  369. t1 = adjacent_bayer[0] + adjacent_bayer[2];
  370. *y++ = (8453 * bayer[1] + 5531 * t0 + 1611 * t1 + 524288) >> 15;
  371. bayer++;
  372. adjacent_bayer++;
  373. }
  374. }
  375. if (width == 2) {
  376. /* Second to last pixel */
  377. t0 = bayer[0] + bayer[2];
  378. if (blue_line) {
  379. *y++ = (8453 * adjacent_bayer[1] + 16594 * bayer[1] +
  380. 1611 * t0 + 524288) >> 15;
  381. } else {
  382. *y++ = (4226 * t0 + 16594 * bayer[1] +
  383. 3223 * adjacent_bayer[1] + 524288) >> 15;
  384. }
  385. /* Last pixel */
  386. t0 = bayer[1] + adjacent_bayer[2];
  387. if (blue_line) {
  388. *y++ = (8453 * adjacent_bayer[1] + 8297 * t0 +
  389. 3223 * bayer[2] + 524288) >> 15;
  390. } else {
  391. *y++ = (8453 * bayer[2] + 8297 * t0 +
  392. 3223 * adjacent_bayer[1] + 524288) >> 15;
  393. }
  394. } else {
  395. /* Last pixel */
  396. if (blue_line) {
  397. *y++ = (8453 * adjacent_bayer[1] + 16594 * bayer[1] +
  398. 3223 * bayer[0] + 524288) >> 15;
  399. } else {
  400. *y++ = (8453 * bayer[0] + 16594 * bayer[1] +
  401. 3223 * adjacent_bayer[1] + 524288) >> 15;
  402. }
  403. }
  404. }
  405. void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv,
  406. int width, int height, unsigned int src_pixfmt, int yvu)
  407. {
  408. int blue_line = 0, start_with_green = 0, x, y;
  409. unsigned char *ydst = yuv;
  410. unsigned char *udst, *vdst;
  411. if (yvu) {
  412. vdst = yuv + width * height;
  413. udst = vdst + width * height / 4;
  414. } else {
  415. udst = yuv + width * height;
  416. vdst = udst + width * height / 4;
  417. }
  418. printf("bayer address(0x%p)", bayer);
  419. /* First calculate the u and v planes 2x2 pixels at a time */
  420. switch (src_pixfmt) {
  421. case V4L2_PIX_FMT_SBGGR8:
  422. for (y = 0; y < height; y += 2) {
  423. for (x = 0; x < width; x += 2) {
  424. int b, g, r;
  425. b  = bayer[x];
  426. g  = bayer[x + 1];
  427. g += bayer[x + width];
  428. r  = bayer[x + width + 1];
  429. *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
  430. *vdst++ = (14456 * r - 6052 * g -  2351 * b + 4210688) >> 15;
  431. }
  432. bayer += 2 * width;
  433. }
  434. blue_line = 1;
  435. break;
  436. case V4L2_PIX_FMT_SRGGB8:
  437. for (y = 0; y < height; y += 2) {
  438. for (x = 0; x < width; x += 2) {
  439. int b, g, r;
  440. r  = bayer[x];
  441. g  = bayer[x + 1];
  442. g += bayer[x + width];
  443. b  = bayer[x + width + 1];
  444. *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
  445. *vdst++ = (14456 * r - 6052 * g -  2351 * b + 4210688) >> 15;
  446. }
  447. bayer += 2 * width;
  448. }
  449. break;
  450. case V4L2_PIX_FMT_SGBRG8:
  451. for (y = 0; y < height; y += 2) {
  452. for (x = 0; x < width; x += 2) {
  453. int b, g, r;
  454. g  = bayer[x];
  455. b  = bayer[x + 1];
  456. r  = bayer[x + width];
  457. g += bayer[x + width + 1];
  458. *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
  459. *vdst++ = (14456 * r - 6052 * g -  2351 * b + 4210688) >> 15;
  460. }
  461. bayer += 2 * width;
  462. }
  463. blue_line = 1;
  464. start_with_green = 1;
  465. break;
  466. case V4L2_PIX_FMT_SGRBG8:
  467. for (y = 0; y < height; y += 2) {
  468. for (x = 0; x < width; x += 2) {
  469. int b, g, r;
  470. g  = bayer[x];
  471. r  = bayer[x + 1];
  472. b  = bayer[x + width];
  473. g += bayer[x + width + 1];
  474. *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15;
  475. *vdst++ = (14456 * r - 6052 * g -  2351 * b + 4210688) >> 15;
  476. }
  477. bayer += 2 * width;
  478. }
  479. start_with_green = 1;
  480. break;
  481. }
  482. bayer -= width * height;
  483. printf("bayer address(0x%p)", bayer);
  484. /* render the first line */
  485. v4lconvert_border_bayer_line_to_y(bayer, bayer + width, ydst, width,
  486. start_with_green, blue_line);
  487. ydst += width;
  488. printf("bayer address(0x%p), height(%d)", bayer, height);
  489. /* reduce height by 2 because of the border */
  490. for (height -= 2; height; height--) {
  491. int t0, t1;
  492. /* (width - 2) because of the border */
  493. const unsigned char *bayer_end = bayer + (width - 2);
  494. if (start_with_green) {
  495. t0 = bayer[1] + bayer[width * 2 + 1];
  496. /* Write first pixel */
  497. t1 = bayer[0] + bayer[width * 2] + bayer[width + 1];
  498. if (blue_line)
  499. *ydst++ = (8453 * bayer[width] + 5516 * t1 +
  500. 1661 * t0 + 524288) >> 15;
  501. else
  502. *ydst++ = (4226 * t0 + 5516 * t1 +
  503. 3223 * bayer[width] + 524288) >> 15;
  504. /* Write second pixel */
  505. t1 = bayer[width] + bayer[width + 2];
  506. if (blue_line)
  507. *ydst++ = (4226 * t1 + 16594 * bayer[width + 1] +
  508. 1611 * t0 + 524288) >> 15;
  509. else
  510. *ydst++ = (4226 * t0 + 16594 * bayer[width + 1] +
  511. 1611 * t1 + 524288) >> 15;
  512. bayer++;
  513. } else {
  514. /* Write first pixel */
  515. t0 = bayer[0] + bayer[width * 2];
  516. if (blue_line) {
  517. *ydst++ = (8453 * bayer[width + 1] + 16594 * bayer[width] +
  518. 1661 * t0 + 524288) >> 15;
  519. } else {
  520. *ydst++ = (4226 * t0 + 16594 * bayer[width] +
  521. 3223 * bayer[width + 1] + 524288) >> 15;
  522. }
  523. }
  524. if (blue_line) {
  525. for (; bayer <= bayer_end - 2; bayer += 2) {
  526. t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2];
  527. t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1];
  528. *ydst++ = (8453 * bayer[width + 1] + 4148 * t1 +
  529. 806 * t0 + 524288) >> 15;
  530. t0 = bayer[2] + bayer[width * 2 + 2];
  531. t1 = bayer[width + 1] + bayer[width + 3];
  532. *ydst++ = (4226 * t1 + 16594 * bayer[width + 2] +
  533. 1611 * t0 + 524288) >> 15;
  534. }
  535. } else {
  536. for (; bayer <= bayer_end - 2; bayer += 2) {
  537. t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2];
  538. t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1];
  539. *ydst++ = (2113 * t0 + 4148 * t1 +
  540. 3223 * bayer[width + 1] + 524288) >> 15;
  541. t0 = bayer[2] + bayer[width * 2 + 2];
  542. t1 = bayer[width + 1] + bayer[width + 3];
  543. *ydst++ = (4226 * t0 + 16594 * bayer[width + 2] +
  544. 1611 * t1 + 524288) >> 15;
  545. }
  546. }
  547. if (bayer < bayer_end) {
  548. /* Write second to last pixel */
  549. t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2];
  550. t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1];
  551. if (blue_line)
  552. *ydst++ = (8453 * bayer[width + 1] + 4148 * t1 +
  553. 806 * t0 + 524288) >> 15;
  554. else
  555. *ydst++ = (2113 * t0 + 4148 * t1 +
  556. 3223 * bayer[width + 1] + 524288) >> 15;
  557. /* write last pixel */
  558. t0 = bayer[2] + bayer[width * 2 + 2];
  559. if (blue_line) {
  560. *ydst++ = (8453 * bayer[width + 1] + 16594 * bayer[width + 2] +
  561. 1661 * t0 + 524288) >> 15;
  562. } else {
  563. *ydst++ = (4226 * t0 + 16594 * bayer[width + 2] +
  564. 3223 * bayer[width + 1] + 524288) >> 15;
  565. }
  566. bayer++;
  567. } else {
  568. /* write last pixel */
  569. t0 = bayer[0] + bayer[width * 2];
  570. t1 = bayer[1] + bayer[width * 2 + 1] + bayer[width];
  571. if (blue_line)
  572. *ydst++ = (8453 * bayer[width + 1] + 5516 * t1 +
  573. 1661 * t0 + 524288) >> 15;
  574. else
  575. *ydst++ = (4226 * t0 + 5516 * t1 +
  576. 3223 * bayer[width + 1] + 524288) >> 15;
  577. }
  578. /* skip 2 border pixels */
  579. bayer += 2;
  580. blue_line = !blue_line;
  581. start_with_green = !start_with_green;
  582. }
  583. /* render the last line */
  584. v4lconvert_border_bayer_line_to_y(bayer + width, bayer, ydst, width,
  585. !start_with_green, !blue_line);
  586. }

##################################################################################

convert.c

##################################################################################

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. #include <linux/videodev2.h>
  7. #include "convert.h"
  8. char *g_src_file = NULL;
  9. char *g_dest_file = NULL;
  10. int g_in_width = 352;
  11. int g_in_height = 292;
  12. unsigned int g_src_fmt = V4L2_PIX_FMT_SGBRG8;
  13. //unsigned int g_dest_fmt = V4L2_PIX_FMT_RGB24;
  14. unsigned int g_dest_fmt = V4L2_PIX_FMT_YUV420;
  15. int process_cmdline(int argc, char **argv)
  16. {
  17. int i;
  18. char *tmp;
  19. for (i = 1; i < argc; i++) {
  20. if (strcmp(argv[i], "-s") == 0) {
  21. g_src_file = argv[++i];
  22. }
  23. else if (strcmp(argv[i], "d") == 0) {
  24. g_dest_file = strdup(argv[++i]);
  25. }
  26. else if (strcmp(argv[i], "-sf") == 0) {
  27. tmp = argv[++i];
  28. if (strlen(tmp) == 4) {
  29. g_src_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);
  30. }
  31. }
  32. else if (strcmp(argv[i], "-df") == 0) {
  33. tmp = argv[++i];
  34. if (strlen(tmp) == 4) {
  35. g_dest_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);
  36. }
  37. }
  38. else if (strcmp(argv[i], "iw") == 0) {
  39. g_in_width = atoi(argv[++i]);
  40. }
  41. else if (strcmp(argv[i], "ih") == 0) {
  42. g_in_height = atoi(argv[++i]);
  43. }
  44. }
  45. if (g_src_file && g_dest_file == NULL) {
  46. g_dest_file = malloc(256);
  47. sprintf(g_dest_file, "%s.out", g_src_file);
  48. }
  49. if (g_in_width == 0 || g_in_height == 0) {
  50. }
  51. }
  52. int get_file_size(int fd)
  53. {
  54. int ret;
  55. struct stat sb;
  56. ret = fstat(fd, &sb);
  57. if (ret == -1) {
  58. return ret;
  59. }
  60. return sb.st_size;
  61. }
  62. int get_bits_per_pixel(unsigned int fmt)
  63. {
  64. int ret;
  65. switch (fmt) {
  66. case V4L2_PIX_FMT_RGB24:
  67. ret = 24;
  68. break;
  69. case V4L2_PIX_FMT_SBGGR8:
  70. case V4L2_PIX_FMT_SGBRG8:
  71. case V4L2_PIX_FMT_SGRBG8:
  72. case V4L2_PIX_FMT_SRGGB8:
  73. ret = 8;
  74. break;
  75. case V4L2_PIX_FMT_YUV420:
  76. ret = 12;
  77. break;
  78. case V4L2_PIX_FMT_YUYV:
  79. case V4L2_PIX_FMT_UYVY:
  80. ret = 16;
  81. break;
  82. default:
  83. ret = -1;
  84. break;
  85. }
  86. return ret;
  87. }
  88. void convert(void *src, void *dest, int width, int height, unsigned int src_fmt, unsigned int dest_fmt)
  89. {
  90. switch (src_fmt) {
  91. case V4L2_PIX_FMT_SGBRG8:
  92. if (dest_fmt == V4L2_PIX_FMT_RGB24) {
  93. v4lconvert_bayer_to_rgb24(src, dest, width, height, src_fmt);
  94. }
  95. else if (dest_fmt == V4L2_PIX_FMT_YUV420) {
  96. v4lconvert_bayer_to_yuv420(src, dest, width, height, src_fmt, 0);
  97. }
  98. break;
  99. default:
  100. break;
  101. }
  102. }
  103. int main(int argc, char *argv[])
  104. {
  105. int ret = 0;
  106. int fd_src = 0;
  107. int fd_dest = 0;
  108. int src_size = 0;
  109. int dest_size = 0;
  110. int pix_num;
  111. void *src = NULL;
  112. void *dest = NULL;
  113. process_cmdline(argc, argv);
  114. if (g_src_file == NULL || g_dest_file == NULL) {
  115. ret = -1;
  116. goto bailout;
  117. }
  118. printf("input file(%s), output file(%s)\n", g_src_file, g_dest_file);
  119. fd_src = open(g_src_file, O_RDONLY);
  120. if (fd_src == -1) {
  121. ret = -2;
  122. goto bailout;
  123. }
  124. fd_dest = open(g_dest_file, O_RDWR | O_CREAT, 0666);
  125. if (fd_dest == -1) {
  126. ret = -3;
  127. goto bailout;
  128. }
  129. src_size = get_file_size(fd_src);
  130. if (src_size == -1) {
  131. ret = -4;
  132. goto bailout;
  133. }
  134. pix_num = src_size / (get_bits_per_pixel(g_src_fmt)/8) ;
  135. //dest_size = pix_num * get_bytes_per_pixel(g_dest_fmt);
  136. ret = get_bits_per_pixel(g_dest_fmt);
  137. dest_size = pix_num * ret / 8;
  138. printf("src_size(%d), dest_size(%d)\n", src_size, dest_size);
  139. src = malloc(src_size);
  140. dest = malloc(dest_size);
  141. if (src == NULL || dest == NULL) {
  142. ret = -5;
  143. goto bailout;
  144. }
  145. ret = read(fd_src, src, src_size);
  146. if (ret != src_size) {
  147. ret = -6;
  148. goto bailout;
  149. }
  150. convert(src, dest, g_in_width, g_in_height, g_src_fmt, g_dest_fmt);
  151. printf("write out file, size=%d\n", dest_size);
  152. ret = write(fd_dest, dest, dest_size);
  153. if (ret != dest_size) {
  154. ret = -1;
  155. goto bailout;
  156. }
  157. bailout:
  158. if (src)
  159. free(src);
  160. if (dest)
  161. free(dest);
  162. if (fd_src)
  163. close(fd_src);
  164. if (fd_dest)
  165. close(fd_dest);
  166. if (g_dest_file)
  167. free(g_dest_file);
  168. printf("ret(%d)\n", ret);
  169. return ret;
  170. }

##################################################################################

 

covert.h

##################################################################################

  1. #ifndef __LIBV4LCONVERT_PRIV_H
  2. #define __LIBV4LCONVERT_PRIV_H
  3. #define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B')
  4. void v4lconvert_bayer_to_rgb24(const unsigned char *bayer,
  5. unsigned char *bgr, int width, int height, unsigned int pixfmt);
  6. void v4lconvert_bayer_to_bgr24(const unsigned char *bayer,
  7. unsigned char *bgr, int width, int height, unsigned int pixfmt);
  8. void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, unsigned char *yuv,
  9. int width, int height, unsigned int src_pixfmt, int yvu);
  10. #endif /* __LIBV4LCONVERT_PRIV_H */

##################################################################################

Makefile

##################################################################################

  1. CONVERT := convert
  2. CFLAGS := -static
  3. CC = gcc
  4. $(CONVERT): convert.c bayer.c
  5. $(CC) -o $@ $^ $(CFLAGS)
  6. clean:
  7. rm -f *.o $(CONVERT)

##################################################################################

RGB32 RGB565转换为YUV444

另外为了在PC显示framebuffer中的数据,写了一个ARGB32或者RGB565到YUV444的转换工具。利用YUVtools显示YUV444图像。

其实可以不用这么麻烦,使用ddms截屏也行。

YUV444是 Y U V分量比为4:4:4,每个像素用24bits表示。

##################################################################################

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. #include <linux/videodev2.h>
  7. char *g_src_file = NULL;
  8. char *g_dest_file = NULL;
  9. int g_in_width = 720;
  10. int g_in_height = 480;
  11. /* V4L2_PIX_FMT_BGR32 */
  12. //unsigned int g_src_fmt = V4L2_PIX_FMT_RGB32;
  13. unsigned int g_src_fmt = V4L2_PIX_FMT_RGB565;
  14. /* V4L2_PIX_FMT_YUYV V4L2_PIX_FMT_YVYU V4L2_PIX_FMT_UYVY V4L2_PIX_FMT_VYUY */
  15. unsigned int g_dest_fmt = V4L2_PIX_FMT_YUV444;
  16. static unsigned char get_R(unsigned char *src, unsigned int fmt)
  17. {
  18. unsigned char R;
  19. switch (fmt) {
  20. case V4L2_PIX_FMT_RGB32:
  21. case V4L2_PIX_FMT_BGR32:
  22. case V4L2_PIX_FMT_RGB24:
  23. R = *(src);
  24. break;
  25. case V4L2_PIX_FMT_RGB565:
  26. R = (*(src) & 0x1F) << 3;
  27. break;
  28. case V4L2_PIX_FMT_SBGGR8:
  29. case V4L2_PIX_FMT_SGBRG8:
  30. case V4L2_PIX_FMT_SGRBG8:
  31. case V4L2_PIX_FMT_YUV420:
  32. case V4L2_PIX_FMT_YUV444:
  33. default:
  34. R = 0;
  35. break;
  36. }
  37. return R;
  38. }
  39. static unsigned char get_G(unsigned char *src, unsigned int fmt)
  40. {
  41. unsigned char G;
  42. switch (fmt) {
  43. case V4L2_PIX_FMT_RGB32:
  44. case V4L2_PIX_FMT_BGR32:
  45. case V4L2_PIX_FMT_RGB24:
  46. G = *(src + 1);
  47. break;
  48. case V4L2_PIX_FMT_RGB565:
  49. G = ((*(src) & 0xE0) >> 3) | ((*(src + 1) & 0x07) << 5);
  50. break;
  51. case V4L2_PIX_FMT_SBGGR8:
  52. case V4L2_PIX_FMT_SGBRG8:
  53. case V4L2_PIX_FMT_SGRBG8:
  54. case V4L2_PIX_FMT_YUV420:
  55. case V4L2_PIX_FMT_YUV444:
  56. default:
  57. G = 0;
  58. break;
  59. }
  60. return G;
  61. }
  62. static unsigned char get_B(unsigned char *src, unsigned int fmt)
  63. {
  64. unsigned char B;
  65. switch (fmt) {
  66. case V4L2_PIX_FMT_RGB32:
  67. case V4L2_PIX_FMT_BGR32:
  68. case V4L2_PIX_FMT_RGB24:
  69. B = *(src + 2);
  70. break;
  71. case V4L2_PIX_FMT_RGB565:
  72. B = (*(src + 1) & 0xF8);
  73. break;
  74. case V4L2_PIX_FMT_SBGGR8:
  75. case V4L2_PIX_FMT_SGBRG8:
  76. case V4L2_PIX_FMT_SGRBG8:
  77. case V4L2_PIX_FMT_YUV420:
  78. case V4L2_PIX_FMT_YUV444:
  79. default:
  80. B = 0;
  81. break;
  82. }
  83. return B;
  84. }
  85. rgb2yuv(char *rgb, char *yuv)
  86. {
  87. int i, j;
  88. unsigned char R, G, B, *y, *u, *v, *alpha;
  89. double RR, GG, BB;
  90. unsigned char *src, *dest;
  91. for (i = 0; i < g_in_height; i++) {
  92. for (j = 0; j < g_in_width; j++) {
  93. src = rgb + (i * g_in_width + j) * get_bpp(g_src_fmt) / 8;
  94. dest = yuv + (i * g_in_width + j) * get_bpp(g_dest_fmt) / 8;
  95. R = get_R(src, g_src_fmt);
  96. G = get_G(src, g_src_fmt);
  97. B = get_B(src, g_src_fmt);
  98. /* normalize to 16 ..235 */
  99. RR = 219 * R / 255 + 16;
  100. GG = 219 * G / 255 + 16;
  101. BB = 219 * B / 255 + 16;
  102. y = dest;
  103. u = dest + 1;
  104. v = dest + 2;
  105. //alpha = dest + 3;
  106. *y = (unsigned char)(0.2991*RR + 0.5849*GG + 0.1159*BB + 0.5);
  107. *u = (unsigned char)(-0.1725*RR - 0.3372*GG + 0.5097*BB + 128.5);
  108. *v = (unsigned char)(0.5097*RR - 0.4254*GG - 0.0843*BB + 128.5);
  109. //*alpha = 255;
  110. }
  111. }
  112. }
  113. int process_cmdline(int argc, char **argv)
  114. {
  115. int i;
  116. char *tmp;
  117. for (i = 1; i < argc; i++) {
  118. if (strcmp(argv[i], "-s") == 0) {
  119. g_src_file = argv[++i];
  120. }
  121. else if (strcmp(argv[i], "-d") == 0) {
  122. g_dest_file = strdup(argv[++i]);
  123. }
  124. else if (strcmp(argv[i], "-sf") == 0) {
  125. tmp = argv[++i];
  126. if (strlen(tmp) == 4) {
  127. g_src_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);
  128. }
  129. }
  130. else if (strcmp(argv[i], "-df") == 0) {
  131. tmp = argv[++i];
  132. if (strlen(tmp) == 4) {
  133. g_dest_fmt = v4l2_fourcc(tmp[0], tmp[1], tmp[2], tmp[3]);
  134. }
  135. }
  136. else if (strcmp(argv[i], "iw") == 0) {
  137. g_in_width = atoi(argv[++i]);
  138. }
  139. else if (strcmp(argv[i], "ih") == 0) {
  140. g_in_height = atoi(argv[++i]);
  141. }
  142. }
  143. if (g_src_file && g_dest_file == NULL) {
  144. g_dest_file = malloc(256);
  145. sprintf(g_dest_file, "%s.out", g_src_file);
  146. }
  147. if (g_in_width == 0 || g_in_height == 0) {
  148. }
  149. }
  150. int get_bpp(unsigned int fmt)
  151. {
  152. int ret;
  153. switch (fmt) {
  154. case V4L2_PIX_FMT_RGB32:
  155. case V4L2_PIX_FMT_BGR32:
  156. ret = 32;
  157. break;
  158. case V4L2_PIX_FMT_RGB24:
  159. ret = 24;
  160. break;
  161. case V4L2_PIX_FMT_RGB565:
  162. ret = 16;
  163. break;
  164. case V4L2_PIX_FMT_SBGGR8:
  165. case V4L2_PIX_FMT_SGBRG8:
  166. case V4L2_PIX_FMT_SGRBG8:
  167. ret = 8;
  168. break;
  169. case V4L2_PIX_FMT_YUV420:
  170. ret = 12;
  171. break;
  172. case V4L2_PIX_FMT_YUYV:
  173. case V4L2_PIX_FMT_UYVY:
  174. ret = 16;
  175. break;
  176. case V4L2_PIX_FMT_YUV444:
  177. ret = 24;
  178. break;
  179. default:
  180. ret = -1;
  181. break;
  182. }
  183. return ret;
  184. }
  185. main(int argc, char *argv[])
  186. {
  187. int ret;
  188. int src_fd, dest_fd;
  189. int src_size, dest_size;
  190. char *src_buf;
  191. char *dest_buf;
  192. process_cmdline(argc, argv);
  193. if (g_src_file == NULL || g_dest_file == NULL) {
  194. ret = -1;
  195. goto bailout;
  196. }
  197. src_fd = open(g_src_file, O_RDONLY);
  198. if (src_fd == -1) {
  199. ret = -2;
  200. goto bailout;
  201. }
  202. dest_fd = open(g_dest_file, O_RDWR | O_CREAT, 0666);
  203. if (dest_fd == -1) {
  204. ret = -3;
  205. goto bailout;
  206. }
  207. src_size = g_in_width * g_in_height * get_bpp(g_src_fmt) / 8;
  208. dest_size = g_in_width * g_in_height * get_bpp(g_dest_fmt) / 8;
  209. src_buf = malloc(src_size);
  210. dest_buf = malloc(dest_size);
  211. ret = read(src_fd, src_buf, src_size);
  212. if (ret != src_size) {
  213. printf("src_size=%d, ret=%d\n", src_size, ret);
  214. ret = -4;
  215. goto bailout;
  216. }
  217. rgb2yuv(src_buf, dest_buf);
  218. printf("write out file, size=%d\n", dest_size);
  219. ret = write(dest_fd, dest_buf, dest_size);
  220. if (ret != dest_size) {
  221. ret = -5;
  222. goto bailout;
  223. }
  224. bailout:
  225. printf("ret(%d)\n", ret);
  226. return ret;
  227. }

##################################################################################

bayer, yuv, RGB转换方法的更多相关文章

  1. 【VS开发】【图像处理】 bayer, yuv, RGB转换方法

    因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作. 网上找了很久也没找到格式转换工具,最后放弃了, ...

  2. 图像处理之基础---yuv420及其rgb,bayer, yuv, RGB的相互转换详解

    YUV格式解析1(播放器——project2) 根据板卡api设计实现yuv420格式的视频播放器 打开*.mp4;*.264类型的文件,实现其播放. 使用的视频格式是YUV420格式   YUV格式 ...

  3. 最简单的视音频播放示例2:GDI播放YUV, RGB

    前一篇文章对“Simplest Media Play”工程作了概括性介绍.后续几篇文章打算详细介绍每个子工程中的几种技术.在记录Direct3D,OpenGL这两种相对复杂的技术之前,打算先记录一种和 ...

  4. 彩色MT9V034摄像头 Bayer转rgb FPGA实现

    1 图像bayer格式介绍 bayer格式是伊士曼·柯达公司科学家Bryce Bayer发明的,Bryce Bayer所发明的拜耳阵列被广泛运用数字图像.Bayer格式是相机内部的原始数据, 一般后缀 ...

  5. YCbCr;YUV;RGB

    1.  来源的差异 yuv色彩模 型来源于rgb模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域. 应用:basic color model used in analogue color ...

  6. 转:YUV RGB 常见视频格式解析

    转: http://www.cnblogs.com/qinjunni/archive/2012/02/23/2364446.html YUV RGB 常见视频格式解析 I420是YUV格式的一种,而Y ...

  7. 80.YCrCb - YUV - RGB之间的介绍

    一,引言 YUV(亦称YCrCb)是被欧洲电视系统所采用的一种颜色编码方法(属于PAL).YUV主要用于优化彩色视频信号的传输,使其向后兼容老式黑白电视.与RGB视频信号传输相比,它最大的优点在于只需 ...

  8. YUV/RGB与H264之间的编解码

    1.源码下载 http://download.videolan.org/x264/snapshots/ 2.编译 ./configure --prefix=./_install --enable-sh ...

  9. YUV RGB播放器 打开, 显示RGB数据

    可以查看RGB像素数据 可以通过菜单栏打开像素数据文件,也可以通过拖拽方式打开文件.如果文件名称中包含了“{w}x{h}”这样的字符串(例如“test_320x420.yuv”),系统会自动解析为该像 ...

随机推荐

  1. 《Spring2之站立会议8》

    <Spring2之站立会议8> 昨天,添加了登录界面: 今天,准备添加注册界面: 遇到的问题:过程中遇到了一些困难,不过还是解决了.

  2. 项目Beta冲刺(团队)第五天

    1.昨天的困难 服务器得不到前端返回的数据 教务处网页的源代码的研究有些困难,有些具体数据还不能得到,jsoup还在探索 2.今天解决的进度 成员 进度 陈家权 点赞界面设计 赖晓连 问答功能各项完善 ...

  3. 【贪心算法】POJ-1862 简单哈夫曼

    一.题目 Description Our chemical biologists have invented a new very useful form of life called stripie ...

  4. Week2-作业1——关于阅读《构建之法》第1、2、16章的疑问与感悟

    关于阅读<构建之法>第1.2.16章的疑问与感悟 术语解释: 第2章,23页 什么是代码覆盖率? ———————————————————— 在测试中的代码覆盖率是指,你运行测试用例后,走过 ...

  5. express框架实现承载静态页面的能力

    我们知道nodejs本身不具有一个web容器的作用,不像tomcat或者IIS这样的服务器一样天然具有web容器承载静态动态页面的能力,如果要原生实现的话需要自己通过路由配置,比较麻烦,而expres ...

  6. linux的桌面介绍

    一:linux桌面环境 1. X Windows桌面环境 X Windows软件是图形显示的核心部分,是直接和PC上的显卡及显示器打交道的底层程序,它控制着linux程序如何在电脑上显示出漂亮的窗口和 ...

  7. win32.gui.api.con(前置,鼠标点击,发送数据的Dome)

    # -*- coding: UTF-8 -*- import win32gui, win32con import os import time import win32gui import win32 ...

  8. 'java' 不是内部或外部命令,也不是可运行的程序的两个解决办法

    第一个原因: 是环境变量path没有配置好,做如下图配置     第二个原因:   如果java环境有一段时间没有启动,再启动的时候提示这个,解决办法是进入path环境配置,如上图中界面,将JAVA_ ...

  9. 10条SQL优化语句,让你的MySQL数据库跑得更快!

    慢SQL消耗了70%~90%的数据库CPU资源: SQL语句独立于程序设计逻辑,相对于对程序源代码的优化,对SQL语句的优化在时间成本和风险上的代价都很低: SQL语句可以有不同的写法: 1 不使用子 ...

  10. go 面试题总结

    1.什么是goroutine,他与process, thread有什么区别? 2. 什么是channel,为什么它可以做到线程安全? 3. 了解读写锁吗,原理是什么样的,为什么可以做到? 4. 如何用 ...