Browse Source

Use png.h in gfxx.c

June 3 weeks ago
parent
commit
572d8a8cb6
Signed by: Curtis McEnroe <june@causal.agency> GPG Key ID: CEA2F97ADCFCD77C
3 changed files with 123 additions and 47 deletions
  1. 3
    1
      gfx/Makefile
  2. 12
    46
      gfx/gfxx.c
  3. 108
    0
      gfx/png.h

+ 3
- 1
gfx/Makefile View File

@@ -5,7 +5,7 @@ BINS = brot gfxx
5 5
 MAN1 = $(BINS:%=man/%.1)
6 6
 
7 7
 CFLAGS += -Wall -Wextra -Wpedantic
8
-LDLIBS = -lm -lz
8
+LDLIBS = -lm
9 9
 LDLIBS_cocoa = -framework Cocoa
10 10
 LDLIBS_x11 = -lX11
11 11
 
@@ -18,6 +18,8 @@ brot.o gfxx.o: gfx.h
18 18
 
19 19
 cocoa.o fb.o x11.o: gfx.h
20 20
 
21
+gfxx.o: png.h
22
+
21 23
 brot: brot.o $(GFX).o
22 24
 	$(CC) $(LDFLAGS) brot.o $(GFX).o $(LDLIBS) $(LDLIBS_$(GFX)) -o $@
23 25
 

+ 12
- 46
gfx/gfxx.c View File

@@ -1,4 +1,4 @@
1
-/* Copyright (c) 2018, Curtis McEnroe <programble@gmail.com>
1
+/* Copyright (C) 2018  Curtis McEnroe <june@causal.agency>
2 2
  *
3 3
  * This program is free software: you can redistribute it and/or modify
4 4
  * it under the terms of the GNU Affero General Public License as published by
@@ -14,7 +14,6 @@
14 14
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 15
  */
16 16
 
17
-#include <arpa/inet.h>
18 17
 #include <err.h>
19 18
 #include <fcntl.h>
20 19
 #include <math.h>
@@ -27,9 +26,9 @@
27 26
 #include <sys/stat.h>
28 27
 #include <sysexits.h>
29 28
 #include <unistd.h>
30
-#include <zlib.h>
31 29
 
32 30
 #include "gfx.h"
31
+#include "png.h"
33 32
 
34 33
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
35 34
 #define MASK(b) ((1 << (b)) - 1)
@@ -329,22 +328,6 @@ static void outOpen(const char *ext) {
329 328
 	}
330 329
 }
331 330
 
332
-static uint32_t crc;
333
-static void pngWrite(const void *ptr, size_t size) {
334
-	fwrite(ptr, size, 1, out.file);
335
-	if (ferror(out.file)) err(EX_IOERR, "%s", out.path);
336
-	crc = crc32(crc, ptr, size);
337
-}
338
-static void pngUint(uint32_t host) {
339
-	uint32_t net = htonl(host);
340
-	pngWrite(&net, 4);
341
-}
342
-static void pngChunk(const char *type, uint32_t size) {
343
-	pngUint(size);
344
-	crc = crc32(0, Z_NULL, 0);
345
-	pngWrite(type, 4);
346
-}
347
-
348 331
 static void pngDump(uint32_t *src, size_t srcWidth, size_t srcHeight) {
349 332
 	int error;
350 333
 
@@ -360,43 +343,26 @@ static void pngDump(uint32_t *src, size_t srcWidth, size_t srcHeight) {
360 343
 		}
361 344
 	}
362 345
 
363
-	uLong deflateSize = compressBound(sizeof(data));
364
-	uint8_t deflate[deflateSize];
365
-	error = compress(deflate, &deflateSize, data, sizeof(data));
366
-	if (error != Z_OK) errx(EX_SOFTWARE, "compress: %d", error);
367
-
368 346
 	outOpen("png");
369 347
 	if (!out.file) return;
370 348
 
371
-	const uint8_t Signature[8] = "\x89PNG\r\n\x1A\n";
372
-	const uint8_t Header[] = { 8, 2, 0, 0, 0 }; // 8-bit truecolor
373 349
 	const char Software[] = "Software";
374 350
 	formatOptions();
375 351
 	uint8_t sbit[3] = { MAX(bits[R], 1), MAX(bits[G], 1), MAX(bits[B], 1) };
376 352
 
377
-	pngWrite(Signature, sizeof(Signature));
378
-
379
-	pngChunk("IHDR", 4 + 4 + sizeof(Header));
380
-	pngUint(srcWidth);
381
-	pngUint(srcHeight);
382
-	pngWrite(Header, sizeof(Header));
383
-	pngUint(crc);
384
-
385
-	pngChunk("tEXt", sizeof(Software) + strlen(options));
386
-	pngWrite(Software, sizeof(Software));
387
-	pngWrite(options, strlen(options));
388
-	pngUint(crc);
353
+	pngHead(out.file, srcWidth, srcHeight, 8, PNGTruecolor);
389 354
 
390
-	pngChunk("sBIT", sizeof(sbit));
391
-	pngWrite(sbit, sizeof(sbit));
392
-	pngUint(crc);
355
+	pngChunk(out.file, "tEXt", sizeof(Software) + strlen(options));
356
+	pngWrite(out.file, (uint8_t *)Software, sizeof(Software));
357
+	pngWrite(out.file, (uint8_t *)options, strlen(options));
358
+	pngInt32(out.file, ~pngCRC);
393 359
 
