Exif中GPS格式

本文是最后一篇关于Exif文章,终于要挑战最大的boss了,这个GPS信息的读取,我找了国内外很多资料都没有找 真正的实例。所以自己前两篇的基础上推断而来的。

读取JPG图片的Exif属性 - Exif信息简介

读取JPG图片的Exif属性 - C代码实现

其实这个只要能够理解前面两篇的内容也就很容易获得GPS信息,但是还是要理解GPS的格式和各种tag参数。可以重新学习一下其格式如下:
   GPS Info IFD Pointer 0x02AE  从上面数据2A0行的后面看数据
   00 05       count of TAGs
   
   00 00       GPSVersionID
   00 01       BYTE
   00 00 00 04 count
   02 02 00 00 value 2.2.0.0
   
   00 01       GPSLatitudeRef
   00 02       ASCII
   00 00 00 02 count
   4E 00 00 00 N North  
   
   00 02       GPSLatitude
   00 05       RATIONAL               前4字节为分子,后4字节为分母,十六进制先转为十进制
   00 00 00 03 count
   00 00 05 46 offset+0c=0x552 16 00 00 00 01 00 00 00 22 00 00 00 01 00 00 00 51 00 00 00 04 00 00 00
                                                       22/1=22                             34/1=34                              81/4= 20.25
                                                      通过windows的右键属性看详细信息:22;34;20.249999999999915
   00 03       GPSLongitudeRef
   00 02
   00 00 00 02 count
   45 00 00 00 East
   
   00 04       GPSLongitude
   00 05       RATIONAL
   00 00 00 03 count
   00 00 05 5E offset+0c=0x56A 71 00 00 00 01 00 00 00 37 00 00 00 01 00 00 00 6C 00 00 00 04 00
                                                       113/1=113                          55/1=55                             108/4=27
                                                    通过windows的右键属性看详细信息:113;55;27.000000000000171
主要的函数还是要进入到如下得函数中:
DecodeExif 函数主要是获取到Eixf属性在图片数据中入口地址:
process_EXIF 主要是对Exif属性做一个前期的处理,为了进一步详细的分析做处理
ProcessExifDir主要是对Exif属性详细的分析和处理。

GPS入口的定位

