xref: /OK3568_Linux_fs/u-boot/tools/rockchip/bmp2gray16.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2020 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * SPDX-License-Identifier:     GPL-2.0+
5*4882a593Smuzhiyun  * Author: Wenping Zhang <wenping.zhang@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <stdio.h>
9*4882a593Smuzhiyun #include <stdlib.h>
10*4882a593Smuzhiyun #include <string.h>
11*4882a593Smuzhiyun #include <rk_eink.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun struct  bmp_header {
14*4882a593Smuzhiyun 	/* Header */
15*4882a593Smuzhiyun 	char signature[2];
16*4882a593Smuzhiyun 	uint32_t	file_size;
17*4882a593Smuzhiyun 	uint32_t	reserved;
18*4882a593Smuzhiyun 	uint32_t	data_offset;
19*4882a593Smuzhiyun 	/* InfoHeader */
20*4882a593Smuzhiyun 	uint32_t	size;
21*4882a593Smuzhiyun 	uint32_t	width;
22*4882a593Smuzhiyun 	uint32_t	height;
23*4882a593Smuzhiyun 	uint16_t	planes;
24*4882a593Smuzhiyun 	uint16_t	bit_count;
25*4882a593Smuzhiyun 	uint32_t	compression;
26*4882a593Smuzhiyun 	uint32_t	image_size;
27*4882a593Smuzhiyun 	uint32_t	x_pixels_per_m;
28*4882a593Smuzhiyun 	uint32_t	y_pixels_per_m;
29*4882a593Smuzhiyun 	uint32_t	colors_used;
30*4882a593Smuzhiyun 	uint32_t	colors_important;
31*4882a593Smuzhiyun 	/* ColorTable */
32*4882a593Smuzhiyun } __attribute__((packed));
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun struct bmp_image {
35*4882a593Smuzhiyun 	struct bmp_header hdr;
36*4882a593Smuzhiyun 	uint8_t color_table[0];
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun struct pixel_u16 {
40*4882a593Smuzhiyun 	uint16_t blue  : 4,
41*4882a593Smuzhiyun 		green : 4,
42*4882a593Smuzhiyun 		red   : 4,
43*4882a593Smuzhiyun 		alpha : 4;
44*4882a593Smuzhiyun } __attribute__((packed));
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun struct pixel_u24 {
47*4882a593Smuzhiyun 	uint8_t blue;
48*4882a593Smuzhiyun 	uint8_t green;
49*4882a593Smuzhiyun 	uint8_t red;
50*4882a593Smuzhiyun } __attribute__((packed));
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun struct pixel_u32 {
53*4882a593Smuzhiyun 	uint8_t blue;
54*4882a593Smuzhiyun 	uint8_t green;
55*4882a593Smuzhiyun 	uint8_t red;
56*4882a593Smuzhiyun 	uint8_t alpha;
57*4882a593Smuzhiyun } __attribute__((packed));
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun //logo partition Header, 64byte
60*4882a593Smuzhiyun struct logo_part_header {
61*4882a593Smuzhiyun 	char magic[4]; /* must be "RKEL" */
62*4882a593Smuzhiyun 	uint32_t  totoal_size;
63*4882a593Smuzhiyun 	uint32_t  screen_width;
64*4882a593Smuzhiyun 	uint32_t  screen_height;
65*4882a593Smuzhiyun 	uint32_t  logo_count;
66*4882a593Smuzhiyun 	char  version[4];
67*4882a593Smuzhiyun 	uint32_t  rsv[10];
68*4882a593Smuzhiyun } __attribute__((packed));
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun // logo image header,32 byte
71*4882a593Smuzhiyun struct grayscale_header {
72*4882a593Smuzhiyun 	char magic[4]; /* must be "GR04" */
73*4882a593Smuzhiyun 	uint16_t x;
74*4882a593Smuzhiyun 	uint16_t y;
75*4882a593Smuzhiyun 	uint16_t w;
76*4882a593Smuzhiyun 	uint16_t h;
77*4882a593Smuzhiyun 	uint32_t logo_type;
78*4882a593Smuzhiyun 	uint32_t data_offset; /* image offset in byte */
79*4882a593Smuzhiyun 	uint32_t data_size; /* image size in byte */
80*4882a593Smuzhiyun 	uint32_t rsv[2];
81*4882a593Smuzhiyun } __attribute__((packed));
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /*
84*4882a593Smuzhiyun  * The start address of logo image in logo.img must be aligned
85*4882a593Smuzhiyun  * in 512 bytes,so the header size must be times of 512 bytes.
86*4882a593Smuzhiyun  * Here we fix the size to 512 bytes, so the count of logo image
87*4882a593Smuzhiyun  * can only support up to 14.
88*4882a593Smuzhiyun  */
89*4882a593Smuzhiyun struct logo_info {
90*4882a593Smuzhiyun 	struct logo_part_header part_hdr;
91*4882a593Smuzhiyun 	struct grayscale_header img_hdr[14];
92*4882a593Smuzhiyun } __attribute__((packed));
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun struct input_img_info {
95*4882a593Smuzhiyun 	char path[256];
96*4882a593Smuzhiyun 	int logo_type;
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun  * Every part of logo.img must be aligned in RK_BLK_SIZE,
101*4882a593Smuzhiyun  * use macro aligned_in_blk to calculate the the real size
102*4882a593Smuzhiyun  */
103*4882a593Smuzhiyun #define RK_BLK_SIZE 512
104*4882a593Smuzhiyun #define ALIGN(x, y)	(((x) + (y) - 1) & ~((y) - 1))
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun struct input_img_info in_img_info[16];
107*4882a593Smuzhiyun uint32_t screen_w;
108*4882a593Smuzhiyun uint32_t screen_h;
109*4882a593Smuzhiyun static const char version[4] = "1.00";
110*4882a593Smuzhiyun static const char *PROG;
111*4882a593Smuzhiyun 
fix_path(const char * path)112*4882a593Smuzhiyun static const char *fix_path(const char *path)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	if (!memcmp(path, "./", 2))
115*4882a593Smuzhiyun 		return path + 2;
116*4882a593Smuzhiyun 	return path;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
print_version(void)119*4882a593Smuzhiyun static void print_version(void)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	printf("Version %s (zwp@rock-chips.com)\n", version);
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
usage(void)124*4882a593Smuzhiyun void usage(void)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	printf("Usage: %s [options] [arguments]\n\n", PROG);
127*4882a593Smuzhiyun 	print_version();
128*4882a593Smuzhiyun 	printf("\t --uboot-logo path");
129*4882a593Smuzhiyun 	printf("\t\t\t Pack uboot logo to logo.img from given path\n");
130*4882a593Smuzhiyun 	printf("\t --charge-logo path");
131*4882a593Smuzhiyun 	printf("\t\t\t Pack charge logo to logo.img from given path\n");
132*4882a593Smuzhiyun 	printf("\t --lowpower-logo path");
133*4882a593Smuzhiyun 	printf("\t\t\t Pack low power logo to logo.img from given path\n");
134*4882a593Smuzhiyun 	printf("\t --kernel-logo path");
135*4882a593Smuzhiyun 	printf("\t\t\t Pack low power logo to logo.img from given path\n");
136*4882a593Smuzhiyun 	printf("\t --poweroff-logo path");
137*4882a593Smuzhiyun 	printf("\t\t\t Pack power off logo to logo.img from given path\n");
138*4882a593Smuzhiyun 	printf("\t --output path");
139*4882a593Smuzhiyun 	printf("\t\t\t Output the grayscale image to path\n");
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
size_of_header(void)142*4882a593Smuzhiyun static inline int size_of_header(void)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	return ALIGN(sizeof(struct logo_info), RK_BLK_SIZE);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
size_of_one_image(void)147*4882a593Smuzhiyun static inline int size_of_one_image(void)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	return ALIGN((screen_w * screen_h) >> 1, RK_BLK_SIZE);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
get_logo_resolution(char * in_path,uint32_t * logo_width,uint32_t * logo_height)152*4882a593Smuzhiyun int get_logo_resolution(char *in_path, uint32_t *logo_width,
153*4882a593Smuzhiyun 			uint32_t *logo_height)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	struct bmp_header bmp_hdr;
156*4882a593Smuzhiyun 	FILE *file;
157*4882a593Smuzhiyun 	int size;
158*4882a593Smuzhiyun 	int ret = 0;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	if (!in_path)
161*4882a593Smuzhiyun 		fprintf(stderr, "Invalid bmp file path.\n");
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	file = fopen(in_path, "rb");
164*4882a593Smuzhiyun 	if (!file) {
165*4882a593Smuzhiyun 		fprintf(stderr, "File %s open failed.\n", in_path);
166*4882a593Smuzhiyun 		return -1;
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 	size = sizeof(struct bmp_header);
169*4882a593Smuzhiyun 	if (size != fread(&bmp_hdr, 1, size, file)) {
170*4882a593Smuzhiyun 		fprintf(stderr, "Incomplete read of file %s.\n", in_path);
171*4882a593Smuzhiyun 		ret = -1;
172*4882a593Smuzhiyun 		goto out;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 	if (!(bmp_hdr.signature[0] == 'B' &&
175*4882a593Smuzhiyun 	      bmp_hdr.signature[1] == 'M')) {
176*4882a593Smuzhiyun 		printf("cat not find bmp file\n");
177*4882a593Smuzhiyun 		ret = -1;
178*4882a593Smuzhiyun 		goto out;
179*4882a593Smuzhiyun 	}
180*4882a593Smuzhiyun 	*logo_width = bmp_hdr.width;
181*4882a593Smuzhiyun 	*logo_height = bmp_hdr.height;
182*4882a593Smuzhiyun 	fprintf(stderr, "logo resolution is %d x %d.\n",
183*4882a593Smuzhiyun 		*logo_width, *logo_height);
184*4882a593Smuzhiyun out:
185*4882a593Smuzhiyun 	fclose(file);
186*4882a593Smuzhiyun 	return ret;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun /*
190*4882a593Smuzhiyun  * The bmp pixel is scan from left-bottom to right-top
191*4882a593Smuzhiyun  */
convert_bmp_idx_to_gray_idx(int idx,uint32_t w,uint32_t h)192*4882a593Smuzhiyun int convert_bmp_idx_to_gray_idx(int idx, uint32_t w, uint32_t h)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	int row = h - (idx / w) - 1;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	return (row * w + idx % w) / 2;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
convert_one_image(char * in_path,void * out_buf,uint32_t offset,struct grayscale_header * gr_hdr,int type)199*4882a593Smuzhiyun int convert_one_image(char *in_path, void *out_buf, uint32_t offset,
200*4882a593Smuzhiyun 		      struct grayscale_header *gr_hdr, int type)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	struct bmp_image *bmp;
203*4882a593Smuzhiyun 	struct bmp_header *bmp_hdr;
204*4882a593Smuzhiyun 	FILE *file;
205*4882a593Smuzhiyun 	void *bmp_buf;
206*4882a593Smuzhiyun 	int size;
207*4882a593Smuzhiyun 	int ret = -1;
208*4882a593Smuzhiyun 	uint8_t *gr16_data = (uint8_t *)out_buf;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (!out_buf || !in_path) {
211*4882a593Smuzhiyun 		fprintf(stderr, "in_path or out_buf is NULL.\n");
212*4882a593Smuzhiyun 		return -1;
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	file = fopen(in_path, "rb");
216*4882a593Smuzhiyun 	if (!file) {
217*4882a593Smuzhiyun 		fprintf(stderr, "File %s open failed.\n", in_path);
218*4882a593Smuzhiyun 		return -1;
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	fseek(file, 0, SEEK_END);
222*4882a593Smuzhiyun 	size = ftell(file);
223*4882a593Smuzhiyun 	fseek(file, 0, SEEK_SET);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	bmp_buf = calloc(1, size);
226*4882a593Smuzhiyun 	if (!bmp_buf) {
227*4882a593Smuzhiyun 		fprintf(stderr, "Allocate memory of %d bytes failed.\n", size);
228*4882a593Smuzhiyun 		fclose(file);
229*4882a593Smuzhiyun 		return -1;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 	if (size != fread(bmp_buf, 1, size, file)) {
232*4882a593Smuzhiyun 		fprintf(stderr, "Incomplete read of file %s.\n", in_path);
233*4882a593Smuzhiyun 		goto out;
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	bmp = (struct bmp_image *)bmp_buf;
237*4882a593Smuzhiyun 	bmp_hdr = &bmp->hdr;
238*4882a593Smuzhiyun 	if (!(bmp_hdr->signature[0] == 'B' &&
239*4882a593Smuzhiyun 	      bmp_hdr->signature[1] == 'M')) {
240*4882a593Smuzhiyun 		printf("cat not find bmp file\n");
241*4882a593Smuzhiyun 		goto out;
242*4882a593Smuzhiyun 	}
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	if (size != le32_to_cpu(bmp_hdr->file_size)) {
245*4882a593Smuzhiyun 		fprintf(stderr, "Invalid BMP file size %d.\n",
246*4882a593Smuzhiyun 			le32_to_cpu(bmp_hdr->file_size));
247*4882a593Smuzhiyun 		goto out;
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun 	printf("bmp_hdr->width=%d, bmp_hdr->height=%d\n",
250*4882a593Smuzhiyun 	       bmp_hdr->width, bmp_hdr->height);
251*4882a593Smuzhiyun 	printf("screen_w=%d, screen_h=%d\n", screen_w, screen_h);
252*4882a593Smuzhiyun 	if (le32_to_cpu(bmp_hdr->width) != screen_w ||
253*4882a593Smuzhiyun 	    le32_to_cpu(bmp_hdr->height) != screen_h) {
254*4882a593Smuzhiyun 		fprintf(stderr, "The image size must same with others.\n");
255*4882a593Smuzhiyun 		goto out;
256*4882a593Smuzhiyun 	}
257*4882a593Smuzhiyun 	//write header
258*4882a593Smuzhiyun 	gr_hdr->magic[0] = 'G';
259*4882a593Smuzhiyun 	gr_hdr->magic[1] = 'R';
260*4882a593Smuzhiyun 	gr_hdr->magic[2] = '0';
261*4882a593Smuzhiyun 	gr_hdr->magic[3] = '4';
262*4882a593Smuzhiyun 	gr_hdr->x = 0;
263*4882a593Smuzhiyun 	gr_hdr->y = 0;
264*4882a593Smuzhiyun 	gr_hdr->w = screen_w;
265*4882a593Smuzhiyun 	gr_hdr->h = screen_h;
266*4882a593Smuzhiyun 	gr_hdr->logo_type = type;
267*4882a593Smuzhiyun 	gr_hdr->data_offset = offset;
268*4882a593Smuzhiyun 	gr_hdr->data_size = screen_w * screen_h / 2;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	printf("bmp depth is %d\n", bmp_hdr->bit_count);
271*4882a593Smuzhiyun 	//convert rgb to gray data, and write to output buffer
272*4882a593Smuzhiyun 	// the used algorithm please refer to below url:
273*4882a593Smuzhiyun 	// https://www.cnblogs.com/zhangjiansheng/p/6925722.html
274*4882a593Smuzhiyun 	// we use below algorithm:
275*4882a593Smuzhiyun 	// Gray = (R*19595 + G*38469 + B*7472) >> 16
276*4882a593Smuzhiyun 	switch (bmp_hdr->bit_count) {
277*4882a593Smuzhiyun 	case 16:{
278*4882a593Smuzhiyun 		struct pixel_u16 *color_u16;
279*4882a593Smuzhiyun 		int i;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 		color_u16 = (struct pixel_u16 *)bmp->color_table;
282*4882a593Smuzhiyun 		for (i = 0; i < screen_w * screen_h / 2; i++) {
283*4882a593Smuzhiyun 			struct pixel_u16 *pix1 = &color_u16[2 * i];
284*4882a593Smuzhiyun 			struct pixel_u16 *pix2 = &color_u16[2 * i + 1];
285*4882a593Smuzhiyun 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
286*4882a593Smuzhiyun 							    screen_h);
287*4882a593Smuzhiyun 			/*
288*4882a593Smuzhiyun 			 * the rgb value of pixel_u16 is 4 bits,
289*4882a593Smuzhiyun 			 * so the counted grayscale value is 4bit
290*4882a593Smuzhiyun 			 */
291*4882a593Smuzhiyun 			uint32_t gray_px1 = (pix1->red * 19595 +
292*4882a593Smuzhiyun 					     pix1->green * 38469 +
293*4882a593Smuzhiyun 					     pix1->blue * 7472) >> 16;
294*4882a593Smuzhiyun 			uint32_t gray_px2 = (pix2->red * 19595 +
295*4882a593Smuzhiyun 					     pix2->green * 38469 +
296*4882a593Smuzhiyun 					     pix2->blue * 7472) >> 16;
297*4882a593Smuzhiyun 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
298*4882a593Smuzhiyun 		}
299*4882a593Smuzhiyun 	}
300*4882a593Smuzhiyun 	break;
301*4882a593Smuzhiyun 	case 24: {
302*4882a593Smuzhiyun 		struct pixel_u24 *color_u24;
303*4882a593Smuzhiyun 		int i;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 		color_u24 = (struct pixel_u24 *)bmp->color_table;
306*4882a593Smuzhiyun 		for (i = 0; i < screen_w * screen_h / 2; i++) {
307*4882a593Smuzhiyun 			struct pixel_u24 *pix1 = &color_u24[2 * i];
308*4882a593Smuzhiyun 			struct pixel_u24 *pix2 = &color_u24[2 * i + 1];
309*4882a593Smuzhiyun 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
310*4882a593Smuzhiyun 							    screen_h);
311*4882a593Smuzhiyun 			/*
312*4882a593Smuzhiyun 			 * The rgb value of pixel_u24 is 8 bits,
313*4882a593Smuzhiyun 			 * so the counted grayscale
314*4882a593Smuzhiyun 			 * value need to divide into 16
315*4882a593Smuzhiyun 			 */
316*4882a593Smuzhiyun 			uint32_t gray_px1 = ((pix1->red * 19595 +
317*4882a593Smuzhiyun 					      pix1->green * 38469 +
318*4882a593Smuzhiyun 					      pix1->blue * 7472) >> 16) >> 4;
319*4882a593Smuzhiyun 			uint32_t gray_px2 = ((pix2->red * 19595 +
320*4882a593Smuzhiyun 					      pix2->green * 38469 +
321*4882a593Smuzhiyun 					      pix2->blue * 7472) >> 16) >> 4;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
324*4882a593Smuzhiyun 		}
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 	break;
327*4882a593Smuzhiyun 	case 32: {
328*4882a593Smuzhiyun 		struct pixel_u32 *color_u32;
329*4882a593Smuzhiyun 		int i;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 		color_u32 = (struct pixel_u32 *)bmp->color_table;
332*4882a593Smuzhiyun 		for (i = 0; i < screen_w * screen_h / 2; i++) {
333*4882a593Smuzhiyun 			struct pixel_u32 *pix1 = &color_u32[2 * i];
334*4882a593Smuzhiyun 			struct pixel_u32 *pix2 = &color_u32[2 * i + 1];
335*4882a593Smuzhiyun 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
336*4882a593Smuzhiyun 							    screen_h);
337*4882a593Smuzhiyun 			/*
338*4882a593Smuzhiyun 			 * The rgb value of pixel_u32 is 8 bits,
339*4882a593Smuzhiyun 			 * so the counted grayscale
340*4882a593Smuzhiyun 			 * value need to divide into 16
341*4882a593Smuzhiyun 			 */
342*4882a593Smuzhiyun 			uint32_t gray_px1 = ((pix1->red * 19595 +
343*4882a593Smuzhiyun 					      pix1->green * 38469 +
344*4882a593Smuzhiyun 					      pix1->blue * 7472) >> 16) >> 4;
345*4882a593Smuzhiyun 			uint32_t gray_px2 = ((pix2->red * 19595 +
346*4882a593Smuzhiyun 					      pix2->green * 38469 +
347*4882a593Smuzhiyun 					      pix2->blue * 7472) >> 16) >> 4;
348*4882a593Smuzhiyun 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
349*4882a593Smuzhiyun 		}
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 	break;
352*4882a593Smuzhiyun 	default:
353*4882a593Smuzhiyun 		ret = -1;
354*4882a593Smuzhiyun 		printf("Invalid bit count[%d],only support 16/24/32 bpp bmp\n",
355*4882a593Smuzhiyun 		       bmp_hdr->bit_count);
356*4882a593Smuzhiyun 	break;
357*4882a593Smuzhiyun 	}
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	fprintf(stderr, "Convert image success\n");
360*4882a593Smuzhiyun 	ret = 0;
361*4882a593Smuzhiyun out:
362*4882a593Smuzhiyun 	free(bmp_buf);
363*4882a593Smuzhiyun 	fclose(file);
364*4882a593Smuzhiyun 	return ret;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
init_grayscale_logo_buf(int logo_count,uint32_t size_one_image)367*4882a593Smuzhiyun void *init_grayscale_logo_buf(int logo_count, uint32_t size_one_image)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	int size;
370*4882a593Smuzhiyun 	void *out_buf;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	if (!logo_count) {
373*4882a593Smuzhiyun 		fprintf(stderr, "No input logo!\n");
374*4882a593Smuzhiyun 		return NULL;
375*4882a593Smuzhiyun 	}
376*4882a593Smuzhiyun 	size = size_of_header();
377*4882a593Smuzhiyun 	fprintf(stderr, "size of header in logo.img is %d\n", size);
378*4882a593Smuzhiyun 	//every pixel of the grayscale image is 4 bits
379*4882a593Smuzhiyun 	size += logo_count * size_one_image;
380*4882a593Smuzhiyun 	out_buf = calloc(1, size);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	return out_buf;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
deinit_grayscale_logo_buf(void * buf)385*4882a593Smuzhiyun void deinit_grayscale_logo_buf(void *buf)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	if (buf) {
388*4882a593Smuzhiyun 		free(buf);
389*4882a593Smuzhiyun 		buf = NULL;
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun 
main(int argc,char * argv[])393*4882a593Smuzhiyun int main(int argc, char *argv[])
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	char out_path[256] = {0};
396*4882a593Smuzhiyun 	void *out_buf;
397*4882a593Smuzhiyun 	int logo_count = 0;
398*4882a593Smuzhiyun 	int i;
399*4882a593Smuzhiyun 	int hdr_size, one_img_size, total_size;
400*4882a593Smuzhiyun 	int ret = -1;
401*4882a593Smuzhiyun 	struct logo_info *logo_hdr;
402*4882a593Smuzhiyun 	FILE *file;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun 	PROG = fix_path(argv[0]);
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	argc--, argv++;
407*4882a593Smuzhiyun 	while (argc > 0 && argv[0][0] == '-') {
408*4882a593Smuzhiyun 		/* it's a opt arg. */
409*4882a593Smuzhiyun 		const char *arg = argv[0];
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 		argc--, argv++;
412*4882a593Smuzhiyun 		if (!strcmp("-h", arg)) {
413*4882a593Smuzhiyun 			usage();
414*4882a593Smuzhiyun 			return 0;
415*4882a593Smuzhiyun 		}  else if (!strcmp("--charge-logo", arg)) {
416*4882a593Smuzhiyun 			int len, i;
417*4882a593Smuzhiyun 			/*
418*4882a593Smuzhiyun 			 * Charge logo are located in directory
419*4882a593Smuzhiyun 			 * u-boot/tools/images/eink/, there are 7
420*4882a593Smuzhiyun 			 * pictures to tell user the battery capacity
421*4882a593Smuzhiyun 			 * during charging
422*4882a593Smuzhiyun 			 */
423*4882a593Smuzhiyun 			for (i = 0; i < 7; i++) {
424*4882a593Smuzhiyun 				int logo_type = EINK_LOGO_CHARGING_0 << i;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 				len = strlen(argv[0]);
427*4882a593Smuzhiyun 				if (len > 256) {
428*4882a593Smuzhiyun 					fprintf(stderr,
429*4882a593Smuzhiyun 						"input charging logo path %s is too long.\n",
430*4882a593Smuzhiyun 						argv[0]);
431*4882a593Smuzhiyun 					return -1;
432*4882a593Smuzhiyun 				}
433*4882a593Smuzhiyun 				printf("charge logo path %s\n", argv[0]);
434*4882a593Smuzhiyun 				memcpy(in_img_info[logo_count].path,
435*4882a593Smuzhiyun 				       argv[0], len);
436*4882a593Smuzhiyun 				in_img_info[logo_count].logo_type = logo_type;
437*4882a593Smuzhiyun 				logo_count++;
438*4882a593Smuzhiyun 				argc--, argv++;
439*4882a593Smuzhiyun 			}
440*4882a593Smuzhiyun 		}  else if (!strcmp("--uboot-logo", arg)) {
441*4882a593Smuzhiyun 			int len = strlen(argv[0]);
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 			if (len > 256) {
444*4882a593Smuzhiyun 				printf("Uboot logo path %s is too long.\n",
445*4882a593Smuzhiyun 				       argv[0]);
446*4882a593Smuzhiyun 				return -1;
447*4882a593Smuzhiyun 			}
448*4882a593Smuzhiyun 			memcpy(in_img_info[logo_count].path, argv[0], len);
449*4882a593Smuzhiyun 			in_img_info[logo_count].logo_type = EINK_LOGO_UBOOT;
450*4882a593Smuzhiyun 			logo_count++;
451*4882a593Smuzhiyun 			argc--, argv++;
452*4882a593Smuzhiyun 		} else if (!strcmp("--kernel-logo", arg)) {
453*4882a593Smuzhiyun 			int len = strlen(argv[0]);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 			if (len > 256) {
456*4882a593Smuzhiyun 				printf("Kernel logo path %s is too long\n",
457*4882a593Smuzhiyun 				       argv[0]);
458*4882a593Smuzhiyun 				return -1;
459*4882a593Smuzhiyun 			}
460*4882a593Smuzhiyun 			memcpy(in_img_info[logo_count].path, argv[0], len);
461*4882a593Smuzhiyun 			in_img_info[logo_count].logo_type = EINK_LOGO_KERNEL;
462*4882a593Smuzhiyun 			logo_count++;
463*4882a593Smuzhiyun 			argc--, argv++;
464*4882a593Smuzhiyun 		} else if (!strcmp("--poweroff-logo", arg)) {
465*4882a593Smuzhiyun 			int len = strlen(argv[0]);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 			if (len > 256) {
468*4882a593Smuzhiyun 				printf("Poweroff logo path %s is too long\n",
469*4882a593Smuzhiyun 				       argv[0]);
470*4882a593Smuzhiyun 				return -1;
471*4882a593Smuzhiyun 			}
472*4882a593Smuzhiyun 			memcpy(in_img_info[logo_count].path, argv[0], len);
473*4882a593Smuzhiyun 			in_img_info[logo_count].logo_type = EINK_LOGO_POWEROFF;
474*4882a593Smuzhiyun 			logo_count++;
475*4882a593Smuzhiyun 			argc--, argv++;
476*4882a593Smuzhiyun 		}  else if (!strcmp("--screen-width", arg)) {
477*4882a593Smuzhiyun 			screen_w = strtoul(argv[0], NULL, 10);
478*4882a593Smuzhiyun 			argc--, argv++;
479*4882a593Smuzhiyun 		}  else if (!strcmp("--screen-height", arg)) {
480*4882a593Smuzhiyun 			screen_h = strtoul(argv[0], NULL, 10);
481*4882a593Smuzhiyun 			argc--, argv++;
482*4882a593Smuzhiyun 		}  else if (!strcmp("--output", arg)) {
483*4882a593Smuzhiyun 			int len = strlen(argv[0]);
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 			if (len > 256) {
486*4882a593Smuzhiyun 				printf("input output path %s is too long.\n",
487*4882a593Smuzhiyun 				       argv[0]);
488*4882a593Smuzhiyun 				return -1;
489*4882a593Smuzhiyun 			}
490*4882a593Smuzhiyun 			memcpy(out_path, argv[0], len);
491*4882a593Smuzhiyun 			argc--, argv++;
492*4882a593Smuzhiyun 		} else {
493*4882a593Smuzhiyun 			fprintf(stderr, "Unknown opt:%s", arg);
494*4882a593Smuzhiyun 			usage();
495*4882a593Smuzhiyun 			return -1;
496*4882a593Smuzhiyun 		}
497*4882a593Smuzhiyun 	}
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	ret = get_logo_resolution(in_img_info[0].path, &screen_w, &screen_h);
500*4882a593Smuzhiyun 	if (ret < 0) {
501*4882a593Smuzhiyun 		fprintf(stderr,
502*4882a593Smuzhiyun 			"Get height and width from logo image failed.\n");
503*4882a593Smuzhiyun 		usage();
504*4882a593Smuzhiyun 		return -1;
505*4882a593Smuzhiyun 	}
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	if (screen_w == 0 || screen_h == 0) {
508*4882a593Smuzhiyun 		fprintf(stderr,
509*4882a593Smuzhiyun 			"The screen weight and screen height must be set.\n");
510*4882a593Smuzhiyun 		usage();
511*4882a593Smuzhiyun 		return -1;
512*4882a593Smuzhiyun 	}
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	file = fopen(out_path, "wb+");
515*4882a593Smuzhiyun 	if (!file) {
516*4882a593Smuzhiyun 		fprintf(stderr, "File %s open failed.\n", out_path);
517*4882a593Smuzhiyun 		usage();
518*4882a593Smuzhiyun 		return -1;
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 	hdr_size = size_of_header();
521*4882a593Smuzhiyun 	one_img_size = size_of_one_image();
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	out_buf = init_grayscale_logo_buf(logo_count, one_img_size);
524*4882a593Smuzhiyun 	if (!out_buf) {
525*4882a593Smuzhiyun 		fprintf(stderr, "Can't malloc buffer for grayscale image.\n");
526*4882a593Smuzhiyun 		fclose(file);
527*4882a593Smuzhiyun 		return -1;
528*4882a593Smuzhiyun 	}
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	logo_hdr = (struct logo_info *)out_buf;
531*4882a593Smuzhiyun 	fprintf(stderr, "logo count is %d,one_img_size=%d,size=%d.\n",
532*4882a593Smuzhiyun 		logo_count, one_img_size, screen_w * screen_h / 2);
533*4882a593Smuzhiyun 	for (i = 0; i < logo_count; i++) {
534*4882a593Smuzhiyun 		char *in_path = in_img_info[i].path;
535*4882a593Smuzhiyun 		int type = in_img_info[i].logo_type;
536*4882a593Smuzhiyun 		void *img_buf;
537*4882a593Smuzhiyun 		int offset = hdr_size + i *  one_img_size;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 		img_buf = out_buf + offset;
540*4882a593Smuzhiyun 		printf("image[%d] start addr=0x%p\n", i, img_buf);
541*4882a593Smuzhiyun 		ret = convert_one_image(in_path, img_buf, offset,
542*4882a593Smuzhiyun 					&logo_hdr->img_hdr[i], type);
543*4882a593Smuzhiyun 		if (ret < 0) {
544*4882a593Smuzhiyun 			printf("Convert image[%d] failed, type is %d\n",
545*4882a593Smuzhiyun 			       i, type);
546*4882a593Smuzhiyun 			break;
547*4882a593Smuzhiyun 		}
548*4882a593Smuzhiyun 	}
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 	if (ret == 0) {
551*4882a593Smuzhiyun 		struct logo_part_header *part_hdr = &logo_hdr->part_hdr;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 		total_size = hdr_size + (i - 1) * one_img_size +
554*4882a593Smuzhiyun 				screen_h * screen_w / 2;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 		//convert success, write header data.
557*4882a593Smuzhiyun 		part_hdr->magic[0] = 'R';
558*4882a593Smuzhiyun 		part_hdr->magic[1] = 'K';
559*4882a593Smuzhiyun 		part_hdr->magic[2] = 'E';
560*4882a593Smuzhiyun 		part_hdr->magic[3] = 'L';
561*4882a593Smuzhiyun 		part_hdr->totoal_size = total_size;
562*4882a593Smuzhiyun 		part_hdr->screen_width = screen_w;
563*4882a593Smuzhiyun 		part_hdr->screen_height = screen_h;
564*4882a593Smuzhiyun 		part_hdr->logo_count = i;
565*4882a593Smuzhiyun 		printf("screen w=%d, h=%d, total_size=%d\n",
566*4882a593Smuzhiyun 		       screen_w, screen_h, total_size);
567*4882a593Smuzhiyun 		memcpy(part_hdr->version, version, 4);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 		// write to output file
570*4882a593Smuzhiyun 		ret = fwrite(out_buf, total_size, 1, file);
571*4882a593Smuzhiyun 		if (ret != 1)
572*4882a593Smuzhiyun 			fprintf(stderr, "write image to file %s failed\n",
573*4882a593Smuzhiyun 				out_path);
574*4882a593Smuzhiyun 	}
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	deinit_grayscale_logo_buf(out_buf);
577*4882a593Smuzhiyun 	ret = fclose(file);
578*4882a593Smuzhiyun 	if (ret != 0)
579*4882a593Smuzhiyun 		printf("Close file[%s] failed, err=%d\n", out_path, ret);
580*4882a593Smuzhiyun 	file = NULL;
581*4882a593Smuzhiyun 	return ret;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun 
584