mksdf.cc (2282B)
1 /* Copyright 2013 Brian Swetland <swetland@frotz.net> 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 19 #include <math.h> 20 21 #include "util.h" 22 23 unsigned char *tex; 24 unsigned tw, th; 25 26 unsigned sample(int x, int y) { 27 if (x < 0) x = 0; 28 if (x >= tw) x = tw-1; 29 if (y < 0) y = 0; 30 if (y > th) y = th-1; 31 return tex[x + y * tw] >> 7; 32 } 33 34 /* this is absurdly brute-force and clunky */ 35 unsigned distance(int cx, int cy, int d) { 36 int x, y; 37 float dn = d*d+1.0, t; 38 unsigned cs = sample(cx, cy); 39 unsigned r; 40 41 for (y = cy - d; y <= cy + d; y++) { 42 for (x = cx - d; x <= cx + d; x++) { 43 if (sample(x, y) != cs) { 44 t = (cx-x)*(cx-x)+(cy-y)*(cy-y); 45 if (t < dn) dn = t; 46 } 47 } 48 } 49 50 dn = sqrt(dn); 51 r = ((127.0 * dn) / ((float) d)); 52 if (r > 127) r = 127; 53 if (cs) 54 return 127 - r; 55 else 56 return 127 + r; 57 } 58 59 /* for each texel in the output texture, find the distance from its 60 * corresponding texel in the input texture to the nearest pixel of 61 * the opposite color 62 */ 63 void generate(unsigned char *map, int mw, int mh, int d) { 64 int x, y; 65 int up = tw / mw; 66 int dn = up / 2; 67 for (y = 0; y < mh; y++) 68 for (x = 0; x < mh; x++) 69 map[y*mw+x] = distance(x * up + dn, y * up + dn, d); 70 } 71 72 int main(int argc, char **argv) { 73 unsigned char *map; 74 unsigned mw, mh; 75 76 if (argc != 4) { 77 fprintf(stderr,"usage: mksdf <pngfile> <size> <outfile>\n"); 78 return -1; 79 } 80 81 mw = mh = atoi(argv[2]); 82 83 if (!(map = (unsigned char*) malloc(mw * mh))) { 84 fprintf(stderr,"out of memory\n"); 85 return -1; 86 } 87 88 tex = (unsigned char*) load_png_gray(argv[1], &tw, &th, 0); 89 if (!tex) { 90 fprintf(stderr,"cannot load source image '%s'\n", argv[1]); 91 return -1; 92 } 93 94 generate(map, mw, mh, tw / mw); 95 96 return save_png_gray(argv[3], map, mw, mh); 97 } 98