glviewvol

annotate src/xfermap.cc @ 7:71b479ffb9f7

curve manipulation works
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 30 Dec 2014 17:28:38 +0200
parents f22be47a3572
children 773f89037a35
rev   line source
nuclear@7 1 #include <math.h>
nuclear@6 2 #include <algorithm>
nuclear@6 3 #include "xfermap.h"
nuclear@6 4
nuclear@6 5 TransferFunc::~TransferFunc()
nuclear@6 6 {
nuclear@6 7 }
nuclear@6 8
nuclear@6 9
nuclear@6 10 // ---- TransferWindow ----
nuclear@6 11
nuclear@6 12 TransferWindow::TransferWindow()
nuclear@6 13 {
nuclear@6 14 soft_rad = 0.5;
nuclear@7 15 for(int i=0; i<3; i++) {
nuclear@6 16 low[i] = 0.5;
nuclear@7 17 high[i] = 1.5;
nuclear@6 18 }
nuclear@6 19 }
nuclear@6 20
nuclear@7 21 void TransferWindow::set_handle(int channel, int handle, float val)
nuclear@7 22 {
nuclear@7 23 float *dest = handle == HANDLE_LOW ? low : high;
nuclear@7 24
nuclear@7 25 if(channel == -1) {
nuclear@7 26 dest[0] = dest[1] = dest[2] = val;
nuclear@7 27 } else {
nuclear@7 28 dest[channel] = val;
nuclear@7 29 }
nuclear@7 30 }
nuclear@7 31
nuclear@7 32 float TransferWindow::get_handle(int channel, int handle) const
nuclear@7 33 {
nuclear@7 34 const float *src = handle == HANDLE_LOW ? low : high;
nuclear@7 35
nuclear@7 36 if(channel == -1) {
nuclear@7 37 return src[0]; // XXX this doens't make much sense
nuclear@7 38 }
nuclear@7 39 return src[channel];
nuclear@7 40 }
nuclear@7 41
nuclear@7 42 int TransferWindow::nearest_handle(int channel, float pos) const
nuclear@7 43 {
nuclear@7 44 float ldist = 0, hdist = 0;
nuclear@7 45
nuclear@7 46 if(channel == -1) {
nuclear@7 47 for(int i=0; i<3; i++) {
nuclear@7 48 ldist += fabs(low[i] - pos);
nuclear@7 49 hdist += fabs(high[i] - pos);
nuclear@7 50 }
nuclear@7 51 } else {
nuclear@7 52 ldist = fabs(low[channel] - pos);
nuclear@7 53 hdist = fabs(high[channel] - pos);
nuclear@7 54 }
nuclear@7 55 return ldist <= hdist ? HANDLE_LOW : HANDLE_HIGH;
nuclear@7 56 }
nuclear@7 57
nuclear@6 58 void TransferWindow::set_interval(float a, float b)
nuclear@6 59 {
nuclear@6 60 float v0 = std::min(a, b);
nuclear@6 61 float v1 = std::max(a, b);
nuclear@6 62
nuclear@7 63 for(int i=0; i<3; i++) {
nuclear@6 64 low[i] = v0;
nuclear@6 65 high[i] = v1;
nuclear@6 66 }
nuclear@6 67 }
nuclear@6 68
nuclear@6 69 void TransferWindow::set_interval(float *rgba_low, float *rgba_high)
nuclear@6 70 {
nuclear@7 71 for(int i=0; i<3; i++) {
nuclear@6 72 low[i] = std::min(rgba_low[i], rgba_high[i]);
nuclear@6 73 high[i] = std::max(rgba_low[i], rgba_high[i]);
nuclear@6 74 }
nuclear@6 75 }
nuclear@6 76
nuclear@6 77 void TransferWindow::set_interval_rgba(int channel, float a, float b)
nuclear@6 78 {
nuclear@6 79 low[channel] = std::min(a, b);
nuclear@6 80 high[channel] = std::max(a, b);
nuclear@6 81 }
nuclear@6 82
nuclear@7 83 void TransferWindow::get_interval(float *aptr, float *bptr) const
nuclear@7 84 {
nuclear@7 85 *aptr = low[0];
nuclear@7 86 *bptr = high[0];
nuclear@7 87 }
nuclear@7 88
nuclear@7 89 void TransferWindow::get_interval_rgba(float *rgba_low, float *rgba_high) const
nuclear@7 90 {
nuclear@7 91 for(int i=0; i<3; i++) {
nuclear@7 92 rgba_low[i] = low[i];
nuclear@7 93 rgba_high[i] = high[i];
nuclear@7 94 }
nuclear@7 95 }
nuclear@7 96
nuclear@7 97 void TransferWindow::get_interval_rgba(int channel, float *aptr, float *bptr) const
nuclear@7 98 {
nuclear@7 99 *aptr = low[channel];
nuclear@7 100 *bptr = high[channel];
nuclear@7 101 }
nuclear@7 102
nuclear@6 103 void TransferWindow::set_soft_radius(float s)
nuclear@6 104 {
nuclear@6 105 soft_rad = s;
nuclear@6 106 }
nuclear@6 107
nuclear@6 108 float TransferWindow::get_soft_radius() const
nuclear@6 109 {
nuclear@6 110 return soft_rad;
nuclear@6 111 }
nuclear@6 112
nuclear@6 113 static inline float smoothstep(float a, float b, float x)
nuclear@6 114 {
nuclear@6 115 if(x < a) return 0.0f;
nuclear@6 116 if(x >= b) return 1.0f;
nuclear@6 117
nuclear@6 118 float t = (x - a) / (b - a);
nuclear@6 119 return t * t * (3.0f - 2.0f * t);
nuclear@6 120 }
nuclear@6 121
nuclear@6 122 float TransferWindow::map(float x) const
nuclear@6 123 {
nuclear@7 124 float rgb[3];
nuclear@7 125 map(x, rgb);
nuclear@7 126
nuclear@7 127 return std::max(rgb[0], std::max(rgb[1], rgb[2]));
nuclear@6 128 }
nuclear@6 129
nuclear@7 130 void TransferWindow::map(float x, float *rgb_value) const
nuclear@6 131 {
nuclear@7 132 for(int i=0; i<3; i++) {
nuclear@7 133 float val = smoothstep(low[i] - soft_rad, low[i] + soft_rad, x);
nuclear@7 134 val *= 1.0 - smoothstep(high[i] - soft_rad, high[i] + soft_rad, x);
nuclear@7 135 rgb_value[i] = val;
nuclear@6 136 }
nuclear@6 137 }