1. #include <stdio.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <time.h>
  9. #include <sys/mman.h>
  10. #include <assert.h>
  11. #include <linux/videodev2.h>
  12. #include <linux/fb.h>
  13. #include <pthread.h>
  14. //照相机延时等待
  15. #define TimeOut 5
  16. //拍照 个数
  17. #define CapNum 10
  18. //设置照片宽度 高度
  19. #define CapWidth 320
  20. #define CapHeight 240
  21. //申请Buf个数
  22. #define ReqButNum 4
  23. //使用前置或者后置Camera 前置设0,后置设1
  24. #define IsRearCamera 0
  25. //设置帧率
  26. #define  FPS 10
  27. //设置格式
  28. #define PIXELFMT V4L2_PIX_FMT_YUYV
  29. #define CapDelay 100*1000
  30. #define CLEAR(x)    memset(&(x), 0, sizeof(x))
  31. typedef unsigned char BYTE;
  32. typedef unsigned short WORD;
  33. typedef unsigned int DWORD;
  34. typedef long LONG;
  35. typedef struct
  36. {
  37. void *start;
  38. int length;
  39. }BUFTYPE;
  40. struct tsp_event {
  41. struct timeval time;
  42. unsigned short type;
  43. unsigned short code;
  44. unsigned int value;
  45. };
  46. typedef struct tagBITMAPFILEHEADER {
  47. WORD  bfType;
  48. DWORD bfSize;
  49. WORD  bfReserved1;
  50. WORD  bfReserved2;
  51. DWORD bfOffBits;
  52. }__attribute__((packed)) BITMAPFILEHEADER, *PBITMAPFILEHEADER;
  53. typedef struct tagBITMAPINFOHEADER {
  54. DWORD biSize;
  55. LONG  biWidth;
  56. LONG  biHeight;
  57. WORD  biPlanes;
  58. WORD  biBitCount;
  59. DWORD biCompression;
  60. DWORD biSizeImage;
  61. LONG  biXPelsPerMeter;
  62. LONG  biYPelsPerMeter;
  63. DWORD biClrUsed;
  64. DWORD biClrImportant;
  65. }__attribute__((packed)) BITMAPINFOHEADER, *PBITMAPINFOHEADER;
  66. static BITMAPFILEHEADER file_head;
  67. static BITMAPINFOHEADER info_head;
  68. typedef struct tagRGBQUAD {
  69. BYTE rgbBlue;
  70. BYTE rgbGreen;
  71. BYTE rgbRed;
  72. BYTE rgbReserved;
  73. }__attribute__((packed)) RGBQUAD;
  74. BUFTYPE *user_buf;
  75. static int n_buffer = 0;
  76. static struct fb_var_screeninfo vinfo;
  77. static struct fb_fix_screeninfo finfo;
  78. static int lcd_buf_size;
  79. static char *fb_buf = NULL;
  80. static int tsp_fd;
  81. static pthread_t capture_tid;
  82. int display_x = 0;
  83. int display_y = 0;
  84. int save_image()
  85. {
  86. FILE *fp;
  87. static int num = 0;
  88. char picture_name[40]={'\0'};
  89. char *addr = (char *)fb_buf;
  90. int length = CapWidth * CapHeight * vinfo.bits_per_pixel / 8;
  91. int fd;
  92. int data_size;
  93. int i,j,k;
  94. char *tmp_buf;
  95. tmp_buf = (char *)malloc(length);
  96. if(tmp_buf == NULL)
  97. {
  98. printf("tmp_buf alloc fail\n");
  99. exit(EXIT_FAILURE);
  100. }
  101. if(access("/udisk/camtest",0)!=0)
  102. {
  103. mkdir("/udisk/camtest", 0777);
  104. }
  105. sprintf(picture_name,"/udisk/camtest/picture%d.bmp",num ++);
  106. printf("write image to sdcard:name:%s\n",picture_name);
  107. data_size = length;
  108. file_head.bfType = 0x4d42;
  109. file_head.bfSize = sizeof(file_head) + sizeof(info_head) + data_size;
  110. file_head.bfReserved1 = file_head.bfReserved2 = 0;
  111. file_head.bfOffBits = sizeof(file_head) + sizeof(info_head);
  112. info_head.biSize = sizeof(info_head);
  113. info_head.biWidth = CapWidth;
  114. info_head.biHeight = CapHeight;
  115. info_head.biPlanes = 1;
  116. info_head.biBitCount = 32;
  117. info_head.biCompression = 0;
  118. info_head.biSizeImage = 0;
  119. info_head.biXPelsPerMeter = 0;
  120. info_head.biYPelsPerMeter = 0;
  121. info_head.biClrUsed = 0;
  122. info_head.biClrImportant = 0;
  123. fd = open(picture_name, O_RDWR | O_CREAT, 0644);
  124. if(fd < 0)
  125. {
  126. perror("create image error\n");
  127. close (fd);
  128. exit(EXIT_FAILURE);
  129. }
  130. write(fd, &file_head, sizeof(file_head));
  131. write(fd, &info_head, sizeof(info_head));
  132. int bmpLineLenth = CapWidth * vinfo.bits_per_pixel / 8;
  133. for(i = 0; i < length; i++)
  134. {
  135. tmp_buf[i] = fb_buf[(CapHeight - i/bmpLineLenth - 1) * finfo.line_length + i%bmpLineLenth];
  136. }
  137. for(i = 0; i < length; i++)
  138. {
  139. fb_buf[(i/bmpLineLenth) * finfo.line_length + i%bmpLineLenth + bmpLineLenth] = tmp_buf[i] ;
  140. }
  141. write(fd, tmp_buf, length);
  142. usleep(500);
  143. close(fd);
  144. return 0;
  145. }
  146. static void *capture_thread(void *pVoid)
  147. {
  148. int ret;
  149. int key_change = 0;
  150. struct tsp_event tsp_value;
  151. #define BTN_TOUCH       0x14a
  152. while(1)
  153. {
  154. printf("capture_thread\n");
  155. ret = read(tsp_fd, &tsp_value, sizeof(struct tsp_event)); /* 如果无数据则休眠 */
  156. if (ret < 0)
  157. {
  158. printf("fail to read\n");
  159. return;
  160. }
  161. //如果触摸释放掉,则开始保存图片
  162. if((tsp_value.code == BTN_TOUCH) && (tsp_value.value == 0))
  163. save_image();
  164. printf("code:%04d,value:%04d\n",tsp_value.code, tsp_value.value);
  165. }
  166. }
  167. //打开摄像头设备
  168. int open_camer_device()
  169. {
  170. int fd;
  171. //非阻塞方式打开,如果打开错误,会立即返回
  172. if((fd = open("/dev/video0",O_RDWR | O_NONBLOCK)) < 0)
  173. {
  174. perror("Fail to open");
  175. exit(EXIT_FAILURE);
  176. }
  177. printf("open cam success %d\n",fd);
  178. return fd;
  179. }
  180. //打开摄像头设备
  181. int open_lcd_device()
  182. {
  183. int fd;
  184. //非阻塞方式打开,如果打开错误,会立即返回
  185. if((fd = open("/dev/fb0",O_RDWR | O_NONBLOCK)) < 0)
  186. {
  187. perror("Fail to open");
  188. exit(EXIT_FAILURE);
  189. }
  190. printf("open lcd success %d\n",fd);
  191. return fd;
  192. }
  193. //申请Camera Buf,并映射到用户空间,利用全局变量user_buf保存映射信息
  194. int init_mmap(int lcd_fd, int cam_fd)
  195. {
  196. int i = 0;
  197. int err;
  198. int ret;
  199. struct v4l2_control ctrl;
  200. struct v4l2_requestbuffers reqbuf;
  201. //mmap framebuffer
  202. fb_buf = (char *)mmap(
  203. NULL,
  204. lcd_buf_size,
  205. PROT_READ | PROT_WRITE,MAP_SHARED ,
  206. lcd_fd,
  207. 0);
  208. if(NULL == fb_buf)
  209. {
  210. perror("Fail to mmap fb_buf");
  211. exit(EXIT_FAILURE);
  212. }
  213. bzero(&reqbuf,sizeof(reqbuf));
  214. reqbuf.count = ReqButNum;
  215. reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  216. reqbuf.memory = V4L2_MEMORY_MMAP;
  217. printf("start VIDIOC_REQBUFS\n");
  218. //申请视频缓冲区(这个缓冲区位于内核空间,需要通过mmap映射)
  219. //这一步操作可能会修改reqbuf.count的值,修改为实际成功申请缓冲区个数
  220. if(-1 == ioctl(cam_fd,VIDIOC_REQBUFS,&reqbuf))
  221. {
  222. perror("Fail to ioctl 'VIDIOC_REQBUFS'");
  223. exit(EXIT_FAILURE);
  224. }
  225. n_buffer = reqbuf.count;
  226. user_buf = calloc(reqbuf.count,sizeof(*user_buf));
  227. if(user_buf == NULL){
  228. fprintf(stderr,"Out of memory\n");
  229. exit(EXIT_FAILURE);
  230. }
  231. //将内核缓冲区映射到用户进程空间
  232. for(i = 0; i < reqbuf.count; i ++)
  233. {
  234. struct v4l2_buffer buf;
  235. bzero(&buf,sizeof(buf));
  236. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  237. buf.memory = V4L2_MEMORY_MMAP;
  238. buf.index = i;
  239. //查询申请到内核缓冲区的信息
  240. if(-1 == ioctl(cam_fd,VIDIOC_QUERYBUF,&buf))
  241. {
  242. perror("Fail to ioctl : VIDIOC_QUERYBUF");
  243. exit(EXIT_FAILURE);
  244. }
  245. user_buf[i].length = buf.length;
  246. user_buf[i].start =
  247. mmap(
  248. NULL,/*start anywhere*/
  249. buf.length,
  250. PROT_READ | PROT_WRITE,
  251. MAP_SHARED,
  252. cam_fd,buf.m.offset
  253. );
  254. if(MAP_FAILED == user_buf[i].start)
  255. {
  256. perror("Fail to mmap\n");
  257. printf("%d\n",i);
  258. exit(EXIT_FAILURE);
  259. }
  260. //  printf("start:08%lx\n",user_buf[i].start);
  261. }
  262. return 0;
  263. }
  264. //初始化视频设备
  265. int init_device(int lcd_fd, int cam_fd)
  266. {
  267. struct v4l2_fmtdesc fmt;
  268. struct v4l2_capability cap;
  269. struct v4l2_format stream_fmt;
  270. struct v4l2_input input;
  271. struct v4l2_control ctrl;
  272. struct v4l2_streamparm stream;
  273. int err;
  274. int ret;
  275. if(-1 == ioctl(lcd_fd,FBIOGET_FSCREENINFO,&finfo))
  276. {
  277. perror("Fail to ioctl:FBIOGET_FSCREENINFO\n");
  278. exit(EXIT_FAILURE);
  279. }
  280. if (-1==ioctl(lcd_fd, FBIOGET_VSCREENINFO, &vinfo))
  281. {
  282. perror("Fail to ioctl:FBIOGET_VSCREENINFO\n");
  283. exit(EXIT_FAILURE);
  284. }
  285. lcd_buf_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
  286. printf("vinfo.xres:%d, vinfo.yres:%d, vinfo.bits_per_pixel:%d, lcd_buf_size:%d, finfo.line_length:%d\n",vinfo.xres, vinfo.yres, vinfo.bits_per_pixel, lcd_buf_size, finfo.line_length);
  287. memset(&fmt,0,sizeof(fmt));
  288. fmt.index = 0;
  289. fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  290. //枚举视频设置支持的格式
  291. while((ret = ioctl(cam_fd,VIDIOC_ENUM_FMT,&fmt)) == 0)
  292. {
  293. fmt.index ++ ;
  294. printf("{pixelformat = %c%c%c%c},description = '%s'\n",
  295. fmt.pixelformat & 0xff,(fmt.pixelformat >> 8)&0xff,
  296. (fmt.pixelformat >> 16) & 0xff,(fmt.pixelformat >> 24)&0xff,
  297. fmt.description);
  298. }
  299. //查询视频设备支持的功能
  300. ret = ioctl(cam_fd,VIDIOC_QUERYCAP,&cap);
  301. if(ret < 0){
  302. perror("FAIL to ioctl VIDIOC_QUERYCAP");
  303. exit(EXIT_FAILURE);
  304. }
  305. if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
  306. {
  307. printf("The Current device is not a video capture device\n");
  308. exit(EXIT_FAILURE);
  309. }
  310. if(!(cap.capabilities & V4L2_CAP_STREAMING))
  311. {
  312. printf("The Current device does not support streaming i/o\n");
  313. exit(EXIT_FAILURE);
  314. }
  315. CLEAR(stream_fmt);
  316. //设置摄像头采集数据格式,如设置采集数据的
  317. //长,宽,图像格式(JPEG,YUYV,MJPEG等格式)
  318. stream_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  319. stream_fmt.fmt.pix.width = CapWidth;
  320. stream_fmt.fmt.pix.height = CapHeight;
  321. stream_fmt.fmt.pix.pixelformat = PIXELFMT;
  322. stream_fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
  323. if(-1 == ioctl(cam_fd,VIDIOC_S_FMT,&stream_fmt))
  324. {
  325. printf("Can't set the fmt\n");
  326. perror("Fail to ioctl\n");
  327. exit(EXIT_FAILURE);
  328. }
  329. printf("VIDIOC_S_FMT successfully\n");
  330. init_mmap(lcd_fd, cam_fd);
  331. //通过S_PARM来设置FPS
  332. /* fimc_v4l2_s_parm */
  333. CLEAR(stream);
  334. stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  335. stream.parm.capture.capturemode = 0;
  336. stream.parm.capture.timeperframe.numerator = 1;
  337. stream.parm.capture.timeperframe.denominator = FPS;
  338. err = ioctl(cam_fd, VIDIOC_S_PARM, &stream);
  339. if(err < 0)
  340. printf("FimcV4l2 start: error %d, VIDIOC_S_PARM", err);
  341. return 0;
  342. }
  343. int start_capturing(int cam_fd)
  344. {
  345. unsigned int i;
  346. enum v4l2_buf_type type;
  347. //将申请的内核缓冲区放入一个队列中
  348. for(i = 0;i < n_buffer;i ++)
  349. {
  350. struct v4l2_buffer buf;
  351. bzero(&buf,sizeof(buf));
  352. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  353. buf.memory = V4L2_MEMORY_MMAP;
  354. buf.index = i;
  355. if(-1 == ioctl(cam_fd,VIDIOC_QBUF,&buf))
  356. {
  357. perror("Fail to ioctl 'VIDIOC_QBUF'");
  358. exit(EXIT_FAILURE);
  359. }
  360. }
  361. //开始采集数据
  362. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  363. if(-1 == ioctl(cam_fd,VIDIOC_STREAMON,&type))
  364. {
  365. printf("i = %d.\n",i);
  366. perror("Fail to ioctl 'VIDIOC_STREAMON'");
  367. exit(EXIT_FAILURE);
  368. }
  369. return 0;
  370. }
  371. inline int clip(int value, int min, int max)
  372. {
  373. return (value > max ? max : value < min ? min : value);
  374. }
  375. //将采集好的数据放到文件中
  376. int process_image(void *addr,int length)
  377. {
  378. unsigned char* in=(char*)addr;
  379. int width=CapWidth;
  380. int height=CapHeight;
  381. int istride=CapWidth *2;
  382. int x,y,j;
  383. int y0,u,y1,v,r,g,b;
  384. long location=0;
  385. //printf("vinfo.xoffset:%d,vinfo.yoffset:%d\n",vinfo.xoffset,vinfo.yoffset);
  386. for ( y = 0; y < height; ++y)
  387. {
  388. for (j = 0, x=0; j < width * 2 ; j += 4,x +=2)
  389. {
  390. location = (x+display_x) * (vinfo.bits_per_pixel/8) + (y+display_y) * finfo.line_length;
  391. y0 = in[j];
  392. u = in[j + 1] - 128;
  393. y1 = in[j + 2];
  394. v = in[j + 3] - 128;
  395. r = (298 * y0 + 409 * v + 128) >> 8;
  396. g = (298 * y0 - 100 * u - 208 * v + 128) >> 8;
  397. b = (298 * y0 + 516 * u + 128) >> 8;
  398. fb_buf[ location + 0] = clip(b, 0, 255);
  399. fb_buf[ location + 1] = clip(g, 0, 255);
  400. fb_buf[ location + 2] = clip(r, 0, 255);
  401. fb_buf[ location + 3] = 255;
  402. r = (298 * y1 + 409 * v + 128) >> 8;
  403. g = (298 * y1 - 100 * u - 208 * v + 128) >> 8;
  404. b = (298 * y1 + 516 * u + 128) >> 8;
  405. fb_buf[ location + 4] = clip(b, 0, 255);
  406. fb_buf[ location + 5] = clip(g, 0, 255);
  407. fb_buf[ location + 6] = clip(r, 0, 255);
  408. fb_buf[ location + 7] = 255;
  409. }        in +=istride;      }
  410. //  usleep(500);
  411. return 0;
  412. }
  413. int read_frame(int cam_fd)
  414. {
  415. struct v4l2_buffer buf;
  416. unsigned int i;
  417. bzero(&buf,sizeof(buf));
  418. buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  419. buf.memory = V4L2_MEMORY_MMAP;
  420. //从Camera buf中把数据拿出来
  421. if(-1 == ioctl(cam_fd,VIDIOC_DQBUF,&buf))
  422. {
  423. perror("Fail to ioctl 'VIDIOC_DQBUF'");
  424. exit(EXIT_FAILURE);
  425. }
  426. assert(buf.index < n_buffer);
  427. process_image(user_buf[buf.index].start,user_buf[buf.index].length);
  428. //把处理过的Buf 重新入队
  429. if(-1 == ioctl(cam_fd,VIDIOC_QBUF,&buf))
  430. {
  431. perror("Fail to ioctl 'VIDIOC_QBUF'");
  432. exit(EXIT_FAILURE);
  433. }
  434. return 1;
  435. }
  436. //利用select 进行超时处理
  437. int mainloop(int cam_fd)
  438. {
  439. int count = 1;//CapNum;
  440. clock_t startTime, finishTime;
  441. double selectTime, frameTime;
  442. while(count++  > 0)
  443. {
  444. for(;;)
  445. {
  446. fd_set fds;
  447. struct timeval tv;
  448. int r;
  449. //  startTime = clock();
  450. FD_ZERO(&fds);
  451. FD_SET(cam_fd,&fds);
  452. /*Timeout*/
  453. tv.tv_sec = TimeOut;
  454. tv.tv_usec = 0;
  455. r = select(cam_fd + 1,&fds,NULL,NULL,&tv);
  456. if(-1 == r)
  457. {
  458. if(EINTR == errno)
  459. continue;
  460. perror("Fail to select");
  461. exit(EXIT_FAILURE);
  462. }
  463. if(0 == r)
  464. {
  465. fprintf(stderr,"select Timeout\n");
  466. exit(EXIT_FAILURE);
  467. }
  468. startTime = clock();
  469. if(read_frame(cam_fd))
  470. {
  471. finishTime = clock();
  472. //      printf("delta:%dms\n", (finishTime - startTime)/1000);
  473. break;
  474. }
  475. }
  476. usleep(CapDelay);
  477. }
  478. return 0;
  479. }
  480. void stop_capturing(int cam_fd)
  481. {
  482. enum v4l2_buf_type type;
  483. type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  484. if(-1 == ioctl(cam_fd,VIDIOC_STREAMOFF,&type))
  485. {
  486. perror("Fail to ioctl 'VIDIOC_STREAMOFF'");
  487. exit(EXIT_FAILURE);
  488. }
  489. return;
  490. }
  491. void uninit_camer_device()
  492. {
  493. unsigned int i;
  494. for(i = 0;i < n_buffer;i ++)
  495. {
  496. if(-1 == munmap(user_buf[i].start, user_buf[i].length))
  497. {
  498. exit(EXIT_FAILURE);
  499. }
  500. }
  501. if (-1 == munmap(fb_buf, lcd_buf_size))
  502. {
  503. perror(" Error: framebuffer device munmap() failed.\n");
  504. exit (EXIT_FAILURE) ;
  505. }
  506. free(user_buf);
  507. return;
  508. }
  509. void close_camer_device(int lcd_fd, int cam_fd)
  510. {
  511. if(-1 == close(lcd_fd))
  512. {
  513. perror("Fail to close lcd_fd");
  514. exit(EXIT_FAILURE);
  515. }
  516. if(-1 == close(cam_fd))
  517. {
  518. perror("Fail to close cam_fd");
  519. exit(EXIT_FAILURE);
  520. }
  521. return;
  522. }
  523. int main()
  524. {
  525. int lcd_fd;
  526. int cam_fd;
  527. if((tsp_fd = open("/dev/event0", O_RDWR)) < 0)
  528. {
  529. printf("Fail to open");
  530. return -1;
  531. }
  532. lcd_fd = open_lcd_device();
  533. cam_fd = open_camer_device();
  534. pthread_create(&capture_tid,NULL,capture_thread,(void *)NULL);
  535. init_device(lcd_fd, cam_fd);
  536. //  init_mmap(lcd_fd, cam_fd);
  537. start_capturing(cam_fd);
  538. mainloop(cam_fd);
  539. stop_capturing(cam_fd);
  540. uninit_camer_device();
  541. close_camer_device(lcd_fd, cam_fd);
  542. return 0;
  543. }