GPS入口的定位就同上篇中关于Exif属性的定位入口是一个道理,因为GPS本身就是一个大section,在这个section中又有很多tag,而且tag的格式也是Exif属性中tag的格式是一样的。所以看到这里就比较简单了,其实就是利用上篇中读取Exif属性的代码来事项GPS。具体是现在Exif中定位到GPS入口下代码:
可以看到在最后的Tag中是可以找到GPS信息的入口,这是就可以定位GPS属性了,所以找到入口地址,进入到GPS所在位置进行分析。
  1. case TAG_GPS_INFO:
  2. unsigned char * SubdirStart;
  3. SubdirStart = OffsetBase + Get32u(ValuePtr);
  4. CalGPS(SubdirStart, OffsetBase);
  5. break;
  1. /*--------------------------------------------------------------------------
  2. Process one of the nested EXIF directories.
  3. --------------------------------------------------------------------------*/
  4. bool Cexif::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
  5. EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP )
  6. {
  7. int de;
  8. int a;
  9. int NumDirEntries;
  10. unsigned ThumbnailOffset = 0;
  11. unsigned ThumbnailSize = 0;
  12. unsigned long gps = 0;
  13. NumDirEntries = Get16u(DirStart);
  14. if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){
  15. strcpy(m_szLastError,"Illegally sized directory");
  16. return 0;
  17. }
  18. for (de=0;de<NumDirEntries;de++)
  19. {
  20. int Tag, Format, Components;
  21. unsigned char * ValuePtr;
  22. /* This actually can point to a variety of things; it must be
  23. cast to other types when used. But we use it as a unsigned char-by-unsigned char
  24. cursor, so we declare it as a pointer to a generic unsigned char here.
  25. */
  26. int BytesCount;
  27. unsigned char * DirEntry;
  28. DirEntry = DirStart+2+12*de;
  29. Tag = Get16u(DirEntry);
  30. Format = Get16u(DirEntry+2);
  31. Components = Get32u(DirEntry+4);
  32. if ((Format-1) >= NUM_FORMATS) {
  33. /* (-1) catches illegal zero case as unsigned underflows to positive large */
  34. strcpy(m_szLastError,"Illegal format code in EXIF dir");
  35. return 0;
  36. }
  37. BytesCount = Components * BytesPerFormat[Format];
  38. if (BytesCount > 4){
  39. unsigned OffsetVal;
  40. OffsetVal = Get32u(DirEntry+8);
  41. /* If its bigger than 4 unsigned chars, the dir entry contains an offset.*/
  42. if (OffsetVal+BytesCount > ExifLength){
  43. /* Bogus pointer offset and / or unsigned charcount value */
  44. strcpy(m_szLastError,"Illegal pointer offset value in EXIF.");
  45. return 0;
  46. }
  47. ValuePtr = OffsetBase+OffsetVal;
  48. }else{
  49. /* 4 unsigned chars or less and value is in the dir entry itself */
  50. ValuePtr = DirEntry+8;
  51. }
  52. if (*LastExifRefdP < ValuePtr+BytesCount){
  53. /* Keep track of last unsigned char in the exif header that was
  54. actually referenced. That way, we know where the
  55. discardable thumbnail data begins.
  56. */
  57. *LastExifRefdP = ValuePtr+BytesCount;
  58. }
  59. /* Extract useful components of tag */
  60. switch(Tag){
  61. case TAG_MAKE:
  62. strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31);
  63. break;
  64. case TAG_MODEL:
  65. strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39);
  66. break;
  67. case TAG_EXIF_VERSION:
  68. strncpy(m_exifinfo->Version,(char*)ValuePtr, 4);
  69. break;
  70. case TAG_DATETIME_ORIGINAL:
  71. strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19);
  72. break;
  73. case TAG_USERCOMMENT:
  74. // Olympus has this padded with trailing spaces. Remove these first.
  75. for (a=BytesCount;;){
  76. a--;
  77. if (((char*)ValuePtr)[a] == ' '){
  78. ((char*)ValuePtr)[a] = '\0';
  79. }else{
  80. break;
  81. }
  82. if (a == 0) break;
  83. }
  84. /* Copy the comment */
  85. if (memcmp(ValuePtr, "ASCII",5) == 0){
  86. for (a=5;a<10;a++){
  87. char c;
  88. c = ((char*)ValuePtr)[a];
  89. if (c != '\0' && c != ' '){
  90. strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199);
  91. break;
  92. }
  93. }
  94. }else{
  95. strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199);
  96. }
  97. break;
  98. case TAG_FNUMBER:
  99. /* Simplest way of expressing aperture, so I trust it the most.
  100. (overwrite previously computd value if there is one)
  101. */
  102. m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);
  103. break;
  104. case TAG_APERTURE:
  105. case TAG_MAXAPERTURE:
  106. /* More relevant info always comes earlier, so only
  107. use this field if we don't have appropriate aperture
  108. information yet.
  109. */
  110. if (m_exifinfo->ApertureFNumber == 0){
  111. m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0)*0.5);
  112. }
  113. break;
  114. case TAG_BRIGHTNESS:
  115. m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);
  116. break;
  117. case TAG_FOCALLENGTH:
  118. /* Nice digital cameras actually save the focal length
  119. as a function of how farthey are zoomed in.
  120. */
  121. m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
  122. break;
  123. case TAG_SUBJECT_DISTANCE:
  124. /* Inidcates the distacne the autofocus camera is focused to.
  125. Tends to be less accurate as distance increases.
  126. */
  127. m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);
  128. break;
  129. case TAG_EXPOSURETIME:
  130. /* Simplest way of expressing exposure time, so I
  131. trust it most. (overwrite previously computd value
  132. if there is one)
  133. */
  134. m_exifinfo->ExposureTime =
  135. (float)ConvertAnyFormat(ValuePtr, Format);
  136. break;
  137. case TAG_SHUTTERSPEED:
  138. /* More complicated way of expressing exposure time,
  139. so only use this value if we don't already have it
  140. from somewhere else.
  141. */
  142. if (m_exifinfo->ExposureTime == 0){
  143. m_exifinfo->ExposureTime = (float)
  144. (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0)));
  145. }
  146. break;
  147. case TAG_FLASH:
  148. if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){
  149. m_exifinfo->FlashUsed = 1;
  150. }else{
  151. m_exifinfo->FlashUsed = 0;
  152. }
  153. break;
  154. case TAG_ORIENTATION:
  155. m_exifinfo->Orientation = (int)ConvertAnyFormat(ValuePtr, Format);
  156. if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){
  157. strcpy(m_szLastError,"Undefined rotation value");
  158. m_exifinfo->Orientation = 0;
  159. }
  160. break;
  161. case TAG_EXIF_IMAGELENGTH:
  162. case TAG_EXIF_IMAGEWIDTH:
  163. /* Use largest of height and width to deal with images
  164. that have been rotated to portrait format.
  165. */
  166. a = (int)ConvertAnyFormat(ValuePtr, Format);
  167. if (ExifImageWidth < a) ExifImageWidth = a;
  168. break;
  169. case TAG_FOCALPLANEXRES:
  170. m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format);
  171. break;
  172. case TAG_FOCALPLANEYRES:
  173. m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format);
  174. break;
  175. case TAG_RESOLUTIONUNIT:
  176. switch((int)ConvertAnyFormat(ValuePtr, Format)){
  177. case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */
  178. case 2: m_exifinfo->ResolutionUnit = 1.0f; break;
  179. case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/
  180. case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/
  181. case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/
  182. }
  183. break;
  184. case TAG_FOCALPLANEUNITS:
  185. switch((int)ConvertAnyFormat(ValuePtr, Format)){
  186. case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */
  187. case 2: m_exifinfo->FocalplaneUnits = 1.0f; break;
  188. case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/
  189. case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/
  190. case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/
  191. }
  192. break;
  193. // Remaining cases contributed by: Volker C. Schoech <schoech(at)gmx(dot)de>
  194. case TAG_EXPOSURE_BIAS:
  195. m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);
  196. break;
  197. case TAG_WHITEBALANCE:
  198. m_exifinfo->Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format);
  199. break;
  200. case TAG_METERING_MODE:
  201. m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);
  202. break;
  203. case TAG_EXPOSURE_PROGRAM:
  204. m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);
  205. break;
  206. case TAG_ISO_EQUIVALENT:
  207. m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
  208. if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
  209. break;
  210. case TAG_COMPRESSION_LEVEL:
  211. m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);
  212. break;
  213. case TAG_XRESOLUTION:
  214. m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);
  215. break;
  216. case TAG_YRESOLUTION:
  217. m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);
  218. break;
  219. case TAG_THUMBNAIL_OFFSET:
  220. ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
  221. break;
  222. case TAG_THUMBNAIL_LENGTH:
  223. ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
  224. break;
  225. case TAG_GPS_INFO:
  226. unsigned char * SubdirStart;
  227. SubdirStart = OffsetBase + Get32u(ValuePtr);
  228. CalGPS(SubdirStart, OffsetBase);
  229. break;
  230. }
  231. if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET || Tag == TAG_GPS_INFO)
  232. {
  233. unsigned char * SubdirStart;
  234. SubdirStart = OffsetBase + Get32u(ValuePtr);
  235. if (SubdirStart < OffsetBase ||
  236. SubdirStart > OffsetBase+ExifLength){
  237. strcpy(m_szLastError,"Illegal subdirectory link");
  238. return 0;
  239. }
  240. ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
  241. continue;
  242. }
  243. }
  244. {
  245. /* In addition to linking to subdirectories via exif tags,
  246. there's also a potential link to another directory at the end
  247. of each directory. This has got to be the result of a
  248. committee!
  249. */
  250. unsigned char * SubdirStart;
  251. unsigned Offset;
  252. Offset = Get16u(DirStart+2+12*NumDirEntries);
  253. if (Offset){
  254. SubdirStart = OffsetBase + Offset;
  255. if (SubdirStart < OffsetBase
  256. || SubdirStart > OffsetBase+ExifLength){
  257. strcpy(m_szLastError,"Illegal subdirectory link");
  258. return 0;
  259. }
  260. ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP);
  261. }
  262. }
  263. if (ThumbnailSize && ThumbnailOffset){
  264. if (ThumbnailSize + ThumbnailOffset <= ExifLength){
  265. /* The thumbnail pointer appears to be valid. Store it. */
  266. m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
  267. m_exifinfo->ThumbnailSize = ThumbnailSize;
  268. }
  269. }
  270. return 1;
  271. }

