获得百度地图

一、前言

  获得地图的方法实际上是给百度地图发送一个获得图片的请求,可以设定的内容包括:图片中心点、标记点、图片大小、地图级别(放大程度)等,具体内容可以参考百度地图的Web服务API中的静态图服务。

  需要注意的是,百度地图使用的经纬度与GPS/北斗模块获得的经纬度不同,百度地图是加密过的,需要调用百度的坐标转换接口。

  获得地图的程序的编写方法与坐标转换如出一辙,可以参考我的另一篇博客:在嵌入式平台上将GPS/北斗模块获取的经纬度转换为百度地图经纬度

  获得的图片类似于下图:

  获得百度地图

 

   图中的标记点可以设置,可以加很多个,但是我编写的程序中只加了一个。

  我希望得到的图片是像手机中的地图一样,自己的位置和标记点的图标是不一样的,经过一番研究之后,发现没有标记点样式可供选择,但是可以通过将markerStyles的值设定为-1来变为自己设定的图片。经过一番研究之后,发现标记点图标始终没有变为自己的图片,不知道是我发送的请求格式有问题还是图片的url地址有问题,最终心态爆炸选择放弃。

二、代码

  1 /**
  2  * filename: baidu_map.c
  3  * author: Suzkfly
  4  * date: 2021-08-21
  5  * platform: linux
  6  *  向百度地图请求获得一张地图图片,图片格式为png。
  7  */
  8 #include <sys/types.h>
  9 #include <sys/socket.h>
 10 #include <stdio.h>
 11 #include <string.h>
 12 #include <netinet/ip.h>
 13 #include <netinet/in.h>
 14 #include <arpa/inet.h>
 15 #include <stdlib.h>
 16 #include <sys/stat.h>
 17 #include <fcntl.h>
 18 #include <unistd.h>
 19 
 20 #define SER_PORT    80                  /* HTTP请求端口固定为80 */
 21 #define SER_ADDR    "220.181.43.101"    /* 百度地图服务IP地址 */
 22 
 23 #define AK          "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"  /* AK,填入自己的AK */
 24 //https://lbsyun.baidu.com/
 25 
 26 /**< /brief 定义地图信息 */
 27 typedef struct baidu_map_info {
 28     int width;              /* 图片宽度,(0, 1024] */
 29     int height;             /* 图片高度,(0, 1024] */
 30     char *p_center_lon;     /* 地图中心点的经度 */
 31     char *p_center_lat;     /* 地图中心点的纬度 */
 32     int zoom;               /* 地图级别,[3, 19],数值越大,地图放大级数越高 */
 33     char *p_mark_lon;       /* 地图上标记点的经度 */
 34     char *p_mark_lat;       /* 地图上标记点的纬度 */
 35 } baidu_map_info_t;
 36 
 37 
 38 /**
 39  * \brief 从百度地图获取一张png图片,并以文件形式存储
 40  *
 41  * \param[in] p_info:要获取的图片信息
 42  * \param[in] p_path:png图片存储路径
 43  *
 44  * \retval 成功返回0,失败返回-1
 45  */
 46 int get_baidu_map (const baidu_map_info_t *p_info, const char *p_path)
 47 {
 48     int ret, i;
 49     int sockfd;
 50     struct sockaddr_in seraddr;
 51     char buf[2048] = { 0 };
 52     int count = 0;                  /* 接收到的字节个数 */
 53     char *p_tmp = NULL;             /* 定义2个临时指针 */
 54     char *p_tmp2 = NULL;
 55     struct timeval tv_out;          /* 设定超时时间 */
 56     unsigned int contet_size = 0;   /* 包含了经纬度的数据长度 */
 57     char len_a[8] = { 0 };
 58     int fd = 0;
 59     int len = 0;
 60     char *p_png = NULL;
 61 
 62 
 63     /* 检查参数 */
 64     if ((p_info == NULL) || (p_path == NULL)) {
 65         return -1;
 66     }
 67     if ((p_info->width <= 0)  || (p_info->width > 1024)  ||
 68         (p_info->height <= 0) || (p_info->height > 1024) ||
 69         (p_info->p_center_lon == NULL) || (p_info->p_center_lat == NULL) ||
 70         (p_info->zoom < 3) || (p_info->zoom > 19) ||
 71         (p_info->p_mark_lon == NULL) || (p_info->p_mark_lat == NULL)) {
 72         return -1;
 73     }
 74         
 75     /* 创建socket套接字 */
 76     seraddr.sin_family = AF_INET;
 77     seraddr.sin_port = htons(SER_PORT);
 78     seraddr.sin_addr.s_addr = inet_addr(SER_ADDR);
 79     sockfd = socket(AF_INET, SOCK_STREAM, 0);
 80     if (-1 == sockfd) {
 81         perror("fail to socket\n");
 82         return -1;
 83     }
 84 
 85     /* 建立连接 */
 86     ret = connect(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr));
 87     if (-1 == ret) {
 88         perror("fail to connect\n");
 89         return -1;
 90     }
 91     
 92     /* 发送HTTP请求报文 */
 93     sprintf(buf, "GET /staticimage/v2?ak=%s&mcode=666666&center=%s,%s&scale=1&width=%d&height=%d&zoom=%d&markers=%s,34.227378 HTTP/1.1\r\n", 
 94             AK, 
 95             p_info->p_center_lon, 
 96             p_info->p_center_lat, 
 97             p_info->width, 
 98             p_info->height, 
 99             p_info->zoom, 
100             p_info->p_mark_lon, 
101             p_info->p_mark_lat);
102     strcat(buf, "Host: api.map.baidu.com\r\n");
103     strcat(buf, "Connection: keep-alive\r\n");
104     strcat(buf, "Cache-Control: max-age=0\r\n");
105     strcat(buf, "Upgrade-Insecure-Requests: 1\r\n");
106     strcat(buf, "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36\r\n");
107     strcat(buf, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n");
108     strcat(buf, "Accept-Encoding: gzip, deflate\r\n");
109     strcat(buf, "Accept-Language: zh-CN,zh;q=0.9\r\n");
110     strcat(buf, "Cookie: BIDUPSID=84DAAE28689E8D659761B94C23DD1528; PSTM=1551188524; BAIDUID=21DB33B682DC4E7201B51C45EE47F0D3:FG=1; Hm_lvt_520a61d0af6df31c19bb0fbd9dba0972=1625539517,1625588877; Hm_lvt_5650c092812f8659cdfe23eeb42024ef=1629194175,1629194194,1629194209,1629194298; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; PSINO=6; ZD_ENTRY=baidu; BDUSS=BGSlNIbmFzbUgxWGt-Y3B3anVsR0VwemtHbURxU1g5cEwzenpTNGR5Y0paRWhoRUFBQUFBJCQAAAAAAAAAAAEAAACARGs7sNfRqcDWuOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnXIGEJ1yBhOH; MCITY=-233%3A; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; BDRCVFR[tox4WRQ4-Km]=mk3SLVN4HKm; BDRCVFR[CLK3Lyfkr9D]=mk3SLVN4HKm; H_PS_PSSID=34399_31253_34404_33848_34449_34073_34092_34107_26350_34323\r\n\r\n");
111     ret = send(sockfd, buf, strlen(buf), 0);
112     if (-1 == ret) {
113         perror("fail to send\n");
114         return -1;
115     }
116 
117     /* 设定接收数据超时时间为3S。这里要根据设备网络情况而定 */
118     tv_out.tv_sec = 3;
119     tv_out.tv_usec = 0;
120     setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv_out, sizeof(tv_out));
121 
122     /* 接收HTTP响应报文 */
123     p_tmp = buf;
124     count = 0;
125     memset(p_tmp, 0, strlen(p_tmp));
126    
127     /* 先接收部分数据,目的是得到整个png图片的大小 */
128     while ((ret = recv(sockfd, p_tmp, 160 - count, 0)) > 0) {
129         count += ret;
130         p_tmp += ret;
131         if (count > 150) {
132             break;
133         }
134     }
135     /* 解析png图片的数据长度 */
136     p_tmp = strstr(buf, "Content-Length: ");
137     if (p_tmp == NULL) {
138         perror("fail to strstr\n");
139         return -1;
140     }
141     p_tmp += strlen("Content-Length: ");
142     p_tmp2 = strstr(p_tmp, "\r\n");
143     strncpy(len_a, p_tmp, p_tmp2 - p_tmp);
144     contet_size = atoi(len_a);
145     printf("png data len = %d\n", contet_size);
146     
147     p_png = malloc(contet_size + 300);  /* 这里加300是为了将剩余的http应答包也接收完 */
148     if (p_png == NULL) {
149         perror("malloc failed\n");
150         return -1;
151     }
152     /* 继续接收后面的数据内容 */
153     p_tmp = p_png;
154     count = 0;
155     while ((ret = recv(sockfd, p_tmp, contet_size + 300 - count, 0)) > 0) {
156         count += ret;
157         p_tmp += ret;
158     }
159     close(sockfd);  /* 关闭套接字 */
160 
161     /* 找到数据内容起始地址 */
162     p_tmp = strstr(p_png, "\r\n\r\n");
163     if (p_tmp == NULL) {
164         perror("fail to strstr\n");
165     }
166     p_tmp += strlen("\r\n\r\n");
167 
168 
169     /* 将数据内容保存到文件中 */
170     fd = open(p_path, O_RDWR | O_CREAT | O_TRUNC, 0666);
171     if (fd < 0) {
172         perror("fail to open\n");
173         return -1;
174     }
175     ret = write(fd, p_tmp, contet_size);
176     if (ret != contet_size) {
177         perror("fail to write\n");
178         return -1;
179     }
180     close(fd);
181     
182     free(p_png);    /* 释放内存 */
183 
184     return 0;
185 }
186 
187 /**
188  * \brief example
189  */
190 int main(int argc, const char *argv[])
191 {
192     int ret = 0;
193     baidu_map_info_t info;
194     char center_lon[] = "108.866211";
195     char center_lat[] = "34.227378";
196     char name[32] = { 0 };
197     int i;
198         
199     info.width = 800;
200     info.height = 480;
201     info.p_center_lon = center_lon;
202     info.p_center_lat = center_lat;
203     info.zoom = 18;
204     info.p_mark_lon = center_lon;
205     info.p_mark_lat = center_lat;
206 
207     ret = get_baidu_map(&info, "map.png");
208     if (ret < 0) {
209         printf("ret = %d\n", ret);
210         return -1;
211     }
212 
213     return 0;
214 }

 

上一篇:小程序学习总结


下一篇:用python批量发送微信消息