]> git.plutz.net Git - stereofy/blob - anaglyph.c
swithed the meaning of the hjust parameter back so that the value accords to the...
[stereofy] / anaglyph.c
1 // Copyright 2011 Paul Hänsch
2 // This file is part of Stereofy
3 //
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.
8 //
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.
13 //
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/>.
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 int error(int code);
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*);
26
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);
36
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;
40
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);}
47   }
48   return anaglyph(in1, in2, out, alg);
49 }
50
51 int error(int code){
52   char *msg = "Unknown Error\n";
53   switch (code) {
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;
59   }
60   fprintf(stderr, "%s", msg); return code;
61 }
62
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;
67   else return v;
68 }
69
70 //green-magenta full-color
71 unsigned char* full_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
72   out[0] = r[0];
73   out[1] = l[1];
74   out[2] = r[2];
75   return out;
76 }
77
78 //green-magenta half-color
79 unsigned char* half_gm(unsigned char *out, const unsigned char *l, const unsigned char *r){
80   out[0] = r[0];
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);
83   out[2] = r[2];
84
85   return out;
86 }
87
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);
96   return out;
97 }
98
99 //red-cyan full-color
100 unsigned char* full_rc(unsigned char *out, const unsigned char *l, const unsigned char *r){
101   out[0] = l[0];
102   out[1] = r[1];
103   out[2] = r[2];
104   return out;
105 }
106
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);
111   out[1] = r[1];
112   out[2] = r[2];
113
114   return out;
115 }
116
117 //red-cyan Dubois
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);
125   return out;
126 }
127
128 //magenta-cyan full-color
129 unsigned char* full_mc(unsigned char *out, const unsigned char *l, const unsigned char *r){
130   out[0] = l[0];
131   out[1] = r[1];
132   out[2] = (unsigned char)(((int)r[2] + (int)l[2]) / 2);
133   return out;
134 }
135
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);
144   return out;
145 }
146
147 //amber-blue Dubois
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);
155   return out;
156 }
157
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;
162
163   if (!strcmp(arg, "-frc")) return &full_rc;
164   if (!strcmp(arg, "-hrc")) return &half_rc;
165   if (!strcmp(arg, "-drc")) return &dubois_rc;
166
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;
171 }
172
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);
176
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);
179   }
180   return 0;
181 }