一、前言
获得地图的方法实际上是给百度地图发送一个获得图片的请求,可以设定的内容包括:图片中心点、标记点、图片大小、地图级别(放大程度)等,具体内容可以参考百度地图的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¢er=%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 }