xref: /rk3399_rockchip-uboot/tools/rockchip/bmp2gray16.c (revision e091b6c996a68a6a0faa2bd3ffdd90b3ba5f44ce)
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 
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 
1190466543cSWenping Zhang static void print_version(void)
1200466543cSWenping Zhang {
1210466543cSWenping Zhang 	printf("Version %s (zwp@rock-chips.com)\n", version);
1220466543cSWenping Zhang }
1230466543cSWenping Zhang 
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");
1360466543cSWenping Zhang 	printf("\t --output path");
1370466543cSWenping Zhang 	printf("\t\t\t Output the grayscale image to path\n");
1380466543cSWenping Zhang }
1390466543cSWenping Zhang 
1400466543cSWenping Zhang static inline int size_of_header(void)
1410466543cSWenping Zhang {
1420466543cSWenping Zhang 	return ALIGN(sizeof(struct logo_info), RK_BLK_SIZE);
1430466543cSWenping Zhang }
1440466543cSWenping Zhang 
1450466543cSWenping Zhang static inline int size_of_one_image(void)
1460466543cSWenping Zhang {
1470466543cSWenping Zhang 	return ALIGN((screen_w * screen_h) >> 1, RK_BLK_SIZE);
1480466543cSWenping Zhang }
1490466543cSWenping Zhang 
1500466543cSWenping Zhang int get_logo_resolution(char *in_path, uint32_t *logo_width,
1510466543cSWenping Zhang 			uint32_t *logo_height)
1520466543cSWenping Zhang {
1530466543cSWenping Zhang 	struct bmp_header bmp_hdr;
1540466543cSWenping Zhang 	FILE *file;
1550466543cSWenping Zhang 	int size;
1560466543cSWenping Zhang 	int ret = 0;
1570466543cSWenping Zhang 
1580466543cSWenping Zhang 	if (!in_path)
1590466543cSWenping Zhang 		fprintf(stderr, "Invalid bmp file path.\n");
1600466543cSWenping Zhang 
1610466543cSWenping Zhang 	file = fopen(in_path, "rb");
1620466543cSWenping Zhang 	if (!file) {
1630466543cSWenping Zhang 		fprintf(stderr, "File %s open failed.\n", in_path);
1640466543cSWenping Zhang 		return -1;
1650466543cSWenping Zhang 	}
1660466543cSWenping Zhang 	size = sizeof(struct bmp_header);
1670466543cSWenping Zhang 	if (size != fread(&bmp_hdr, 1, size, file)) {
1680466543cSWenping Zhang 		fprintf(stderr, "Incomplete read of file %s.\n", in_path);
1690466543cSWenping Zhang 		ret = -1;
1700466543cSWenping Zhang 		goto out;
1710466543cSWenping Zhang 	}
1720466543cSWenping Zhang 	if (!(bmp_hdr.signature[0] == 'B' &&
1730466543cSWenping Zhang 	      bmp_hdr.signature[1] == 'M')) {
1740466543cSWenping Zhang 		printf("cat not find bmp file\n");
1750466543cSWenping Zhang 		ret = -1;
1760466543cSWenping Zhang 		goto out;
1770466543cSWenping Zhang 	}
1780466543cSWenping Zhang 	*logo_width = bmp_hdr.width;
1790466543cSWenping Zhang 	*logo_height = bmp_hdr.height;
1800466543cSWenping Zhang 	fprintf(stderr, "logo resolution is %d x %d.\n",
1810466543cSWenping Zhang 		*logo_width, *logo_height);
1820466543cSWenping Zhang out:
1830466543cSWenping Zhang 	fclose(file);
1840466543cSWenping Zhang 	return ret;
1850466543cSWenping Zhang }
1860466543cSWenping Zhang 
1870466543cSWenping Zhang /*
1880466543cSWenping Zhang  * The bmp pixel is scan from left-bottom to right-top
1890466543cSWenping Zhang  */
1900466543cSWenping Zhang int convert_bmp_idx_to_gray_idx(int idx, uint32_t w, uint32_t h)
1910466543cSWenping Zhang {
1920466543cSWenping Zhang 	int row = h - (idx / w) - 1;
1930466543cSWenping Zhang 
1940466543cSWenping Zhang 	return (row * w + idx % w) / 2;
1950466543cSWenping Zhang }
1960466543cSWenping Zhang 
1970466543cSWenping Zhang int convert_one_image(char *in_path, void *out_buf, uint32_t offset,
1980466543cSWenping Zhang 		      struct grayscale_header *gr_hdr, int type)
1990466543cSWenping Zhang {
2000466543cSWenping Zhang 	struct bmp_image *bmp;
2010466543cSWenping Zhang 	struct bmp_header *bmp_hdr;
2020466543cSWenping Zhang 	FILE *file;
2030466543cSWenping Zhang 	void *bmp_buf;
2040466543cSWenping Zhang 	int size;
2050466543cSWenping Zhang 	int ret = -1;
2060466543cSWenping Zhang 	uint8_t *gr16_data = (uint8_t *)out_buf;
2070466543cSWenping Zhang 
2080466543cSWenping Zhang 	if (!out_buf || !in_path) {
2090466543cSWenping Zhang 		fprintf(stderr, "in_path or out_buf is NULL.\n");
2100466543cSWenping Zhang 		return -1;
2110466543cSWenping Zhang 	}
2120466543cSWenping Zhang 
2130466543cSWenping Zhang 	file = fopen(in_path, "rb");
2140466543cSWenping Zhang 	if (!file) {
2150466543cSWenping Zhang 		fprintf(stderr, "File %s open failed.\n", in_path);
2160466543cSWenping Zhang 		return -1;
2170466543cSWenping Zhang 	}
2180466543cSWenping Zhang 
2190466543cSWenping Zhang 	fseek(file, 0, SEEK_END);
2200466543cSWenping Zhang 	size = ftell(file);
2210466543cSWenping Zhang 	fseek(file, 0, SEEK_SET);
2220466543cSWenping Zhang 
2230466543cSWenping Zhang 	bmp_buf = calloc(1, size);
2240466543cSWenping Zhang 	if (!bmp_buf) {
2250466543cSWenping Zhang 		fprintf(stderr, "Allocate memory of %d bytes failed.\n", size);
2260466543cSWenping Zhang 		fclose(file);
2270466543cSWenping Zhang 		return -1;
2280466543cSWenping Zhang 	}
2290466543cSWenping Zhang 	if (size != fread(bmp_buf, 1, size, file)) {
2300466543cSWenping Zhang 		fprintf(stderr, "Incomplete read of file %s.\n", in_path);
2310466543cSWenping Zhang 		goto out;
2320466543cSWenping Zhang 	}
2330466543cSWenping Zhang 
2340466543cSWenping Zhang 	bmp = (struct bmp_image *)bmp_buf;
2350466543cSWenping Zhang 	bmp_hdr = &bmp->hdr;
2360466543cSWenping Zhang 	if (!(bmp_hdr->signature[0] == 'B' &&
2370466543cSWenping Zhang 	      bmp_hdr->signature[1] == 'M')) {
2380466543cSWenping Zhang 		printf("cat not find bmp file\n");
2390466543cSWenping Zhang 		goto out;
2400466543cSWenping Zhang 	}
2410466543cSWenping Zhang 
2420466543cSWenping Zhang 	if (size != le32_to_cpu(bmp_hdr->file_size)) {
2430466543cSWenping Zhang 		fprintf(stderr, "Invalid BMP file size %d.\n",
2440466543cSWenping Zhang 			le32_to_cpu(bmp_hdr->file_size));
2450466543cSWenping Zhang 		goto out;
2460466543cSWenping Zhang 	}
2470466543cSWenping Zhang 	printf("bmp_hdr->width=%d, bmp_hdr->height=%d\n",
2480466543cSWenping Zhang 	       bmp_hdr->width, bmp_hdr->height);
2490466543cSWenping Zhang 	printf("screen_w=%d, screen_h=%d\n", screen_w, screen_h);
2500466543cSWenping Zhang 	if (le32_to_cpu(bmp_hdr->width) != screen_w ||
2510466543cSWenping Zhang 	    le32_to_cpu(bmp_hdr->height) != screen_h) {
2520466543cSWenping Zhang 		fprintf(stderr, "The image size must same with others.\n");
2530466543cSWenping Zhang 		goto out;
2540466543cSWenping Zhang 	}
2550466543cSWenping Zhang 	//write header
2560466543cSWenping Zhang 	gr_hdr->magic[0] = 'G';
2570466543cSWenping Zhang 	gr_hdr->magic[1] = 'R';
2580466543cSWenping Zhang 	gr_hdr->magic[2] = '0';
2590466543cSWenping Zhang 	gr_hdr->magic[3] = '4';
2600466543cSWenping Zhang 	gr_hdr->x = 0;
2610466543cSWenping Zhang 	gr_hdr->y = 0;
2620466543cSWenping Zhang 	gr_hdr->w = screen_w;
2630466543cSWenping Zhang 	gr_hdr->h = screen_h;
2640466543cSWenping Zhang 	gr_hdr->logo_type = type;
2650466543cSWenping Zhang 	gr_hdr->data_offset = offset;
2660466543cSWenping Zhang 	gr_hdr->data_size = screen_w * screen_h / 2;
2670466543cSWenping Zhang 
2680466543cSWenping Zhang 	printf("bmp depth is %d\n", bmp_hdr->bit_count);
2690466543cSWenping Zhang 	//convert rgb to gray data, and write to output buffer
2700466543cSWenping Zhang 	// the used algorithm please refer to below url:
2710466543cSWenping Zhang 	// https://www.cnblogs.com/zhangjiansheng/p/6925722.html
2720466543cSWenping Zhang 	// we use below algorithm:
2730466543cSWenping Zhang 	// Gray = (R*19595 + G*38469 + B*7472) >> 16
2740466543cSWenping Zhang 	switch (bmp_hdr->bit_count) {
2750466543cSWenping Zhang 	case 16:{
2760466543cSWenping Zhang 		struct pixel_u16 *color_u16;
2770466543cSWenping Zhang 		int i;
2780466543cSWenping Zhang 
2790466543cSWenping Zhang 		color_u16 = (struct pixel_u16 *)bmp->color_table;
2800466543cSWenping Zhang 		for (i = 0; i < screen_w * screen_h / 2; i++) {
2810466543cSWenping Zhang 			struct pixel_u16 *pix1 = &color_u16[2 * i];
2820466543cSWenping Zhang 			struct pixel_u16 *pix2 = &color_u16[2 * i + 1];
2830466543cSWenping Zhang 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
2840466543cSWenping Zhang 							    screen_h);
2850466543cSWenping Zhang 			/*
2860466543cSWenping Zhang 			 * the rgb value of pixel_u16 is 4 bits,
2870466543cSWenping Zhang 			 * so the counted grayscale value is 4bit
2880466543cSWenping Zhang 			 */
2890466543cSWenping Zhang 			uint32_t gray_px1 = (pix1->red * 19595 +
2900466543cSWenping Zhang 					     pix1->green * 38469 +
2910466543cSWenping Zhang 					     pix1->blue * 7472) >> 16;
2920466543cSWenping Zhang 			uint32_t gray_px2 = (pix2->red * 19595 +
2930466543cSWenping Zhang 					     pix2->green * 38469 +
2940466543cSWenping Zhang 					     pix2->blue * 7472) >> 16;
2950466543cSWenping Zhang 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
2960466543cSWenping Zhang 		}
2970466543cSWenping Zhang 	}
2980466543cSWenping Zhang 	break;
2990466543cSWenping Zhang 	case 24: {
3000466543cSWenping Zhang 		struct pixel_u24 *color_u24;
3010466543cSWenping Zhang 		int i;
3020466543cSWenping Zhang 
3030466543cSWenping Zhang 		color_u24 = (struct pixel_u24 *)bmp->color_table;
3040466543cSWenping Zhang 		for (i = 0; i < screen_w * screen_h / 2; i++) {
3050466543cSWenping Zhang 			struct pixel_u24 *pix1 = &color_u24[2 * i];
3060466543cSWenping Zhang 			struct pixel_u24 *pix2 = &color_u24[2 * i + 1];
3070466543cSWenping Zhang 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
3080466543cSWenping Zhang 							    screen_h);
3090466543cSWenping Zhang 			/*
3100466543cSWenping Zhang 			 * The rgb value of pixel_u24 is 8 bits,
3110466543cSWenping Zhang 			 * so the counted grayscale
3120466543cSWenping Zhang 			 * value need to divide into 16
3130466543cSWenping Zhang 			 */
3140466543cSWenping Zhang 			uint32_t gray_px1 = ((pix1->red * 19595 +
3150466543cSWenping Zhang 					      pix1->green * 38469 +
3160466543cSWenping Zhang 					      pix1->blue * 7472) >> 16) >> 4;
3170466543cSWenping Zhang 			uint32_t gray_px2 = ((pix2->red * 19595 +
3180466543cSWenping Zhang 					      pix2->green * 38469 +
3190466543cSWenping Zhang 					      pix2->blue * 7472) >> 16) >> 4;
3200466543cSWenping Zhang 
3210466543cSWenping Zhang 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
3220466543cSWenping Zhang 		}
3230466543cSWenping Zhang 	}
3240466543cSWenping Zhang 	break;
3250466543cSWenping Zhang 	case 32: {
3260466543cSWenping Zhang 		struct pixel_u32 *color_u32;
3270466543cSWenping Zhang 		int i;
3280466543cSWenping Zhang 
3290466543cSWenping Zhang 		color_u32 = (struct pixel_u32 *)bmp->color_table;
3300466543cSWenping Zhang 		for (i = 0; i < screen_w * screen_h / 2; i++) {
3310466543cSWenping Zhang 			struct pixel_u32 *pix1 = &color_u32[2 * i];
3320466543cSWenping Zhang 			struct pixel_u32 *pix2 = &color_u32[2 * i + 1];
3330466543cSWenping Zhang 			int j = convert_bmp_idx_to_gray_idx(2 * i, screen_w,
3340466543cSWenping Zhang 							    screen_h);
3350466543cSWenping Zhang 			/*
3360466543cSWenping Zhang 			 * The rgb value of pixel_u32 is 8 bits,
3370466543cSWenping Zhang 			 * so the counted grayscale
3380466543cSWenping Zhang 			 * value need to divide into 16
3390466543cSWenping Zhang 			 */
3400466543cSWenping Zhang 			uint32_t gray_px1 = ((pix1->red * 19595 +
3410466543cSWenping Zhang 					      pix1->green * 38469 +
3420466543cSWenping Zhang 					      pix1->blue * 7472) >> 16) >> 4;
3430466543cSWenping Zhang 			uint32_t gray_px2 = ((pix2->red * 19595 +
3440466543cSWenping Zhang 					      pix2->green * 38469 +
3450466543cSWenping Zhang 					      pix2->blue * 7472) >> 16) >> 4;
3460466543cSWenping Zhang 			gr16_data[j] = gray_px1 | (gray_px2 << 4);
3470466543cSWenping Zhang 		}
3480466543cSWenping Zhang 	}
3490466543cSWenping Zhang 	break;
3500466543cSWenping Zhang 	default:
3510466543cSWenping Zhang 		ret = -1;
3520466543cSWenping Zhang 		printf("Invalid bit count[%d],only support 16/24/32 bpp bmp\n",
3530466543cSWenping Zhang 		       bmp_hdr->bit_count);
3540466543cSWenping Zhang 	break;
3550466543cSWenping Zhang 	}
3560466543cSWenping Zhang 
3570466543cSWenping Zhang 	fprintf(stderr, "Convert image success\n");
3580466543cSWenping Zhang 	ret = 0;
3590466543cSWenping Zhang out:
3600466543cSWenping Zhang 	free(bmp_buf);
3610466543cSWenping Zhang 	fclose(file);
3620466543cSWenping Zhang 	return ret;
3630466543cSWenping Zhang }
3640466543cSWenping Zhang 
365*e091b6c9SWenping Zhang void *init_grayscale_logo_buf(int logo_count, uint32_t size_one_image)
3660466543cSWenping Zhang {
3670466543cSWenping Zhang 	int size;
3680466543cSWenping Zhang 	void *out_buf;
3690466543cSWenping Zhang 
3700466543cSWenping Zhang 	if (!logo_count) {
3710466543cSWenping Zhang 		fprintf(stderr, "No input logo!\n");
3720466543cSWenping Zhang 		return NULL;
3730466543cSWenping Zhang 	}
3740466543cSWenping Zhang 	size = size_of_header();
3750466543cSWenping Zhang 	fprintf(stderr, "size of header in logo.img is %d\n", size);
3760466543cSWenping Zhang 	//every pixel of the grayscale image is 4 bits
377*e091b6c9SWenping Zhang 	size += logo_count * size_one_image;
3780466543cSWenping Zhang 	out_buf = calloc(1, size);
3790466543cSWenping Zhang 
3800466543cSWenping Zhang 	return out_buf;
3810466543cSWenping Zhang }
3820466543cSWenping Zhang 
3830466543cSWenping Zhang void deinit_grayscale_logo_buf(void *buf)
3840466543cSWenping Zhang {
3850466543cSWenping Zhang 	if (buf) {
3860466543cSWenping Zhang 		free(buf);
3870466543cSWenping Zhang 		buf = NULL;
3880466543cSWenping Zhang 	}
3890466543cSWenping Zhang }
3900466543cSWenping Zhang 
3910466543cSWenping Zhang int main(int argc, char *argv[])
3920466543cSWenping Zhang {
3930466543cSWenping Zhang 	char out_path[256] = {0};
3940466543cSWenping Zhang 	void *out_buf;
3950466543cSWenping Zhang 	int logo_count = 0;
3960466543cSWenping Zhang 	int i;
3970466543cSWenping Zhang 	int hdr_size, one_img_size, total_size;
3980466543cSWenping Zhang 	int ret = -1;
3990466543cSWenping Zhang 	struct logo_info *logo_hdr;
4000466543cSWenping Zhang 	FILE *file;
4010466543cSWenping Zhang 
4020466543cSWenping Zhang 	PROG = fix_path(argv[0]);
4030466543cSWenping Zhang 
4040466543cSWenping Zhang 	argc--, argv++;
4050466543cSWenping Zhang 	while (argc > 0 && argv[0][0] == '-') {
4060466543cSWenping Zhang 		/* it's a opt arg. */
4070466543cSWenping Zhang 		const char *arg = argv[0];
4080466543cSWenping Zhang 
4090466543cSWenping Zhang 		argc--, argv++;
4100466543cSWenping Zhang 		if (!strcmp("-h", arg)) {
4110466543cSWenping Zhang 			usage();
4120466543cSWenping Zhang 			return 0;
4130466543cSWenping Zhang 		}  else if (!strcmp("--charge-logo", arg)) {
4140466543cSWenping Zhang 			int len, i;
4150466543cSWenping Zhang 			/*
4160466543cSWenping Zhang 			 * Charge logo are located in directory
4170466543cSWenping Zhang 			 * u-boot/tools/images/eink/, there are 7
4180466543cSWenping Zhang 			 * pictures to tell user the battery capacity
4190466543cSWenping Zhang 			 * during charging
4200466543cSWenping Zhang 			 */
4210466543cSWenping Zhang 			for (i = 0; i < 7; i++) {
4220466543cSWenping Zhang 				int logo_type = EINK_LOGO_CHARGING_0 << i;
4230466543cSWenping Zhang 
4240466543cSWenping Zhang 				len = strlen(argv[0]);
4250466543cSWenping Zhang 				if (len > 256) {
4260466543cSWenping Zhang 					fprintf(stderr,
4270466543cSWenping Zhang 						"input charging logo path %s is too long.\n",
4280466543cSWenping Zhang 						argv[0]);
4290466543cSWenping Zhang 					return -1;
4300466543cSWenping Zhang 				}
4310466543cSWenping Zhang 				printf("charge logo path %s\n", argv[0]);
4320466543cSWenping Zhang 				memcpy(in_img_info[logo_count].path,
4330466543cSWenping Zhang 				       argv[0], len);
4340466543cSWenping Zhang 				in_img_info[logo_count].logo_type = logo_type;
4350466543cSWenping Zhang 				logo_count++;
4360466543cSWenping Zhang 				argc--, argv++;
4370466543cSWenping Zhang 			}
4380466543cSWenping Zhang 		}  else if (!strcmp("--uboot-logo", arg)) {
4390466543cSWenping Zhang 			int len = strlen(argv[0]);
4400466543cSWenping Zhang 
4410466543cSWenping Zhang 			if (len > 256) {
4420466543cSWenping Zhang 				printf("Uboot logo path %s is too long.\n",
4430466543cSWenping Zhang 				       argv[0]);
4440466543cSWenping Zhang 				return -1;
4450466543cSWenping Zhang 			}
4460466543cSWenping Zhang 			memcpy(in_img_info[logo_count].path, argv[0], len);
4470466543cSWenping Zhang 			in_img_info[logo_count].logo_type = EINK_LOGO_UBOOT;
4480466543cSWenping Zhang 			logo_count++;
4490466543cSWenping Zhang 			argc--, argv++;
4500466543cSWenping Zhang 		} else if (!strcmp("--kernel-logo", arg)) {
4510466543cSWenping Zhang 			int len = strlen(argv[0]);
4520466543cSWenping Zhang 
4530466543cSWenping Zhang 			if (len > 256) {
4540466543cSWenping Zhang 				printf("Kernel logo path %s is too long\n",
4550466543cSWenping Zhang 				       argv[0]);
4560466543cSWenping Zhang 				return -1;
4570466543cSWenping Zhang 			}
4580466543cSWenping Zhang 			memcpy(in_img_info[logo_count].path, argv[0], len);
4590466543cSWenping Zhang 			in_img_info[logo_count].logo_type = EINK_LOGO_KERNEL;
4600466543cSWenping Zhang 			logo_count++;
4610466543cSWenping Zhang 			argc--, argv++;
4620466543cSWenping Zhang 		}  else if (!strcmp("--screen-width", arg)) {
4630466543cSWenping Zhang 			screen_w = strtoul(argv[0], NULL, 10);
4640466543cSWenping Zhang 			argc--, argv++;
4650466543cSWenping Zhang 		}  else if (!strcmp("--screen-height", arg)) {
4660466543cSWenping Zhang 			screen_h = strtoul(argv[0], NULL, 10);
4670466543cSWenping Zhang 			argc--, argv++;
4680466543cSWenping Zhang 		}  else if (!strcmp("--output", arg)) {
4690466543cSWenping Zhang 			int len = strlen(argv[0]);
4700466543cSWenping Zhang 
4710466543cSWenping Zhang 			if (len > 256) {
4720466543cSWenping Zhang 				printf("input output path %s is too long.\n",
4730466543cSWenping Zhang 				       argv[0]);
4740466543cSWenping Zhang 				return -1;
4750466543cSWenping Zhang 			}
4760466543cSWenping Zhang 			memcpy(out_path, argv[0], len);
4770466543cSWenping Zhang 			argc--, argv++;
4780466543cSWenping Zhang 		} else {
4790466543cSWenping Zhang 			fprintf(stderr, "Unknown opt:%s", arg);
4800466543cSWenping Zhang 			usage();
4810466543cSWenping Zhang 			return -1;
4820466543cSWenping Zhang 		}
4830466543cSWenping Zhang 	}
4840466543cSWenping Zhang 
4850466543cSWenping Zhang 	ret = get_logo_resolution(in_img_info[0].path, &screen_w, &screen_h);
4860466543cSWenping Zhang 	if (ret < 0) {
4870466543cSWenping Zhang 		fprintf(stderr,
4880466543cSWenping Zhang 			"Get height and width from logo image failed.\n");
4890466543cSWenping Zhang 		usage();
4900466543cSWenping Zhang 		return -1;
4910466543cSWenping Zhang 	}
4920466543cSWenping Zhang 
4930466543cSWenping Zhang 	if (screen_w == 0 || screen_h == 0) {
4940466543cSWenping Zhang 		fprintf(stderr,
4950466543cSWenping Zhang 			"The screen weight and screen height must be set.\n");
4960466543cSWenping Zhang 		usage();
4970466543cSWenping Zhang 		return -1;
4980466543cSWenping Zhang 	}
4990466543cSWenping Zhang 
5000466543cSWenping Zhang 	file = fopen(out_path, "wb+");
5010466543cSWenping Zhang 	if (!file) {
5020466543cSWenping Zhang 		fprintf(stderr, "File %s open failed.\n", out_path);
5030466543cSWenping Zhang 		usage();
5040466543cSWenping Zhang 		return -1;
5050466543cSWenping Zhang 	}
506*e091b6c9SWenping Zhang 	hdr_size = size_of_header();
507*e091b6c9SWenping Zhang 	one_img_size = size_of_one_image();
5080466543cSWenping Zhang 
509*e091b6c9SWenping Zhang 	out_buf = init_grayscale_logo_buf(logo_count, one_img_size);
5100466543cSWenping Zhang 	if (!out_buf) {
5110466543cSWenping Zhang 		fprintf(stderr, "Can't malloc buffer for grayscale image.\n");
5120466543cSWenping Zhang 		fclose(file);
5130466543cSWenping Zhang 		return -1;
5140466543cSWenping Zhang 	}
5150466543cSWenping Zhang 
5160466543cSWenping Zhang 	logo_hdr = (struct logo_info *)out_buf;
5170466543cSWenping Zhang 	fprintf(stderr, "logo count is %d,one_img_size=%d,size=%d.\n",
5180466543cSWenping Zhang 		logo_count, one_img_size, screen_w * screen_h / 2);
5190466543cSWenping Zhang 	for (i = 0; i < logo_count; i++) {
5200466543cSWenping Zhang 		char *in_path = in_img_info[i].path;
5210466543cSWenping Zhang 		int type = in_img_info[i].logo_type;
5220466543cSWenping Zhang 		void *img_buf;
5230466543cSWenping Zhang 		int offset = hdr_size + i *  one_img_size;
5240466543cSWenping Zhang 
5250466543cSWenping Zhang 		img_buf = out_buf + offset;
5260466543cSWenping Zhang 		printf("image[%d] start addr=0x%p\n", i, img_buf);
5270466543cSWenping Zhang 		ret = convert_one_image(in_path, img_buf, offset,
5280466543cSWenping Zhang 					&logo_hdr->img_hdr[i], type);
5290466543cSWenping Zhang 		if (ret < 0) {
5300466543cSWenping Zhang 			printf("Convert image[%d] failed, type is %d\n",
5310466543cSWenping Zhang 			       i, type);
5320466543cSWenping Zhang 			break;
5330466543cSWenping Zhang 		}
5340466543cSWenping Zhang 	}
5350466543cSWenping Zhang 
5360466543cSWenping Zhang 	if (ret == 0) {
5370466543cSWenping Zhang 		struct logo_part_header *part_hdr = &logo_hdr->part_hdr;
5380466543cSWenping Zhang 
5390466543cSWenping Zhang 		total_size = hdr_size + (i - 1) * one_img_size +
5400466543cSWenping Zhang 				screen_h * screen_w / 2;
5410466543cSWenping Zhang 
5420466543cSWenping Zhang 		//convert success, write header data.
5430466543cSWenping Zhang 		part_hdr->magic[0] = 'R';
5440466543cSWenping Zhang 		part_hdr->magic[1] = 'K';
5450466543cSWenping Zhang 		part_hdr->magic[2] = 'E';
5460466543cSWenping Zhang 		part_hdr->magic[3] = 'L';
5470466543cSWenping Zhang 		part_hdr->totoal_size = total_size;
5480466543cSWenping Zhang 		part_hdr->screen_width = screen_w;
5490466543cSWenping Zhang 		part_hdr->screen_height = screen_h;
5500466543cSWenping Zhang 		part_hdr->logo_count = i;
5510466543cSWenping Zhang 		printf("screen w=%d, h=%d, total_size=%d\n",
5520466543cSWenping Zhang 		       screen_w, screen_h, total_size);
5530466543cSWenping Zhang 		memcpy(part_hdr->version, version, 4);
5540466543cSWenping Zhang 
5550466543cSWenping Zhang 		// write to output file
5560466543cSWenping Zhang 		ret = fwrite(out_buf, total_size, 1, file);
5570466543cSWenping Zhang 		if (ret != 1)
5580466543cSWenping Zhang 			fprintf(stderr, "write image to file %s failed\n",
5590466543cSWenping Zhang 				out_path);
5600466543cSWenping Zhang 	}
5610466543cSWenping Zhang 
5620466543cSWenping Zhang 	deinit_grayscale_logo_buf(out_buf);
5630466543cSWenping Zhang 	ret = fclose(file);
5640466543cSWenping Zhang 	if (ret != 0)
5650466543cSWenping Zhang 		printf("Close file[%s] failed, err=%d\n", out_path, ret);
5660466543cSWenping Zhang 	file = NULL;
5670466543cSWenping Zhang 	return ret;
5680466543cSWenping Zhang }
5690466543cSWenping Zhang 
570