1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*
* png-file.c
*
* PNG output
*
* (c) 2006-2007 Thomas White <taw27@cam.ac.uk>
*
* synth2d - Two-Dimensional Crystallographic Fourier Synthesis
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <png.h>
#include <math.h>
#include <stdlib.h>
#include <fftw3.h>
#include "data.h"
#include "colwheel.h"
#include "renderer.h"
int png_write_real(const char *filename, fftw_complex *out, double brightness, double gamma_angle, int width, int height, int nx, int ny) {
FILE *fh;
png_structp png_ptr;
png_infop info_ptr;
png_bytep *row_pointers;
int xn, yn;
int width_n, height_n;
ComplexArray cxar;
fh = fopen(filename, "wb");
if (!fh) {
fprintf(stderr, "Couldn't open output file.\n");
return 1;
}
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if ( !png_ptr ) {
fprintf(stderr, "Couldn't create PNG write structure.\n");
fclose(fh);
return 1;
}
info_ptr = png_create_info_struct(png_ptr);
if ( !info_ptr ) {
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
fprintf(stderr, "Couldn't create PNG info structure.\n");
fclose(fh);
return 1;
}
if ( setjmp(png_jmpbuf(png_ptr)) ) {
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fh);
fprintf(stderr, "PNG write failed.\n");
return 1;
}
png_init_io(png_ptr, fh);
width_n = (int)renderer_width(width, height, gamma_angle, nx, ny);
height_n = (int)renderer_height(width, height, gamma_angle, nx, ny);
cxar = renderer_draw(out, width, height, gamma_angle, nx, ny);
png_set_IHDR(png_ptr, info_ptr, width_n, height_n, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
/* Write the image data */
row_pointers = malloc(height_n*sizeof(png_bytep *));
for ( yn=0; yn<height_n; yn++ ) {
row_pointers[yn] = malloc(width_n*3);
for ( xn=0; xn<width_n; xn++ ) {
row_pointers[yn][3*xn] = 0;
row_pointers[yn][3*xn+1] = 0;
row_pointers[yn][3*xn+2] = 0;
}
}
for ( yn=0; yn<height_n; yn++ ) {
for ( xn=0; xn<width_n; xn++ ) {
double re, im, am, ph;
re = cxar.re[xn+width_n*yn];
im = cxar.im[xn+width_n*yn];
am = sqrt(re*re + im*im) / brightness;
ph = atan2(im, re);
if ( am > 1 ) am = 1;
row_pointers[yn][3*xn] = (png_byte)255*colwheel_red(am, ph);
row_pointers[yn][3*xn+1] = (png_byte)255*colwheel_green(am, ph);
row_pointers[yn][3*xn+2] = (png_byte)255*colwheel_blue(am, ph);
}
}
for ( yn=0; yn<height_n/2+1; yn++ ) {
png_bytep scratch;
scratch = row_pointers[yn];
row_pointers[yn] = row_pointers[height_n-yn-1];
row_pointers[height_n-yn-1] = scratch;
}
png_set_rows(png_ptr, info_ptr, row_pointers);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
for ( yn=0; yn<height_n; yn++ ) {
free(row_pointers[yn]);
}
free(row_pointers);
fclose(fh);
return 0;
}
int png_write(const char *filename, fftw_complex *out, double norm, int nx, int ny) {
return png_write_real(filename, out, norm, data_gamma(), data_width(), data_height(), nx, ny);
}
|