eobish
diff utils/tileproc.c @ 0:465ca72c9657
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 17 Jan 2015 18:37:28 +0200 |
parents | |
children | 0baf4e98315e |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/utils/tileproc.c Sat Jan 17 18:37:28 2015 +0200 1.3 @@ -0,0 +1,196 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <string.h> 1.7 +#include <math.h> 1.8 +#include <float.h> 1.9 +#include <errno.h> 1.10 +#ifndef WIN32 1.11 +#include <alloca.h> 1.12 +#else 1.13 +#include <malloc.h> 1.14 +#endif 1.15 +#include <imago2.h> 1.16 + 1.17 +struct palentry { 1.18 + float r, g, b; 1.19 + struct palentry *next; 1.20 +}; 1.21 + 1.22 +int load_palette(const char *fname); 1.23 +int proc_tile(const char *fname); 1.24 +float find_nearest(float r, float g, float b); 1.25 + 1.26 +struct palentry *palette; 1.27 +int palsize; 1.28 + 1.29 +int main(int argc, char **argv) 1.30 +{ 1.31 + int i; 1.32 + 1.33 + for(i=1; i<argc; i++) { 1.34 + if(argv[i][0] == '-') { 1.35 + switch(argv[i][1]) { 1.36 + case 'p': 1.37 + if(load_palette(argv[++i]) == -1) { 1.38 + return 1; 1.39 + } 1.40 + break; 1.41 + 1.42 + default: 1.43 + fprintf(stderr, "invalid option: %s\n", argv[i]); 1.44 + return 1; 1.45 + } 1.46 + } else { 1.47 + if(proc_tile(argv[i]) == -1) { 1.48 + return 1; 1.49 + } 1.50 + } 1.51 + } 1.52 + return 0; 1.53 +} 1.54 + 1.55 +int load_palette(const char *fname) 1.56 +{ 1.57 + FILE *fp; 1.58 + char buf[128]; 1.59 + struct palentry *newpal; 1.60 + struct palentry *head = 0, *tail; 1.61 + int nent = 0; 1.62 + 1.63 + if(!(fp = fopen(fname, "r"))) { 1.64 + fprintf(stderr, "failed to open palette file: %s: %s\n", fname, strerror(errno)); 1.65 + return -1; 1.66 + } 1.67 + 1.68 + while(fgets(buf, sizeof buf, fp)) { 1.69 + struct palentry *pent; 1.70 + char *endp, *line = buf; 1.71 + int r, g, b; 1.72 + 1.73 + if(!line || !*line) continue; 1.74 + 1.75 + if(*line == '#') { /* hex html-like values */ 1.76 + unsigned int val = strtol(line + 1, &endp, 16); 1.77 + if(endp == line) { 1.78 + fprintf(stderr, "unrecognized line \"%s\" in palette file: %s\n", line, fname); 1.79 + goto fail; 1.80 + } 1.81 + 1.82 + r = (val >> 16) & 0xff; 1.83 + g = (val >> 8) & 0xff; 1.84 + b = val & 0xff; 1.85 + } else { 1.86 + fprintf(stderr, "unrecognized line \"%s\" in palette file: %s\n", line, fname); 1.87 + goto fail; 1.88 + } 1.89 + 1.90 + if(!(pent = malloc(sizeof *pent))) { 1.91 + perror("failed to allocate palette entry"); 1.92 + goto fail; 1.93 + } 1.94 + pent->r = (float)r / 255.0; 1.95 + pent->g = (float)g / 255.0; 1.96 + pent->b = (float)b / 255.0; 1.97 + pent->next = 0; 1.98 + 1.99 + if(head) { 1.100 + tail->next = pent; 1.101 + tail = pent; 1.102 + } else { 1.103 + head = tail = pent; 1.104 + } 1.105 + nent++; 1.106 + } 1.107 + 1.108 + /* flatten */ 1.109 + if(!(newpal = malloc(nent * sizeof *newpal))) { 1.110 + fprintf(stderr, "failed to allocate %d palette entries: %s\n", nent, strerror(errno)); 1.111 + goto fail; 1.112 + } 1.113 + palette = newpal; 1.114 + palsize = nent; 1.115 + 1.116 + while(head) { 1.117 + struct palentry *ent = head; 1.118 + head = head->next; 1.119 + 1.120 + *newpal++ = *ent; 1.121 + free(ent); 1.122 + } 1.123 + 1.124 + printf("loaded palette: %s (%d colors)\n", fname, nent); 1.125 + 1.126 + fclose(fp); 1.127 + return 0; 1.128 + 1.129 +fail: 1.130 + fclose(fp); 1.131 + while(head) { 1.132 + void *tmp = head; 1.133 + head = head->next; 1.134 + free(tmp); 1.135 + } 1.136 + return -1; 1.137 +} 1.138 + 1.139 +int proc_tile(const char *fname) 1.140 +{ 1.141 + int i; 1.142 + int xsz, ysz; 1.143 + unsigned char *pixels, *pptr; 1.144 + char *outfname, *cptr; 1.145 + FILE *fp; 1.146 + const char *magic = "TILEIMAG"; 1.147 + 1.148 + outfname = alloca(strlen(fname) + 4); 1.149 + strcpy(outfname, fname); 1.150 + if((cptr = strrchr(outfname, '.'))) { 1.151 + *cptr = 0; 1.152 + } 1.153 + strcat(outfname, ".til"); 1.154 + 1.155 + printf("processing tile: %s -> %s\n", fname, outfname); 1.156 + 1.157 + if(!(pixels = img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGB24))) { 1.158 + fprintf(stderr, "failed to load source tile image: %s\n", fname); 1.159 + return -1; 1.160 + } 1.161 + if(!(fp = fopen(outfname, "wb"))) { 1.162 + fprintf(stderr, "failed to open output tile image for writing: %s: %s\n", outfname, strerror(errno)); 1.163 + img_free_pixels(pixels); 1.164 + return -1; 1.165 + } 1.166 + /* write header */ 1.167 + fwrite(magic, 1, 8, fp); 1.168 + fwrite(&xsz, sizeof xsz, 1, fp); 1.169 + fwrite(&ysz, sizeof ysz, 1, fp); 1.170 + 1.171 + pptr = pixels; 1.172 + for(i=0; i<xsz * ysz; i++) { 1.173 + int idx = find_nearest(pptr[0] / 255.0, pptr[1] / 255.0, pptr[2] / 255.0); 1.174 + fputc(idx, fp); 1.175 + pptr += 3; 1.176 + } 1.177 + img_free_pixels(pixels); 1.178 + fclose(fp); 1.179 + return 0; 1.180 +} 1.181 + 1.182 +float find_nearest(float r, float g, float b) 1.183 +{ 1.184 + int i, res; 1.185 + float mindist = FLT_MAX; 1.186 + 1.187 + for(i=0; i<palsize; i++) { 1.188 + float dr = r - palette[i].r; 1.189 + float dg = g - palette[i].g; 1.190 + float db = b - palette[i].b; 1.191 + float dist = dr * dr + dg * dg + db * db; 1.192 + 1.193 + if(dist < mindist) { 1.194 + mindist = dist; 1.195 + res = i; 1.196 + } 1.197 + } 1.198 + return res; 1.199 +}