/* * colscale.c * * Colour scales * * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY, * a research centre of the Helmholtz Association. * * Authors: * 2009-2020 Thomas White * * This file is part of CrystFEL. * * CrystFEL is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CrystFEL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CrystFEL. If not, see . * */ #include #include #include #include #include "colscale.h" /** \file colscale.h */ static void render_rgb(double val, double max, double *rp, double *gp, double *bp) { int s; double p; double r, g, b; s = val / (max/6); p = fmod(val, max/6.0); p /= (max/6.0); r = 0.0; g = 0.0; b = 0.0; if ( (val < 0.0) ) { p = fabs(val) / (max/6.0); *rp = 0.0; *gp = 0.5*p; *bp = 0.0; return; } if ( (val > max) ) { s = 6; } switch ( s ) { case 0 : /* Black to blue */ r = 0; g = 0; b = p; break; case 1 : /* Blue to pink */ r = p; g = 0; b = 1.0; break; case 2 : /* Pink to red */ r = 1.0; g = 0; b = (1.0-p)*1.0; break; case 3 : /* Red to Orange */ r = 1.0; g = 0.5*p; b = 0; break; case 4 : /* Orange to Yellow */ r = 1.0; g = 0.5 + 0.5*p; b = 0; break; case 5 : /* Yellow to White */ r = 1.0; g = 1.0; b = 1.0*p; break; case 6 : /* Pixel has hit the maximum value */ r = 1.0; g = 1.0; b = 1.0; break; } *rp = r; *gp = g; *bp = b; } static void render_geoptimiser(double val, double max, double *rp, double *gp, double *bp) { double r; double p; r = val/max; if ( val < 0.0 ) { *rp = 0.0; *gp = 0.0; *bp = 0.0; return; } if ( r >= 0.0 && r < 0.059 ) { p = (r-0.0)/(0.059-0.0); *rp = 0.0; *gp = 0.0; *bp = ((91.0/256.0)-0.0)*p; return; } if ( r >= 0.059 && r < 0.220 ) { p = (r-0.059)/(0.220-0.059); *rp = ((122.0/256.0)-0.0)*p; *gp = 0.0; *bp = ((227.0/256.0)-(91.0/256.0))*p+(91.0/256.0); return; } if ( r >= 0.220 && r < 0.376 ) { p = (r-0.220)/(0.376-0.220); *rp = ((195.0/256.0)-(122.0/256.0))*p+(122.0/256.0); *gp = 0.0; *bp = ((93.0/256.0)-(227.0/256.0))*p+(227.0/256.0); return; } if ( r >= 0.376 && r < 0.498 ) { p = (r-0.376)/(0.498-0.376); *rp = ((238.0/256.0)-(195.0/256.0))*p+(195.0/256.0); *gp = ((76.0/256.0)-0.0)*p; *bp = (0.0-(93.0/256.0))*p+(93.0/256.0); return; } if ( r >= 0.498 && r < 0.564 ) { p = (r-0.498)/(0.564-0.498); *rp = (1.0-(238.0/256.0))*p+(238.0/256.0); *gp = ((117.0/256.0)-(76.0/256.0))*p+(76.0/256.0); *bp = 0.0; return; } if ( r >= 0.564 && r < 0.815 ) { p = (r-0.564)/(0.815-0.564); *rp = 1.0; *gp = ((234.0/256.0)-(117.0/256.0))*p+(117.0/256.0); *bp = 0.0; return; } if ( r >= 0.815 && r < 1.0 ) { p = (r-0.815)/(1.0-0.815); *rp = 1.0; *gp = (1.0-(234.0/256.0))*p+(234.0/256.0); *bp = (1.0-0.0)*p; return; } if ( r >= 1.0 ) { *rp = 1.0; *gp = 1.0; *bp = 1.0; return; } } static void render_ratio(double val, double max, double *rp, double *gp, double *bp) { if ( val <= 1.0 ) { render_rgb(val, 2.0, rp, gp, bp); } else { /* Your homework is to simplify this expression */ val = ((val-1.0)/(max-1.0)) * (max/2.0) + max/2.0; render_rgb(val, max, rp, gp, bp); } } static void render_mono(double val, double max, double *rp, double *gp, double *bp) { double p; p = val / max; if ( val < 0.0 ) p = 0.0; if ( val > max ) p = 1.0; *rp = p; *gp = p; *bp = p; } static void render_invmono(double val, double max, double *rp, double *gp, double *bp) { double p; p = val / max; p = 1.0 - p; if ( val < 0.0 ) p = 1.0; if ( val > max ) p = 0.0; *rp = p; *gp = p; *bp = p; } void colscale_lookup(double val, double max, int scale, double *rp, double *gp, double *bp) { switch ( scale ) { case SCALE_COLOUR : render_rgb(val, max, rp, gp, bp); break; case SCALE_MONO : render_mono(val, max, rp, gp, bp); break; case SCALE_INVMONO : render_invmono(val, max, rp, gp, bp); break; case SCALE_RATIO : render_ratio(val, max, rp, gp, bp); break; case SCALE_GEOPTIMISER : render_geoptimiser(val, max, rp, gp, bp); break; } }