linux -- camera shot 拍照功能的更多相关文章

  1. 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo

    杂家前文是在2012年的除夕之夜仓促完成,后来很多人指出了一些问题,琐事缠身一直没有进行升级.后来随着我自己的使用,越来越发现不出个升级版的demo是不行了.有时候就连我自己用这个demo测一些性能. ...

  2. Android开发技巧——Camera拍照功能

    本篇是我对开发项目的拍照功能过程中,对Camera拍照使用的总结.由于camera2是在api level 21(5.0.1)才引入的,而Camera到6.0仍可使用,所以暂未考虑camera2. 文 ...

  3. Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能

    Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...

  4. Android Camera开发系列(上)——Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片

    Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 最近也是在搞个破相机,兼容性那叫一个不忍直视啊,于是自己翻阅了一些基本的资料,自己实现了一 ...

  5. 通过Camera进行拍照

    Android通过Camera来控制拍照,使用Camera比较简单,按步骤进行即可: 下面用一个示例来演示: Activity: package com.home.activity; import j ...

  6. Java乔晓松-android中调用系统拍照功能并显示拍照的图片

    android中调用系统拍照功能并显示拍照的图片 如果你是拍照完,利用onActivityResult获取data数据,把data数据转换成Bitmap数据,这样获取到的图片,是拍照的照片的缩略图 代 ...

  7. 微信小程序(有始有终,全部代码)开发--- 新增模块: 图片选取以及拍照功能

    开篇语 前几天发了一篇: <简年15: 微信小程序(有始有终,全部代码)开发---跑步App+音乐播放器 > 后来又发了BUG修复的版本: 简年18: 微信小程序(有始有终,全部代码)开发 ...

  8. HTML5 使用FileReader实现调用相册、拍照功能

    HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取结果的事件模型. FileReader的使用方式非常简 ...

  9. 相机拍照功能之权限和Android版本问题

    代码改变世界 相机拍照功能之权限和Android版本问题 对于Android 6.0之前,想要使用系统的相机进行拍照,那么只要在AndroidManifedt.xml中进行添加相应的权限,主要是两个: ...

