bool ColorConvert::test() { Image a(123, 234, 3, 3); Noise::apply(a, 0.3, 0.7); // Gotta be in-gamut for all our spaces tested Image b = a; if (!nearlyEqual(a, xyz2rgb(rgb2xyz(a)))) return false; string spaces[] = {"xyz", "rgb", "argb", "yuv", "lab", "hsv"}; for (int i = 0; i < 6; i++) { for (int j = 0; j < i; j++) { printf("%s -> %s -> %s\n", spaces[j].c_str(), spaces[i].c_str(), spaces[j].c_str()); Image to = apply(a, spaces[j], spaces[i]); Image from = apply(to, spaces[i], spaces[j]); if (!nearlyEqual(a, from)) return false; } { // Check luminance is preserved printf("y -> %s -> y\n", spaces[i].c_str()); Image y = a.channel(0); Image to = apply(y, "y", spaces[i]); Image from = apply(to, spaces[i], "y"); if (!nearlyEqual(y, from)) return false; } } return true; }
void Image::rgb2xyz() { if (xyz_data == nullptr) xyz_data = new precision[3 * width * height]; for (unsigned int h = 0; h < height; h++) { for (unsigned int w = 0; w < width; w++) { auto rc = this->rc(w, h); auto gc = this->gc(w, h); auto bc = this->bc(w, h); precision x, y, z; rgb2xyz(rc, gc, bc, &x, &y, &z); this->x(w, h, x); this->y(w, h, y); this->z(w, h, z); } } }
// BANG - calculate and output void cs_bang(t_cs *x) { if(x->attr_mode == ps_rgb2hsl) rgb2hsl(x, x->val1, x->val2, x->val3); // first for speed else if(x->attr_mode == ps_hsl2rgb) hsl2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_no_transform) no_transform(x); else if(x->attr_mode == ps_rgb2cmy) rgb2cmy(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_cmy2rgb) cmy2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2hsv) rgb2hsv(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_hsv2rgb) hsv2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2xyz) rgb2xyz(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_xyz2rgb) xyz2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2uvw) rgb2uvw(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_uvw2rgb) uvw2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2retinalcone) rgb2cone(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_retinalcone2rgb) cone2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2lab) rgb2lab(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_lab2rgb) lab2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2yiq) rgb2yiq(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_yiq2rgb) yiq2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2hls) rgb2hls(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_hls2rgb) hls2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2rgbcie) rgb2rgbcie(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgbcie2rgb) rgbcie2rgb(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgb2rgbsmpte) rgb2rgbsmpte(x, x->val1, x->val2, x->val3); else if(x->attr_mode == ps_rgbsmpte2rgb) rgbsmpte2rgb(x, x->val1, x->val2, x->val3); if(x->attr_outputtype == ps_packed){ Atom temp_list[3]; atom_setlong(temp_list+0, x->calc1); atom_setlong(temp_list+1, x->calc2); atom_setlong(temp_list+2, x->calc3); outlet_list(x->out1, 0L, 3, temp_list); // output the result } else{ outlet_int(x->out3, x->calc3); // output the result outlet_int(x->out2, x->calc2); // output the result outlet_int(x->out1, x->calc1); // output the result } }
Image ColorConvert::rgb2argb(Image im) { return xyz2argb(rgb2xyz(im)); }
Image ColorConvert::rgb2lab(Image im) { assert(im.channels == 3, "Image does not have 3 channels\n"); return xyz2lab(rgb2xyz(im)); }
Image ColorConvert::apply(Image im, string from, string to) { // check for the trivial case assert(from != to, "color conversion from %s to %s is pointless\n", from.c_str(), to.c_str()); // unsupported destination color spaces if (to == "yuyv" || to == "uyvy") { panic("Unsupported destination color space: %s\n", to.c_str()); } // direct conversions that don't have to go via rgb if (from == "yuyv" && to == "yuv") { return yuyv2yuv(im); } else if (from == "uyvy" && to == "yuv") { return uyvy2yuv(im); } else if (from == "xyz" && to == "lab") { return xyz2lab(im); } else if (from == "lab" && to == "xyz") { return lab2xyz(im); } else if (from == "argb" && to == "xyz") { return argb2xyz(im); } else if (from == "xyz" && to == "argb") { return xyz2argb(im); } else if (from != "rgb" && to != "rgb") { // conversions that go through rgb Image halfway = apply(im, from, "rgb"); return apply(halfway, "rgb", to); } else if (from == "rgb") { // from rgb if (to == "hsv" || to == "hsl" || to == "hsb") { return rgb2hsv(im); } else if (to == "yuv") { return rgb2yuv(im); } else if (to == "xyz") { return rgb2xyz(im); } else if (to == "y" || to == "gray" || to == "grayscale" || to == "luminance") { return rgb2y(im); } else if (to == "lab") { return rgb2lab(im); } else if (to == "argb") { return rgb2argb(im); } else { panic("Unknown color space %s\n", to.c_str()); } } else { //(to == "rgb") if (from == "hsv" || from == "hsl" || from == "hsb") { return hsv2rgb(im); } else if (from == "yuv") { return yuv2rgb(im); } else if (from == "xyz") { return xyz2rgb(im); } else if (from == "y" || from == "gray" || from == "grayscale" || from == "luminance") { return y2rgb(im); } else if (from == "lab") { return lab2rgb(im); } else if (from == "uyvy") { return uyvy2rgb(im); } else if (from == "yuyv") { return yuyv2rgb(im); } else if (from == "argb") { return argb2rgb(im); } else { panic("Unknown color space %s\n", from.c_str()); } } // keep the compiler happy return Image(); }
double *rgb2lab(double arr[]) { double *xyz = rgb2xyz(arr); double *lab = xyz2lab(xyz); free(xyz); return lab; }