aimage.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5. #include "../../sources/libs/lz4x.h"
  6. #define STBI_KEEP_STDIO
  7. #define STB_IMAGE_IMPLEMENTATION
  8. #include "../../sources/libs/stb_image.h"
  9. #define STB_IMAGE_WRITE_IMPLEMENTATION
  10. #include "../../sources/libs/stb_image_write.h"
  11. #define STB_IMAGE_RESIZE_IMPLEMENTATION
  12. #include "stb_image_resize.h"
  13. typedef struct image {
  14. void *data;
  15. int width;
  16. int height;
  17. bool is_hdr;
  18. } gpu_texture_t;
  19. static bool ends_with(const char *s, const char *end) {
  20. size_t len_s = strlen(s);
  21. size_t len_end = strlen(end);
  22. return strncmp(s + len_s - len_end, end, len_end) == 0;
  23. }
  24. static gpu_texture_t read_png_jpg(const char *filename) {
  25. int width, height, n;
  26. char *data = stbi_load(filename, &width, &height, &n, 4);
  27. gpu_texture_t img = { .data = data, .width = width, .height = height, .is_hdr = false };
  28. return img;
  29. }
  30. static gpu_texture_t read_hdr(const char *filename) {
  31. int width, height, n;
  32. float *data = stbi_loadf(filename, &width, &height, &n, 4);
  33. gpu_texture_t img = { .data = data, .width = width, .height = height, .is_hdr = true };
  34. return img;
  35. }
  36. static void *scale_image(gpu_texture_t img, int width, int height) {
  37. unsigned char *scaled = malloc(width * height * 4);
  38. stbir_resize_uint8_generic(img.data, img.width, img.height, img.width * 4, scaled, width, height, width * 4, 4, 3, 0,
  39. STBIR_EDGE_CLAMP, STBIR_FILTER_BOX, STBIR_COLORSPACE_SRGB, 0);
  40. return scaled;
  41. }
  42. // Courtesy of https://github.com/Kode/kraffiti
  43. static void write_ico_header(FILE *file) {
  44. fputc(0, file);
  45. fputc(0, file);
  46. short type_ico = 1;
  47. fwrite(&type_ico, 1, 2, file);
  48. short img_count = 5;
  49. fwrite(&img_count, 1, 2, file);
  50. }
  51. static void write_ico_entry(FILE *file, int width, int height, int size, int offset) {
  52. fputc(width == 256 ? 0 : width, file);
  53. fputc(height == 256 ? 0 : height, file);
  54. fputc(0, file);
  55. fputc(0, file);
  56. short color_planes = 1;
  57. fwrite(&color_planes, 1, 2, file);
  58. short bpp = 32;
  59. fwrite(&bpp, 1, 2, file);
  60. fwrite(&size, 1, 4, file);
  61. fwrite(&offset, 1, 4, file);
  62. }
  63. void export_ico(const char *from, const char *to) {
  64. gpu_texture_t img = read_png_jpg(from);
  65. FILE *file = fopen(to, "wb");
  66. unsigned char *data256 = scale_image(img, 256, 256);
  67. unsigned char *data48 = scale_image(img, 48, 48);
  68. unsigned char *data32 = scale_image(img, 32, 32);
  69. unsigned char *data24 = scale_image(img, 24, 24);
  70. unsigned char *data16 = scale_image(img, 16, 16);
  71. int comp = 4;
  72. int png256_len;
  73. int png48_len;
  74. int png32_len;
  75. int png24_len;
  76. int png16_len;
  77. unsigned char *png256 = stbi_write_png_to_mem(data256, 256 * comp, 256, 256, comp, &png256_len);
  78. unsigned char *png48 = stbi_write_png_to_mem(data48, 48 * comp, 48, 48, comp, &png48_len);
  79. unsigned char *png32 = stbi_write_png_to_mem(data32, 32 * comp, 32, 32, comp, &png32_len);
  80. unsigned char *png24 = stbi_write_png_to_mem(data24, 24 * comp, 24, 24, comp, &png24_len);
  81. unsigned char *png16 = stbi_write_png_to_mem(data16, 16 * comp, 16, 16, comp, &png16_len);
  82. write_ico_header(file);
  83. const int ico_header_size = 6;
  84. const int ico_entry_size = 16;
  85. int ico_offset = ico_header_size + ico_entry_size * 5;
  86. write_ico_entry(file, 16, 16, png16_len, ico_offset);
  87. ico_offset += png16_len;
  88. write_ico_entry(file, 24, 24, png24_len, ico_offset);
  89. ico_offset += png24_len;
  90. write_ico_entry(file, 32, 32, png32_len, ico_offset);
  91. ico_offset += png32_len;
  92. write_ico_entry(file, 48, 48, png48_len, ico_offset);
  93. ico_offset += png48_len;
  94. write_ico_entry(file, 256, 256, png256_len, ico_offset);
  95. fwrite(png16, 1, png16_len, file);
  96. fwrite(png24, 1, png24_len, file);
  97. fwrite(png32, 1, png32_len, file);
  98. fwrite(png48, 1, png48_len, file);
  99. fwrite(png256, 1, png256_len, file);
  100. fclose(file);
  101. free(data256);
  102. free(data48);
  103. free(data32);
  104. free(data24);
  105. free(data16);
  106. free(png256);
  107. free(png48);
  108. free(png32);
  109. free(png24);
  110. free(png16);
  111. }
  112. void export_png(const char *from, const char *to, int width, int height) {
  113. gpu_texture_t img = read_png_jpg(from);
  114. if (width > 0 && height > 0) {
  115. unsigned char *scaled = scale_image(img, width, height);
  116. free(img.data);
  117. img.data = scaled;
  118. }
  119. else {
  120. width = img.width;
  121. height = img.height;
  122. }
  123. int comp = 4;
  124. stbi_write_png(to, width, height, comp, (unsigned char *)img.data, width * comp);
  125. free(img.data);
  126. }
  127. static void write_k(int width, int height, const char *format, char *data, int size, const char *filename) {
  128. FILE *file = fopen(filename, "wb");
  129. fputc((unsigned char)width, file);
  130. fputc((unsigned char)(width >> 8), file);
  131. fputc((unsigned char)(width >> 16), file);
  132. fputc((unsigned char)(width >> 24), file);
  133. fputc((unsigned char)height, file);
  134. fputc((unsigned char)(height >> 8), file);
  135. fputc((unsigned char)(height >> 16), file);
  136. fputc((unsigned char)(height >> 24), file);
  137. fputc(format[0], file);
  138. fputc(format[1], file);
  139. fputc(format[2], file);
  140. fputc(format[3], file);
  141. fwrite(data, 1, size, file);
  142. fclose(file);
  143. }
  144. void export_k(const char *from, const char *to) {
  145. gpu_texture_t img;
  146. if (ends_with(from, ".hdr")) {
  147. img = read_hdr(from);
  148. }
  149. else {
  150. img = read_png_jpg(from);
  151. }
  152. int pixel_size = img.is_hdr ? 16 : 4;
  153. int max = LZ4_compress_bound(img.width * img.height * pixel_size);
  154. char *compressed = malloc(max);
  155. int compressed_size = LZ4_compress_default((char *)img.data, compressed, img.width * img.height * pixel_size, max);
  156. write_k(img.width, img.height, img.is_hdr ? "LZ4F" : "LZ4 ", compressed, compressed_size, to);
  157. free(compressed);
  158. free(img.data);
  159. }