blob: 34685581fd56f480b80567c9fcb96e75ef23fa74 [file] [log] [blame]
b.liu90f385f2025-02-20 19:57:52 +08001#include <stdio.h>
2#include <unistd.h>
3#include <stdlib.h>
4#include <errno.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <stdint.h>
10
11#include "logo_partition.h"
12
13#pragma pack(push, 1) // 取消结构体对齐
14typedef struct {
15 uint16_t bfType; // 文件类型,应为"BM"(0x4D42)
16 uint32_t bfSize; // 文件总大小
17 uint16_t bfReserved1; // 保留字段
18 uint16_t bfReserved2;
19 uint32_t bfOffBits; // 像素数据偏移量
20} BITMAPFILEHEADER;
21
22typedef struct {
23 uint32_t biSize; // 信息头大小(通常为40)
24 int32_t biWidth; // 图像宽度(像素)
25 int32_t biHeight; // 图像高度(像素)
26 uint16_t biPlanes; // 颜色平面数(必须为1)
27 uint16_t biBitCount; // 每像素位数(如24表示RGB)
28 uint32_t biCompression; // 压缩类型(0表示无压缩)
29 uint32_t biSizeImage; // 像素数据大小(含填充)
30 int32_t biXPelsPerMeter;// 水平分辨率(像素/米)
31 int32_t biYPelsPerMeter;// 垂直分辨率
32 uint32_t biClrUsed; // 实际使用的颜色数
33 uint32_t biClrImportant; // 重要颜色数
34} BITMAPINFOHEADER;
35#pragma pack(pop)
36
37#define ANIM_PIC_MAX 30 // 开机动画的最大图片数量 (1.bmp - 30.bmp)
38
39static mbtk_logo_header_t logo_header = {
40 .addr = LOGO_ADDR_START,
41 .pic_width = 240,
42 .pic_height = 320,
43 .bg_rgb = 0x00000000 // black
44};
45
46static mbtk_animation_header_t animation_header = {
47 .addr = ANIMATION_ADDR_START,
48 .pic_num = 0,
49 .pic_width = 240,
50 .pic_height = 320,
51 .frame_rate = 10,
52 .bg_rgb = 0x00000000 // black
53};
54
55static int is_directory_exists(const char *path) {
56 struct stat stats;
57 if (stat(path, &stats) == 0 && S_ISDIR(stats.st_mode)) {
58 return 1; // 目录存在
59 }
60 printf("%s not exists.\n", path);
61 return 0; // 目录不存在或路径是文件
62}
63
64static void help()
65{
66 //printf("logo_partition_generate [pic_dir] -a [logo_w] -b [logo_h] -c [logo_bg] -d [anim_num] -e [anim_w] -f [anim_h] -g [anim_rate] -i [anim_bg]\n");
67 printf("logo_partition_generate [pic_dir] -a [logo_bg] -b [anim_rate] -c [anim_bg]\n");
68}
69
70static int bmp_read(const char* file_name, uint32 *width, uint32 *height, char *buff, int buff_size)
71{
72 FILE* file = fopen(file_name, "rb");
73 if (!file) return 0; // 文件不存在
74
75 // 读取文件头和信息头
76 BITMAPFILEHEADER file_header;
77 BITMAPINFOHEADER info_header;
78 fread(&file_header, sizeof(file_header), 1, file);
79 fread(&info_header, sizeof(info_header), 1, file);
80
81 // 验证是否为BMP文件
82 if (file_header.bfType != 0x4D42) {
83 fclose(file);
84 return -1;
85 }
86
87 // 仅支持24位无压缩格式
88 if (info_header.biBitCount != 24 || info_header.biCompression != 0) {
89 fclose(file);
90 return -1;
91 }
92
93 *width = info_header.biWidth;
94 *height = abs(info_header.biHeight); // 高度可能为负(表示从上到下存储)
95
96 // 计算每行实际字节数(含4字节对齐填充)
97 uint32_t row_size = ((info_header.biWidth * 3 + 3) / 4) * 4; // [[9, 18]]
98 uint32_t data_size = row_size * abs(info_header.biHeight); // [[9, 17]]
99 if(buff_size < data_size) {
100 printf("buff_size too small...");
101 return -1;
102 }
103
104 // 分配内存并读取像素数据
105 fseek(file, file_header.bfOffBits, SEEK_SET); // 定位到数据区 [[2, 8, 15]]
106 fread(buff, 1, data_size, file);
107 fclose(file);
108
109 return data_size;
110}
111
112static int write_header(int fd, mbtk_logo_header_t *logo_h, mbtk_animation_header_t *anim_h)
113{
114 if(-1 == lseek(fd, 0, SEEK_SET)) {
115 printf("lseek() fail:%d\n", errno);
116 return -1;
117 }
118
119 if(sizeof(mbtk_logo_header_t) != write(fd, logo_h, sizeof(mbtk_logo_header_t))) {
120 printf("Write logo header fail:%d\n", errno);
121 return -1;
122 }
123
124 if(sizeof(mbtk_animation_header_t) != write(fd, anim_h, sizeof(mbtk_animation_header_t))) {
125 printf("Write anim header fail:%d\n", errno);
126 return -1;
127 }
128
129 return 0;
130}
131
132static int write_item_logo(int fd, const char *dir, mbtk_logo_header_t *logo_h)
133{
134 if(-1 == lseek(fd, logo_h->addr, SEEK_SET)) {
135 printf("lseek() fail:%d\n", errno);
136 return -1;
137 }
138
139 char pic_name[256] = {0};
140 char buff[4 * 1024 * 1024] = {0}; // 4MB
141 int len = 0;
142 snprintf(pic_name, sizeof(pic_name), "%s/%s", dir, "logo.bmp");
143 if((len = bmp_read(pic_name, &(logo_h->pic_width), &(logo_h->pic_height), buff, sizeof(buff))) <= 0) {
144 printf("bmp_read() fail.\n");
145 return -1;
146 }
147
148 if(len != write(fd, buff, len)) {
149 printf("Write logo buffer fail:%d\n", errno);
150 return -1;
151 }
152
153 return 0;
154}
155
156static int write_item_anim(int fd, const char *dir, mbtk_animation_header_t *anim_h)
157{
158 if(-1 == lseek(fd, anim_h->addr, SEEK_SET)) {
159 printf("lseek() fail:%d\n", errno);
160 return -1;
161 }
162
163 char pic_name[256] = {0};
164 char buff[4 * 1024 * 1024] = {0}; // 4MB
165 int len, i = 1; // 1.bmp - ANIM_PIC_MAX.bmp
166
167 for(; i <= ANIM_PIC_MAX; i++) {
168 memset(pic_name, 0, sizeof(pic_name));
169 snprintf(pic_name, sizeof(pic_name), "%s/%d.bmp", dir, i);
170
171/*
172 if(!is_directory_exists(pic_name)) {
173 anim_h->pic_num = i - 1;
174 printf("Anim pic num is : %d\n", i - 1);
175 return 0;
176 }
177*/
178
179 len = bmp_read(pic_name, &(anim_h->pic_width), &(anim_h->pic_height), buff, sizeof(buff));
180 if(len == 0) { // 文件不存在
181 anim_h->pic_num = i - 1;
182 printf("Anim pic num is : %d\n", i - 1);
183 return 0;
184 } else if(len < 0) {
185 printf("bmp_read() fail.\n");
186 return -1;
187 }
188
189 if(len != write(fd, buff, len)) {
190 printf("Write logo buffer fail:%d\n", errno);
191 return -1;
192 }
193 }
194
195 anim_h->pic_num = ANIM_PIC_MAX;
196 return 0;
197}
198
199
200/*
201*
202* logo_partition_generate [pic_dir] -a [logo_w] -b [logo_h] -c [logo_bg] -d [anim_num] -e [anim_w] -f [anim_h] -g [anim_rate] -i [anim_bg]
203* logo_partition_generate [pic_dir] -a [logo_bg] -b [anim_rate] -c [anim_bg]
204*/
205int main(int argc, char *argv[])
206{
207 int ch;
208 char *out_bin = "logo.img";
209 uint32 temp_int;
210 if(argc < 2) {
211 help();
212 return -1;
213 }
214
215 char *dir = argv[1];
216 if(!is_directory_exists(dir)) {
217 printf("Dir %s not exists.\n", dir);
218 return -1;
219 }
220
221 while((ch = getopt(argc, argv, "a:b:c:"))!= -1){
222 switch(ch)
223 {
224#if 0
225 case 'a':
226 temp_int = (uint32)atoi(optarg);
227 if(temp_int > 0) {
228 logo_header.pic_width = temp_int;
229 } else {
230 printf("logo width error.");
231 }
232 break;
233 case 'b':
234 temp_int = (uint32)atoi(optarg);
235 if(temp_int > 0) {
236 logo_header.pic_height = temp_int;
237 } else {
238 printf("logo height error.");
239 }
240 break;
241 case 'c':
242 temp_int = (uint32)strtoul(optarg, NULL, 0); // 自动识别
243 logo_header.bg_rgb = temp_int & 0x00FFFFFF;
244 break;
245 case 'd':
246 temp_int = (uint32)atoi(optarg);
247 if(temp_int > 0) {
248 animation_header.pic_num = temp_int;
249 } else {
250 printf("animation number error.");
251 }
252 break;
253 case 'e':
254 temp_int = (uint32)atoi(optarg);
255 if(temp_int > 0) {
256 animation_header.pic_width = temp_int;
257 } else {
258 printf("animation width error.");
259 }
260 break;
261 case 'f':
262 temp_int = (uint32)atoi(optarg);
263 if(temp_int > 0) {
264 animation_header.pic_height = temp_int;
265 } else {
266 printf("animation height error.");
267 }
268 break;
269 case 'g':
270 temp_int = (uint32)atoi(optarg);
271 if(temp_int > 0) {
272 animation_header.frame_rate = temp_int;
273 } else {
274 printf("animation frame_rate error.");
275 }
276 break;
277 case 'i':
278 temp_int = (uint32)strtoul(optarg, NULL, 0); // 自动识别
279 animation_header.bg_rgb = temp_int & 0x00FFFFFF;
280 break;
281#else
282 case 'a':
283 temp_int = (uint32)strtoul(optarg, NULL, 0); // 自动识别
284 logo_header.bg_rgb = temp_int & 0x00FFFFFF;
285 break;
286 case 'b':
287 temp_int = (uint32)atoi(optarg);
288 if(temp_int > 0) {
289 animation_header.frame_rate = temp_int;
290 } else {
291 printf("animation frame_rate error.");
292 }
293 break;
294 case 'c':
295 temp_int = (uint32)strtoul(optarg, NULL, 0); // 自动识别
296 animation_header.bg_rgb = temp_int & 0x00FFFFFF;
297 break;
298#endif
299 default:
300 help();
301 return -1;
302 }
303 }
304
305 printf("Before Logo : addr - 0x%x, w - %d, h - %d, bg - 0x%06x\n", logo_header.addr ,logo_header.pic_width, logo_header.pic_height, logo_header.bg_rgb);
306 printf("Before Anim : addr - 0x%x, w - %d, h - %d, bg - 0x%06x, num - %d, frame_rate - %d\n", animation_header.addr ,animation_header.pic_width, animation_header.pic_height, animation_header.bg_rgb,
307 animation_header.pic_num, animation_header.frame_rate);
308
309 int fd = open(out_bin, O_WRONLY | O_TRUNC | O_CREAT, 0644);
310 if(fd < 0) {
311 printf("Open(%s) fail:%d\n", out_bin, errno);
312 return -1;
313 }
314
315 if(write_item_logo(fd, dir, &logo_header)) {
316 printf("write_item_logo() fail.");
317 goto fail;
318 }
319
320 if(write_item_anim(fd, dir, &animation_header)) {
321 printf("write_item_anim() fail.");
322 goto fail;
323 }
324
325 // Write header in the last.
326 if(write_header(fd, &logo_header, &animation_header)) {
327 printf("write_header() fail.");
328 goto fail;
329 }
330
331 printf("After Logo : addr - 0x%x, w - %d, h - %d, bg - 0x%06x\n", logo_header.addr ,logo_header.pic_width, logo_header.pic_height, logo_header.bg_rgb);
332 printf("After Anim : addr - 0x%x, w - %d, h - %d, bg - 0x%06x, num - %d, frame_rate - %d\n", animation_header.addr ,animation_header.pic_width, animation_header.pic_height, animation_header.bg_rgb,
333 animation_header.pic_num, animation_header.frame_rate);
334
335 printf("Success generate logo_partition bin:%s\n", out_bin);
336 close(fd);
337 return 0;
338fail:
339 close(fd);
340 return -1;
341}
342