1 // Copyright 2011 Paul Hänsch
2 // This file is part of Stereofy
4 // Stereofy is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Stereofy is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Stereofy. If not, see <http://www.gnu.org/licenses/>.
22 int mm(int v, int min, int max);
23 int anaglyph(FILE *in1, FILE *in2, FILE *out,
24 unsigned char* (*alg)(unsigned char*, const unsigned char*, const unsigned char*) );
25 unsigned char* (*parse_func(const char *arg))(unsigned char*, const unsigned char*, const unsigned char*);
27 unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
28 unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
29 unsigned char* dubois_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
30 unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
31 unsigned char* half_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
32 unsigned char* dubois_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
33 unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r);
34 unsigned char* dubois_mc(unsigned char *out, const unsigned char *l, const unsigned char *r);
35 unsigned char* dubois_ab(unsigned char *out, const unsigned char *l, const unsigned char *r);
37 int main(int argc, char *argv[]){
38 FILE *in1, *in2, *out; int cnt; in1 = in2 = out = NULL;
39 unsigned char* (*alg)(unsigned char[], const unsigned char[], const unsigned char[]) = &dubois_rc;
41 if (argc < 4 || argc > 5) return error(1);
42 for (cnt = 1; cnt < argc; cnt++) {
43 if (argv[cnt][0] == '-') alg = parse_func(argv[cnt]);
44 else if (!in1){ if ((in1 = fopen(argv[cnt], "r")) == NULL) return error(2);}
45 else if (!in2){ if ((in2 = fopen(argv[cnt], "r")) == NULL) return error(2);}
46 else if (!out){ if ((out = fopen(argv[cnt], "w")) == NULL) return error(3);}
48 return anaglyph(in1, in2, out, alg);
52 char *msg = "Unknown Error\n";
54 case 1: msg = "Usage: anaglyph [ -[fhd]gm | -[fhd]rc | -fmc | -dab ] left.rgb right.rgb output.rgb\n"; break;
55 case 2: msg = "Could not open input file for reading\n"; break;
56 case 3: msg = "Could not open output file for writing\n"; break;
57 case 4: msg = "Unexpected end of file\n"; break;
58 case 5: msg = "Cannot write to output file\n"; break;
60 fprintf(stderr, "%s", msg); return code;
63 // min-max to prevent overflowing in Dubois calculations
64 int mm(int v, int min, int max){
65 if (v < min) return min;
66 else if (v > max) return max;
70 //green-magenta full-color
71 unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
78 //green-magenta half-color
79 unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
81 //green channel is derived from chroma value of left image
82 out[1] = (unsigned char)(int)((299*(int)l[0] + 587*(int)l[1] + 114*(int)l[2]) / 1000);
88 //green-magenta Dubois
89 unsigned char* dubois_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
90 out[0] = (unsigned char)mm((-62*(int)l[0] + -158*(int)l[1] + -39*(int)l[2] +
91 529*(int)r[0] + 705*(int)r[1] + 24*(int)r[2]) / 1000, 0, 255);
92 out[1] = (unsigned char)mm((284*(int)l[0] + 668*(int)l[1] + 143*(int)l[2] +
93 -16*(int)r[0] + -15*(int)r[1] + -65*(int)r[2]) / 1000, 0, 255);
94 out[2] = (unsigned char)mm((-15*(int)l[0] + -27*(int)l[1] + 21*(int)l[2] +
95 9*(int)r[0] + 75*(int)r[1] + 937*(int)r[2]) / 1000, 0, 255);
100 unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
107 //red-cyan half-color
108 unsigned char* half_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
109 //red channel is derived from chroma value of left image
110 out[0] = (unsigned char)(int)((299*(int)l[0] + 587*(int)l[1] + 114*(int)l[2]) / 1000);
118 unsigned char* dubois_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
119 out[0] = (unsigned char) mm((456*(int)l[0] + 500*(int)l[1] + 176*(int)l[2] +
120 -43*(int)r[0] + -88*(int)r[1] + -2*(int)r[2]) / 1000, 0, 255);
121 out[1] = (unsigned char) mm((-40*(int)l[0] + -38*(int)l[1] + -16*(int)l[2] +
122 378*(int)r[0] + 734*(int)r[1] + -18*(int)r[2]) / 1000, 0, 255);
123 out[2] = (unsigned char) mm((-15*(int)l[0] + -21*(int)l[1] + -5*(int)l[2] +
124 -72*(int)r[0] +-113*(int)r[1] + 1226*(int)r[2]) / 1000, 0, 255);
128 //magenta-cyan full-color
129 unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
132 out[2] = (unsigned char)(((int)r[2] + (int)l[2]) / 2);
136 //magenta-cyan experimental
137 unsigned char* experimental_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
138 out[0] = (unsigned char) mm((556*(int)l[0] + 400*(int)l[1] + 176*(int)l[2] +
139 -43*(int)r[0] + -88*(int)r[1] + -2*(int)r[2]) / 950, 0, 255);
140 out[1] = (unsigned char) mm((-40*(int)l[0] + -38*(int)l[1] + -16*(int)l[2] +
141 278*(int)r[0] + 734*(int)r[1] + -18*(int)r[2]) / 1100, 0, 255);
142 out[2] = (unsigned char) mm((-15*(int)l[0] + -21*(int)l[1] + 600*(int)l[2] +
143 -72*(int)r[0] +-113*(int)r[1] + 621*(int)r[2]) / 950, 0, 255);
148 unsigned char* dubois_ab(unsigned char *out, const unsigned char *l, const unsigned char *r){
149 out[0] = (unsigned char)mm((1062*(int)l[0] + -205*(int)l[1] +299*(int)l[2] +
150 -16*(int)r[0] +-123*(int)r[1] + -17*(int)r[2]) / 1000, 0, 255);
151 out[1] = (unsigned char)mm((-26*(int)l[0] + 908*(int)l[1] + 68*(int)l[2] +
152 6*(int)r[0] + 62*(int)r[1] + -17*(int)r[2]) / 1000, 0, 255);
153 out[2] = (unsigned char)mm((-38*(int)l[0] + -173*(int)l[1] + 22*(int)l[2] +
154 94*(int)r[0] + 185*(int)r[1] + 911*(int)r[2]) / 1000, 0, 255);
158 unsigned char* (*parse_func(const char *arg))(unsigned char*, const unsigned char*, const unsigned char*){
159 if (!strcmp(arg, "-fgm")) return &full_gm;
160 if (!strcmp(arg, "-hgm")) return &half_gm;
161 if (!strcmp(arg, "-dgm")) return &dubois_gm;
163 if (!strcmp(arg, "-frc")) return &full_rc;
164 if (!strcmp(arg, "-hrc")) return &half_rc;
165 if (!strcmp(arg, "-drc")) return &dubois_rc;
167 if (!strcmp(arg, "-fmc")) return &full_mc;
168 if (!strcmp(arg, "-dab")) return &dubois_ab;
169 if (!strcmp(arg, "-emc")) return &experimental_mc;
170 exit(error(1)); return &dubois_rc;
173 int anaglyph(FILE *in1, FILE *in2, FILE *out,
174 unsigned char* (*alg)(unsigned char*, const unsigned char*, const unsigned char*) ){
175 unsigned char *i1 = malloc(3), *i2 = malloc(3), *o = malloc(3);
177 while (fread( i1, 1, 3, in1) && fread( i2, 1, 3, in2)){
178 if (!fwrite(alg( o, i1, i2), 1, 3, out)) return error(5);