详细分析GPS属性

关于GPS属性的分析如下:

00 00       GPSVersionID
  00 01       BYTE
  00 00 00 04 count
  02 02 00 00 value 2.2.0.0

通过代码实现如下:
  1. int Cexif::CalGPS(unsigned char * GPSStart, unsigned char * OffsetBase)
  2. {
  3. int ret = 0;
  4. int de;
  5. int a;
  6. int NumDirEntries;
  7. unsigned char * ValuePtr;
  8. NumDirEntries = Get16u(GPSStart);
  9. memset(&m_gpsInfo, 0, sizeof(tag_GPSInfo));
  10. for (de = 0; de<NumDirEntries; de++)
  11. {
  12. int Tag, Format, Components;
  13. unsigned char * ValuePtr;
  14. /* This actually can point to a variety of things; it must be
  15. cast to other types when used. But we use it as a unsigned char-by-unsigned char
  16. cursor, so we declare it as a pointer to a generic unsigned char here.
  17. */
  18. int BytesCount;
  19. unsigned char * DirEntry;
  20. DirEntry = GPSStart + 2 + 12 * de;
  21. Tag = Get16u(DirEntry);
  22. Format = Get16u(DirEntry + 2);
  23. Components = Get32u(DirEntry + 4);
  24. BytesCount = Components * BytesPerFormat[Format];
  25. if (BytesCount > 4)
  26. {
  27. unsigned OffsetVal;
  28. OffsetVal = Get32u(DirEntry + 8);
  29. ValuePtr = OffsetBase + OffsetVal;
  30. }
  31. else
  32. {
  33. /* 4 unsigned chars or less and value is in the dir entry itself */
  34. ValuePtr = DirEntry + 8;
  35. }
  36. /* Extract useful components of tag */
  37. switch (Tag)
  38. {
  39. case TAG_GPS_VERSION:
  40. strncpy(m_gpsInfo.GPSVersion, (char*)ValuePtr, 10);
  41. break;
  42. case TAG_GPS_LATITUDEREF:
  43. strncpy(m_gpsInfo.GPSLatRef, (char*)ValuePtr, 1);
  44. break;
  45. case TAG_GPS_LATITUDE:
  46. float lat;
  47. lat = (float)ConvertAnyFormat(ValuePtr, Format);
  48. lat += ((float)ConvertAnyFormat(ValuePtr + 8, Format))/60;
  49. lat += ((float)ConvertAnyFormat(ValuePtr + 16, Format))/3600;
  50. m_gpsInfo.GPSLat = lat;
  51. break;
  52. case TAG_GPS_LONGITUDEREF:
  53. strncpy(m_gpsInfo.GPSLogRef, (char*)ValuePtr, 1);
  54. break;
  55. case TAG_GPS_LONGITUDE:
  56. float longitude;
  57. longitude = (float)ConvertAnyFormat(ValuePtr, Format);
  58. longitude += ((float)ConvertAnyFormat(ValuePtr + 8, Format)) / 60;
  59. longitude += ((float)ConvertAnyFormat(ValuePtr + 16, Format)) / 3600;
  60. m_gpsInfo.GPSLog = longitude;
  61. break;
  62. case TAG_GPS_ALTITUDEREF:
  63. strncpy(m_gpsInfo.GPSAltRef, (char*)ValuePtr, 1);
  64. break;
  65. case TAG_GPS_ALTITUDE:
  66. m_gpsInfo.GPSAlt = (float)ConvertAnyFormat(ValuePtr, Format);
  67. break;
  68. case TAG_BRIGHTNESS:
  69. m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);
  70. break;
  71. case TAG_FOCALLENGTH:
  72. /* Nice digital cameras actually save the focal length
  73. as a function of how farthey are zoomed in.
  74. */
  75. m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
  76. break;
  77. case TAG_SUBJECT_DISTANCE:
  78. /* Inidcates the distacne the autofocus camera is focused to.
  79. Tends to be less accurate as distance increases.
  80. */
  81. m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);
  82. break;
  83. case TAG_EXPOSURETIME:
  84. /* Simplest way of expressing exposure time, so I
  85. trust it most. (overwrite previously computd value
  86. if there is one)
  87. */
  88. m_exifinfo->ExposureTime =
  89. (float)ConvertAnyFormat(ValuePtr, Format);
  90. break;
  91. }
  92. }
  93. return ret;
  94. }