394
-	pngChunk("IDAT", deflateSize);
395
-	pngWrite(deflate, deflateSize);
396
-	pngUint(crc);
360
+	pngChunk(out.file, "sBIT", sizeof(sbit));
361
+	pngWrite(out.file, sbit, sizeof(sbit));
362
+	pngInt32(out.file, ~pngCRC);
397 363
 
398
-	pngChunk("IEND", 0);
399
-	pngUint(crc);
364
+	pngData(out.file, data, sizeof(data));
365
+	pngTail(out.file);
400 366
 
401 367
 	error = fclose(out.file);
402 368
 	if (error) err(EX_IOERR, "%s", out.path);

+ 108
- 0
gfx/png.h View File

@@ -0,0 +1,108 @@
1
+/* Copyright (C) 2018  Curtis McEnroe <june@causal.agency>
2
+ *
3
+ * This program is free software: you can redistribute it and/or modify
4
+ * it under the terms of the GNU Affero General Public License as published by
5
+ * the Free Software Foundation, either version 3 of the License, or
6
+ * (at your option) any later version.
7
+ *
8
+ * This program is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
+ * GNU Affero General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Affero General Public License
14
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
+ */
16
+
17
+#include <err.h>
18
+#include <stdint.h>
19
+#include <stdio.h>
20
+#include <stdlib.h>
21
+#include <sysexits.h>
22
+
23
+static inline uint32_t pngCRCTable(uint8_t n) {
24
+	static uint32_t table[256];
25
+	if (table[1]) return table[n];
26
+	for (int i = 0; i < 256; ++i) {
27
+		table[i] = i;
28
+		for (int j = 0; j < 8; ++j) {
29
+			table[i] = (table[i] >> 1) ^ (table[i] & 1 ? 0xEDB88320 : 0);
30
+		}
31
+	}
32
+	return table[n];
33
+}
34
+
35
+static uint32_t pngCRC;
36
+
37
+static inline void pngWrite(FILE *file, const uint8_t *ptr, uint32_t len) {
38
+	if (!fwrite(ptr, len, 1, file)) err(EX_IOERR, "pngWrite");
39
+	for (uint32_t i = 0; i < len; ++i) {
40
+		pngCRC = pngCRCTable(pngCRC ^ ptr[i]) ^ (pngCRC >> 8);
41
+	}
42
+}
43
+static inline void pngInt32(FILE *file, uint32_t n) {
44
+	pngWrite(file, (uint8_t []) { n >> 24, n >> 16, n >> 8, n }, 4);
45
+}
46
+static inline void pngChunk(FILE *file, char type[static 4], uint32_t len) {
47
+	pngInt32(file, len);
48
+	pngCRC = ~0;
49
+	pngWrite(file, (uint8_t *)type, 4);
50
+}
51
+
52
+enum {
53
+	PNGGrayscale,
54
+	PNGTruecolor = 2,
55
+	PNGIndexed,
56
+	PNGAlpha,
57
+};
58
+
59
+static inline void pngHead(
60
+	FILE *file, uint32_t width, uint32_t height, uint8_t depth, uint8_t color
61
+) {
62
+	pngWrite(file, (uint8_t *)"\x89PNG\r\n\x1A\n", 8);
63
+	pngChunk(file, "IHDR", 13);
64
+	pngInt32(file, width);
65
+	pngInt32(file, height);
66
+	pngWrite(file, &depth, 1);
67
+	pngWrite(file, &color, 1);
68
+	pngWrite(file, (uint8_t []) { 0, 0, 0 }, 3);
69
+	pngInt32(file, ~pngCRC);
70
+}
71
+
72
+static inline void pngPalette(FILE *file, const uint8_t *pal, uint32_t len) {
73
+	pngChunk(file, "PLTE", len);
74
+	pngWrite(file, pal, len);
75
+	pngInt32(file, ~pngCRC);
76
+}
77
+
78
+enum {
79
+	PNGNone,
80
+	PNGSub,
81
+	PNGUp,
82
+	PNGAverage,
83
+	PNGPaeth,
84
+};
85
+
86
+static inline void pngData(FILE *file, const uint8_t *data, uint32_t len) {
87
+	uint32_t adler1 = 1, adler2 = 0;
88
+	for (uint32_t i = 0; i < len; ++i) {
89
+		adler1 = (adler1 + data[i]) % 65521;
90
+		adler2 = (adler1 + adler2) % 65521;
91
+	}
92
+	uint32_t zlen = 2 + 5 * ((len + 0xFFFE) / 0xFFFF) + len + 4;
93
+	pngChunk(file, "IDAT", zlen);
94
+	pngWrite(file, (uint8_t []) { 0x08, 0x1D }, 2);
95
+	for (; len > 0xFFFF; data += 0xFFFF, len -= 0xFFFF) {
96
+		pngWrite(file, (uint8_t []) { 0x00, 0xFF, 0xFF, 0x00, 0x00 }, 5);
97
+		pngWrite(file, data, 0xFFFF);
98
+	}
99
+	pngWrite(file, (uint8_t []) { 0x01, len, len >> 8, ~len, ~len >> 8 }, 5);
100
+	pngWrite(file, data, len);
101
+	pngInt32(file, adler2 << 16 | adler1);
102
+	pngInt32(file, ~pngCRC);
103
+}
104
+
105
+static inline void pngTail(FILE *file) {
106
+	pngChunk(file, "IEND", 0);
107
+	pngInt32(file, ~pngCRC);
108
+}

Loading…
Cancel
Save