glviewvol
changeset 1:cc9e0d8590e2
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 27 Dec 2014 06:32:28 +0200 |
parents | 7bdf40403b9c |
children | 701507c8238f |
files | src/dicomview.cc src/image.cc src/main.cc src/volume.cc src/volume.h |
diffstat | 5 files changed, 240 insertions(+), 11 deletions(-) [+] |
line diff
1.1 --- a/src/dicomview.cc Sat Dec 27 02:35:58 2014 +0200 1.2 +++ b/src/dicomview.cc Sat Dec 27 06:32:28 2014 +0200 1.3 @@ -1,21 +1,36 @@ 1.4 #include "opengl.h" 1.5 #include "dicomview.h" 1.6 +#include "rend_fast.h" 1.7 1.8 +static int win_width, win_height; 1.9 static float cam_theta, cam_phi, cam_dist = 6; 1.10 1.11 +static Renderer *rend; 1.12 + 1.13 extern "C" { 1.14 1.15 int init() 1.16 { 1.17 + rend = new RendererFast; 1.18 + if(!rend->init()) { 1.19 + return -1; 1.20 + } 1.21 + 1.22 + return 0; 1.23 } 1.24 1.25 void cleanup() 1.26 { 1.27 + rend->destroy(); 1.28 + delete rend; 1.29 } 1.30 1.31 void ev_display() 1.32 { 1.33 glClear(GL_COLOR_BUFFER_BIT); 1.34 + 1.35 + rend->update(0); 1.36 + rend->render(); 1.37 } 1.38 1.39 void ev_reshape(int x, int y) 1.40 @@ -23,11 +38,25 @@ 1.41 win_width = x; 1.42 win_height = y; 1.43 1.44 - glViweport(0, 0, x, y); 1.45 + glViewport(0, 0, x, y); 1.46 } 1.47 1.48 -void ev_keyboard(int key, int press, int x, int y); 1.49 -void ev_mouse_button(int bn, int press, int x, int y); 1.50 -void ev_mouse_motion(int x, int y); 1.51 +void ev_keyboard(int key, int press, int x, int y) 1.52 +{ 1.53 + if(press) { 1.54 + switch(key) { 1.55 + case 27: 1.56 + quit(); 1.57 + } 1.58 + } 1.59 +} 1.60 + 1.61 +void ev_mouse_button(int bn, int press, int x, int y) 1.62 +{ 1.63 +} 1.64 + 1.65 +void ev_mouse_motion(int x, int y) 1.66 +{ 1.67 +} 1.68 1.69 } // extern "C"
2.1 --- a/src/image.cc Sat Dec 27 02:35:58 2014 +0200 2.2 +++ b/src/image.cc Sat Dec 27 06:32:28 2014 +0200 2.3 @@ -1,3 +1,4 @@ 2.4 +#include <string.h> 2.5 #include <imago2.h> 2.6 #include "image.h" 2.7 2.8 @@ -39,7 +40,7 @@ 2.9 // TODO dicom loader ... ? 2.10 2.11 int x, y; 2.12 - float *pixels = img_load_pixels(fname, &x, &y, IMG_FMT_GREYF); 2.13 + float *pixels = (float*)img_load_pixels(fname, &x, &y, IMG_FMT_GREYF); 2.14 if(!pixels) { 2.15 return false; 2.16 }
3.1 --- a/src/main.cc Sat Dec 27 02:35:58 2014 +0200 3.2 +++ b/src/main.cc Sat Dec 27 06:32:28 2014 +0200 3.3 @@ -19,8 +19,6 @@ 3.4 static void mouse(int bn, int state, int x, int y); 3.5 static void motion(int x, int y); 3.6 3.7 -static float cam_theta, cam_phi, cam_dist = 6; 3.8 - 3.9 int main(int argc, char **argv) 3.10 { 3.11 glutInit(&argc, argv); 3.12 @@ -30,7 +28,8 @@ 3.13 3.14 glutDisplayFunc(display); 3.15 glutReshapeFunc(reshape); 3.16 - glutKeyboardFunc(keyb); 3.17 + glutKeyboardFunc(key_down); 3.18 + glutKeyboardUpFunc(key_up); 3.19 glutMouseFunc(mouse); 3.20 glutMotionFunc(motion); 3.21
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/volume.cc Sat Dec 27 06:32:28 2014 +0200 4.3 @@ -0,0 +1,198 @@ 4.4 +#include <stdio.h> 4.5 +#include <string.h> 4.6 +#include <ctype.h> 4.7 +#include <errno.h> 4.8 +#include <math.h> 4.9 +#include "volume.h" 4.10 + 4.11 +static char *strip_space(char *s); 4.12 + 4.13 + 4.14 +Volume::~Volume() 4.15 +{ 4.16 +} 4.17 + 4.18 +int Volume::num_samples(int dim) const 4.19 +{ 4.20 + return 0; 4.21 +} 4.22 + 4.23 +void Volume::normalf(float *norm, float x, float y, float z, float delta) 4.24 +{ 4.25 + float dx, dy, dz; 4.26 + dx = dy = dz = delta; 4.27 + 4.28 + if(num_samples(0) > 0) { 4.29 + // discrete volume 4.30 + dx /= (float)num_samples(0); 4.31 + dy /= (float)num_samples(1); 4.32 + dz /= (float)num_samples(2); 4.33 + } 4.34 + 4.35 + norm[0] = valuef(x + dx, y, z) - valuef(x - dx, y, z); 4.36 + norm[1] = valuef(x, y + dy, z) - valuef(x, y - dy, z); 4.37 + norm[2] = valuef(x, y, z + dz) - valuef(x, y, z - dz); 4.38 + 4.39 + float len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]); 4.40 + if(len != 0.0) { 4.41 + norm[0] /= len; 4.42 + norm[1] /= len; 4.43 + norm[2] /= len; 4.44 + } 4.45 +} 4.46 + 4.47 +void Volume::normali(float *norm, int x, int y, int z) 4.48 +{ 4.49 + int sz[3]; 4.50 + 4.51 + if((sz[0] = num_samples(0)) <= 0) { 4.52 + // if it's a continuous volume, just call normalf 4.53 + normalf(norm, x, y, z); 4.54 + return; 4.55 + } 4.56 + sz[1] = num_samples(1); 4.57 + sz[2] = num_samples(2); 4.58 + 4.59 + int prevx = x <= 0 ? 0 : x; 4.60 + int nextx = x >= sz[0] - 1 ? sz[0] - 1 : x; 4.61 + int prevy = y <= 0 ? 0 : y; 4.62 + int nexty = y >= sz[1] - 1 ? sz[1] - 1 : y; 4.63 + int prevz = z <= 0 ? 0 : z; 4.64 + int nextz = z >= sz[2] - 1 ? sz[2] - 1 : z; 4.65 + 4.66 + norm[0] = valuei(nextx, y, z) - valuei(prevx, y, z); 4.67 + norm[1] = valuei(x, nexty, z) - valuei(x, prevy, z); 4.68 + norm[2] = valuei(x, y, nextz) - valuei(x, y, prevz); 4.69 + 4.70 + float len = sqrt(norm[0] * norm[0] + norm[1] * norm[1] + norm[2] * norm[2]); 4.71 + if(len != 0.0) { 4.72 + norm[0] /= len; 4.73 + norm[1] /= len; 4.74 + norm[2] /= len; 4.75 + } 4.76 +} 4.77 + 4.78 +// ---- VoxelVolume (discrete) implementation ---- 4.79 +VoxelVolume::VoxelVolume() 4.80 +{ 4.81 + size[0] = size[1] = size[2] = 0; 4.82 +} 4.83 + 4.84 +bool VoxelVolume::load(const char *fname) 4.85 +{ 4.86 + FILE *fp = fopen(fname, "r"); 4.87 + if(!fp) { 4.88 + fprintf(stderr, "failed to open file: %s: %s\n", fname, strerror(errno)); 4.89 + return false; 4.90 + } 4.91 + 4.92 + char buf[512]; 4.93 + while(fgets(buf, sizeof buf, fp)) { 4.94 + char *line = strip_space(buf); 4.95 + 4.96 + Image img; 4.97 + if(!img.load(line)) { 4.98 + slices.clear(); 4.99 + return false; 4.100 + } 4.101 + 4.102 + if(slices.empty()) { 4.103 + size[0] = img.width; 4.104 + size[1] = img.height; 4.105 + } else { 4.106 + if(img.width != size[0] || img.height != size[1]) { 4.107 + fprintf(stderr, "slice %d \"%s\" size mismatch (%dx%d, %dx%d expected)\n", 4.108 + (int)slices.size(), line, img.width, img.height, size[0], size[1]); 4.109 + slices.clear(); 4.110 + return false; 4.111 + } 4.112 + } 4.113 + 4.114 + slices.push_back(img); 4.115 + img.pixels = 0; // otherwise the destructor will free it 4.116 + } 4.117 + 4.118 + size[2] = slices.size(); 4.119 + fclose(fp); 4.120 + return true; 4.121 +} 4.122 + 4.123 +int VoxelVolume::num_samples(int dim) const 4.124 +{ 4.125 + return size[dim]; 4.126 +} 4.127 + 4.128 +static inline int clamp(int x, int low, int high) 4.129 +{ 4.130 + return x < low ? low : (x > high ? high : x); 4.131 +} 4.132 + 4.133 +static inline float lookup(int x0, int y0, int x1, int y1, float tx, float ty, 4.134 + float *pixels, int width, int height) 4.135 +{ 4.136 + float v00, v01, v10, v11; 4.137 + 4.138 + v00 = pixels[y0 * width + x0]; 4.139 + v01 = pixels[y1 * width + x0]; 4.140 + v10 = pixels[y0 * width + x1]; 4.141 + v11 = pixels[y1 * width + x1]; 4.142 + 4.143 + float v0 = v00 + (v01 - v00) * ty; 4.144 + float v1 = v10 + (v11 - v10) * ty; 4.145 + 4.146 + return v0 + (v1 - v0) * tx; 4.147 +} 4.148 + 4.149 +float VoxelVolume::valuef(float x, float y, float z) const 4.150 +{ 4.151 + if(slices.empty()) { 4.152 + return 0.0f; 4.153 + } 4.154 + 4.155 + float floor_x = floor(x); 4.156 + float ceil_x = ceil(x); 4.157 + float tx = x - floor_x; 4.158 + 4.159 + float floor_y = floor(y); 4.160 + float ceil_y = ceil(y); 4.161 + float ty = y - floor_y; 4.162 + 4.163 + float floor_z = floor(z); 4.164 + float ceil_z = ceil(z); 4.165 + float tz = z - floor_z; 4.166 + 4.167 + int x0 = clamp(floor_x, 0, size[0] - 1); 4.168 + int x1 = clamp(ceil_x, 0, size[0] - 1); 4.169 + 4.170 + int y0 = clamp(floor_y, 0, size[1] - 1); 4.171 + int y1 = clamp(ceil_y, 0, size[1] - 1); 4.172 + 4.173 + int s0 = clamp(floor_z, 0, size[2] - 1); 4.174 + int s1 = clamp(ceil_z, 0, size[2] - 1); 4.175 + 4.176 + float val_s0 = lookup(x0, y0, x1, y1, tx, ty, slices[s0].pixels, size[0], size[1]); 4.177 + float val_s1 = lookup(x0, y0, x1, y1, tx, ty, slices[s1].pixels, size[0], size[1]); 4.178 + 4.179 + return val_s0 + (val_s1 - val_s0) * tz; 4.180 +} 4.181 + 4.182 +float VoxelVolume::valuei(int x, int y, int z) const 4.183 +{ 4.184 + x = clamp(x, 0, size[0] - 1); 4.185 + y = clamp(y, 0, size[1] - 1); 4.186 + z = clamp(z, 0, size[2] - 1); 4.187 + 4.188 + return slices[z].pixels[y * size[0] + x]; 4.189 +} 4.190 + 4.191 +static char *strip_space(char *s) 4.192 +{ 4.193 + while(*s && isspace(*s)) s++; 4.194 + if(!*s) return 0; 4.195 + 4.196 + char *end = s + strlen(s) - 1; 4.197 + while(end > s && isspace(*end)) end--; 4.198 + end[1] = 0; 4.199 + 4.200 + return s; 4.201 +}
5.1 --- a/src/volume.h Sat Dec 27 02:35:58 2014 +0200 5.2 +++ b/src/volume.h Sat Dec 27 06:32:28 2014 +0200 5.3 @@ -1,16 +1,18 @@ 5.4 #ifndef VOLUME_H_ 5.5 #define VOLUME_H_ 5.6 5.7 +#include <vector> 5.8 #include "image.h" 5.9 5.10 class Volume { 5.11 public: 5.12 virtual ~Volume(); 5.13 5.14 - // returns -1 if the volume is continuously defined 5.15 + // returns 0 if the volume is continuously defined 5.16 virtual int num_samples(int dim) const; 5.17 5.18 - // central differences offset will be delta / num_samples 5.19 + // central differences offset will be delta / num_samples for discrete volumes 5.20 + // and delta for continuous volumes 5.21 virtual void normalf(float *norm, float x, float y, float z, float delta = 1.0); 5.22 virtual void normali(float *norm, int x, int y, int z); 5.23 5.24 @@ -20,11 +22,11 @@ 5.25 5.26 class VoxelVolume : public Volume { 5.27 protected: 5.28 + int size[3]; 5.29 std::vector<Image> slices; 5.30 5.31 public: 5.32 VoxelVolume(); 5.33 - ~VoxelVolume(); 5.34 5.35 bool load(const char *fname); 5.36