aboutsummaryrefslogtreecommitdiff
path: root/xormat/png.h
blob: 8c15c293ba22274e85257edbb124413c1ff0dca1 (plain) (blame)
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
#include <stdio.h>
#include <png.h>

#ifndef use_png_library
#define use_png_library
#endif

static generic * png_image_import (character * path, natural * width, natural * height) {
	FILE    * file = null;
	natural * data = null;

	png_byte    colour_type  = 0;
	png_byte    bit_depth    = 0;
	png_bytep * row_pointers = null;

	png_structp structure   = null;
	png_infop   information = null;

	fatal_failure (path   == null, "png_image_import: File path is null pointer.");
	fatal_failure (width  == null, "png_image_import: Width is null pointer.");
	fatal_failure (height == null, "png_image_import: Height is null pointer.");

	file = fopen (path, "rb");

	fatal_failure (file == null, path);

	structure   = png_create_read_struct (PNG_LIBPNG_VER_STRING, null, null, null);
	information = png_create_info_struct (structure);

	png_init_io   (structure, file);
	png_read_info (structure, information);

	* width       = png_get_image_width  (structure, information);
	* height      = png_get_image_height (structure, information);
	  colour_type = png_get_color_type   (structure, information);
	  bit_depth   = png_get_bit_depth    (structure, information);

	if (bit_depth == 16) {
		png_set_strip_16 (structure);
	}

	if (colour_type == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb (structure);
	}

	if ((colour_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) {
		png_set_expand_gray_1_2_4_to_8 (structure);
	}

	if (png_get_valid (structure, information, PNG_INFO_tRNS)) {
		png_set_tRNS_to_alpha (structure);
	}

	if ((colour_type == PNG_COLOR_TYPE_RGB) || (colour_type == PNG_COLOR_TYPE_GRAY) || (colour_type == PNG_COLOR_TYPE_PALETTE)) {
		png_set_filler (structure, 0xff, PNG_FILLER_AFTER);
	}

	if ((colour_type == PNG_COLOR_TYPE_GRAY) || (colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
		png_set_gray_to_rgb (structure);
	}

	png_read_update_info (structure, information);

	row_pointers = allocate ((* height) * sizeof (* row_pointers));

	for (natural index = 0; index < (* height); ++index) {
		row_pointers [index] = allocate (png_get_rowbytes (structure, information));
	}

	png_read_image (structure, row_pointers);

	fclose (file);

	data = allocate ((* width) * (* height) * sizeof (* data));

	for (natural index = 0; index < (* height); ++index) {
		memory_copy (& data [index * (* width)], row_pointers [index], (* width) * sizeof (* data));

		row_pointers [index] = deallocate (row_pointers [index]);
	}

	row_pointers = deallocate (row_pointers);

	png_destroy_read_struct (& structure, & information, null);

	return (data);
}

static procedure png_image_export (character * path, natural * data, natural width, natural height) {
	png_image image = { 0 };

	fatal_failure (path   == null, "png_image_export: File path is null pointer.");
	fatal_failure (data   == null, "png_image_export: Data is null pointer.");
	fatal_failure (width  == 0,    "png_image_export: Width is equal to zero.");
	fatal_failure (height == 0,    "png_image_export: Height is equal to zero.");

	image.version = PNG_IMAGE_VERSION;
	image.format  = PNG_FORMAT_RGBA;
	image.width   = width;
	image.height  = height;

	png_image_write_to_file (& image, path, 0, data, 0, null);

	png_image_free (& image);
}