]> git.plutz.net Git - stereofy/blob - anaglyph.c
initial commit
[stereofy] / anaglyph.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int error(int code);
6 int mm(int v, int min, int max);
7 int anaglyph(FILE *in1, FILE *in2, FILE *out, char *alg);
8 unsigned char* colorize(unsigned char *out, const unsigned char *left, const unsigned char *right, const char *alg);
9 unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
10 unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
11 unsigned char* dubois_gm(unsigned char *out, const unsigned char *l, const unsigned char *r);
12 unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
13 unsigned char* half_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
14 unsigned char* dubois_rc(unsigned char *out, const unsigned char *l, const unsigned char *r);
15 unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r);
16 unsigned char* dubois_mc(unsigned char *out, const unsigned char *l, const unsigned char *r);
17 unsigned char* dubois_ab(unsigned char *out, const unsigned char *l, const unsigned char *r);
18
19 int main(int argc, char *argv[]){
20   FILE *in1, *in2, *out; int cnt; char *alg = malloc(5);
21   in1 = in2 = out = NULL; alg = strcpy(alg, "-dgm");
22
23   if (argc < 4 || argc > 5) return error(1);
24   for (cnt = 1; cnt < argc; cnt++) {
25     if (argv[cnt][0] == '-') alg = strcpy(alg, argv[cnt]);
26     else if (!in1){ if ((in1 = fopen(argv[cnt], "r")) == NULL) return error(2);}
27     else if (!in2){ if ((in2 = fopen(argv[cnt], "r")) == NULL) return error(2);}
28     else if (!out){ if ((out = fopen(argv[cnt], "w")) == NULL) return error(3);}
29   }
30   return anaglyph(in1, in2, out, alg);
31 }
32
33 int error(int code){
34   char *msg = "Unknown Error\n";
35   switch (code) {
36     case 1: msg = "Usage: anaglyph [ -[fhd]gm | -[fhd]rc | -fmc | -dab ] left.rgb right.rgb output.rgb\n";
37     case 2: msg = "Could not open input file for reading\n";
38     case 3: msg = "Could not open output file for writing\n";
39     case 4: msg = "Unexpected end of file\n";
40     case 5: msg = "Cannot write to output file\n";
41   }
42   fprintf(stderr, msg); return code;
43 }
44
45 // min-max to prevent overflowing in Dubois calculations
46 int mm(int v, int min, int max){
47   if (v < min) return min;
48   else if (v > max) return max;
49   else return v;
50 }
51
52 //green-magenta full-color
53 unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
54   out[0] = r[0];
55   out[1] = l[1];
56   out[2] = r[2];
57   return out;
58 }
59
60 //green-magenta half-color
61 unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
62   out[0] = r[0];
63   //green channel is derived from chroma value of left image
64   out[1] = (unsigned char)(int)((299*(int)l[0] + 587*(int)l[1] + 114*(int)l[2]) / 1000);
65   out[2] = r[2];
66
67   return out;
68 }
69
70 //green-magenta Dubois
71 unsigned char* dubois_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
72   out[0] = (unsigned char)mm((-62*(int)l[0] + -158*(int)l[1] + -39*(int)l[2] +
73         529*(int)r[0] + 705*(int)r[1] +   24*(int)r[2]) / 1000, 0, 255);
74   out[1] = (unsigned char)mm((284*(int)l[0] +  668*(int)l[1] + 143*(int)l[2] +
75         -16*(int)r[0] + -15*(int)r[1] +  -65*(int)r[2]) / 1000, 0, 255);
76   out[2] = (unsigned char)mm((-15*(int)l[0] +  -27*(int)l[1] +  21*(int)l[2] +
77           9*(int)r[0] +  75*(int)r[1] +  937*(int)r[2]) / 1000, 0, 255);
78   return out;
79 }
80
81 //red-cyan full-color
82 unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
83   out[0] = l[0];
84   out[1] = r[1];
85   out[2] = r[2];
86   return out;
87 }
88
89 //red-cyan half-color
90 unsigned char* half_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
91   //red channel is derived from chroma value of left image
92   out[0] = (unsigned char)(int)((299*(int)l[0] + 587*(int)l[1] + 114*(int)l[2]) / 1000);
93   out[1] = r[1];
94   out[2] = r[2];
95
96   return out;
97 }
98
99 //red-cyan Dubois
100 unsigned char* dubois_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
101   out[0] = (unsigned char)mm((456*(int)l[0] +  500*(int)l[1] + 176*(int)l[2] +
102         -43*(int)r[0] + -88*(int)r[1] +   -2*(int)r[2]) / 1000, 0, 255);
103   out[1] = (unsigned char)mm((-40*(int)l[0] +  -38*(int)l[1] + -16*(int)l[2] +
104         378*(int)r[0] + 734*(int)r[1] +  -18*(int)r[2]) / 1000, 0, 255);
105   out[2] = (unsigned char)mm((-15*(int)l[0] +  -21*(int)l[1] +  -5*(int)l[2] +
106         -72*(int)r[0] +-113*(int)r[1] + 1226*(int)r[2]) / 1000, 0, 255);
107   return out;
108 }
109
110 //magenta-cyan full-color
111 unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
112   out[0] = l[0];
113   out[1] = r[1];
114   out[2] = (unsigned char)(((int)r[2] + (int)l[2]) / 2);
115   return out;
116 }
117
118 //magenta-cyan "Dubois"
119 unsigned char* dubois_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
120   out[0] = (unsigned char)mm((529*(int)l[0] + 705*(int)l[1] + 24*(int)l[2] +
121         -62*(int)r[0] +-158*(int)r[1] +  -39*(int)r[2]) / 1000, 0, 255);
122   out[1] = (unsigned char)mm((-40*(int)l[0] +  -38*(int)l[1] + -16*(int)l[2] +
123         378*(int)r[0] + 734*(int)r[1] +  -18*(int)r[2]) / 1000, 0, 255);
124   out[2] = (unsigned char)mm((-15*(int)l[0] +  -24*(int)l[1] +   8*(int)l[2] +
125         -32*(int)r[0] + -19*(int)r[1] + 1081*(int)r[2]) / 1000, 0, 255);
126
127 //  out[2] = (unsigned char)mm((-15*(int)l[0] +  -27*(int)l[1] +  21*(int)l[2] + gm
128 //        9*(int)r[0] +  75*(int)r[1] +  937*(int)r[2]) / 1000, 0, 255);
129 //  out[2] = (unsigned char)mm((-15*(int)l[0] +  -21*(int)l[1] +  -5*(int)l[2] + rc
130 //      -72*(int)r[0] +-113*(int)r[1] + 1226*(int)r[2]) / 1000, 0, 255);
131   return out;
132 }
133
134 //amber-blue Dubois
135 unsigned char* dubois_ab(unsigned char *out, const unsigned char *l, const unsigned char *r){
136   out[0] = (unsigned char)mm((1062*(int)l[0] + -205*(int)l[1] +299*(int)l[2] +
137         -16*(int)r[0] +-123*(int)r[1] +  -17*(int)r[2]) / 1000, 0, 255);
138   out[1] = (unsigned char)mm((-26*(int)l[0] +  908*(int)l[1] +  68*(int)l[2] +
139           6*(int)r[0] +  62*(int)r[1] +  -17*(int)r[2]) / 1000, 0, 255);
140   out[2] = (unsigned char)mm((-38*(int)l[0] + -173*(int)l[1] +  22*(int)l[2] +
141          94*(int)r[0] + 185*(int)r[1] +  911*(int)r[2]) / 1000, 0, 255);
142   return out;
143 }
144
145 unsigned char* colorize(unsigned char *out, const unsigned char *left, const unsigned char *right, const char *alg){
146   if (!strcmp(alg, "-fgm")) return full_gm(out, left, right);
147   if (!strcmp(alg, "-hgm")) return half_gm(out, left, right);
148   if (!strcmp(alg, "-dgm")) return dubois_gm(out, left, right);
149
150   if (!strcmp(alg, "-frc")) return full_rc(out, left, right);
151   if (!strcmp(alg, "-hrc")) return half_rc(out, left, right);
152   if (!strcmp(alg, "-drc")) return dubois_rc(out, left, right);
153
154   if (!strcmp(alg, "-fmc")) return full_mc(out, left, right);
155   if (!strcmp(alg, "-dmc")) return dubois_mc(out, left, right);
156   if (!strcmp(alg, "-dab")) return dubois_ab(out, left, right);
157   exit(error(1)); return out;
158 }
159
160 int anaglyph(FILE *in1, FILE *in2, FILE *out, char *alg){
161   unsigned char *i1 = malloc(3), *i2 = malloc(3), *o = malloc(3);
162
163   while (fread( i1, 1, 3, in1) && fread( i2, 1, 3, in2)){
164     if (!fwrite(colorize( o, i1, i2, alg), 1, 3, out)) return error(5);
165   }
166   return 0;
167 }