Demo最终实现的结果

参考文档

http://blog.csdn.net/fioletfly/article/details/53605959
http://blog.csdn.net/fioletfly/article/details/54094940
http://blog.csdn.net/xuan_oscar/article/details/2449624

尾巴

关于源码的话,本来是直接上传的,但是想想还是留给真正有需要的人吧。想要源码的可以私信交流啊!

读取JPG图片的Exif属性(三) - Exif属性读取GPS信息代码(C/C++实现)相关推荐

  1. python的image读取的图片是什么类型的-opencv python 读取图像/显示图像/保存图像...

    以前也用过opencv, 不过都是按需使用, 掌握的知识很零散, 这次希望能够系统学习opencv-python 本文直接从Gui Features开始. 1 读取图片 使用cv2.imread()函 ...

  2. jpg图片的Exif及gps信息和示例分析

    转自:http://www.verydemo.com/demo_c173_i10439.html jpg图片的Exif及gps信息和示例分析 分类:  操作系统 /  Windows /  文章 jp ...

  3. python批量修改图片的exif信息,增加GPS信息。

      有时候需要给图片增加地理信息,比如在用无人机影像做3维建模或者正射影像时,可以将无人机的gps写入图片,然后用ODM快速完成三维模型与正射影像生成.   ODM的使用方法可以参看下面这篇博客. h ...

  4. python读取raw图片文件_python读取raw binary图片并提取统计信息的实例

    python读取raw binary图片并提取统计信息的实例 发布时间:2020-09-08 23:22:52 来源:脚本之家 阅读:66 用python语言读取二进制图片文件,并提取非零数据统计信息 ...

  5. JAVA 拍照 exif GPS_读取图片EXIF块中GPS信息,转换为高德地图API坐标

    最近两天做了一个需求,从APP端上传的照片信息里面读取出GPS位置信息,然后翻译成可读的地点信息. 总结一下,分为三步: (1)提取图片中的GPS信息,使用到了metadata-extractor; ...

  6. 轻松获取图片和视频文件的Exif信息-Java篇

    前言 随着现在实景地图的如火如荼建设,无人机等航拍测绘手段的不断升级,我们在获取全景照片或者正射影像,全景视频等数据上更加快速.便捷.由于无人机本身不进行相关数据的处理,比如全景地图的生成.视频的信息 ...

  7. java根据exif旋转,关于图片文件旋转JPEG与EXIF信息

    关于图片文件旋转JPEG与EXIF信息 2019/10/31 0:36:39  YuLimin  程序员俱乐部  我要评论(1) 摘要:关于图片文件旋转JPEG与EXIF信息比如某相机拍摄出来的相片, ...

  8. 关于图片文件旋转JPEG与EXIF信息

    关于图片文件旋转JPEG与EXIF信息 比如某相机拍摄出来的相片,文件分辨率比如宽度7360像素,高度4912像素 十进制表示为 DEC : 7360 * 4912 十六进制则为 HEX : 1CC0 ...

  9. JPG图片EXIF信息提取工具exif

    JPG图片EXIF信息提取工具exif 有相机生成的JPG图片(如照片)都包含有EXIF信息.这些信息包括拍照所使用的设备.地理位置.拍摄时间等敏感信息.Kali Linux内置了EXIF信息提取工具 ...

  10. opencv java 显示图片_【opencv三】利用opencv读取显示图片

    在opencv中读取显示图片的头文件是highgui.hpp. 整体代码如下,如要测试自己的图片,需要将代码段中的图片地址更改为自己图片的绝对路径. #include "opencv2/hi ...

