volmetrics

annotate src/volume.cc @ 6:e6485ef45e6e

visualize volume
author Eleni Maria Stea <elene.mst@gmail.com>
date Sat, 18 Jan 2014 01:57:52 +0200
parents 92c163c939be
children 928954bfefd7
rev   line source
elene@6 1 #include <GL/glew.h>
elene@6 2
elene@6 3 #include <assert.h>
elene@6 4
elene@5 5 #include <ctype.h>
elene@5 6 #include <errno.h>
elene@4 7 #include <stdio.h>
elene@5 8 #include <string.h>
elene@5 9
elene@5 10 #include <string>
elene@5 11 #include <vector>
elene@4 12
elene@3 13 #include "volume.h"
elene@4 14
elene@5 15 static char *strip_whitespaces(char *buf);
elene@5 16
elene@4 17 Volume::Volume()
elene@4 18 {
elene@4 19 width = height = 0;
elene@5 20 zaspect = 1;
elene@6 21 vol_tex_valid = false;
elene@6 22
elene@6 23 glGenTextures(1, &vol_tex);
elene@4 24 }
elene@4 25
elene@6 26 Volume::~Volume()
elene@6 27 {
elene@6 28 glDeleteTextures(1, &vol_tex);
elene@6 29 }
elene@6 30
elene@6 31 void Volume::create_vol_tex() const
elene@6 32 {
elene@6 33 if(slices.empty())
elene@6 34 return;
elene@6 35
elene@6 36 glBindTexture(GL_TEXTURE_3D, vol_tex);
elene@6 37 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
elene@6 38 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
elene@6 39 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
elene@6 40 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
elene@6 41 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
elene@6 42
elene@6 43 assert(glGetError() == GL_NO_ERROR);
elene@6 44 glTexImage3D(GL_TEXTURE_3D, 0, GL_LUMINANCE, width, height,
elene@6 45 slices.size(), 0, GL_LUMINANCE, GL_FLOAT, 0);
elene@6 46 assert(glGetError() == GL_NO_ERROR);
elene@6 47
elene@6 48 for(size_t i=0; i<slices.size(); i++) {
elene@6 49 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, width, height,
elene@6 50 1, GL_LUMINANCE, GL_FLOAT, slices[i].get_pixels());
elene@6 51 }
elene@6 52 }
elene@6 53
elene@6 54 bool Volume::load(const char *fname)
elene@4 55 {
elene@5 56 FILE *fp = fopen(fname, "r");
elene@5 57 if(!fp) {
elene@5 58 fprintf(stderr, "Failed to open file: %s: %s\n", fname, strerror(errno));
elene@5 59 return false;
elene@5 60 }
elene@5 61
elene@5 62 char buf[512];
elene@5 63 if(!fgets(buf, sizeof buf, fp)) {
elene@5 64 fprintf(stderr, "Empty file: %s.\n", fname);
elene@5 65 return false;
elene@5 66 }
elene@5 67 if(strstr(buf, "VOLUME") != buf) {
elene@5 68 fprintf(stderr, "Invalid volume file format: %s\n", fname);
elene@5 69 return false;
elene@5 70 }
elene@5 71
elene@5 72 bool reading_slices = false;
elene@5 73 std::vector<std::string> img_fnames;
elene@5 74
elene@5 75 while(fgets(buf, sizeof buf, fp)) {
elene@5 76 char *line = strip_whitespaces(buf);
elene@5 77 if(!line || *line == 0 || *line == '#')
elene@5 78 continue;
elene@5 79
elene@5 80 if(reading_slices == false) {
elene@5 81 if(strcmp(line, "SLICES") == 0)
elene@5 82 reading_slices = true;
elene@5 83
elene@5 84 sscanf(line, "zaspect = %f", &zaspect);
elene@5 85 }
elene@5 86 else {
elene@5 87 img_fnames.push_back(line);
elene@5 88 }
elene@5 89 }
elene@5 90
elene@5 91 fclose(fp);
elene@5 92
elene@5 93 for(size_t i=0; i<img_fnames.size(); i++) {
elene@5 94 Image img;
elene@5 95 if(img.load(img_fnames[i].c_str())) {
elene@5 96 push_slice(std::move(img));
elene@5 97 }
elene@5 98 else {
elene@5 99 fprintf(stderr, "Failed to load slice: %s\n", img_fnames[i].c_str());
elene@5 100 }
elene@5 101 }
elene@5 102
elene@4 103 return true;
elene@4 104 }
elene@4 105
elene@4 106 bool Volume::push_slice(Image &&slice)
elene@4 107 {
elene@4 108 if(slices.empty()) {
elene@4 109 width = slice.get_width();
elene@4 110 height = slice.get_height();
elene@4 111 }
elene@4 112 else {
elene@4 113 if(width != slice.get_width() || height != slice.get_height()) {
elene@4 114 fprintf(stderr, "failed to load slice no: %d\n", (int)slices.size() + 1);
elene@4 115 return false;
elene@4 116 }
elene@4 117 }
elene@4 118
elene@4 119 slices.push_back(slice);
elene@4 120 return true;
elene@4 121 }
elene@5 122
elene@6 123 const Image *Volume::get_slice(int num_slice) const
elene@6 124 {
elene@6 125 if(num_slice >= (int)slices.size() || num_slice < 0)
elene@6 126 return 0;
elene@6 127
elene@6 128 return &slices[num_slice];
elene@6 129 }
elene@6 130
elene@6 131 const Image *Volume::get_slice_by_z(float z) const
elene@6 132 {
elene@6 133 int idx = get_slice_idx_by_z(z);
elene@6 134 return get_slice(idx);
elene@6 135 }
elene@6 136
elene@6 137 int Volume::get_slice_count() const
elene@6 138 {
elene@6 139 return (int)slices.size();
elene@6 140 }
elene@6 141
elene@6 142 int Volume::get_slice_idx_by_z(float z) const
elene@6 143 {
elene@6 144 int last_slice_idx = (int)slices.size() - 1;
elene@6 145 int idx = z * last_slice_idx;
elene@6 146 if(idx < 0) {
elene@6 147 idx = 0;
elene@6 148 }
elene@6 149 else if(idx > last_slice_idx) {
elene@6 150 idx = last_slice_idx;
elene@6 151 }
elene@6 152
elene@6 153 return idx;
elene@6 154 }
elene@6 155
elene@6 156 unsigned int Volume::get_texture() const
elene@6 157 {
elene@6 158 if(!vol_tex_valid) {
elene@6 159 create_vol_tex();
elene@6 160 vol_tex_valid = true;
elene@6 161 }
elene@6 162
elene@6 163 return vol_tex;
elene@6 164 }
elene@6 165
elene@5 166 void Volume::draw()
elene@5 167 {
elene@5 168 }
elene@5 169
elene@5 170 static char *strip_whitespaces(char *buf)
elene@5 171 {
elene@5 172 while(*buf && isspace(*buf))
elene@5 173 buf++;
elene@5 174
elene@5 175 if(!*buf)
elene@5 176 return 0;
elene@5 177
elene@5 178 char *end = buf + strlen(buf) - 1;
elene@5 179 while(end > buf && isspace(*end))
elene@5 180 end--;
elene@5 181 end[1] = 0;
elene@5 182 return buf;
elene@5 183 }