-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpngha.h
162 lines (135 loc) · 4.5 KB
/
pngha.h
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
#ifndef PNGHA
#include<stdio.h>
#include<stdlib.h>
#define ADLER_BASE 65521
unsigned int adler32(unsigned char *data, size_t len)
{
int a = 1, b = 0;
// Process each byte of the data in order
for (int i = 0; i < len; ++i)
{
a = (a + data[i]) % ADLER_BASE;
b = (b + a) % ADLER_BASE;
}
return (b << 16) | a;
}
void inverse_copy32(char *array, int value, int index)
{
array[index + 0] = (value >> 24) & 0xFF;
array[index + 1] = (value >> 16) & 0xFF;
array[index + 2] = (value >> 8) & 0xFF;
array[index + 3] = (value >> 0) & 0xFF;
}
void copy32(char *array, int value, int index)
{
array[index + 0] = (value >> 0) & 0xFF;
array[index + 1] = (value >> 8) & 0xFF;
array[index + 2] = (value >> 16) & 0xFF;
array[index + 3] = (value >> 24) & 0xFF;
}
/* Table of CRCs of all 8-bit messages. */
unsigned long crc_table[256];
/* Flag: has the table been computed? Initially false. */
int crc_table_computed = 0;
/* Make the table for a fast CRC. */
void make_crc_table(void)
{
unsigned long c;
int n, k;
for (n = 0; n < 256; n++)
{
c = (unsigned long) n;
for (k = 0; k < 8; k++)
{
if (c & 1) c = 0xedb88320L ^ (c >> 1);
else c = c >> 1;
}
crc_table[n] = c;
}
crc_table_computed = 1;
}
void crc(unsigned char *chunk, int size)
{
unsigned long c = 0xffffffffL;
if (!crc_table_computed) make_crc_table();
for (int n = 4; n < size - 4; n++) c = crc_table[(c ^ chunk[n]) & 0xff] ^ (c >> 8);
c ^= 0xffffffffL;
inverse_copy32(chunk, c, size - 4);
}
void rgb_to_png(const char* filename, unsigned char* rgb, int width, int height)
{
char header[] = {
137, 80, 78, 71, 13, 10, 26, 10
};
char IHDR[] = {
0, 0, 0, 13, // 4 bytes for data size
73, 72, 68, 82, //Spells IHDR
(width >> 24) & 0xFF, (width >> 16) & 0xFF, (width >> 8) & 0xFF, (width >> 0) & 0xFF,
(height >> 24) & 0xFF, (height >> 16) & 0xFF, (height >> 8) & 0xFF, (height >> 0) & 0xFF,
8, 2, 0, 0, 0, //Format parameters
0, 0, 0, 0 // CRC
};
crc(IHDR, sizeof(IHDR));
int pixelWidth = width * 3;
int pixelLength = pixelWidth * height;
int dataLength = (6/*6 is for 0size0*/ + pixelWidth) * height;
char* IDAT = (char*)calloc(18/*InitialData*/ + dataLength, 1);
inverse_copy32(IDAT, dataLength + 2/*header*/ + 4/*adler*/, 0); //Data Length parameter
IDAT[4] = 73; //I
IDAT[5] = 68; //D
IDAT[6] = 65; //A
IDAT[7] = 84; //T
IDAT[8] = 0x78; //Compression header
IDAT[9] = 0xDA; //Compression header
unsigned char headerOffset[4] = {
((pixelWidth + 1) >> 0) & 0xFF,
((pixelWidth + 1) >> 8) & 0xFF,
(~(pixelWidth + 1) >> 0) & 0xFF,
(~(pixelWidth + 1) >> 8) & 0xFF
};
char* adlerRGB = (char*)calloc(pixelLength + height, 1);
int pos = 10, offset = 0;
for(int y = 0; y < height; y++)
{
//Data row header
if(y == height - 1) IDAT[pos++] = 0x01;
else IDAT[pos++] = 0x00;
IDAT[pos++] = headerOffset[0];
IDAT[pos++] = headerOffset[1];
IDAT[pos++] = headerOffset[2];
IDAT[pos++] = headerOffset[3];
IDAT[pos++] = 0x00;
//Putting zeroes in the adler
adlerRGB[y * width * 3 + offset] = 0x00;
offset++;
for(int x = 0; x < width; x++)
{
int index = (x + y * width) * 3;
//Copying rgb into data array
IDAT[pos++] = rgb[index + 0];
IDAT[pos++] = rgb[index + 1];
IDAT[pos++] = rgb[index + 2];
//Copying rgb int adler
adlerRGB[index + offset] = rgb[index];
adlerRGB[index + offset + 1] = rgb[index + 1];
adlerRGB[index + offset + 2] = rgb[index + 2];
}
}
unsigned long adl = adler32(adlerRGB, pixelLength + height); free(adlerRGB);
inverse_copy32(IDAT, adl, 18+dataLength - 8);
crc(IDAT, 18+dataLength);
char IEND[] = {
0, 0, 0, 0, // Data Length
73, 69, 78, 68, // Spells IEND
174, 66, 96, 130 // CRC
};
FILE *file = fopen(filename, "wb");
fwrite(header, sizeof(header), 1, file);
fwrite(IHDR, sizeof(IHDR), 1, file);
fwrite(IDAT, 18+dataLength, 1, file);
fwrite(IEND, sizeof(IEND), 1, file);
fclose(file);
free(IDAT);
}
#endif
#define PNGHA