Skip to content

Commit 35962f9

Browse files
committed
Extract graphing stuff to its own files.
1 parent 07e3559 commit 35962f9

File tree

6 files changed

+201
-190
lines changed

6 files changed

+201
-190
lines changed

GNUmakefile

+4-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ endif
6464
${THE_TESTS}: is-check-installed ${THE_LIBRARY} check_mandelbrot.c
6565
${SILENT}${CC} ${CFLAGS} ${CAIRO_CFLAGS} ${GD_CFLAGS} ${CHECK_CFLAGS} -o ${THE_TESTS} check_mandelbrot.c ${THE_LIBRARY} ${LIBS} ${CAIRO_LIBS} ${GD_LIBS} ${MPC_LIBS} ${CHECK_LIBS}
6666

67-
${THE_LIBRARY}: is-cairo-installed is-gd-installed is-mpc-installed mandelbrot.h mandelbrot.c
68-
${SILENT}${CC} ${CFLAGS} ${CAIRO_CFLAGS} ${GD_CFLAGS} ${MPC_CFLAGS} -c mandelbrot.c
69-
${SILENT}ar rc ${THE_LIBRARY} mandelbrot.o
67+
${THE_LIBRARY}: is-cairo-installed is-gd-installed is-mpc-installed graph.h graph.c mandelbrot.h mandelbrot.c
68+
${SILENT}${CC} ${CFLAGS} ${CAIRO_CFLAGS} ${GD_CFLAGS} -c graph.c
69+
${SILENT}${CC} ${CFLAGS} ${MPC_CFLAGS} -c mandelbrot.c
70+
${SILENT}ar rc ${THE_LIBRARY} graph.o mandelbrot.o
7071
${SILENT}ranlib ${THE_LIBRARY}
7172

7273
${THE_PROGRAM}: ${THE_LIBRARY} mandelbrot.h main.c

check_mandelbrot.c

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <stdbool.h>
55
#include <stdio.h>
66

7+
#include "graph.h"
78
#include "mandelbrot.h"
89

910
static void

graph.c

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include <string.h>
2+
3+
#include <cairo/cairo.h>
4+
#include <gd.h>
5+
6+
#include "graph.h"
7+
8+
graph_t
9+
graph_create(const char *backend, const size_t width, const size_t height,
10+
const complex double center, const double range)
11+
{
12+
graph_t image = {
13+
0,
14+
{ NULL },
15+
width,
16+
height,
17+
center,
18+
range,
19+
get_extreme_coordinates(width, height, center, range),
20+
{
21+
{ 0, 0, 0 },
22+
{ 176, 229, 247 },
23+
{ 245, 137, 169 },
24+
{ 154, 227, 194 },
25+
},
26+
};
27+
28+
if (0 == strcmp("cairo", backend)) {
29+
image.image_type = CAIRO;
30+
31+
image.cairo_image = cairo_create(
32+
cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height));
33+
34+
cairo_set_line_width(image.cairo_image, 0.1);
35+
} else {
36+
image.image_type = GD;
37+
38+
image.gd_image = gdImageCreate(width, height);
39+
40+
for (size_t i = 0; i < NUM_COLORS; i++) {
41+
gdImageColorAllocate(image.gd_image,
42+
image.colormap[i][0],
43+
image.colormap[i][1],
44+
image.colormap[i][2]);
45+
}
46+
}
47+
48+
return image;
49+
}
50+
51+
extremes_t
52+
get_extreme_coordinates(const size_t width, const size_t height,
53+
const complex double center, const double range)
54+
{
55+
extremes_t coords;
56+
57+
if (width < height) {
58+
coords.lower_left =
59+
creal(center) - (range * width/height) / 2.0
60+
+ I * cimag(center)
61+
- I * (range) / 2.0;
62+
coords.upper_right =
63+
creal(center) + (range * width/height) / 2.0
64+
+ I * cimag(center)
65+
+ I * (range) / 2.0;
66+
} else {
67+
coords.lower_left =
68+
creal(center) - (range) / 2.0
69+
+ I * cimag(center)
70+
- I * (range * height/width) / 2.0;
71+
coords.upper_right =
72+
creal(center) + (range) / 2.0
73+
+ I * cimag(center)
74+
+ I * (range * height/width) / 2.0;
75+
}
76+
77+
return coords;
78+
}
79+
80+
static double
81+
graph_get_a(const graph_t graph, const size_t horizontal)
82+
{
83+
const double minimum_a = creal(graph.extremes.lower_left);
84+
const double maximum_a = creal(graph.extremes.upper_right);
85+
86+
return minimum_a
87+
+ horizontal / (graph.width / (maximum_a - minimum_a));
88+
}
89+
90+
static double
91+
graph_get_b(const graph_t graph, const size_t vertical)
92+
{
93+
const double minimum_b = cimag(graph.extremes.lower_left);
94+
const double maximum_b = cimag(graph.extremes.upper_right);
95+
96+
return minimum_b
97+
+ vertical / (graph.height / (maximum_b - minimum_b));
98+
}
99+
100+
complex double
101+
graph_get_coordinates(const graph_t graph, const size_t i, const size_t j)
102+
{
103+
return graph_get_a(graph, i) + I * graph_get_b(graph, j);
104+
}
105+
106+
void
107+
graph_set_pixel(const graph_t graph,
108+
const size_t horizontal, const size_t vertical,
109+
const size_t colormap_entry)
110+
{
111+
switch (graph.image_type) {
112+
case CAIRO:
113+
cairo_rectangle(graph.cairo_image, horizontal, vertical, 1, 1);
114+
cairo_set_source_rgb(graph.cairo_image,
115+
graph.colormap[colormap_entry][0] / 255.0,
116+
graph.colormap[colormap_entry][1] / 255.0,
117+
graph.colormap[colormap_entry][2] / 255.0);
118+
cairo_fill(graph.cairo_image);
119+
break;
120+
case GD:
121+
gdImageSetPixel(graph.gd_image, horizontal, vertical,
122+
colormap_entry);
123+
break;
124+
default:
125+
break;
126+
}
127+
}
128+
129+
void
130+
graph_write(const graph_t graph, const char *outputfile)
131+
{
132+
FILE *pngout;
133+
134+
switch (graph.image_type) {
135+
case CAIRO:
136+
cairo_surface_write_to_png(cairo_get_target(graph.cairo_image),
137+
outputfile);
138+
break;
139+
case GD:
140+
pngout = fopen(outputfile, "wb");
141+
gdImagePng(graph.gd_image, pngout);
142+
fclose(pngout);
143+
break;
144+
default:
145+
break;
146+
}
147+
}
148+
149+
void
150+
graph_destroy(const graph_t graph)
151+
{
152+
switch (graph.image_type) {
153+
case CAIRO:
154+
cairo_destroy(graph.cairo_image);
155+
break;
156+
case GD:
157+
gdImageDestroy(graph.gd_image);
158+
break;
159+
default:
160+
break;
161+
}
162+
}
163+