随机推荐

  1. Code a simple telnet client using sockets in python

    测试端口是否开放的python脚本 原文: https://www.binarytides.com/code-telnet-client-sockets-python/ 配置: 120.79.14.8 ...

  2. 反编译示例:mxd检查

    gisoralce在博客园发布了一个mxd检查工具,主要功能是将arcgis的mxd数据源有效性(含矢量和影像)检查.检查是否为相对路径,自动保存为相对路径. 这是一个未加壳的.NET程序,正好拿来练 ...

  3. LDA基本介绍以及LDA源码分析(BLEI)

    基本介绍: topic model,主题模型介绍:http://www.cnblogs.com/lixiaolun/p/4455764.html  以及 (http://blog.csdn.net/h ...

  4. KineticJS教程(3)

    KineticJS教程(3) 作者: ysm  3.图形对象 3.1.Shape Kinetic提供了一个Shape对象用于在层上绘制图形,我们可以通过Kinetic.Shape()构造方法返回一个S ...

  5. css3和html5的学习

    本文是此链接的源代码.http://www.imooc.com/learn/77 关于的html5的使用: transition----含义是:过渡的过程,能够对各种属性设置变化. 有5中过渡的形式: ...

  6. Python 函数返回多值

    返回多值函数可以返回多个值吗?答案是肯定的.比如在游戏中经常需要从一个点移动到另一个点,给出坐标.位移和角度,就可以计算出新的坐标:# math包提供了sin()和 cos()函数,我们先用impor ...

  7. 深入探讨Linux静态库与动态库的详解(转)

    2.生成动态库并使用 linux下编译时通过 -shared 参数可以生成动态库(.so)文件,如下 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. 一.静 ...

  8. jquery 获取css position的值

      jquery 获取css position的值 CreateTime--2018年5月28日14:03:12 Author:Marydon 1.情景展示 <div id="aa&q ...

  9. 转:sock_ev——linux平台socket事件框架(socket代理类) .

    前面分析了对socket基本操作的封装,并按照数据的传送方式写了两个类,本篇将写一个代理类提供给库的使用者使用的类. /**************************************** ...

  10. jquery 获取html <img /> 位置时出错问题

    如图所示,这样端口小图片都是通过jquery html()方法设置的(参数html就是画整个图片的html字符串),如图: 但是出现图片没有完全渲染完的问题,如图: 从图中可以看出在代码运行到断点的时 ...