最新文章

  1. C++:随笔4--对象
  2. Linux基础常用命令
  3. gitlab新建项目_基础架构之GitLab
  4. Auto-Publishing and Monitoring APIs With Spring Boot--转
  5. 手把手教您如何识别翻新机子
  6. Hive的基本操作-创建表的格式
  7. mysql操作xml字段_SQL XML 字段操作
  8. linux svn可视化工具,CentOS6.5安装SVN 可视化管理工具iF.SVNAdmin
  9. 史上最贵域名诞生!360斥资1700万美元买360.com
  10. Intelij IDEA解决Dependency无法更新问题
  11. python入门经典代码-python经典入门学习锦集就这篇够了,强烈建议收藏!
  12. MS08067 第一期 “恶意代码分析”实战班 12.17号开班~
  13. 个人计算机之前,很久之前的个人pc机 文曲星,是什么档次,jrs还有印象么?
  14. GA/GP中的适应度函数
  15. sql删除元组_SQL笔记
  16. 【POJ】1003_Hangover宿醉
  17. python识别屏幕内容_python之屏幕抓取
  18. wireshark蓝牙数据包分析_Wireshark数据包分析
  19. 一个浪漫又悲情的爱情故事——笛卡尔心形线
  20. LeetCode881:救生艇 (C、C++实现)

热门文章

  1. 【营销学堂】从饥饿营销到口碑营销
  2. 如何将高程数据转成南方CASS的DAT格式
  3. python输出dat格式_输出dat文件
  4. android绘画时钟,Android画个时钟玩玩
  5. Matlab与Excel文件的数据交换
  6. 【耀杨闯荡华儿街】当曹阿门问起hascode()和equals()方法“上篇”
  7. word文档打不开怎么办,word安全模式怎么解除,word打不开的解决办法
  8. 野火 FireConfig 配置连接Wifi
  9. java反射--Field用法实践
  10. java 反射 field.set,java 反射之Field