hdc.c 4.5 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
#include <sys/types.h>

#include <stdio.h>
#include <stdlib.h>

#include "libpng/png.h"

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned int hdc_color_t;

typedef unsigned short hdc_pixel_t;

#define HDC_ARGB(a, r, g, b)	\
	((hdc_color_t)(((uint8_t)(r)|\
	(((unsigned)(uint8_t)(g))<<8))|\
	(((unsigned long)(uint8_t)(b))<<16)|\
	(((unsigned long)(uint8_t)(a))<<24)))
#define HDC_RGB(r, g, b)	HDC_ARGB(255, (r), (g), (b))

#define HDC_RGB_R(c)	((c) & 0xff)
#define HDC_RGB_G(c)	(((c) >> 8)  & 0xff)
#define HDC_RGB_B(c)	(((c) >> 16) & 0xff)
#define HDC_RGB_A(c)	(((c) >> 24) & 0xff)

/* convert HDC color to BBBBBGGGGGGRRRRR */
uint16_t hdc_color_to_565(hdc_color_t c)
{
	uint16_t pixel;

	pixel = ((HDC_RGB_B(c)>> 3) << 11) | ((HDC_RGB_G(c) >> 2) << 5) | (HDC_RGB_R(c) >> 3);

	return pixel;
}
/* convert HDC color to RRRRRGGGGGGBBBBB */
uint16_t hdc_color_to_565p(hdc_color_t c)
{
	uint16_t pixel;

	pixel = ((HDC_RGB_R(c) >> 3) << 11) | ((HDC_RGB_G(c) >> 2) << 5) | (HDC_RGB_B(c)>> 3);
	return pixel;
}

/* png image information */
png_structp png_ptr;
png_infop info_ptr;

struct hdc_image_header
{
	uint32_t magic;

	uint32_t width;
	uint32_t height;

	/* transparent color */
	uint32_t tmask;

	/* reserved */
	uint32_t reserved;
};
struct hdc_image_header header;

int main(int argc, char** argv)
{
	int bit_depth;
	int color_type;
	double gamma;
	int width, height;
	FILE *src_fp, *dst_fp;
	png_uint_32 x, y;
	png_bytep row;
	png_bytep data;
	hdc_pixel_t *ptr;

	src_fp = fopen(argv[1], "rb");
	dst_fp = fopen(argv[2], "wb");

	if (src_fp == NULL || dst_fp == NULL) 
	{
		printf("can't open file for read or write\n");
		return -1;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL)
	{
		return -1;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
		return -1;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		png_read_end(png_ptr, NULL);

		/* destroy png struct */
		png_destroy_info_struct(png_ptr, &info_ptr);
		png_destroy_read_struct(&png_ptr, NULL, NULL);

		fclose(src_fp);fclose(dst_fp);

		return (-1);
	}

	png_init_io(png_ptr, src_fp);

	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
		&color_type, NULL, NULL, NULL);

	if (bit_depth == 16)
		png_set_strip_16(png_ptr);
	if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);
	if (bit_depth < 8)
		png_set_expand(png_ptr);
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);
	if (color_type == PNG_COLOR_TYPE_GRAY ||
		color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);

	/* set gamma conversion */
	if (png_get_gAMA(png_ptr, info_ptr, &gamma))
		png_set_gamma(png_ptr, (double)2.2, gamma);

	png_read_update_info(png_ptr, info_ptr);

	/* write HDC file header */
	sprintf((char *)&header.magic, "HDC%c", '\0');
	header.width	= info_ptr->width;
	header.height	= info_ptr->height;
	header.tmask	= 0;
	header.reserved = 0;
	fwrite(&header, 1, sizeof(struct hdc_image_header), dst_fp);

	row = (png_bytep) malloc (png_get_rowbytes(png_ptr, info_ptr));
	if (row == NULL) goto _return;

	ptr = (hdc_pixel_t*) malloc (header.width * header.height * sizeof(hdc_pixel_t));
	switch (info_ptr->color_type)
	{
	case PNG_COLOR_TYPE_RGBA:
		for (y = 0; y < info_ptr->height; y++)
		{
			png_read_row(png_ptr, row, png_bytep_NULL);
			for (x = 0; x < info_ptr->width; x++)
			{
				data = &(row[x * 4]);

				ptr[x + y * info_ptr->width] = hdc_color_to_565p(HDC_ARGB((255 - data[3]), data[0], data[1], data[2]));
			}
		}

		break;

	case PNG_COLOR_TYPE_PALETTE:
		for (y = 0; y < info_ptr->height; y++)
		{
			png_read_row(png_ptr, row, png_bytep_NULL);
			for (x = 0; x < info_ptr->width; x++)
			{
				data = &(row[x]);

				ptr[x] = hdc_color_to_565p(HDC_ARGB(0, info_ptr->palette[data[0]].red,
					info_ptr->palette[data[0]].green,
					info_ptr->palette[data[0]].blue));
			}
		}

	default:
		break;
	};

	fwrite(ptr, 1, header.height * header.width * sizeof(hdc_pixel_t), dst_fp);

_return:
	png_read_end(png_ptr, NULL);

	/* destroy png struct */
	png_destroy_info_struct(png_ptr, &info_ptr);
	png_destroy_read_struct(&png_ptr, NULL, NULL);

	fclose(src_fp);
	fclose(dst_fp);
	free(ptr);

	return 0;
}