/* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/ void shadeSunView(float col_r[3], const float view[3]) { GroupObject *go; LampRen *lar; float sview[3]; bool do_init = true; for (go=R.lights.first; go; go= go->next) { lar= go->lampren; if (lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)) { float sun_collector[3]; float colorxyz[3]; if (do_init) { normalize_v3_v3(sview, view); mul_m3_v3(R.imat, sview); if (sview[2] < 0.0f) sview[2] = 0.0f; normalize_v3(sview); do_init = false; } GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz); xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], lar->sunsky->sky_colorspace); ramp_blend(lar->sunsky->skyblendtype, col_r, lar->sunsky->skyblendfac, sun_collector); } } }
pixel_t get_color(array_t *image, size_t bitdepth) { uint32_t pixel_num = 0; lab_pixel_t *avg = NULL; for (size_t i = 0; i < image->size; i++) { array_t *row = ((array_t *) image->ptr); for (size_t j = 0; j < row->size; j++) { pixel_num++; pixel_t rgb = ((pixel_t *) row->ptr)[j]; xyz_pixel_t xyz = rgb_to_xyz(rgb); lab_pixel_t lab = xyz_to_lab(xyz); if (avg == NULL) { avg = malloc(sizeof(lab_pixel_t)); *avg = lab; } else { avg->L = running_avg(avg->L, lab->L, pixel_num); avg->a = running_avg(avg->a, lab->a, pixel_num); avg->b = running_avg(avg->b, lab->b, pixel_num); } } } xyz_pixel_t xyz_avg = lab_to_xyz(*avg); return xyz_to_rgb(xyz_avg); }
void color_init() { double x, y, z, r, g, b; struct colourSystem* cs = &SMPTEsystem; for(int ii = 0; ii < TEMP_ENTRIES; ++ii) { double temp = base_temp + step * ii; bbTemp = temp; spectrum_to_xyz(bb_spectrum, &x, &y, &z); xyz_to_rgb(cs, x, y, z, &r, &g, &b); constrain_rgb(&r, &g, &b); norm_rgb(&r, &g, &b); temp_table[ii][0] = r; temp_table[ii][1] = g; temp_table[ii][2] = b; } }
void spectrum(double t1, double t2, int N, unsigned char *d) { int i,j,dj; double X,Y,Z,R,G,B,L,M,S, Lw, Mw, Sw; struct colourSystem *cs = &CIEsystem; j = 0; dj = 1; if (t1<t2) { double t = t1; t1 = t2; t2 = t; j = N-1; dj=-1; } for (i=0; i<N; i++) { bbTemp = t1 + (t2-t1)/N*i; // integrate blackbody radiation spectrum to XYZ spectrum_to_xyz(bb_spectrum, &X, &Y, &Z); // normalize highest temperature to white (in LMS system) xyz_to_lms(X,Y,Z,&L,&M,&S); if (i==0) { Lw=1/L; Mw=1/M; Sw=1/S; } L *= Lw; M *= Mw; S *= Sw; lms_to_xyz(L,M,S,&X,&Y,&Z); // convert to RGB xyz_to_rgb(cs, X, Y, Z, &R, &G, &B); constrain_rgb(&R, &G, &B); norm_rgb(&R, &G, &B); d[(j<<2)] = (unsigned char) ((double)R*255); d[(j<<2)+1] = (unsigned char) ((double)G*255); d[(j<<2)+2] = (unsigned char) ((double)B*255); d[(j<<2)+3] = (B>0.1)? B*255 : 0; j += dj; } }
//------------------------------------------------------------------------------ NBodyWnd::NBodyWnd(int sz, std::string caption) :SDLWindow(sz, sz, 35000.0, caption) ,m_camOrient(0) ,m_starRenderType(1) ,m_flags(dspSTARS | dspAXIS | dspHELP | dspDUST | dspH2) ,m_bDumpImage(false) ,m_galaxy() ,m_colNum(200) ,m_t0(1000) ,m_t1(10000) ,m_dt( (m_t1-m_t0) /m_colNum) { double x, y, z; for (int i=0; i<m_colNum; ++i) { Color &col = m_col[i]; colourSystem *cs = &SMPTEsystem; bbTemp = m_t0 + m_dt*i; spectrum_to_xyz(bb_spectrum, &x, &y, &z); xyz_to_rgb(cs, x, y, z, &col.r, &col.g, &col.b); norm_rgb(&col.r, &col.g, &col.b); } }
int main() { float t, x, y, z, r, g, b; struct colourSystem *cs = &SMPTEsystem; printf("Temperature x y z R G B\n"); printf("----------- ------ ------ ------ ----- ----- -----\n"); for (t = 1000; t <= 10000; t+= 500) { bbTemp = t; spectrum_to_xyz(bb_spectrum, &x, &y, &z); xyz_to_rgb(cs, x, y, z, &r, &g, &b); printf(" %5.0f K %.4f %.4f %.4f ", t, x, y, z); if (constrain_rgb(&r, &g, &b)) { norm_rgb(&r, &g, &b); printf("%.3f %.3f %.3f (Approximation)\n", r, g, b); } else { norm_rgb(&r, &g, &b); printf("%.3f %.3f %.3f\n", r, g, b); } } return 0; }
static void plotMonochromeWavelengths( pixel ** const pixels, int const pixcols, int const pixrows, pixval const maxval, const struct colorSystem * const cs, bool const upvp, int const xBias, int const yBias) { int const pxcols = pixcols - xBias; int const pxrows = pixrows - yBias; int x; /* The wavelength we're plotting */ for (x = (upvp? 420 : 450); x <= 650; x += (upvp? 10 : (x > 470 && x < 600) ? 5 : 10)) { pixel rgbcolor; /* Ick. Drop legends that overlap and twiddle position so they appear at reasonable positions with respect to the tongue. */ if (!overlappingLegend(upvp, x)) { double cx, cy, cz, jr, jg, jb, jmax; char wl[20]; int bx = 0, by = 0, tx, ty, r, g, b; int icx, icy; /* Location of the color on the tongue */ if (x < 520) { bx = Sz(-22); by = Sz(2); } else if (x < 535) { bx = Sz(-8); by = Sz(-6); } else { bx = Sz(4); } computeMonochromeColorLocation(x, pxcols, pxrows, upvp, &icx, &icy); /* Draw the tick mark */ PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); tx = icx + ((x < 520) ? Sz(-2) : ((x >= 535) ? Sz(2) : 0)); ty = icy + ((x < 520) ? 0 : ((x >= 535) ? Sz(-1) : Sz(-2))); ppmd_line(pixels, pixcols, pixrows, Maxval, B(icx, icy), B(tx, ty), PPMD_NULLDRAWPROC, (char *) &rgbcolor); /* The following flailing about sets the drawing color to the hue corresponding to the pure wavelength (constrained to the display gamut). */ if (upvp) { double up, vp; up = ((double) icx) / (pxcols - 1); vp = 1.0 - ((double) icy) / (pxrows - 1); upvp_to_xy(up, vp, &cx, &cy); cz = 1.0 - (cx + cy); } else { cx = ((double) icx) / (pxcols - 1); cy = 1.0 - ((double) icy) / (pxrows - 1); cz = 1.0 - (cx + cy); } xyz_to_rgb(cs, cx, cy, cz, &jr, &jg, &jb); (void) constrain_rgb(&jr, &jg, &jb); /* Scale to max(rgb) = 1 */ jmax = MAX(jr, MAX(jg, jb)); if (jmax > 0) { jr = jr / jmax; jg = jg / jmax; jb = jb / jmax; } /* gamma correct from linear rgb to nonlinear rgb. */ gamma_correct_rgb(cs, &jr, &jg, &jb); r = Maxval * jr; g = Maxval * jg; b = Maxval * jb; PPM_ASSIGN(rgbcolor, (pixval) r, (pixval) g, (pixval) b); sprintf(wl, "%d", x); ppmd_text(pixels, pixcols, pixrows, Maxval, B(icx + bx, icy + by), Sz(6), 0, wl, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } } }
static void fillInTongue(pixel ** const pixels, int const pixcols, int const pixrows, pixval const maxval, const struct colorSystem * const cs, bool const upvp, int const xBias, int const yBias, bool const highlightGamut) { int const pxcols = pixcols - xBias; int const pxrows = pixrows - yBias; int y; /* Scan the image line by line and fill the tongue outline with the RGB values determined by the color system for the x-y co-ordinates within the tongue. */ for (y = 0; y < pxrows; ++y) { bool present; /* There is some tongue on this line */ int leftEdge; /* x position of leftmost pixel in tongue on this line */ int rightEdge; /* same, but rightmost */ findTongue(pixels, pxcols, xBias, y, &present, &leftEdge, &rightEdge); if (present) { int x; for (x = leftEdge; x <= rightEdge; ++x) { double cx, cy, cz, jr, jg, jb, jmax; int r, g, b, mx; if (upvp) { double up, vp; up = ((double) x) / (pxcols - 1); vp = 1.0 - ((double) y) / (pxrows - 1); upvp_to_xy(up, vp, &cx, &cy); cz = 1.0 - (cx + cy); } else { cx = ((double) x) / (pxcols - 1); cy = 1.0 - ((double) y) / (pxrows - 1); cz = 1.0 - (cx + cy); } xyz_to_rgb(cs, cx, cy, cz, &jr, &jg, &jb); mx = Maxval; /* Check whether the requested color is within the gamut achievable with the given color system. If not, draw it in a reduced intensity, interpolated by desaturation to the closest within-gamut color. */ if (constrain_rgb(&jr, &jg, &jb)) { mx = highlightGamut ? Maxval : ((Maxval + 1) * 3) / 4; } /* Scale to max(rgb) = 1. */ jmax = MAX(jr, MAX(jg, jb)); if (jmax > 0) { jr = jr / jmax; jg = jg / jmax; jb = jb / jmax; } /* gamma correct from linear rgb to nonlinear rgb. */ gamma_correct_rgb(cs, &jr, &jg, &jb); r = mx * jr; g = mx * jg; b = mx * jb; PPM_ASSIGN(Bixels(y, x), (pixval) r, (pixval) g, (pixval) b); } } } }
inline value_type lab_to_rgb(const value_type& v) { value_type lab = v - value_type(0,128,128); return xyz_to_rgb(lab_to_xyz(lab)); }
rgb_color& from_xyz(const color_xyz& xyz) { xyz_to_rgb(xyz, this); return *this; }