Guest User

Frame grabber source code

a guest
Apr 13th, 2013
1,726
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.41 KB | None | 0 0
  1. //to compile gcc main.c rs232.c -Wall -O2 -o grab -lSDL
  2. #include <stdio.h> /* Standard input/output definitions */
  3. #include <string.h> /* String function definitions */
  4. #include <unistd.h> /* UNIX standard function definitions */
  5. #include <fcntl.h> /* File control definitions */
  6. #include <errno.h> /* Error number definitions */
  7. #include <termios.h> /* POSIX terminal control definitions */
  8. #include <stdint.h>
  9. #include "rs232.h"
  10. //#define rgb565
  11. #define rawRGB
  12. //#define yuv422
  13. #define preview
  14. #define timeLapse
  15. //#define simulate
  16. //#define simulateWithRand
  17. //#define simulateWithPattern
  18. #ifdef preview
  19. #include <SDL/SDL.h>
  20. #endif
  21. #ifdef simulateWithRand
  22. #include <time.h> /* time */
  23. #endif
  24. // ttyACM0
  25. //qcif 176 × 144
  26. #define Width_G 640
  27. #define Height_G 480
  28. #define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
  29.  
  30. // RGB -> YUV
  31. #define RGB2Y(R, G, B) CLIP(( ( 66 * (R) + 129 * (G) + 25 * (B) + 128) >> 8) + 16)
  32. #define RGB2U(R, G, B) CLIP(( ( -38 * (R) - 74 * (G) + 112 * (B) + 128) >> 8) + 128)
  33. #define RGB2V(R, G, B) CLIP(( ( 112 * (R) - 94 * (G) - 18 * (B) + 128) >> 8) + 128)
  34.  
  35. // YUV -> RGB
  36. #define C(Y) ( (Y) - 16 )
  37. #define D(U) ( (U) - 128 )
  38. #define E(V) ( (V) - 128 )
  39.  
  40. #define YUV2R(Y, U, V) CLIP(( 298 * C(Y) + 409 * E(V) + 128) >> 8)
  41. #define YUV2G(Y, U, V) CLIP(( 298 * C(Y) - 100 * D(U) - 208 * E(V) + 128) >> 8)
  42. #define YUV2B(Y, U, V) CLIP(( 298 * C(Y) + 516 * D(U) + 128) >> 8)
  43.  
  44. // RGB -> YCbCr
  45. #define CRGB2Y(R, G, B) CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16)
  46. #define CRGB2Cb(R, G, B) CLIP((36962 * (B - CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) ) >> 16) + 128)
  47. #define CRGB2Cr(R, G, B) CLIP((46727 * (R - CLIP((19595 * R + 38470 * G + 7471 * B ) >> 16) ) >> 16) + 128)
  48.  
  49. // YCbCr -> RGB
  50. #define CYCbCr2R(Y, Cb, Cr) CLIP( Y + ( 91881 * Cr >> 16 ) - 179 )
  51. #define CYCbCr2G(Y, Cb, Cr) CLIP( Y - (( 22544 * Cb + 46793 * Cr ) >> 16) + 135)
  52. #define CYCbCr2B(Y, Cb, Cr) CLIP( Y + (116129 * Cb >> 16 ) - 226 )
  53. struct __attribute__ ((__packed__)) TGAheader
  54. {
  55. int8_t idlength;
  56. int8_t colourmaptype;
  57. int8_t datatypecode;
  58. int16_t colourmaporigin;
  59. int16_t colourmaplength;
  60. int8_t colourmapdepth;
  61. int16_t x_origin;
  62. int16_t y_origin;
  63. int16_t width;
  64. int16_t height;
  65. int8_t bitsperpixel;
  66. int8_t imagedescriptor;
  67.  
  68. // pixel data follows header
  69.  
  70. };
  71. struct TGAheader tgahead;
  72. // How many frames time values to keep
  73. // The higher the value the smoother the result is...
  74. // Don't make it 0 or less :)
  75. char port=24;
  76. #ifdef preview
  77. #define FRAME_VALUES 10
  78.  
  79. // An array to store frame times:
  80. uint32_t frametimes[FRAME_VALUES];
  81.  
  82. // Last calculated SDL_GetTicks
  83. uint32_t frametimelast;
  84.  
  85. // total frames rendered
  86. uint32_t framecount;
  87.  
  88. // the value you want
  89. float framespersecond;
  90.  
  91. // This function gets called once on startup.
  92.  
  93. void fpsinit() {
  94.  
  95. // Set all frame times to 0ms.
  96. memset(frametimes, 0, sizeof(frametimes));
  97. framecount = 0;
  98. framespersecond = 0;
  99. frametimelast = SDL_GetTicks();
  100.  
  101. }
  102.  
  103. void fpsthink() {
  104.  
  105. uint32_t frametimesindex;
  106. uint32_t getticks;
  107. uint32_t count;
  108. uint32_t i;
  109.  
  110. // frametimesindex is the position in the array. It ranges from 0 to FRAME_VALUES.
  111. // This value rotates back to 0 after it hits FRAME_VALUES.
  112. frametimesindex = framecount % FRAME_VALUES;
  113.  
  114. // store the current time
  115. getticks = SDL_GetTicks();
  116.  
  117. // save the frame time value
  118. frametimes[frametimesindex] = getticks - frametimelast;
  119.  
  120. // save the last frame time for the next fpsthink
  121. frametimelast = getticks;
  122.  
  123. // increment the frame count
  124. framecount++;
  125.  
  126. // Work out the current framerate
  127.  
  128. // The code below could be moved into another function if you don't need the value every frame.
  129.  
  130. // I've included a test to see if the whole array has been written to or not. This will stop
  131. // strange values on the first few (FRAME_VALUES) frames.
  132. if (framecount < FRAME_VALUES) {
  133.  
  134. count = framecount;
  135.  
  136. } else {
  137.  
  138. count = FRAME_VALUES;
  139.  
  140. }
  141.  
  142. // add up all the values and divide to get the average frame time.
  143. framespersecond = 0;
  144. for (i = 0; i < count; i++) {
  145.  
  146. framespersecond += frametimes[i];
  147.  
  148. }
  149.  
  150. framespersecond /= count;
  151.  
  152. // now to make it an actual frames per second value...
  153. framespersecond = 1000.f / framespersecond;
  154.  
  155. }
  156. #endif
  157. /*int open_port(void)
  158. {
  159. int fd; // File descriptor for the port
  160. fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
  161. if (fd == -1)
  162. {
  163. /*
  164. * Could not open the port.
  165. */
  166.  
  167. /* puts("open_port: Unable to open /dev/ttyACM0");
  168. }
  169. else
  170. {
  171. struct termios options;
  172. //fcntl(fd, F_SETFL, 0);
  173. fcntl(fd, F_SETFL, FNDELAY);
  174. /*
  175. * Get the current options for the port...
  176. */
  177.  
  178. // tcgetattr(fd, &options);
  179.  
  180. /*
  181. * Set the baud rates to 2M
  182. */
  183.  
  184.  
  185.  
  186. /* cfsetispeed(&options, B2000000);
  187. cfsetospeed(&options, B2000000);
  188. printf("2000000 = %d",B2000000);
  189. /*
  190. * Enable the receiver and set local mode...
  191. */
  192.  
  193. /*options.c_cflag |= (CLOCAL | CREAD);
  194. options.c_cflag &= ~CSIZE; // Mask the int8_tacter size bits
  195. options.c_cflag |= CS8; // Select 8 data bits
  196. //no parity bit
  197. options.c_cflag &= ~PARENB;
  198. options.c_cflag &= ~CSTOPB;
  199. options.c_cflag &= ~CSIZE;
  200. options.c_cflag |= CS8;
  201. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);//raw mode
  202.  
  203. /*
  204. * Set the new options for the port...
  205. */
  206. /*
  207. tcsetattr(fd, TCSANOW, &options);
  208. }
  209. return (fd);
  210. }*/
  211. #ifdef preview
  212. void saveSurface(uint8_t * pixDat)
  213. {
  214. FILE * myfile=fopen("capture.tga","wb");
  215. fwrite(&tgahead,1,sizeof(tgahead),myfile);
  216. #ifdef rgb565
  217. fwrite(pixDat,2,Width_G*Height_G,myfile);
  218. #else
  219. fwrite(pixDat,3,Width_G*Height_G,myfile);
  220. #endif
  221. fclose(myfile);
  222. }
  223. #endif
  224. inline double clampD(double val)
  225. {
  226. if (val < 0.0)
  227. {
  228. //printf("Clamped at %f\n",val);
  229. val=0.0;
  230. }
  231. if (val > 255.0)
  232. {
  233. //printf("Clamped at %f\n",val);
  234. val=255.0;
  235. }
  236. }
  237. #ifdef timeLapse
  238. int getkey() {
  239. int character;
  240. struct termios orig_term_attr;
  241. struct termios new_term_attr;
  242.  
  243. /* set the terminal to raw mode */
  244. tcgetattr(fileno(stdin), &orig_term_attr);
  245. memcpy(&new_term_attr, &orig_term_attr, sizeof(struct termios));
  246. new_term_attr.c_lflag &= ~(ECHO|ICANON);
  247. new_term_attr.c_cc[VTIME] = 0;
  248. new_term_attr.c_cc[VMIN] = 0;
  249. tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);
  250.  
  251. /* read a character from the stdin stream without blocking */
  252. /* returns EOF (-1) if no character is available */
  253. character = fgetc(stdin);
  254.  
  255. /* restore the original terminal attributes */
  256. tcsetattr(fileno(stdin), TCSANOW, &orig_term_attr);
  257.  
  258. return character;
  259. }
  260. #endif
  261. void waitImg(void)
  262. {
  263. //puts("Waiting for 'IMG ' command to start transfer");
  264. static const char Sig[]="RDY";
  265. uint8_t tempC,x;
  266. uint32_t junkC=0;
  267. //puts("Waiting for RDY command");
  268. for (x=0;x<3;x++)
  269. {
  270. do {
  271. RS232_PollComport(port,&tempC,1);
  272. if (tempC != Sig[x])
  273. {
  274. junkC++;
  275. printf("Junk Char %d or %c while waiting for %c so far skiped %d\n",tempC,tempC,Sig[x],junkC);
  276. }
  277. } while (tempC != Sig[x]);
  278. }
  279. if (junkC != 0)
  280. printf("%d junk bytes skipped\n",junkC);
  281. //puts("Waiting for response");
  282. //RS232_SendByte(port,'R');
  283. //if (junkC == 3)
  284. // RS232_PollComport(port,&tempC,1);//skip 1 byte
  285. //puts(" ");
  286. //puts("Ok to get data now");
  287. }
  288. int main()
  289. {
  290. tgahead.idlength=0;
  291. tgahead.colourmaptype=0;
  292. tgahead.datatypecode=2;
  293. tgahead.colourmaporigin=0;
  294. tgahead.colourmaplength=0;
  295. tgahead.colourmapdepth=16;
  296. tgahead.x_origin=0;
  297. tgahead.y_origin=0;
  298. tgahead.width=Width_G;
  299. tgahead.height=Height_G;
  300. #ifdef rgb565
  301. tgahead.bitsperpixel=16;
  302. #else
  303. tgahead.bitsperpixel=24;
  304. #endif
  305. tgahead.imagedescriptor=0;
  306. if (sizeof(tgahead) != 18)
  307. {
  308. printf("Size of TGA header is %d\n",sizeof(tgahead));
  309. return 1;
  310. }
  311. #ifdef simulateWithRand
  312. /* initialize random seed: */
  313. srand (time(NULL));
  314. #endif
  315. #ifdef preview
  316. //initate sdl
  317. uint16_t skipB=0;
  318. SDL_Surface* screen = NULL;
  319. #ifdef rgb565
  320. SDL_Surface* image = SDL_CreateRGBSurface(SDL_SWSURFACE,Width_G,Height_G,16,be16toh(0xF800),be16toh(0x07e0),be16toh(0x1F),0);
  321. #else
  322. SDL_Surface* image = SDL_CreateRGBSurface(SDL_SWSURFACE,Width_G,Height_G,24,0x0000ff,0x00ff00,0xff0000,0);
  323. #endif
  324. printf("Image Pitch %d\n",image->pitch);
  325. //Start SDL
  326. SDL_Init(SDL_INIT_EVERYTHING);
  327. //Set up screen
  328. screen = SDL_SetVideoMode(Width_G,Height_G, 32, SDL_SWSURFACE );
  329. SDL_Event event;
  330. uint8_t saveImg=0;
  331. #endif
  332. //int fd=open_port();
  333. tryagain:
  334. if(RS232_OpenComport(port, 500000))
  335. {
  336. printf("Can not open comport %d\n",port);
  337. /*if (port == 25)
  338. return(0);
  339. else
  340. port++;*/
  341. goto killPGM;
  342. }
  343. //imageRaw = malloc(176*2304*2);
  344. #ifndef preview
  345. FILE * myfile=fopen("out.tga","wb");
  346. fwrite(&tgahead,1,sizeof(tgahead),myfile);
  347. #endif
  348. #ifndef rgb565
  349. uint8_t yuvDat[4];
  350. #endif
  351. int bytes;
  352. #ifdef rawRGB
  353. uint8_t rawP;
  354. #endif
  355. #ifdef simulate
  356. uint16_t pix=0;
  357. uint8_t buff=0;
  358. #endif
  359. #ifdef preview
  360. int exitLoop=1;
  361. fpsinit();
  362. //skipB=128;
  363.  
  364. while (exitLoop)
  365. {
  366. SDL_LockSurface(image);
  367. uint8_t * imgPtr=image->pixels;
  368. //puts("Grabbing image");
  369. #endif
  370. uint16_t x,y;
  371. x=0;
  372. y=0;
  373. #ifdef simulate
  374. #ifndef simulateWithRand
  375. #ifndef simulateWithPattern
  376. pix++;
  377. printf("Pixel Value: %d\n",pix);
  378. #endif
  379. #endif
  380. #endif
  381. #ifdef simulateWithPattern
  382. pix=0;
  383. #endif
  384. //skipB=1;
  385. #ifdef rgb565
  386. bytes=((Width_G*Height_G)*2);
  387. #else
  388. bytes=0;
  389. #endif
  390. #ifndef simulate
  391. waitImg();
  392. #endif
  393. while (1)
  394. {
  395. #ifdef simulate
  396. int n=1;
  397. /*if (x&1)
  398. buff=pix>>8;
  399. else
  400. {
  401. #ifdef simulateWithRand
  402. pix=rand();
  403. #endif
  404. buff=pix&255;
  405. }*/
  406. #ifdef simulateWithPattern
  407. #ifdef rgb565
  408. pix++;
  409. #elif defined yuv422
  410. yuvDat[0]=buff++;
  411. yuvDat[1]=buff++;
  412. yuvDat[2]=buff++;
  413. yuvDat[3]=buff++;
  414. #else
  415. rawP=buff++;
  416. #endif
  417. #endif
  418. #else
  419. #ifdef rawRGB
  420. int n =RS232_PollComport(port,&rawP,1);
  421. #elif defined rgb565
  422. int n = RS232_PollComport(port,imgPtr,128);
  423. #else
  424. int n = RS232_PollComport(port,yuvDat,4);
  425. if (n < 4)
  426. printf("Read %d bytes instead of 4\n",n);
  427. #endif
  428. //printf("X: %d Y: %d \r",x,y);
  429. #endif
  430. if (n ==0)
  431. {
  432. //usleep(100);
  433. puts("0 bytes read");
  434. continue;
  435. }
  436. #ifndef preview
  437. fputc(buff, myfile);
  438. #endif
  439. #ifdef preview
  440. if (skipB==0)
  441. {
  442. #ifdef rgb565
  443. imgPtr+=128;
  444. x+=128;
  445. #elif defined rawRGB
  446. //see what color this pixel should set to
  447. /*R G
  448. G B*/
  449. if (y&1)
  450. {//odd
  451. if (x&1)//if odd
  452. imgPtr[2]=rawP;//blue
  453. else
  454. imgPtr[1]=rawP;//green
  455. }
  456. else
  457. {//even
  458. if (x&1)//if odd pixel
  459. imgPtr[1]=rawP;//green
  460. else
  461. *imgPtr=rawP;//red
  462. }
  463. imgPtr+=3;//next pixel
  464. x++;
  465. #else
  466. //yuvDat=(uint8_t *)&buff;
  467. x+=4;
  468. #endif
  469.  
  470. #ifdef yuv422
  471. if (((x & 3)==0) && (x != 0))
  472. {//convert pixels
  473. /*
  474. Y = pixel0;
  475. U = pixel1;
  476. Y1 = pixel2;
  477. V = pixel3;
  478. */
  479. /* *imgPtr++=yuvDat[0] + 1.4075 * (yuvDat[3] - 128.0);//red
  480. *imgPtr++=yuvDat[0] - 0.3455 * (yuvDat[1] - 128) - (0.7169 * (yuvDat[3] - 128));//green
  481. *imgPtr++=yuvDat[0] + 1.7790 * (yuvDat[1] - 128);//blue
  482. *imgPtr++=yuvDat[2] + 1.4075 * (yuvDat[3] - 128);//red
  483. *imgPtr++=yuvDat[2] - 0.3455 * (yuvDat[1] - 128) - (0.7169 * (yuvDat[3] - 128));//green
  484. *imgPtr++=yuvDat[2] + 1.7790 * (yuvDat[1] - 128);//blue */
  485. *imgPtr++=YUV2R(yuvDat[0],yuvDat[1],yuvDat[3]);
  486. *imgPtr++=YUV2G(yuvDat[0],yuvDat[1],yuvDat[3]);
  487. *imgPtr++=YUV2B(yuvDat[0],yuvDat[1],yuvDat[3]);
  488. *imgPtr++=YUV2R(yuvDat[2],yuvDat[1],yuvDat[3]);
  489. *imgPtr++=YUV2G(yuvDat[2],yuvDat[1],yuvDat[3]);
  490. *imgPtr++=YUV2B(yuvDat[2],yuvDat[1],yuvDat[3]);
  491. }
  492. #endif
  493. #ifdef rawRGB
  494. if (x==Width_G)
  495. #else
  496. if (x==Width_G*2)//size is same for both yuv422 and rgb565
  497. #endif
  498. {
  499. //if (y==0)
  500. // skipB=1;
  501. //if (y/96*96 == y)
  502. // skipB=1;
  503. #ifdef rawRGB
  504. if (y&1)
  505. {
  506. //do bayer interopulation
  507. imgPtr-=Width_G*6;//go back 2 rows
  508. uint16_t wx;
  509. for (wx=0;wx<Width_G;wx+=2)
  510. {
  511. //this will do a 2x2 pixel rectangle
  512. /*R G
  513. G B*/
  514. imgPtr[1+wx*3]=imgPtr[4+wx*3];//green
  515. imgPtr[2+wx*3]=imgPtr[((Width_G+wx)*3)+5];//blue
  516.  
  517. imgPtr[3+wx*3]=imgPtr[wx*3];//red
  518. imgPtr[5+wx*3]=imgPtr[((Width_G+wx)*3)+5];//blue
  519.  
  520. imgPtr[((Width_G+wx)*3)]=imgPtr[wx*3];//red
  521. imgPtr[((Width_G+wx)*3)+2]=imgPtr[((Width_G+wx)*3)+5];//blue
  522.  
  523. imgPtr[((Width_G+wx)*3)+3]=imgPtr[wx*3];//red
  524. imgPtr[((Width_G+wx)*3)+4]=imgPtr[((Width_G+wx)*3)+1];//green
  525. }
  526. //imgPtr+=Width_G*6;//go back to the origional posistion
  527. SDL_UnlockSurface(image);
  528. SDL_BlitSurface(image, NULL, screen, NULL );
  529. SDL_Flip(screen);
  530. SDL_LockSurface(image);
  531. imgPtr=image->pixels+(y*image->pitch);
  532. }
  533. #endif
  534. while( SDL_PollEvent( &event ) )
  535. {
  536. if( event.type == SDL_QUIT )
  537. {
  538. //Quit the program
  539. exitLoop=0;
  540. goto quit;
  541. }
  542. if (event.type == SDL_KEYDOWN)
  543. {
  544. if (event.key.keysym.sym == SDLK_s)
  545. {
  546. puts("Saving Image");
  547. saveImg=1;
  548. }
  549. else if (event.key.keysym.sym == SDLK_l)
  550. {
  551. puts("Going back a line");
  552. y--;
  553. }
  554. else if (event.key.keysym.sym == SDLK_p)
  555. {
  556. puts("skipping 31 reads");
  557. skipB=31;
  558. }
  559. else
  560. {
  561. puts("skipping read");
  562. skipB=1;
  563. }
  564. }
  565. }
  566. y++;
  567. //if (((y/96)*96) == y)
  568. //{
  569. //printf("y = %d\n",y);
  570. #ifndef simulate
  571. if (y!=Height_G)
  572. {
  573. waitImg();
  574. imgPtr=image->pixels+(y*image->pitch);
  575. }
  576. #endif
  577. //}
  578. //if (y!=Height_G)
  579. //{
  580. #ifndef rawRGB
  581. if ((y&31) == 0)
  582. {
  583. SDL_UnlockSurface(image);
  584. SDL_BlitSurface(image, NULL, screen, NULL );
  585. SDL_Flip(screen);
  586. SDL_LockSurface(image);
  587. imgPtr=image->pixels+(y*image->pitch);
  588. }
  589. #endif
  590. //}
  591. x=0;
  592. }
  593. }
  594. else
  595. {
  596. skipB--;
  597. puts("Byte Skipped");
  598. }
  599. #endif
  600. #ifdef rgb565
  601. bytes-=128;
  602. #elif defined yuv422
  603. bytes+=4;
  604. #else
  605. bytes++;
  606. #endif
  607. //printf("Grabing image on byte %d y: %d\r",bytes,y); makes program run slower
  608. #ifdef rgb565
  609. if (bytes <= 0)
  610. #else
  611. if (y==Height_G)//if (bytes == ((Width_G*Height_G)*2))
  612. #endif
  613. {//same for both rgb565 and yuv422
  614. #ifdef preview
  615. if (saveImg != 0)
  616. {
  617. saveImg=0;
  618. SDL_LockSurface(image);
  619. saveSurface(image->pixels);
  620. SDL_UnlockSurface(image);
  621. SDL_SaveBMP(image,"OUT.bmp");
  622. }
  623. #ifdef timeLapse
  624. else
  625. {//time lapse
  626. static int count=0;
  627. count++;
  628. static char buf[1024];
  629. sprintf(buf,"frame %d",count);
  630. SDL_SaveBMP(image,buf);
  631. }
  632. #endif
  633. #endif
  634. break;
  635. }
  636. //usleep(100);
  637. }//end of loop
  638. quit:
  639.  
  640. #ifdef preview
  641. SDL_UnlockSurface(image);
  642. SDL_BlitSurface(image, NULL, screen, NULL );
  643. SDL_Flip(screen);
  644. fpsthink();
  645. printf("Frames Per Second %f\n", framespersecond);
  646. }
  647. #ifndef simulate
  648. puts("Serial Port Closed");
  649. RS232_CloseComport(port);
  650. #endif
  651. killPGM:
  652. SDL_FreeSurface(image);
  653. //Quit SDL
  654. SDL_Quit();
  655. #endif
  656. #ifndef preview
  657. fclose(myfile);
  658. #endif
  659. puts("");
  660. return 0;
  661.  
  662. }
Advertisement
Add Comment
Please, Sign In to add comment