PNG  IHDR!@ PLTE>O`jqv GitEXtPage
pngenerator.c - metalympiada
git clone git://metalympiada.org/
Log | Files | README | LICENSE

pngenerator.c (5159B)


   1 #include <math.h>
   2 #include <png.h>
   3 #include <stdint.h>
   4 #include <stdio.h>
   5 #include <stdlib.h>
   6 #include <string.h>
   7 
   8 #define WIDTH 256
   9 #define HEIGHT 256
  10 const uint16_t ITERATIONS = 201;
  11 const uint16_t MAX_STEPS = 14;
  12 const double MIN_DISTANCE = 0.008;
  13 const size_t CAPACITY = 16384;
  14 
  15 typedef struct vec3 {
  16     double x, y, z;
  17 } vec3;
  18 
  19 static vec3 vec3_add(const vec3 a, const vec3 b) {
  20     vec3 v = {a.x + b.x, a.y + b.y, a.z + b.z};
  21     return v;
  22 }
  23 
  24 static vec3 vec3_sub(const vec3 a, const vec3 b) {
  25     vec3 v = {a.x - b.x, a.y - b.y, a.z - b.z};
  26     return v;
  27 }
  28 
  29 static vec3 vec3_mult(const vec3 a, const double c) {
  30     vec3 v = {c*a.x, c*a.y, c*a.z};
  31     return v;
  32 }
  33 
  34 static double sqnorm(const vec3 v) {
  35     return v.x*v.x + v.y*v.y + v.z*v.z;
  36 }
  37 
  38 static double norm(const vec3 v) {
  39     return sqrt(sqnorm(v));
  40 }
  41 
  42 static double vec3_sqdist(const vec3 v, const vec3 w) {
  43     return sqnorm(vec3_sub(v, w));
  44 }
  45 
  46 typedef struct slice {
  47     char* buffer;
  48     size_t len;
  49     size_t cap;
  50 } slice;
  51 
  52 static void
  53 png_write_slice(png_structp png_ptr, const png_bytep data, const png_size_t size)
  54 {
  55     slice* p = png_get_io_ptr(png_ptr);
  56     if ((p->len + size) > p->cap) {
  57         size_t newcap = 2*p->cap + size;
  58         p->buffer = realloc(p->buffer, newcap);
  59         p->cap = newcap;
  60     }
  61     memcpy(p->buffer + p->len, data, size);
  62     p->len += size;
  63 }
  64 
  65 static png_color
  66 num2col(const uint32_t num)
  67 {
  68     png_color col = {(num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff};
  69     return col;
  70 }
  71 
  72 extern slice
  73 pngenerate(char * const text, const uint32_t background, const uint32_t foreground)
  74 {
  75     slice state = {
  76         .buffer = malloc(CAPACITY),
  77         .len = 0,
  78         .cap = CAPACITY
  79     };
  80 
  81     png_structp png_ptr = 
  82         png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  83     png_set_write_fn(png_ptr, &state, png_write_slice, NULL);
  84     png_infop info_ptr = png_create_info_struct(png_ptr);
  85     png_set_compression_level(png_ptr, 9);
  86 
  87     png_color b = num2col(background), f = num2col(foreground);
  88     png_color step = {(f.red - b.red) / 4, (f.green - b.green) / 4, (f.blue - b.blue) / 4};
  89     png_color palette[4];
  90     palette[0] = b;
  91     for (size_t i = 0; i < 3; i++) {
  92         png_color c = {f.red - i*step.red, f.green - i*step.green, f.blue - i*step.blue};
  93         palette[3 - i] = c;
  94     }
  95     png_set_IHDR(png_ptr, info_ptr, WIDTH, HEIGHT, 2, PNG_COLOR_TYPE_PALETTE,
  96                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
  97                  PNG_FILTER_TYPE_DEFAULT);
  98     png_set_PLTE(png_ptr, info_ptr, palette, 4);
  99 
 100     const png_text page = {
 101         .compression = PNG_TEXT_COMPRESSION_NONE,
 102         .key = "Page",
 103         .text = text
 104     };
 105     png_set_text(png_ptr, info_ptr, &page, 1);
 106 
 107     png_bytep buffer = calloc(WIDTH * HEIGHT / 4, sizeof(png_byte));
 108     png_bytep rows[HEIGHT];
 109     for (size_t i = 0; i < HEIGHT; i++)
 110         rows[i] = buffer + i * WIDTH / 4;
 111 
 112     time_t t;
 113     srand((unsigned) time(&t));
 114     
 115     vec3 v[4] = {{-sqrt(3), -sqrt(2), -1}, {sqrt(3), -sqrt(2), -1}, {0, -sqrt(2), 2}, {0, sqrt(2), 0}};
 116     double s = -sqrt(3) * ((double) rand() / RAND_MAX - 0.5);
 117     double c = sqrt(1.0 - s*s);
 118     for (size_t i = 0; i < 3; i++) {
 119         double ox = v[i].x;
 120 	v[i].x = c*v[i].x - s*v[i].z;
 121 	v[i].z = s*ox + c*v[i].z;
 122     }
 123     for (size_t j = 0; j < HEIGHT; j++) {
 124         for (size_t i = 0; i < WIDTH; i++) {
 125             double x = (double) i * 2 / (double) WIDTH - 1.0;
 126             double y = (double) j * -2 / (double) HEIGHT + 1.0;
 127             vec3 position = {x, y, -1.1};
 128             vec3 dir = {x, y, 2.2};
 129             double distance = norm(dir);
 130             const vec3 direction = vec3_mult(dir, 1.0/distance);
 131 
 132             uint16_t steps;
 133             for(steps = 0; steps < MAX_STEPS; steps++) {
 134                 double d;
 135                 vec3 p = position;
 136                 for (int i = 0; i < 9; i++) {
 137                     vec3 center = v[0];
 138                     d = vec3_sqdist(p, v[0]);
 139                     for (int j = 1; j < 4; j++) {
 140                         double di = vec3_sqdist(p, v[j]);
 141                         if (di < d) {
 142                             d = di;
 143                             center = v[j];
 144                         }
 145                     }
 146                     p = vec3_sub(vec3_mult(p, 2), center);
 147                 }
 148                 d = sqrt(d) / (double) (1 << 8);
 149                 
 150 		if (d < MIN_DISTANCE) {
 151     		    break;
 152 		}
 153 		distance += d;
 154 		if (distance >= 6.0) {
 155     		    steps = MAX_STEPS;
 156     		    break;
 157 		}
 158 		position = vec3_add(position, vec3_mult(direction, d));
 159             }
 160             char val = (char) (3.6 - 3.0*steps/MAX_STEPS) & 3;
 161             buffer[j*(WIDTH >> 2) + (i >> 2)] |= val << (((i & 3) ^ 3) << 1); 
 162         }
 163     }
 164     png_set_rows(png_ptr, info_ptr, rows);
 165 
 166     png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
 167     png_destroy_write_struct(&png_ptr, &info_ptr);
 168 
 169     return state;
 170 }
 171 
 172 int
 173 main()
 174 {
 175     FILE* fp = fopen("test.png", "wb");
 176     const slice s = pngenerate("<h1>Title</h1>Hello!!<img src=\"#\">", 0x153e4f, 0x118282);
 177     fwrite(s.buffer, 1, s.len, fp);
 178     fclose(fp);
 179     return 0;
 180 }
jUIDATxo#Gvǫ,91>8@7A[jC`(@r!i9dQ !- h%AS$ͯ^7IcB?]U{/5?ϓu kњV. r隀GzVlh=Rx= ZfPZ^ zc!Q=kQ4kQHS:vԁbuTf5(=iwe;57*\V6t$8fֽU2>q"`Yu , VH% L+Q8VHW@Wt'!mAբS-Hx^jf\uE\p V3{Aޖ)+ۂ:bSvw ?t[JvD O3 6 z&wWljdH-V0& Z]9.˨6Z9旑V\V0Z d<(^B3'`_9~ ށV+RQ߇$QI(rz`y6f2dUA.]6b(>]0@gK L=c }cIi BĒe|cfHX@v5n$8KN=J- jI#|x9wPmVUx@ @5\6ZaD:Ƒʙ* cKRSxKT^RƷc.(C=' h% N r0Y*?v 4Մ+(\o (c7i R魮8Yg@+2rəI?Āmv̦V3(C&X&? I }KAj8jHX6"d+Β 7E"p[cm%6-uMY+~& -7r 41(܏T@A] 碕V| wsh;-J&]R ނfPD[v0. 0a&uOzQƓPl+#\ArxF:{E=Jހb "- `:f͹aTCnoA38\s=P)Cg"dw7`k@bvwqbʎ#uȟ4 {ydh- oj2L Aw띦 )P&}Y%!gLMHX̛dΠ󣤇 !aH1|Ń .<3 _wT ]0Hַ-"Uk-R^^. ^dB';Nܥvrw0_]h9 mNCim]n;}-?{k's)NukmpÛfp۠V5C3th`N{Mhjfhj{ۘ'Gh__*ʴl1 {i"6:C ut {D8 0Q>; 'p GVԼ wuZUpQ:~j3[ճg({&7XWU~j ({ (K3# GU +V-LVjḧ z=Y 3}UmI]1wWp ARQ|cТ Z5* WY9z:m#TxF&f%}w`!^kupc)k:~]kOJN@gz~_ _LVQ.MsgUtvkT396ЍTe!q\bG|M̠bVx;Mn>G`x˳t]:8ܩ),IXxë3t׻pn!Q:>mpy> AI;Ā_3lЉ5p _S=>y.Cl=q)tR'WZ-2rzwW!,,5'Vx\"wW~l'%@ c.X"eݕOs&"pX}*#y=]LJb.8`3|[2T<].]XLZEtq\[CގÖnrǞHC~8/EɦC ב̪Xpg-]yPc-fT. =a$bT^6 O~6"ȏpV& NnC˭}t.:TXVOP+>m1`nJZsRihAnĊnZ0ǻp,7 4i8civ;qH˳`C(g[son@d' 9e y@ep0~0ѧ0dP\`UjC!a[6rGvO"F *v 1(oj\XACA bV9苄?qfԣ=djvI@d4"z\ڛHOS|L|9OpSF-GK/JD@d[I;$tEŏ#@"r*+oI8|4@)E2bRq~GcmdΎ@F8GojOFa})9:F(p%1?~HI5d㹰;9 uN9m<88E9Hs_xΝ#* 9͌WAO7r&#k(V 4= ٜk]C(pZaB0x &E&x@Q|I =s~m'pl-kJ8b'K,`#caRsznMT)Jם[taWIM 1_A1 P`heU v ?[FRGٛf eկCED"`2v M99!-\DJIh{@WKVf)} ^fdi8#F %6;Ey!Eg^elpj@:qoT>m>= QFm8|I. *WǝM:|ΔY\fEl8Uϫbu(جi2O#`| yetGӅvxpuZ[q^]h(8 <5%sTu^!mB=DnրQBXyN/ w5i㶒Da < G0Q8*PS4qrt<`n OGm:́4wH!8ڦ!u3qGT 7@x tK"QX&؍g`e(r (ӸfU^W1ꊝ8,`)܇l%T #\x5(p(V 7 0"s)98% %`]ݙ\8>-ZH] du3ypfbyl{^;;#SWzEOں,5z PlӠJr(DZ\(9@qruA1))(RiC_M /5OYB"|vkqh߽ˆA?W뇨GNů(4Ih znQ?W2ե \fol:AI@^2PfU,65T.o͟t|p*uÍ`8,zJJs `S 65c# 5BdK@=|[жkGKkB[\6{iJή[qL"B\{ 1E{sIENDB`