graph.h

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <complex.h>
2+
3+
typedef struct extreme_coordinates {
4+
complex double lower_left;
5+
complex double upper_right;
6+
} extremes_t;
7+
8+
enum ImageType { CAIRO, GD };
9+
10+
#define NUM_COLORS 4
11+
12+
typedef struct graph {
13+
enum ImageType image_type;
14+
union {
15+
void *gd_image; /* gdImagePtr */
16+
void *cairo_image; /* cairo_t * */
17+
};
18+
const size_t width;
19+
const size_t height;
20+
const complex double center;
21+
const double range;
22+
const extremes_t extremes;
23+
const size_t colormap[NUM_COLORS][3];
24+
} graph_t;
25+
26+
extremes_t get_extreme_coordinates(const size_t, const size_t, const complex double, const double);
27+
graph_t graph_create(const char *, const size_t, const size_t, const complex double, const double);
28+
void graph_destroy(const graph_t);
29+
complex double graph_get_coordinates(graph_t, const size_t, const size_t);
30+
void graph_set_pixel(const graph_t, const size_t, const size_t, const size_t);
31+
void graph_write(const graph_t, const char *);

mandelbrot.c

+2-160
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
#include <complex.h>
2-
#include <string.h>
3-
4-
#include <cairo/cairo.h>
5-
#include <gd.h>
2+
#include <stdlib.h>
63

74
#ifdef USE_MPC
85
#include <mpc.h>
96
#endif
107

8+
#include "graph.h"
119
#include "mandelbrot.h"
1210

1311
size_t
@@ -71,162 +69,6 @@ choose_escape_color(const complex double c, const size_t maximum_iterations)
7169
return escape;
7270
}
7371

