rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 A simple interactive mandelbrot fractal explorer
|
nuclear@0
|
3 Copyright (C) John Tsiombikas <nuclear@member.fsf.org>
|
nuclear@0
|
4
|
nuclear@0
|
5 This program is free software: you can redistribute it and/or modify
|
nuclear@0
|
6 it under the terms of the GNU General Public License as published by
|
nuclear@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
nuclear@0
|
8 (at your option) any later version.
|
nuclear@0
|
9
|
nuclear@0
|
10 This program is distributed in the hope that it will be useful,
|
nuclear@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@0
|
13 GNU General Public License for more details.
|
nuclear@0
|
14
|
nuclear@0
|
15 You should have received a copy of the GNU General Public License
|
nuclear@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
nuclear@0
|
17 */
|
nuclear@0
|
18 #include <stdio.h>
|
nuclear@0
|
19 #include <stdlib.h>
|
nuclear@0
|
20 #include <string.h>
|
nuclear@0
|
21 #include <errno.h>
|
nuclear@0
|
22 #include "palette.h"
|
nuclear@0
|
23
|
nuclear@0
|
24 struct palnode {
|
nuclear@0
|
25 double t;
|
nuclear@0
|
26 double r, g, b;
|
nuclear@0
|
27 struct palnode *next;
|
nuclear@0
|
28 };
|
nuclear@0
|
29
|
nuclear@0
|
30 static void fill_palette(struct palnode *list);
|
nuclear@0
|
31 static void free_list(struct palnode *list);
|
nuclear@0
|
32
|
nuclear@0
|
33 int load_palette(const char *fname)
|
nuclear@0
|
34 {
|
nuclear@0
|
35 FILE *fp;
|
nuclear@0
|
36 int res;
|
nuclear@0
|
37
|
nuclear@0
|
38 if(!(fp = fopen(fname, "r"))) {
|
nuclear@0
|
39 fprintf(stderr, "failed to open palette file: %s: %s\n", fname, strerror(errno));
|
nuclear@0
|
40 return -1;
|
nuclear@0
|
41 }
|
nuclear@0
|
42 res = load_palette_file(fp);
|
nuclear@0
|
43 fclose(fp);
|
nuclear@0
|
44 return res;
|
nuclear@0
|
45 }
|
nuclear@0
|
46
|
nuclear@0
|
47 int load_palette_file(FILE *fp)
|
nuclear@0
|
48 {
|
nuclear@0
|
49 char buf[256];
|
nuclear@0
|
50 struct palnode *palist = 0, *patail = 0;
|
nuclear@0
|
51
|
nuclear@0
|
52 if(!fgets(buf, sizeof buf, fp) || strstr(buf, "GRAD") != buf) {
|
nuclear@0
|
53 fprintf(stderr, "invalid palette file, lack of magic!\n");
|
nuclear@0
|
54 return -1;
|
nuclear@0
|
55 }
|
nuclear@0
|
56
|
nuclear@0
|
57 while(fgets(buf, sizeof buf, fp)) {
|
nuclear@0
|
58 struct palnode *node;
|
nuclear@0
|
59 float t, r, g, b;
|
nuclear@0
|
60
|
nuclear@0
|
61 if(sscanf(buf, "%f %f %f %f", &t, &r, &g, &b) != 4) {
|
nuclear@0
|
62 fprintf(stderr, "invalid palette file format\n");
|
nuclear@0
|
63 free_list(palist);
|
nuclear@0
|
64 return -1;
|
nuclear@0
|
65 }
|
nuclear@0
|
66
|
nuclear@0
|
67 if(!(node = malloc(sizeof *node))) {
|
nuclear@0
|
68 fprintf(stderr, "failed to allocate memory for list node\n");
|
nuclear@0
|
69 free_list(palist);
|
nuclear@0
|
70 return -1;
|
nuclear@0
|
71 }
|
nuclear@0
|
72 node->t = t;
|
nuclear@0
|
73 node->r = r;
|
nuclear@0
|
74 node->g = g;
|
nuclear@0
|
75 node->b = b;
|
nuclear@0
|
76 node->next = 0;
|
nuclear@0
|
77
|
nuclear@0
|
78 if(palist) {
|
nuclear@0
|
79 patail->next = node;
|
nuclear@0
|
80 patail = node;
|
nuclear@0
|
81 } else {
|
nuclear@0
|
82 palist = patail = node;
|
nuclear@0
|
83 }
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@0
|
86 fill_palette(palist);
|
nuclear@0
|
87 free_list(palist);
|
nuclear@0
|
88 return 0;
|
nuclear@0
|
89 }
|
nuclear@0
|
90
|
nuclear@0
|
91 static void fill_palette(struct palnode *list)
|
nuclear@0
|
92 {
|
nuclear@0
|
93 int i;
|
nuclear@0
|
94 struct palnode *start, *end;
|
nuclear@0
|
95 static const struct palnode last = {1.0, 0.0, 0.0, 0.0, 0};
|
nuclear@0
|
96
|
nuclear@0
|
97 memset(palette, 0, sizeof palette);
|
nuclear@0
|
98 if(!list) {
|
nuclear@0
|
99 return;
|
nuclear@0
|
100 }
|
nuclear@0
|
101
|
nuclear@0
|
102 start = list;
|
nuclear@0
|
103 end = list->next;
|
nuclear@0
|
104
|
nuclear@0
|
105 while(start && start != &last) {
|
nuclear@0
|
106 int sidx, eidx, count;
|
nuclear@0
|
107 double r, g, b, dr, dg, db;
|
nuclear@0
|
108
|
nuclear@0
|
109 if(!end) {
|
nuclear@0
|
110 end = (struct palnode*)&last;
|
nuclear@0
|
111 }
|
nuclear@0
|
112
|
nuclear@0
|
113 sidx = (int)(start->t * PAL_SIZE);
|
nuclear@0
|
114 eidx = (int)(end->t * PAL_SIZE);
|
nuclear@0
|
115 count = eidx - sidx;
|
nuclear@0
|
116
|
nuclear@0
|
117 r = start->r;
|
nuclear@0
|
118 g = start->g;
|
nuclear@0
|
119 b = start->b;
|
nuclear@0
|
120 dr = (end->r - start->r) / count;
|
nuclear@0
|
121 dg = (end->g - start->g) / count;
|
nuclear@0
|
122 db = (end->b - start->b) / count;
|
nuclear@0
|
123
|
nuclear@0
|
124 for(i=0; i<count; i++) {
|
nuclear@0
|
125 palette[sidx + i].r = (int)(r * 255.0);
|
nuclear@0
|
126 palette[sidx + i].g = (int)(g * 255.0);
|
nuclear@0
|
127 palette[sidx + i].b = (int)(b * 255.0);
|
nuclear@0
|
128 r += dr;
|
nuclear@0
|
129 g += dg;
|
nuclear@0
|
130 b += db;
|
nuclear@0
|
131 }
|
nuclear@0
|
132
|
nuclear@0
|
133 start = end;
|
nuclear@0
|
134 end = end->next;
|
nuclear@0
|
135 }
|
nuclear@0
|
136 }
|
nuclear@0
|
137
|
nuclear@0
|
138 static void free_list(struct palnode *list)
|
nuclear@0
|
139 {
|
nuclear@0
|
140 while(list) {
|
nuclear@0
|
141 void *tmp = list;
|
nuclear@0
|
142 list = list->next;
|
nuclear@0
|
143 free(tmp);
|
nuclear@0
|
144 }
|
nuclear@0
|
145 }
|