--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int error(int code);
+int mm(int v, int min, int max);
+int anaglyph(FILE *in1, FILE *in2, FILE *out, char *alg);
+unsigned char* colorize(unsigned char *out, const unsigned char *left, const unsigned char *right, const char *alg);
+unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* dubois_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* half_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* dubois_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* dubois_mc(unsigned char *out, const unsigned char *l, const unsigned char *r);
+unsigned char* dubois_ab(unsigned char *out, const unsigned char *l, const unsigned char *r);
+
+int main(int argc, char *argv[]){
+ FILE *in1, *in2, *out; int cnt; char *alg = malloc(5);
+ in1 = in2 = out = NULL; alg = strcpy(alg, "-dgm");
+
+ if (argc < 4 || argc > 5) return error(1);
+ for (cnt = 1; cnt < argc; cnt++) {
+ if (argv[cnt][0] == '-') alg = strcpy(alg, argv[cnt]);
+ else if (!in1){ if ((in1 = fopen(argv[cnt], "r")) == NULL) return error(2);}
+ else if (!in2){ if ((in2 = fopen(argv[cnt], "r")) == NULL) return error(2);}
+ else if (!out){ if ((out = fopen(argv[cnt], "w")) == NULL) return error(3);}
+ }
+ return anaglyph(in1, in2, out, alg);
+}
+
+int error(int code){
+ char *msg = "Unknown Error\n";
+ switch (code) {
+ case 1: msg = "Usage: anaglyph [ -[fhd]gm | -[fhd]rc | -fmc | -dab ] left.rgb right.rgb output.rgb\n";
+ case 2: msg = "Could not open input file for reading\n";
+ case 3: msg = "Could not open output file for writing\n";
+ case 4: msg = "Unexpected end of file\n";
+ case 5: msg = "Cannot write to output file\n";
+ }
+ fprintf(stderr, msg); return code;
+}
+
+// min-max to prevent overflowing in Dubois calculations
+int mm(int v, int min, int max){
+ if (v < min) return min;
+ else if (v > max) return max;
+ else return v;
+}
+
+//green-magenta full-color
+unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = r[0];
+ out[1] = l[1];
+ out[2] = r[2];
+ return out;
+}
+
+//green-magenta half-color
+unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = r[0];
+ //green channel is derived from chroma value of left image
+ out[1] = (unsigned char)(int)((299*(int)l[0] + 587*(int)l[1] + 114*(int)l[2]) / 1000);
+ out[2] = r[2];
+
+ return out;
+}
+
+//green-magenta Dubois
+unsigned char* dubois_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = (unsigned char)mm((-62*(int)l[0] + -158*(int)l[1] + -39*(int)l[2] +
+ 529*(int)r[0] + 705*(int)r[1] + 24*(int)r[2]) / 1000, 0, 255);
+ out[1] = (unsigned char)mm((284*(int)l[0] + 668*(int)l[1] + 143*(int)l[2] +
+ -16*(int)r[0] + -15*(int)r[1] + -65*(int)r[2]) / 1000, 0, 255);
+ out[2] = (unsigned char)mm((-15*(int)l[0] + -27*(int)l[1] + 21*(int)l[2] +
+ 9*(int)r[0] + 75*(int)r[1] + 937*(int)r[2]) / 1000, 0, 255);
+ return out;
+}
+
+//red-cyan full-color
+unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = l[0];
+ out[1] = r[1];
+ out[2] = r[2];
+ return out;
+}
+
+//red-cyan half-color
+unsigned char* half_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ //red channel is derived from chroma value of left image
+ out[0] = (unsigned char)(int)((299*(int)l[0] + 587*(int)l[1] + 114*(int)l[2]) / 1000);
+ out[1] = r[1];
+ out[2] = r[2];
+
+ return out;
+}
+
+//red-cyan Dubois
+unsigned char* dubois_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = (unsigned char)mm((456*(int)l[0] + 500*(int)l[1] + 176*(int)l[2] +
+ -43*(int)r[0] + -88*(int)r[1] + -2*(int)r[2]) / 1000, 0, 255);
+ out[1] = (unsigned char)mm((-40*(int)l[0] + -38*(int)l[1] + -16*(int)l[2] +
+ 378*(int)r[0] + 734*(int)r[1] + -18*(int)r[2]) / 1000, 0, 255);
+ out[2] = (unsigned char)mm((-15*(int)l[0] + -21*(int)l[1] + -5*(int)l[2] +
+ -72*(int)r[0] +-113*(int)r[1] + 1226*(int)r[2]) / 1000, 0, 255);
+ return out;
+}
+
+//magenta-cyan full-color
+unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = l[0];
+ out[1] = r[1];
+ out[2] = (unsigned char)(((int)r[2] + (int)l[2]) / 2);
+ return out;
+}
+
+//magenta-cyan "Dubois"
+unsigned char* dubois_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = (unsigned char)mm((529*(int)l[0] + 705*(int)l[1] + 24*(int)l[2] +
+ -62*(int)r[0] +-158*(int)r[1] + -39*(int)r[2]) / 1000, 0, 255);
+ out[1] = (unsigned char)mm((-40*(int)l[0] + -38*(int)l[1] + -16*(int)l[2] +
+ 378*(int)r[0] + 734*(int)r[1] + -18*(int)r[2]) / 1000, 0, 255);
+ out[2] = (unsigned char)mm((-15*(int)l[0] + -24*(int)l[1] + 8*(int)l[2] +
+ -32*(int)r[0] + -19*(int)r[1] + 1081*(int)r[2]) / 1000, 0, 255);
+
+// out[2] = (unsigned char)mm((-15*(int)l[0] + -27*(int)l[1] + 21*(int)l[2] + gm
+// 9*(int)r[0] + 75*(int)r[1] + 937*(int)r[2]) / 1000, 0, 255);
+// out[2] = (unsigned char)mm((-15*(int)l[0] + -21*(int)l[1] + -5*(int)l[2] + rc
+// -72*(int)r[0] +-113*(int)r[1] + 1226*(int)r[2]) / 1000, 0, 255);
+ return out;
+}
+
+//amber-blue Dubois
+unsigned char* dubois_ab(unsigned char *out, const unsigned char *l, const unsigned char *r){
+ out[0] = (unsigned char)mm((1062*(int)l[0] + -205*(int)l[1] +299*(int)l[2] +
+ -16*(int)r[0] +-123*(int)r[1] + -17*(int)r[2]) / 1000, 0, 255);
+ out[1] = (unsigned char)mm((-26*(int)l[0] + 908*(int)l[1] + 68*(int)l[2] +
+ 6*(int)r[0] + 62*(int)r[1] + -17*(int)r[2]) / 1000, 0, 255);
+ out[2] = (unsigned char)mm((-38*(int)l[0] + -173*(int)l[1] + 22*(int)l[2] +
+ 94*(int)r[0] + 185*(int)r[1] + 911*(int)r[2]) / 1000, 0, 255);
+ return out;
+}
+
+unsigned char* colorize(unsigned char *out, const unsigned char *left, const unsigned char *right, const char *alg){
+ if (!strcmp(alg, "-fgm")) return full_gm(out, left, right);
+ if (!strcmp(alg, "-hgm")) return half_gm(out, left, right);
+ if (!strcmp(alg, "-dgm")) return dubois_gm(out, left, right);
+
+ if (!strcmp(alg, "-frc")) return full_rc(out, left, right);
+ if (!strcmp(alg, "-hrc")) return half_rc(out, left, right);
+ if (!strcmp(alg, "-drc")) return dubois_rc(out, left, right);
+
+ if (!strcmp(alg, "-fmc")) return full_mc(out, left, right);
+ if (!strcmp(alg, "-dmc")) return dubois_mc(out, left, right);
+ if (!strcmp(alg, "-dab")) return dubois_ab(out, left, right);
+ exit(error(1)); return out;
+}
+
+int anaglyph(FILE *in1, FILE *in2, FILE *out, char *alg){
+ unsigned char *i1 = malloc(3), *i2 = malloc(3), *o = malloc(3);
+
+ while (fread( i1, 1, 3, in1) && fread( i2, 1, 3, in2)){
+ if (!fwrite(colorize( o, i1, i2, alg), 1, 3, out)) return error(5);
+ }
+ return 0;
+}