eobish

view 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 source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <math.h>
5 #include <float.h>
6 #include <errno.h>
7 #ifndef WIN32
8 #include <alloca.h>
9 #else
10 #include <malloc.h>
11 #endif
12 #include <imago2.h>
14 struct palentry {
15 float r, g, b;
16 struct palentry *next;
17 };
19 int load_palette(const char *fname);
20 int proc_tile(const char *fname);
21 float find_nearest(float r, float g, float b);
23 struct palentry *palette;
24 int palsize;
26 int main(int argc, char **argv)
27 {
28 int i;
30 for(i=1; i<argc; i++) {
31 if(argv[i][0] == '-') {
32 switch(argv[i][1]) {
33 case 'p':
34 if(load_palette(argv[++i]) == -1) {
35 return 1;
36 }
37 break;
39 default:
40 fprintf(stderr, "invalid option: %s\n", argv[i]);
41 return 1;
42 }
43 } else {
44 if(proc_tile(argv[i]) == -1) {
45 return 1;
46 }
47 }
48 }
49 return 0;
50 }
52 int load_palette(const char *fname)
53 {
54 FILE *fp;
55 char buf[128];
56 struct palentry *newpal;
57 struct palentry *head = 0, *tail;
58 int nent = 0;
60 if(!(fp = fopen(fname, "r"))) {
61 fprintf(stderr, "failed to open palette file: %s: %s\n", fname, strerror(errno));
62 return -1;
63 }
65 while(fgets(buf, sizeof buf, fp)) {
66 struct palentry *pent;
67 char *endp, *line = buf;
68 int r, g, b;
70 if(!line || !*line) continue;
72 if(*line == '#') { /* hex html-like values */
73 unsigned int val = strtol(line + 1, &endp, 16);
74 if(endp == line) {
75 fprintf(stderr, "unrecognized line \"%s\" in palette file: %s\n", line, fname);
76 goto fail;
77 }
79 r = (val >> 16) & 0xff;
80 g = (val >> 8) & 0xff;
81 b = val & 0xff;
82 } else {
83 fprintf(stderr, "unrecognized line \"%s\" in palette file: %s\n", line, fname);
84 goto fail;
85 }
87 if(!(pent = malloc(sizeof *pent))) {
88 perror("failed to allocate palette entry");
89 goto fail;
90 }
91 pent->r = (float)r / 255.0;
92 pent->g = (float)g / 255.0;
93 pent->b = (float)b / 255.0;
94 pent->next = 0;
96 if(head) {
97 tail->next = pent;
98 tail = pent;
99 } else {
100 head = tail = pent;
101 }
102 nent++;
103 }
105 /* flatten */
106 if(!(newpal = malloc(nent * sizeof *newpal))) {
107 fprintf(stderr, "failed to allocate %d palette entries: %s\n", nent, strerror(errno));
108 goto fail;
109 }
110 palette = newpal;
111 palsize = nent;
113 while(head) {
114 struct palentry *ent = head;
115 head = head->next;
117 *newpal++ = *ent;
118 free(ent);
119 }
121 printf("loaded palette: %s (%d colors)\n", fname, nent);
123 fclose(fp);
124 return 0;
126 fail:
127 fclose(fp);
128 while(head) {
129 void *tmp = head;
130 head = head->next;
131 free(tmp);
132 }
133 return -1;
134 }
136 int proc_tile(const char *fname)
137 {
138 int i;
139 int xsz, ysz;
140 unsigned char *pixels, *pptr;
141 char *outfname, *cptr;
142 FILE *fp;
143 const char *magic = "TILEIMAG";
145 outfname = alloca(strlen(fname) + 4);
146 strcpy(outfname, fname);
147 if((cptr = strrchr(outfname, '.'))) {
148 *cptr = 0;
149 }
150 strcat(outfname, ".til");
152 printf("processing tile: %s -> %s\n", fname, outfname);
154 if(!(pixels = img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGB24))) {
155 fprintf(stderr, "failed to load source tile image: %s\n", fname);
156 return -1;
157 }
158 if(!(fp = fopen(outfname, "wb"))) {
159 fprintf(stderr, "failed to open output tile image for writing: %s: %s\n", outfname, strerror(errno));
160 img_free_pixels(pixels);
161 return -1;
162 }
163 /* write header */
164 fwrite(magic, 1, 8, fp);
165 fwrite(&xsz, sizeof xsz, 1, fp);
166 fwrite(&ysz, sizeof ysz, 1, fp);
168 pptr = pixels;
169 for(i=0; i<xsz * ysz; i++) {
170 int idx = find_nearest(pptr[0] / 255.0, pptr[1] / 255.0, pptr[2] / 255.0);
171 fputc(idx, fp);
172 pptr += 3;
173 }
174 img_free_pixels(pixels);
175 fclose(fp);
176 return 0;
177 }
179 float find_nearest(float r, float g, float b)
180 {
181 int i, res;
182 float mindist = FLT_MAX;
184 for(i=0; i<palsize; i++) {
185 float dr = r - palette[i].r;
186 float dg = g - palette[i].g;
187 float db = b - palette[i].b;
188 float dist = dr * dr + dg * dg + db * db;
190 if(dist < mindist) {
191 mindist = dist;
192 res = i;
193 }
194 }
195 return res;
196 }