png.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2020 K. Lange
  5. *
  6. * libtoaru_png: PNG decoder
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <toaru/graphics.h>
  11. #include <toaru/inflate.h>
  12. /**
  13. * Read 32-bit big-endian value from file.
  14. */
  15. unsigned int read_32(FILE * f) {
  16. unsigned char a = fgetc(f);
  17. unsigned char b = fgetc(f);
  18. unsigned char c = fgetc(f);
  19. unsigned char d = fgetc(f);
  20. return (a << 24) | (b << 16) | (c << 8) | d;
  21. }
  22. /**
  23. * Read 16-bit big-endian value from file.
  24. */
  25. unsigned int read_16(FILE * f) {
  26. unsigned char a = fgetc(f);
  27. unsigned char b = fgetc(f);
  28. return (a << 8) | b;
  29. }
  30. /**
  31. * (Debug) Return a chunk type as a string.
  32. */
  33. __attribute__((unused))
  34. static char* reorder_type(unsigned int type) {
  35. static char out[4];
  36. out[0] = (type >> 24) & 0xFF;
  37. out[1] = (type >> 16) & 0xFF;
  38. out[2] = (type >> 8) & 0xFF;
  39. out[3] = (type >> 0) & 0xFF;
  40. return out;
  41. }
  42. /**
  43. * Internal PNG decoder state for use with inflate.
  44. */
  45. struct png_ctx {
  46. FILE * f; /* File being decoded. */
  47. sprite_t * sprite; /* Sprite being generated. */
  48. int y; /* Cursor pointers for writing out bitmap data */
  49. int x;
  50. char buffer[4]; /* A buffer to hold a pixel's worth of data until it can
  51. be written out to the image with the right filter. */
  52. int buf_off; /* How much data is in the above buffer */
  53. int seen_ihdr; /* Whether the IHDR was seen; for error handling */
  54. unsigned int width; /* Image width (dup from sprite) */
  55. unsigned int height; /* Image height (dup from sprite) */
  56. int bit_depth; /* Bit depth of the image */
  57. int color_type; /* PNG color type */
  58. int compression; /* Compression method (must be 0) */
  59. int filter; /* Filter method (must be 0) */
  60. int interlace; /* Interlace method (we only support 0) */
  61. unsigned int size; /* Remaining IDAT chunk size */
  62. int sf; /* Current scanline filter type */
  63. };
  64. /* PNG chunk types */
  65. #define PNG_IHDR 0x49484452
  66. #define PNG_IDAT 0x49444154
  67. #define PNG_IEND 0x49454e44
  68. /* PNG filter types */
  69. #define PNG_FILTER_NONE 0
  70. #define PNG_FILTER_SUB 1
  71. #define PNG_FILTER_UP 2
  72. #define PNG_FILTER_AVG 3
  73. #define PNG_FILTER_PAETH 4
  74. /**
  75. * Read a byte from the IDAT chunk.
  76. * Tracks when an IDAT has been read to completion and
  77. * can load the next IDAT (or bail of this was the last one)
  78. */
  79. static uint8_t _get(struct inflate_context * ctx) {
  80. struct png_ctx * c = (ctx->input_priv);
  81. if (c->size == 0) {
  82. /* Read the CRC32 from the end of this IDAT */
  83. unsigned int check = read_32(c->f);
  84. (void)check; /* ... and in theory check it... */
  85. /* Read the next IDAT chunk header */
  86. unsigned int size = read_32(c->f);
  87. unsigned int type = read_32(c->f);
  88. if (type != PNG_IDAT) {
  89. /* This isn't an IDAT? That's wrong! */
  90. fprintf(stderr, "And this is the wrong type (0x%x), I'm just bailing.\n", type);
  91. fprintf(stderr, "size read was 0x%x\n", size);
  92. exit(0);
  93. }
  94. }
  95. /* Read one byte from the input */
  96. c->size--;
  97. int i = fgetc(c->f);
  98. /* If this was EOF, we should handle that error case... probably... */
  99. if (i < 0) fprintf(stderr, "This is probably not good.\n");
  100. return i;
  101. }
  102. /**
  103. * Paeth predictor
  104. * Described in section 6.6 of the RFC
  105. */
  106. #define ABS(a) ((a >= 0) ? (a) : -(a))
  107. static int paeth(int a, int b, int c) {
  108. int p = a + b - c;
  109. int pa = ABS(p - a);
  110. int pb = ABS(p - b);
  111. int pc = ABS(p - c);
  112. if (pa <= pb && pa <= pc) return a;
  113. else if (pb <= pc) return b;
  114. return c;
  115. }
  116. /**
  117. * Handle decompressed output from the inflater
  118. *
  119. * Writes pixel data to the image, and applies relevant filters.
  120. */
  121. static void _write(struct inflate_context * ctx, unsigned int sym) {
  122. struct png_ctx * c = (ctx->input_priv);
  123. /* Put this byte into the short buffer */
  124. c->buffer[c->buf_off] = sym;
  125. c->buf_off++;
  126. /* If this is the beginning of a scanline... */
  127. if (c->x == -1 && c->buf_off == 1) {
  128. /* Then this is the scanline filter type */
  129. c->sf = sym;
  130. /* Reset the buffer, advance to the beginning of the actual scanline */
  131. c->x = 0;
  132. c->buf_off = 0;
  133. } else if (c->buf_off == 4) {
  134. /*
  135. * Obtain pixel data from short buffer;
  136. * For color type 6, this is always in R G B A order in the
  137. * bytestream, so we don't have to worry about subpixel ordering
  138. * or weird color masks.
  139. */
  140. unsigned int r = c->buffer[0];
  141. unsigned int g = c->buffer[1];
  142. unsigned int b = c->buffer[2];
  143. unsigned int a = c->buffer[3];
  144. /* Apply filters */
  145. if (c->sf == PNG_FILTER_SUB) {
  146. /* Add raw value to the pixel on the left */
  147. if (c->x > 0) {
  148. uint32_t left = SPRITE((c->sprite), (c->x - 1), (c->y));
  149. r += _RED(left);
  150. g += _GRE(left);
  151. b += _BLU(left);
  152. a += _ALP(left);
  153. }
  154. } else if (c->sf == PNG_FILTER_UP) {
  155. /* Add raw value to the pixel above */
  156. if (c->y > 0) {
  157. uint32_t up = SPRITE((c->sprite), (c->x), (c->y - 1));
  158. r += _RED(up);
  159. g += _GRE(up);
  160. b += _BLU(up);
  161. a += _ALP(up);
  162. }
  163. } else if (c->sf == PNG_FILTER_AVG) {
  164. /* Add raw value to the average of the pixel above and left */
  165. uint32_t left = (c->x > 0) ? SPRITE((c->sprite), (c->x - 1), (c->y)) : 0;
  166. uint32_t up = (c->y > 0) ? SPRITE((c->sprite), (c->x), (c->y - 1)) : 0;
  167. r += ((int)_RED(left) + (int)_RED(up)) / 2;
  168. g += ((int)_GRE(left) + (int)_GRE(up)) / 2;
  169. b += ((int)_BLU(left) + (int)_BLU(up)) / 2;
  170. a += ((int)_ALP(left) + (int)_ALP(up)) / 2;
  171. } else if (c->sf == PNG_FILTER_PAETH) {
  172. /* Use the Paeth predictor */
  173. uint32_t left = (c->x > 0) ? SPRITE((c->sprite), (c->x - 1), (c->y)) : 0;
  174. uint32_t up = (c->y > 0) ? SPRITE((c->sprite), (c->x), (c->y - 1)) : 0;
  175. uint32_t upleft = (c->x > 0 && c->y > 0) ? SPRITE((c->sprite), (c->x - 1), (c->y - 1)) : 0;
  176. r = ((int)r + paeth((int)_RED(left),(int)_RED(up),(int)_RED(upleft))) % 256;
  177. g = ((int)g + paeth((int)_GRE(left),(int)_GRE(up),(int)_GRE(upleft))) % 256;
  178. b = ((int)b + paeth((int)_BLU(left),(int)_BLU(up),(int)_BLU(upleft))) % 256;
  179. a = ((int)a + paeth((int)_ALP(left),(int)_ALP(up),(int)_ALP(upleft))) % 256;
  180. }
  181. /* Write new pixel to the image */
  182. SPRITE((c->sprite), (c->x), (c->y)) = rgba(r,g,b,a);
  183. /* Reset the short buffer */
  184. c->buf_off = 0;
  185. /* Advance to next pixel */
  186. c->x++;
  187. if (c->x == (int)c->width) {
  188. /* Advance to next line; next read is scanline filter type */
  189. c->x = -1;
  190. c->y++;
  191. }
  192. }
  193. }
  194. int load_sprite_png(sprite_t * sprite, char * filename) {
  195. FILE * f = fopen(filename,"r");
  196. if (!f) {
  197. fprintf(stderr, "Failed to open file %s\n", filename);
  198. return 1;
  199. }
  200. /* Read the PNG signature */
  201. unsigned char sig[] = {137, 80, 78, 71, 13, 10, 26, 10};
  202. for (int i = 0; i < 8; ++i) {
  203. unsigned char c = fgetc(f);
  204. if (c != sig[i]) {
  205. fprintf(stderr, "byte %d (%d) does not match expected (%d)\n", i, c, sig[i]);
  206. goto _error;
  207. }
  208. }
  209. /* Set up context for future calls to inflate */
  210. struct png_ctx c;
  211. c.sprite = sprite;
  212. c.x = -1;
  213. c.y = 0;
  214. c.f = f;
  215. c.buf_off = 0;
  216. c.seen_ihdr = 0;
  217. while (1) {
  218. /* read chunks */
  219. unsigned int size = read_32(f);
  220. unsigned int type = read_32(f);
  221. if (feof(f)) break;
  222. switch (type) {
  223. case PNG_IHDR:
  224. {
  225. /* Image should only have one IHDR */
  226. if (c.seen_ihdr) return 1;
  227. c.seen_ihdr = 1;
  228. c.width = read_32(f); /* 4 */
  229. c.height = read_32(f); /* 8 */
  230. c.bit_depth = fgetc(f); /* 9 */
  231. c.color_type = fgetc(f); /* 10 */
  232. c.compression = fgetc(f); /* 11 */
  233. c.filter = fgetc(f); /* 12 */
  234. c.interlace = fgetc(f); /* 13 */
  235. /* Invalid / non-standard compression and filter types */
  236. if (c.compression != 0) return 1;
  237. if (c.filter != 0) return 1;
  238. /* 0 for none, 1 for Adam7 */
  239. if (c.interlace != 0 && c.interlace != 1) return 1;
  240. if (c.bit_depth != 8) return 1; /* Sorry */
  241. if (c.color_type != 6) return 1; /* Sorry */
  242. /* Allocate space */
  243. sprite->width = c.width;
  244. sprite->height = c.height;
  245. sprite->bitmap = malloc(sizeof(uint32_t) * sprite->width * sprite->height);
  246. sprite->masks = NULL;
  247. sprite->alpha = (c.color_type == 4 || c.color_type == 6) ? ALPHA_EMBEDDED : 0;
  248. sprite->blank = 0;
  249. /* Skip */
  250. for (unsigned int i = 13; i < size; ++i) fgetc(f);
  251. }
  252. break;
  253. case PNG_IDAT:
  254. {
  255. /* First two bytes of IDAT data are ZLIB header */
  256. unsigned int cflags = fgetc(f);
  257. if ((cflags & 0xF) != 8) {
  258. /* Compression type must be 8 */
  259. fprintf(stderr, "Expected flags to be 8 but it's 0x%x\n", cflags);
  260. return 1;
  261. }
  262. unsigned int aflags = fgetc(f);
  263. if (aflags & (1 << 5)) {
  264. fprintf(stderr, "There are preset bytes and I don't know what to do.\n");
  265. return 1;
  266. }
  267. struct inflate_context ctx;
  268. ctx.input_priv = &c;
  269. ctx.output_priv = &c;
  270. ctx.get_input = _get;
  271. ctx.write_output = _write;
  272. ctx.ring = NULL; /* use builtin */
  273. c.size = size - 2; /* 2 for the bytes we already read */
  274. deflate_decompress(&ctx);
  275. /* The IDATs contain a ZLIB stream, so they end with an
  276. * adler32 checksum. Skip that. */
  277. unsigned int adler = read_32(f);
  278. (void)adler;
  279. }
  280. break;
  281. case PNG_IEND:
  282. /* We don't actually have anything to do here. */
  283. break;
  284. default:
  285. /* IHDR must be first */
  286. if (!c.seen_ihdr) return 1;
  287. //fprintf(stderr, "I don't know what this is! %4s 0x%x\n", reorder_type(type), type);
  288. /* Skip */
  289. for (unsigned int i = 0; i < size; ++i) fgetc(f);
  290. break;
  291. }
  292. unsigned int crc32 = read_32(f);
  293. (void)crc32;
  294. }
  295. /*
  296. * Data in PNGs is unpremultiplied, but our sprites expect
  297. * premultiplied alpha, so convert the image data
  298. */
  299. for (int y = 0; y < sprite->height; ++y) {
  300. for (int x = 0; x < sprite->width; ++x) {
  301. SPRITE(sprite,x,y) = premultiply(SPRITE(sprite,x,y));
  302. }
  303. }
  304. return 0;
  305. _error:
  306. fclose(f);
  307. return 1;
  308. }