include stdint.h
[rigol] / png.c
CommitLineData
3df14711
MG
1#include <string.h>
2#include <stdint.h>
3#include <arpa/inet.h>
4#include <zlib.h>
070fd3ff
MG
5#include <stdio.h>
6#include <stdlib.h>
3df14711
MG
7
8#include "png.h"
9
e8e713c3
MG
10#define CHUNK 16384
11#define WIDTH 320
12#define HEIGHT 234
13
3df14711
MG
14/* Table of CRCs of all 8-bit messages. */
15static unsigned long crc_table[256];
16
17/* Flag: has the table been computed? Initially false. */
18static int crc_table_computed = 0;
19
20/* Make the table for a fast CRC. */
21static void make_crc_table(void)
22{
23 unsigned long c;
24 int n, k;
25
26 for (n = 0; n < 256; n++) {
27 c = (unsigned long) n;
28 for (k = 0; k < 8; k++) {
29 if (c & 1)
30 c = 0xedb88320L ^ (c >> 1);
31 else
32 c = c >> 1;
33 }
34 crc_table[n] = c;
35 }
36 crc_table_computed = 1;
37}
38
39/* Update a running CRC with the bytes buf[0..len-1]--the CRC
40 should be initialized to all 1's, and the transmitted value
41 is the 1's complement of the final running CRC (see the
42 crc() routine below). */
43
44static unsigned long update_crc(unsigned long crc, unsigned char *buf,
45 int len)
46{
47 unsigned long c = crc;
48 int n;
49
50 if (!crc_table_computed)
51 make_crc_table();
52 for (n = 0; n < len; n++) {
53 c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
54 }
55 return c;
56}
57
58/* Return the CRC of the bytes buf[0..len-1]. */
59static unsigned long crc(unsigned char *buf, int len)
60{
61 return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
62}
63
64unsigned char *lcd2png(unsigned char *lcd, int *len)
65{
e8e713c3
MG
66 unsigned char screen_conv[(WIDTH*HEIGHT*3)+HEIGHT]; /* 320*234 RGB + scanline filter byte */
67 unsigned char *pos;
3df14711 68 unsigned char lut[256][3];
e8e713c3
MG
69 unsigned char *screen_deflated;
70 int deflated_size;
7ba4ad35 71 unsigned char *image = NULL;
3df14711
MG
72 unsigned char *outpos;
73 static const unsigned char png[] = {137, 80, 78, 71, 13, 10, 26, 10};
e8e713c3
MG
74 static unsigned char idat[] = {'I', 'D', 'A', 'T'};
75 static unsigned char iend[] = {'I', 'E', 'N', 'D'};
3df14711
MG
76 static unsigned char ihdr[] = {'I', 'H', 'D', 'R',
77 0x00, 0x00, 0x01, 0x40, /* 320 - Width */
78 0x00, 0x00, 0x00, 0xea, /* 234 - Height */
79 0x08, /* Bit depth */
80 0x02, /* RGB Truecolor, Colour type */
81 0x00, /* Deflate, Compression method */
e8e713c3 82 0x00, /* Adaptive, Filter method */
3df14711
MG
83 0x00 /* No interlace, Interlace method */
84 };
3df14711
MG
85 uint32_t l;
86 int i;
e8e713c3 87 int ret;
3df14711 88 int toalloc = 0;
e8e713c3 89 int flush;
070fd3ff 90 z_stream strm;
3df14711
MG
91
92 for(i = 0; i < 256; i++) {
93 lut[i][0] = ((i >> 6) * 0x55);
94 lut[i][1] = ((((i >> 3) & 7) * 0x49) >> 1);
95 lut[i][2] = (((i & 7) * 0x49) >> 1);
96 }
97
e8e713c3
MG
98 pos = screen_conv;
99 for(i = 0; i < (WIDTH*HEIGHT); i++) {
100 if ((i % WIDTH) == 0) {
101 *pos++ = 0x00; /* No adaptive filter */
102 }
103 *pos++ = lut[lcd[i]][0];
104 *pos++ = lut[lcd[i]][1];
105 *pos++ = lut[lcd[i]][2];
3df14711
MG
106 }
107
070fd3ff
MG
108 strm.zalloc = Z_NULL;
109 strm.zfree = Z_NULL;
110 strm.opaque = Z_NULL;
e8e713c3 111 if (deflateInit(&strm, Z_BEST_COMPRESSION) != Z_OK) {
070fd3ff
MG
112 perror("deflateInit");
113 exit(EXIT_FAILURE);
114 }
115
e8e713c3
MG
116 strm.avail_in = sizeof(screen_conv);
117 strm.next_in = screen_conv;
118
119 toalloc = 0;
7ba4ad35 120 strm.avail_out = 0;
e8e713c3
MG
121 screen_deflated = NULL;
122 flush = Z_NO_FLUSH;
123
124 do {
125 if (strm.avail_out == 0) {
126 toalloc += CHUNK;
127 screen_deflated = realloc(screen_deflated, toalloc);
128 if (screen_deflated == NULL) {
129 perror("realloc");
130 exit(EXIT_FAILURE);
131 }
132
133 strm.avail_out = CHUNK;
134 strm.next_out = screen_deflated + (toalloc - CHUNK);
135 }
136
137 ret = deflate(&strm, flush);
138 if (ret == Z_STREAM_ERROR) {
139 perror("deflate");
140 exit(EXIT_FAILURE);
141 }
142
143 if(strm.avail_in == 0) {
144 flush = Z_FINISH;
145 }
146 } while(ret != Z_STREAM_END);
147 deflated_size = toalloc - strm.avail_out;
070fd3ff 148
e8e713c3
MG
149 deflateEnd(&strm);
150
e8e713c3
MG
151 image = malloc(sizeof(png) +
152 sizeof(ihdr) + 8 + /* 8 = length, csum */
153 sizeof(idat) + deflated_size + 8 +
154 sizeof(iend) + 8);
155
156 if (image == NULL) {
157 perror("malloc");
2d17f2ab 158 return NULL;
e8e713c3
MG
159 }
160
3df14711 161 outpos = image;
7ba4ad35
MG
162
163 /* PNG signature */
3df14711
MG
164 memcpy(outpos, png, sizeof(png));
165 outpos += sizeof(png);
166
7ba4ad35 167 /* IHDR */
3df14711
MG
168 l = htonl(sizeof(ihdr) - 4); /* "IHDR" is not counted */
169 memcpy(outpos, &l, sizeof(l));
170 outpos += sizeof(l);
171 memcpy(outpos, ihdr, sizeof(ihdr));
172 outpos += sizeof(ihdr);
e8e713c3
MG
173 l = htonl(crc(ihdr, sizeof(ihdr)));
174 memcpy(outpos, &l, sizeof(l));
175 outpos += sizeof(l);
176
7ba4ad35 177 /* IDAT */
e8e713c3
MG
178 l = htonl(deflated_size);
179 memcpy(outpos, &l, sizeof(l));
180 outpos += sizeof(l);
181 memcpy(outpos, idat, sizeof(idat));
182 outpos += sizeof(idat);
183 memcpy(outpos, screen_deflated, deflated_size);
184 free(screen_deflated);
185 outpos +=deflated_size;
186 l = htonl(crc(outpos-deflated_size-sizeof(idat), deflated_size+sizeof(idat)));
3df14711
MG
187 memcpy(outpos, &l, sizeof(l));
188 outpos += sizeof(l);
189
7ba4ad35 190 /* IEND */
3df14711
MG
191 l = htonl(sizeof(iend) - 4); /* "IEND" is not counted */
192 memcpy(outpos, &l, sizeof(l));
193 outpos += sizeof(l);
194 memcpy(outpos, iend, sizeof(iend));
195 outpos += sizeof(iend);
e8e713c3 196 l = htonl(crc(iend, sizeof(iend)));
3df14711
MG
197 memcpy(outpos, &l, sizeof(l));
198 outpos += sizeof(l);
199
200 *len = (int)(outpos - image);
201 return image;
202}
Impressum, Datenschutz