74-
graph_t
75-
graph_create(const char *backend, const size_t width, const size_t height,
76-
const complex double center, const double range)
77-
{
78-
graph_t image = {
79-
0,
80-
{ NULL },
81-
width,
82-
height,
83-
center,
84-
range,
85-
get_extreme_coordinates(width, height, center, range),
86-
{
87-
{ 0, 0, 0 },
88-
{ 176, 229, 247 },
89-
{ 245, 137, 169 },
90-
{ 154, 227, 194 },
91-
},
92-
};
93-
94-
if (0 == strcmp("cairo", backend)) {
95-
image.image_type = CAIRO;
96-
97-
image.cairo_image = cairo_create(
98-
cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height));
99-
100-
cairo_set_line_width(image.cairo_image, 0.1);
101-
} else {
102-
image.image_type = GD;
103-
104-
image.gd_image = gdImageCreate(width, height);
105-
106-
for (size_t i = 0; i < NUM_COLORS; i++) {
107-
gdImageColorAllocate(image.gd_image,
108-
image.colormap[i][0],
109-
image.colormap[i][1],
110-
image.colormap[i][2]);
111-
}
112-
}
113-
114-
return image;
115-
}
116-
117-
extremes_t
118-
get_extreme_coordinates(const size_t width, const size_t height,
119-
const complex double center, const double range)
120-
{
121-
extremes_t coords;
122-
123-
if (width < height) {
124-
coords.lower_left =
125-
creal(center) - (range * width/height) / 2.0
126-
+ I * cimag(center)
127-
- I * (range) / 2.0;
128-
coords.upper_right =
129-
creal(center) + (range * width/height) / 2.0
130-
+ I * cimag(center)
131-
+ I * (range) / 2.0;
132-
} else {
133-
coords.lower_left =
134-
creal(center) - (range) / 2.0
135-
+ I * cimag(center)
136-
- I * (range * height/width) / 2.0;
137-
coords.upper_right =
138-
creal(center) + (range) / 2.0
139-
+ I * cimag(center)
140-
+ I * (range * height/width) / 2.0;
141-
}
142-
143-
return coords;
144-
}
145-
146-
static double
147-
graph_get_a(const graph_t graph, const size_t horizontal)
148-
{
149-
const double minimum_a = creal(graph.extremes.lower_left);
150-
const double maximum_a = creal(graph.extremes.upper_right);
151-
152-
return minimum_a
153-
+ horizontal / (graph.width / (maximum_a - minimum_a));
154-
}
155-
156-
static double
157-
graph_get_b(const graph_t graph, const size_t vertical)
158-
{
159-
const double minimum_b = cimag(graph.extremes.lower_left);
160-
const double maximum_b = cimag(graph.extremes.upper_right);
161-
162-
return minimum_b
163-
+ vertical / (graph.height / (maximum_b - minimum_b));
164-
}
165-
166-
complex double
167-
graph_get_coordinates(const graph_t graph, const size_t i, const size_t j)
168-
{
169-
return graph_get_a(graph, i) + I * graph_get_b(graph, j);
170-
}
171-
172-
static void
173-
graph_set_pixel(const graph_t graph,
174-
const size_t horizontal, const size_t vertical,
175-
const size_t colormap_entry)
176-
{
177-
switch (graph.image_type) {
178-
case CAIRO:
179-
cairo_rectangle(graph.cairo_image, horizontal, vertical, 1, 1);
180-
cairo_set_source_rgb(graph.cairo_image,
181-
graph.colormap[colormap_entry][0] / 255.0,
182-
graph.colormap[colormap_entry][1] / 255.0,
183-
graph.colormap[colormap_entry][2] / 255.0);
184-
cairo_fill(graph.cairo_image);
185-
break;
186-
case GD:
187-
gdImageSetPixel(graph.gd_image, horizontal, vertical,
188-
colormap_entry);
189-
break;
190-
default:
191-
break;
192-
}
193-
}
194-
195-
static void
196-
graph_write(const graph_t graph, const char *outputfile)
197-
{
198-
FILE *pngout;
199-
200-
switch (graph.image_type) {
201-
case CAIRO:
202-
cairo_surface_write_to_png(cairo_get_target(graph.cairo_image),
203-
outputfile);
204-
break;
205-
case GD:
206-
pngout = fopen(outputfile, "wb");
207-
gdImagePng(graph.gd_image, pngout);
208-
fclose(pngout);
209-
break;
210-
default:
211-
break;
212-
}
213-
}
214-
215-
void
216-
graph_destroy(const graph_t graph)
217-
{
218-
switch (graph.image_type) {
219-
case CAIRO:
220-
cairo_destroy(graph.cairo_image);
221-
break;
222-
case GD:
223-
gdImageDestroy(graph.gd_image);
224-
break;
225-
default:
226-
break;
227-
}
228-
}
229-
23072
void mandelbrot(const char *backend, const char *outputfile,
23173
const size_t width, const size_t height, const size_t iterations,
23274
const complex double center, const double range)

0 commit comments

Comments
 (0)