xref: /rk3399_rockchip-uboot/tools/rockchip/bmp2gray16.c (revision 74b82d96352d663d36c285f7ac3c44c046222db1)
10466543cSWenping Zhang /*
20466543cSWenping Zhang  * (C) Copyright 2020 Rockchip Electronics Co., Ltd
30466543cSWenping Zhang  *
40466543cSWenping Zhang  * SPDX-License-Identifier:     GPL-2.0+
50466543cSWenping Zhang  * Author: Wenping Zhang <wenping.zhang@rock-chips.com>
60466543cSWenping Zhang  */
70466543cSWenping Zhang 
80466543cSWenping Zhang #include <stdio.h>
90466543cSWenping Zhang #include <stdlib.h>
100466543cSWenping Zhang #include <string.h>
110466543cSWenping Zhang #include <rk_eink.h>
120466543cSWenping Zhang 
130466543cSWenping Zhang struct  bmp_header {
140466543cSWenping Zhang 	/* Header */
150466543cSWenping Zhang 	char signature[2];
160466543cSWenping Zhang 	uint32_t	file_size;
170466543cSWenping Zhang 	uint32_t	reserved;
180466543cSWenping Zhang 	uint32_t	data_offset;
190466543cSWenping Zhang 	/* InfoHeader */
200466543cSWenping Zhang 	uint32_t	size;
210466543cSWenping Zhang 	uint32_t	width;
220466543cSWenping Zhang 	uint32_t	height;
230466543cSWenping Zhang 	uint16_t	planes;
240466543cSWenping Zhang 	uint16_t	bit_count;
250466543cSWenping Zhang 	uint32_t	compression;
260466543cSWenping Zhang 	uint32_t	image_size;
270466543cSWenping Zhang 	uint32_t	x_pixels_per_m;
280466543cSWenping Zhang 	uint32_t	y_pixels_per_m;
290466543cSWenping Zhang 	uint32_t	colors_used;
300466543cSWenping Zhang 	uint32_t	colors_important;
310466543cSWenping Zhang 	/* ColorTable */
320466543cSWenping Zhang } __attribute__((packed));
330466543cSWenping Zhang 
340466543cSWenping Zhang struct bmp_image {
350466543cSWenping Zhang 	struct bmp_header hdr;
360466543cSWenping Zhang 	uint8_t color_table[0];
370466543cSWenping Zhang };
380466543cSWenping Zhang 
390466543cSWenping Zhang struct pixel_u16 {
400466543cSWenping Zhang 	uint16_t blue  : 4,
410466543cSWenping Zhang 		green : 4,
420466543cSWenping Zhang 		red   : 4,
430466543cSWenping Zhang 		alpha : 4;
440466543cSWenping Zhang } __attribute__((packed));
450466543cSWenping Zhang 
460466543cSWenping Zhang struct pixel_u24 {
470466543cSWenping Zhang 	uint8_t blue;
480466543cSWenping Zhang 	uint8_t green;
490466543cSWenping Zhang 	uint8_t red;
500466543cSWenping Zhang } __attribute__((packed));
510466543cSWenping Zhang 
520466543cSWenping Zhang struct pixel_u32 {
530466543cSWenping Zhang 	uint8_t blue;
540466543cSWenping Zhang 	uint8_t green;
550466543cSWenping Zhang 	uint8_t red;
560466543cSWenping Zhang 	uint8_t alpha;
570466543cSWenping Zhang } __attribute__((packed));
580466543cSWenping Zhang 
590466543cSWenping Zhang //logo partition Header, 64byte
600466543cSWenping Zhang struct logo_part_header {
610466543cSWenping Zhang 	char magic[4]; /* must be "RKEL" */
620466543cSWenping Zhang 	uint32_t  totoal_size;
630466543cSWenping Zhang 	uint32_t  screen_width;
640466543cSWenping Zhang 	uint32_t  screen_height;
650466543cSWenping Zhang 	uint32_t  logo_count;
660466543cSWenping Zhang 	char  version[4];
670466543cSWenping Zhang 	uint32_t  rsv[10];
680466543cSWenping Zhang } __attribute__((packed));
690466543cSWenping Zhang 
700466543cSWenping Zhang // logo image header,32 byte
710466543cSWenping Zhang struct grayscale_header {
720466543cSWenping Zhang 	char magic[4]; /* must be "GR04" */
730466543cSWenping Zhang 	uint16_t x;
740466543cSWenping Zhang 	uint16_t y;
750466543cSWenping Zhang 	uint16_t w;
760466543cSWenping Zhang 	uint16_t h;
770466543cSWenping Zhang 	uint32_t logo_type;
780466543cSWenping Zhang 	uint32_t data_offset; /* image offset in byte */
790466543cSWenping Zhang 	uint32_t data_size; /* image size in byte */
800466543cSWenping Zhang 	uint32_t rsv[2];
810466543cSWenping Zhang } __attribute__((packed));
820466543cSWenping Zhang 
830466543cSWenping Zhang /*
840466543cSWenping Zhang  * The start address of logo image in logo.img must be aligned
850466543cSWenping Zhang  * in 512 bytes,so the header size must be times of 512 bytes.
860466543cSWenping Zhang  * Here we fix the size to 512 bytes, so the count of logo image
870466543cSWenping Zhang  * can only support up to 14.
880466543cSWenping Zhang  */
890466543cSWenping Zhang struct logo_info {
900466543cSWenping Zhang 	struct logo_part_header part_hdr;
910466543cSWenping Zhang 	struct grayscale_header img_hdr[14];
920466543cSWenping Zhang } __attribute__((packed));
930466543cSWenping Zhang 
940466543cSWenping Zhang struct input_img_info {
950466543cSWenping Zhang 	char path[256];
960466543cSWenping Zhang 	int logo_type;
970466543cSWenping Zhang };
980466543cSWenping Zhang 
990466543cSWenping Zhang /*
1000466543cSWenping Zhang  * Every part of logo.img must be aligned in RK_BLK_SIZE,
1010466543cSWenping Zhang  * use macro aligned_in_blk to calculate the the real size
1020466543cSWenping Zhang  */
1030466543cSWenping Zhang #define RK_BLK_SIZE 512
1040466543cSWenping Zhang #define ALIGN(x, y)	(((x) + (y) - 1) & ~((y) - 1))
1050466543cSWenping Zhang 
1060466543cSWenping Zhang struct input_img_info in_img_info[16];
1070466543cSWenping Zhang uint32_t screen_w;
1080466543cSWenping Zhang uint32_t screen_h;
1090466543cSWenping Zhang static const char version[4] = "1.00";
1100466543cSWenping Zhang static const char *PROG;
1110466543cSWenping Zhang 
fix_path(const char * path)1120466543cSWenping Zhang static const char *fix_path(const char *path)
1130466543cSWenping Zhang {
1140466543cSWenping Zhang 	if (!memcmp(path, "./", 2))
1150466543cSWenping Zhang 		return path + 2;
1160466543cSWenping Zhang 	return path;
1170466543cSWenping Zhang }
1180466543cSWenping Zhang 
print_version(void)1190466543cSWenping Zhang static void print_version(void)
1200466543cSWenping Zhang {
1210466543cSWenping Zhang 	printf("Version %s (zwp@rock-chips.com)\n", version);
1220466543cSWenping Zhang }
1230466543cSWenping Zhang 
usage(void)1240466543cSWenping Zhang void usage(void)
1250466543cSWenping Zhang {
1260466543cSWenping Zhang 	printf("Usage: %s [options] [arguments]\n\n", PROG);
1270466543cSWenping Zhang 	print_version();
1280466543cSWenping Zhang 	printf("\t --uboot-logo path");
1290466543cSWenping Zhang 	printf("\t\t\t Pack uboot logo to logo.img from given path\n");
1300466543cSWenping Zhang 	printf("\t --charge-logo path");
1310466543cSWenping Zhang 	printf("\t\t\t Pack charge logo to logo.img from given path\n");
1320466543cSWenping Zhang 	printf("\t --lowpower-logo path");
1330466543cSWenping Zhang 	printf("\t\t\t Pack low power logo to logo.img from given path\n");
1340466543cSWenping Zhang 	printf("\t --kernel-logo path");
1350466543cSWenping Zhang 	printf("\t\t\t Pack low power logo to logo.img from given path\n");
136*74b82d96SZorro Liu 	printf("\t --poweroff-logo path");
137*74b82d96SZorro Liu 	printf("\t\t\t Pack power off logo to logo.img from given path\n");
1380466543cSWenping Zhang 	printf("\t --output path");
1390466543cSWenping Zhang 	printf("\t\t\t Output the grayscale image to path\n");
1400466543cSWenping Zhang }
1410466543cSWenping Zhang 
size_of_header(void)1420466543cSWenping Zhang static inline int size_of_header(void)
1430466543cSWenping Zhang {
1440466543cSWenping Zhang 	return ALIGN(sizeof(struct logo_info), RK_BLK_SIZE);
1450466543cSWenping Zhang }
1460466543cSWenping Zhang 
size_of_one_image(void)1470466543cSWenping Zhang static inline int size_of_one_image(void)
1480466543cSWenping Zhang {
1490466543cSWenping Zhang 	return ALIGN((screen_w * screen_h) >> 1, RK_BLK_SIZE);
1500466543cSWenping Zhang }
1510466543cSWenping Zhang 
get_logo_resolution(char * in_path,uint32_t * logo_width,uint32_t * logo_height)1520466543cSWenping Zhang int get_logo_resolution(char *in_path, uint32_t *logo_width,
1530466543cSWenping Zhang 			uint32_t *logo_height)
1540466543cSWenping Zhang {
1550466543cSWenping Zhang 	struct bmp_header bmp_hdr;
1560466543cSWenping Zhang 	FILE *file;
1570466543cSWenping Zhang 	int size;
1580466543cSWenping Zhang 	int ret = 0;
1590466543cSWenping Zhang 
1600466543cSWenping Zhang 	if (!in_path)
1610466543cSWenping Zhang 		fprintf(stderr, "Invalid bmp file path.\n");
1620466543cSWenping Zhang 
1630466543cSWenping Zhang 	file = fopen(in_path, "rb");
1640466543cSWenping Zhang 	if (!file) {
1650466543cSWenping Zhang 		fprintf(stderr, "File %s open failed.\n", in_path);
1660466543cSWenping Zhang 		return -1;
1670466543cSWenping Zhang 	}
1680466543cSWenping Zhang 	size = sizeof(struct bmp_header);
1690466543cSWenping Zhang 	if (size != fread(&bmp_hdr, 1, size, file)) {
1700466543cSWenping Zhang 		fprintf(stderr, "Incomplete read of file %s.\n", in_path);
1710466543cSWenping Zhang 		ret = -1;
1720466543cSWenping Zhang 		goto out;
1730466543cSWenping Zhang 	}
1740466543cSWenping Zhang 	if (!(bmp_hdr.signature[0] == 'B' &&
1750466543cSWenping Zhang 	      bmp_hdr.signature[1] == 'M')) {
1760466543cSWenping Zhang 		printf("cat not find bmp file\n");
1770466543cSWenping Zhang 		ret = -1;
1780466543cSWenping Zhang 		goto out;
1790466543cSWenping Zhang 	}
1800466543cSWenping Zhang 	*logo_width = bmp_hdr.width;
1810466543cSWenping Zhang 	*logo_height = bmp_hdr.height;
1820466543cSWenping Zhang 	fprintf(stderr, "logo resolution is %d x %d.\n",
1830466543cSWenping Zhang 		*logo_width, *logo_height);
1840466543cSWenping Zhang out:
1850466543cSWenping Zhang 	fclose(file);
1860466543cSWenping Zhang 	return ret;
1870466543cSWenping Zhang }
1880466543cSWenping Zhang 
1890466543cSWenping Zhang /*
1900466543cSWenping Zhang  * The bmp pixel is scan from left-bottom to right-top
1910466543cSWenping Zhang  */
convert_bmp_idx_to_gray_idx(int idx,uint32_t w,uint32_t h)1920466543cSWenping Zhang int convert_bmp_idx_to_gray_idx(int idx, uint32_t w, uint32_t h)
1930466543cSWenping Zhang {
1940466543cSWenping Zhang 	int row = h - (idx / w) - 1;
1950466543cSWenping Zhang 
1960466543cSWenping Zhang 	return (row * w + idx % w) / 2;
1970466543cSWenping Zhang }
1980466543cSWenping Zhang 
convert_one_image(char * in_path,void * out_buf,uint32_t offset,struct grayscale_header * gr_hdr,int type)1990466543cSWenping Zhang int convert_one_image(char *in_path, void *out_buf, uint32_t offset,
2000466543cSWenping Zhang 		      struct grayscale_header *gr_hdr, int type)
2010466543cSWenping Zhang {
2020466543cSWenping Zhang 	struct bmp_image *bmp;
2030466543cSWenping Zhang 	struct bmp_header *bmp_hdr;
2040466543cSWenping Zhang 	FILE *file;
2050466543cSWenping Zhang 	void *bmp_buf;
2060466543cSWenping Zhang 	int size;
2070466543cSWenping Zhang 	int ret = -1;
2080466543cSWenping Zhang 	uint8_t *gr16_data = (uint8_t *)out_buf;
2090466543cSWenping Zhang 
2100466543cSWenping Zhang 	if (!out_buf || !in_path) {
2110466543cSWenping Zhang 		fprintf(stderr, "in_path or out_buf is NULL.\n");
2120466543cSWenping Zhang 		return -1;
2130466543cSWenping Zhang 	}
2140466543cSWenping Zhang 
2150466543cSWenping Zhang 	file = fopen(in_path, "rb");
2160466543cSWenping Zhang 	if (!file) {
2170466543cSWenping Zhang 		fprintf(stderr, "File %s open failed.\n", in_path);
2180466543cSWenping Zhang 		return -1;
2190466543cSWenping Zhang 	}
2200466543cSWenping Zhang 
2210466543cSWenping Zhang 	fseek(file, 0, SEEK_END);
2220466543cSWenping Zhang 	size = ftell(file);
2230466543cSWenping Zhang 	fseek(file, 0, SEEK_SET);
2240466543cSWenping Zhang 
2250466543cSWenping Zhang 	bmp_buf = calloc(1, size);
2260466543cSWenping Zhang 	if (!bmp_buf) {
2270466543cSWenping Zhang 		fprintf(stderr, "Allocate memory of %d bytes failed.\n", size);
2280466543cSWenping Zhang 		fclose(file);
2290466543cSWenping Zhang 		return -1;
2300466543cSWenping Zhang 	}
2310466543cSWenping Zhang 	if (size != fread(bmp_buf, 1, size, file)) {
2320466543cSWenping Zhang 		fprintf(stderr, "Incomplete read of file %s.\n", in_path);
2330466543cSWenping Zhang 		goto out;
2340466543cSWenping Zhang 	}
2350466543cSWenping Zhang 
2360466543cSWenping Zhang 	bmp = (struct bmp_image *)bmp_buf;
2370466543cSWenping Zhang 	bmp_hdr = &bmp->hdr;
2380466543cSWenping Zhang 	if (!(bmp_hdr->signature[0] == 'B' &&
2390466543cSWenping Zhang 	      bmp_hdr->signature[1] == 'M')) {
2400466543cSWenping Zhang 		printf("cat not find bmp file\n");
2410466543cSWenping Zhang 		goto out;
2420466543cSWenping Zhang 	}
2430466543cSWenping Zhang 
2440466543cSWenping Zhang 	if (size != le32_to_cpu(bmp_hdr->file_size)) {
2450466543cSWenping Zhang 		fprintf(stderr, "Invalid BMP file size %d.\n",
2460466543cSWenping Zhang 			le32_to_cpu(bmp_hdr->file_size));
2470466543cSWenping Zhang 		goto out;
2480466543cSWenping Zhang 	}
2490466543cSWenping Zhang 	printf("bmp_hdr->width=%d, bmp_hdr->height=%d\n",
2500466543cSWenping Zhang 	       bmp_hdr->width, bmp_hdr->height);
2510466543cSWenping Zhang 	printf("screen_w=%d, screen_h=%d\n", screen_w, screen_h);
2520466543cSWenping Zhang 	if (le32_to_cpu(bmp_hdr->width) != screen_w ||
2530466543cSWenping Zhang 	    le32_to_cpu(bmp_hdr->height) != screen_h) {
2540466543cSWenping Zhang 		fprintf(stderr, "The image size must same with others.\n");
2550466543cSWenping Zhang 		goto out;
2560466543cSWenping Zhang 	}
2570466543cSWenping Zhang 	//write header
2580466543cSWenping Zhang 	gr_hdr->magic[0] = 'G';
2590466543cSWenping Zhang 	gr_hdr->magic[1] = 'R';
2600466543cSWenping Zhang 	gr_hdr->magic[2] = '0';
2610466543cSWenping Zhang 	gr_hdr->magic[3] = '4';
2620466543cSWenping Zhang 	gr_hdr->x = 0;
2630466543cSWenping Zhang 	gr_hdr->y = 0;
2640466543cSWenping Zhang 	gr_hdr->w = screen_w;
2650466543cSWenping Zhang 	gr_hdr->h = screen_h;
2660466543cSWenping Zhang 	gr_hdr->logo_type = type;
2670466543cSWenping Zhang 	gr_hdr->data_offset = offset;
2680466543cSWenping Zhang 	gr_hdr->data_size = screen_w * screen_h / 2;
2690466543cSWenping Zhang 
2700466543cSWenping Zhang 	printf("bmp depth is %d\n", bmp_hdr->bit_count);
2710466543cSWenping Zhang 	//convert rgb to gray data, and write to output buffer
2720466543cSWenping Zhang 	// the used algorithm please refer to below url:
2730466543cSWenping Zhang 	// https://www.cnblogs.com/zhangjiansheng/p/6925722.html
2740466543cSWenping Zhang 	// we use below algorithm:
2750466543cSWenping Zhang 	// Gray = (R*19595 + G*38469 + B*7472) >> 16
2760466543cSWenping Zhang 	switch (bmp_hdr->bit_count) {
2770466543cSWenping Zhang 	case 16:{
2780466543cSWenping Zhang 		struct pixel_u16 *color_u16;
2790466543cSWenping Zhang 		int i;
2800466543cSWenping Zhang 
2810466543cSWenping Zhang 		color_u16 = (struct pixel_u16 *)bmp->color_table;
2820466543cSWenping Zhang 		for (i = 0; i < screen_w * screen_h / 2; i++) {
2830466543cSWenping Zhang 			struct pixel_u16 *pix1 = &color_u16[2 * i];
2840466543cSWenping Zhang 			struct pixel_u16 *pix2 = &color_u16[2 * i + 1];
2850466543cSWenping Zhang 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
2860466543cSWenping Zhang 							    screen_h);
2870466543cSWenping Zhang 			/*
2880466543cSWenping Zhang 			 * the rgb value of pixel_u16 is 4 bits,
2890466543cSWenping Zhang 			 * so the counted grayscale value is 4bit
2900466543cSWenping Zhang 			 */
2910466543cSWenping Zhang 			uint32_t gray_px1 = (pix1->red * 19595 +
2920466543cSWenping Zhang 					     pix1->green * 38469 +
2930466543cSWenping Zhang 					     pix1->blue * 7472) >> 16;
2940466543cSWenping Zhang 			uint32_t gray_px2 = (pix2->red * 19595 +
2950466543cSWenping Zhang 					     pix2->green * 38469 +
2960466543cSWenping Zhang 					     pix2->blue * 7472) >> 16;
2970466543cSWenping Zhang 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
2980466543cSWenping Zhang 		}
2990466543cSWenping Zhang 	}
3000466543cSWenping Zhang 	break;
3010466543cSWenping Zhang 	case 24: {
3020466543cSWenping Zhang 		struct pixel_u24 *color_u24;
3030466543cSWenping Zhang 		int i;
3040466543cSWenping Zhang 
3050466543cSWenping Zhang 		color_u24 = (struct pixel_u24 *)bmp->color_table;
3060466543cSWenping Zhang 		for (i = 0; i < screen_w * screen_h / 2; i++) {
3070466543cSWenping Zhang 			struct pixel_u24 *pix1 = &color_u24[2 * i];
3080466543cSWenping Zhang 			struct pixel_u24 *pix2 = &color_u24[2 * i + 1];
3090466543cSWenping Zhang 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
3100466543cSWenping Zhang 							    screen_h);
3110466543cSWenping Zhang 			/*
3120466543cSWenping Zhang 			 * The rgb value of pixel_u24 is 8 bits,
3130466543cSWenping Zhang 			 * so the counted grayscale
3140466543cSWenping Zhang 			 * value need to divide into 16
3150466543cSWenping Zhang 			 */
3160466543cSWenping Zhang 			uint32_t gray_px1 = ((pix1->red * 19595 +
3170466543cSWenping Zhang 					      pix1->green * 38469 +
3180466543cSWenping Zhang 					      pix1->blue * 7472) >> 16) >> 4;
3190466543cSWenping Zhang 			uint32_t gray_px2 = ((pix2->red * 19595 +
3200466543cSWenping Zhang 					      pix2->green * 38469 +
3210466543cSWenping Zhang 					      pix2->blue * 7472) >> 16) >> 4;
3220466543cSWenping Zhang 
3230466543cSWenping Zhang 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
3240466543cSWenping Zhang 		}
3250466543cSWenping Zhang 	}
3260466543cSWenping Zhang 	break;
3270466543cSWenping Zhang 	case 32: {
3280466543cSWenping Zhang 		struct pixel_u32 *color_u32;
3290466543cSWenping Zhang 		int i;
3300466543cSWenping Zhang 
3310466543cSWenping Zhang 		color_u32 = (struct pixel_u32 *)bmp->color_table;
3320466543cSWenping Zhang 		for (i = 0; i < screen_w * screen_h / 2; i++) {
3330466543cSWenping Zhang 			struct pixel_u32 *pix1 = &color_u32[2 * i];
3340466543cSWenping Zhang 			struct pixel_u32 *pix2 = &color_u32[2 * i + 1];
3350466543cSWenping Zhang 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
3360466543cSWenping Zhang 							    screen_h);
3370466543cSWenping Zhang 			/*
3380466543cSWenping Zhang 			 * The rgb value of pixel_u32 is 8 bits,
3390466543cSWenping Zhang 			 * so the counted grayscale
3400466543cSWenping Zhang 			 * value need to divide into 16
3410466543cSWenping Zhang 			 */
3420466543cSWenping Zhang 			uint32_t gray_px1 = ((pix1->red * 19595 +
3430466543cSWenping Zhang 					      pix1->green * 38469 +
3440466543cSWenping Zhang 					      pix1->blue * 7472) >> 16) >> 4;
3450466543cSWenping Zhang 			uint32_t gray_px2 = ((pix2->red * 19595 +
3460466543cSWenping Zhang 					      pix2->green * 38469 +
3470466543cSWenping Zhang 					      pix2->blue * 7472) >> 16) >> 4;
3480466543cSWenping Zhang 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
3490466543cSWenping Zhang 		}
3500466543cSWenping Zhang 	}
3510466543cSWenping Zhang 	break;
3520466543cSWenping Zhang 	default:
3530466543cSWenping Zhang 		ret = -1;
3540466543cSWenping Zhang 		printf("Invalid bit count[%d],only support 16/24/32 bpp bmp\n",
3550466543cSWenping Zhang 		       bmp_hdr->bit_count);
3560466543cSWenping Zhang 	break;
3570466543cSWenping Zhang 	}
3580466543cSWenping Zhang 
3590466543cSWenping Zhang 	fprintf(stderr, "Convert image success\n");
3600466543cSWenping Zhang 	ret = 0;
3610466543cSWenping Zhang out:
3620466543cSWenping Zhang 	free(bmp_buf);
3630466543cSWenping Zhang 	fclose(file);
3640466543cSWenping Zhang 	return ret;
3650466543cSWenping Zhang }
3660466543cSWenping Zhang 
init_grayscale_logo_buf(int logo_count,uint32_t size_one_image)367e091b6c9SWenping Zhang void *init_grayscale_logo_buf(int logo_count, uint32_t size_one_image)
3680466543cSWenping Zhang {
3690466543cSWenping Zhang 	int size;
3700466543cSWenping Zhang 	void *out_buf;
3710466543cSWenping Zhang 
3720466543cSWenping Zhang 	if (!logo_count) {
3730466543cSWenping Zhang 		fprintf(stderr, "No input logo!\n");
3740466543cSWenping Zhang 		return NULL;
3750466543cSWenping Zhang 	}
3760466543cSWenping Zhang 	size = size_of_header();
3770466543cSWenping Zhang 	fprintf(stderr, "size of header in logo.img is %d\n", size);
3780466543cSWenping Zhang 	//every pixel of the grayscale image is 4 bits
379e091b6c9SWenping Zhang 	size += logo_count * size_one_image;
3800466543cSWenping Zhang 	out_buf = calloc(1, size);
3810466543cSWenping Zhang 
3820466543cSWenping Zhang 	return out_buf;
3830466543cSWenping Zhang }
3840466543cSWenping Zhang 
deinit_grayscale_logo_buf(void * buf)3850466543cSWenping Zhang void deinit_grayscale_logo_buf(void *buf)
3860466543cSWenping Zhang {
3870466543cSWenping Zhang 	if (buf) {
3880466543cSWenping Zhang 		free(buf);
3890466543cSWenping Zhang 		buf = NULL;
3900466543cSWenping Zhang 	}
3910466543cSWenping Zhang }
3920466543cSWenping Zhang 
main(int argc,char * argv[])3930466543cSWenping Zhang int main(int argc, char *argv[])
3940466543cSWenping Zhang {
3950466543cSWenping Zhang 	char out_path[256] = {0};
3960466543cSWenping Zhang 	void *out_buf;
3970466543cSWenping Zhang 	int logo_count = 0;
3980466543cSWenping Zhang 	int i;
3990466543cSWenping Zhang 	int hdr_size, one_img_size, total_size;
4000466543cSWenping Zhang 	int ret = -1;
4010466543cSWenping Zhang 	struct logo_info *logo_hdr;
4020466543cSWenping Zhang 	FILE *file;
4030466543cSWenping Zhang 
4040466543cSWenping Zhang 	PROG = fix_path(argv[0]);
4050466543cSWenping Zhang 
4060466543cSWenping Zhang 	argc--, argv++;
4070466543cSWenping Zhang 	while (argc > 0 && argv[0][0] == '-') {
4080466543cSWenping Zhang 		/* it's a opt arg. */
4090466543cSWenping Zhang 		const char *arg = argv[0];
4100466543cSWenping Zhang 
4110466543cSWenping Zhang 		argc--, argv++;
4120466543cSWenping Zhang 		if (!strcmp("-h", arg)) {
4130466543cSWenping Zhang 			usage();
4140466543cSWenping Zhang 			return 0;
4150466543cSWenping Zhang 		}  else if (!strcmp("--charge-logo", arg)) {
4160466543cSWenping Zhang 			int len, i;
4170466543cSWenping Zhang 			/*
4180466543cSWenping Zhang 			 * Charge logo are located in directory
4190466543cSWenping Zhang 			 * u-boot/tools/images/eink/, there are 7
4200466543cSWenping Zhang 			 * pictures to tell user the battery capacity
4210466543cSWenping Zhang 			 * during charging
4220466543cSWenping Zhang 			 */
4230466543cSWenping Zhang 			for (i = 0; i < 7; i++) {
4240466543cSWenping Zhang 				int logo_type = EINK_LOGO_CHARGING_0 << i;
4250466543cSWenping Zhang 
4260466543cSWenping Zhang 				len = strlen(argv[0]);
4270466543cSWenping Zhang 				if (len > 256) {
4280466543cSWenping Zhang 					fprintf(stderr,
4290466543cSWenping Zhang 						"input charging logo path %s is too long.\n",
4300466543cSWenping Zhang 						argv[0]);
4310466543cSWenping Zhang 					return -1;
4320466543cSWenping Zhang 				}
4330466543cSWenping Zhang 				printf("charge logo path %s\n", argv[0]);
4340466543cSWenping Zhang 				memcpy(in_img_info[logo_count].path,
4350466543cSWenping Zhang 				       argv[0], len);
4360466543cSWenping Zhang 				in_img_info[logo_count].logo_type = logo_type;
4370466543cSWenping Zhang 				logo_count++;
4380466543cSWenping Zhang 				argc--, argv++;
4390466543cSWenping Zhang 			}
4400466543cSWenping Zhang 		}  else if (!strcmp("--uboot-logo", arg)) {
4410466543cSWenping Zhang 			int len = strlen(argv[0]);
4420466543cSWenping Zhang 
4430466543cSWenping Zhang 			if (len > 256) {
4440466543cSWenping Zhang 				printf("Uboot logo path %s is too long.\n",
4450466543cSWenping Zhang 				       argv[0]);
4460466543cSWenping Zhang 				return -1;
4470466543cSWenping Zhang 			}
4480466543cSWenping Zhang 			memcpy(in_img_info[logo_count].path, argv[0], len);
4490466543cSWenping Zhang 			in_img_info[logo_count].logo_type = EINK_LOGO_UBOOT;
4500466543cSWenping Zhang 			logo_count++;
4510466543cSWenping Zhang 			argc--, argv++;
4520466543cSWenping Zhang 		} else if (!strcmp("--kernel-logo", arg)) {
4530466543cSWenping Zhang 			int len = strlen(argv[0]);
4540466543cSWenping Zhang 
4550466543cSWenping Zhang 			if (len > 256) {
4560466543cSWenping Zhang 				printf("Kernel logo path %s is too long\n",
4570466543cSWenping Zhang 				       argv[0]);
4580466543cSWenping Zhang 				return -1;
4590466543cSWenping Zhang 			}
4600466543cSWenping Zhang 			memcpy(in_img_info[logo_count].path, argv[0], len);
4610466543cSWenping Zhang 			in_img_info[logo_count].logo_type = EINK_LOGO_KERNEL;
4620466543cSWenping Zhang 			logo_count++;
4630466543cSWenping Zhang 			argc--, argv++;
464*74b82d96SZorro Liu 		} else if (!strcmp("--poweroff-logo", arg)) {
465*74b82d96SZorro Liu 			int len = strlen(argv[0]);
466*74b82d96SZorro Liu 
467*74b82d96SZorro Liu 			if (len > 256) {
468*74b82d96SZorro Liu 				printf("Poweroff logo path %s is too long\n",
469*74b82d96SZorro Liu 				       argv[0]);
470*74b82d96SZorro Liu 				return -1;
471*74b82d96SZorro Liu 			}
472*74b82d96SZorro Liu 			memcpy(in_img_info[logo_count].path, argv[0], len);
473*74b82d96SZorro Liu 			in_img_info[logo_count].logo_type = EINK_LOGO_POWEROFF;
474*74b82d96SZorro Liu 			logo_count++;
475*74b82d96SZorro Liu 			argc--, argv++;
4760466543cSWenping Zhang 		}  else if (!strcmp("--screen-width", arg)) {
4770466543cSWenping Zhang 			screen_w = strtoul(argv[0], NULL, 10);
4780466543cSWenping Zhang 			argc--, argv++;
4790466543cSWenping Zhang 		}  else if (!strcmp("--screen-height", arg)) {
4800466543cSWenping Zhang 			screen_h = strtoul(argv[0], NULL, 10);
4810466543cSWenping Zhang 			argc--, argv++;
4820466543cSWenping Zhang 		}  else if (!strcmp("--output", arg)) {
4830466543cSWenping Zhang 			int len = strlen(argv[0]);
4840466543cSWenping Zhang 
4850466543cSWenping Zhang 			if (len > 256) {
4860466543cSWenping Zhang 				printf("input output path %s is too long.\n",
4870466543cSWenping Zhang 				       argv[0]);
4880466543cSWenping Zhang 				return -1;
4890466543cSWenping Zhang 			}
4900466543cSWenping Zhang 			memcpy(out_path, argv[0], len);
4910466543cSWenping Zhang 			argc--, argv++;
4920466543cSWenping Zhang 		} else {
4930466543cSWenping Zhang 			fprintf(stderr, "Unknown opt:%s", arg);
4940466543cSWenping Zhang 			usage();
4950466543cSWenping Zhang 			return -1;
4960466543cSWenping Zhang 		}
4970466543cSWenping Zhang 	}
4980466543cSWenping Zhang 
4990466543cSWenping Zhang 	ret = get_logo_resolution(in_img_info[0].path, &screen_w, &screen_h);
5000466543cSWenping Zhang 	if (ret < 0) {
5010466543cSWenping Zhang 		fprintf(stderr,
5020466543cSWenping Zhang 			"Get height and width from logo image failed.\n");
5030466543cSWenping Zhang 		usage();
5040466543cSWenping Zhang 		return -1;
5050466543cSWenping Zhang 	}
5060466543cSWenping Zhang 
5070466543cSWenping Zhang 	if (screen_w == 0 || screen_h == 0) {
5080466543cSWenping Zhang 		fprintf(stderr,
5090466543cSWenping Zhang 			"The screen weight and screen height must be set.\n");
5100466543cSWenping Zhang 		usage();
5110466543cSWenping Zhang 		return -1;
5120466543cSWenping Zhang 	}
5130466543cSWenping Zhang 
5140466543cSWenping Zhang 	file = fopen(out_path, "wb+");
5150466543cSWenping Zhang 	if (!file) {
5160466543cSWenping Zhang 		fprintf(stderr, "File %s open failed.\n", out_path);
5170466543cSWenping Zhang 		usage();
5180466543cSWenping Zhang 		return -1;
5190466543cSWenping Zhang 	}
520e091b6c9SWenping Zhang 	hdr_size = size_of_header();
521e091b6c9SWenping Zhang 	one_img_size = size_of_one_image();
5220466543cSWenping Zhang 
523e091b6c9SWenping Zhang 	out_buf = init_grayscale_logo_buf(logo_count, one_img_size);
5240466543cSWenping Zhang 	if (!out_buf) {
5250466543cSWenping Zhang 		fprintf(stderr, "Can't malloc buffer for grayscale image.\n");
5260466543cSWenping Zhang 		fclose(file);
5270466543cSWenping Zhang 		return -1;
5280466543cSWenping Zhang 	}
5290466543cSWenping Zhang 
5300466543cSWenping Zhang 	logo_hdr = (struct logo_info *)out_buf;
5310466543cSWenping Zhang 	fprintf(stderr, "logo count is %d,one_img_size=%d,size=%d.\n",
5320466543cSWenping Zhang 		logo_count, one_img_size, screen_w * screen_h / 2);
5330466543cSWenping Zhang 	for (i = 0; i < logo_count; i++) {
5340466543cSWenping Zhang 		char *in_path = in_img_info[i].path;
5350466543cSWenping Zhang 		int type = in_img_info[i].logo_type;
5360466543cSWenping Zhang 		void *img_buf;
5370466543cSWenping Zhang 		int offset = hdr_size + i *  one_img_size;
5380466543cSWenping Zhang 
5390466543cSWenping Zhang 		img_buf = out_buf + offset;
5400466543cSWenping Zhang 		printf("image[%d] start addr=0x%p\n", i, img_buf);
5410466543cSWenping Zhang 		ret = convert_one_image(in_path, img_buf, offset,
5420466543cSWenping Zhang 					&logo_hdr->img_hdr[i], type);
5430466543cSWenping Zhang 		if (ret < 0) {
5440466543cSWenping Zhang 			printf("Convert image[%d] failed, type is %d\n",
5450466543cSWenping Zhang 			       i, type);
5460466543cSWenping Zhang 			break;
5470466543cSWenping Zhang 		}
5480466543cSWenping Zhang 	}
5490466543cSWenping Zhang 
5500466543cSWenping Zhang 	if (ret == 0) {
5510466543cSWenping Zhang 		struct logo_part_header *part_hdr = &logo_hdr->part_hdr;
5520466543cSWenping Zhang 
5530466543cSWenping Zhang 		total_size = hdr_size + (i - 1) * one_img_size +
5540466543cSWenping Zhang 				screen_h * screen_w / 2;
5550466543cSWenping Zhang 
5560466543cSWenping Zhang 		//convert success, write header data.
5570466543cSWenping Zhang 		part_hdr->magic[0] = 'R';
5580466543cSWenping Zhang 		part_hdr->magic[1] = 'K';
5590466543cSWenping Zhang 		part_hdr->magic[2] = 'E';
5600466543cSWenping Zhang 		part_hdr->magic[3] = 'L';
5610466543cSWenping Zhang 		part_hdr->totoal_size = total_size;
5620466543cSWenping Zhang 		part_hdr->screen_width = screen_w;
5630466543cSWenping Zhang 		part_hdr->screen_height = screen_h;
5640466543cSWenping Zhang 		part_hdr->logo_count = i;
5650466543cSWenping Zhang 		printf("screen w=%d, h=%d, total_size=%d\n",
5660466543cSWenping Zhang 		       screen_w, screen_h, total_size);
5670466543cSWenping Zhang 		memcpy(part_hdr->version, version, 4);
5680466543cSWenping Zhang 
5690466543cSWenping Zhang 		// write to output file
5700466543cSWenping Zhang 		ret = fwrite(out_buf, total_size, 1, file);
5710466543cSWenping Zhang 		if (ret != 1)
5720466543cSWenping Zhang 			fprintf(stderr, "write image to file %s failed\n",
5730466543cSWenping Zhang 				out_path);
5740466543cSWenping Zhang 	}
5750466543cSWenping Zhang 
5760466543cSWenping Zhang 	deinit_grayscale_logo_buf(out_buf);
5770466543cSWenping Zhang 	ret = fclose(file);
5780466543cSWenping Zhang 	if (ret != 0)
5790466543cSWenping Zhang 		printf("Close file[%s] failed, err=%d\n", out_path, ret);
5800466543cSWenping Zhang 	file = NULL;
5810466543cSWenping Zhang 	return ret;
5820466543cSWenping Zhang }
5830466543cSWenping Zhang 
584