Image Demosaicking with Contour Stencils
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
gen_mstencils.c
Go to the documentation of this file.
1 
18 #include <stdio.h>
19 #include <string.h>
20 #include "basic.h"
21 #include "edge.h"
22 #include "temsub.h"
23 
25 #define NUMSTENCILS 8
26 
28 #define WEIGHT_PI_8_FACTOR 3.847759065022573512
29 
30 
32 
35 
36 
38 cfa_color GetBayerColor(int RedX, int RedY, int x, int y)
39 {
40  return ((y & 1) == RedY) ?
41  (((x & 1) == RedX) ? COLOR_RED : COLOR_GREEN)
42  : (((x & 1) == RedX) ? COLOR_GREEN : COLOR_BLUE);
43 }
44 
45 
47 static int IsValidEdge(int RedX, int RedY, float Radius,
48  int x1, int y1, int x2, int y2)
49 {
50  const int SqrRadius = (int)(Radius*Radius);
51  cfa_color Color1 = GetBayerColor(RedX, RedY, x1, y1);
52  int MaxDistSqr = (Color1 == COLOR_GREEN) ? 4 : 8;
53 
54  return (
55  /* Make sure endpoints have the same color */
56  (Color1 == GetBayerColor(RedX, RedY, x2, y2))
57  /* (x1,y1) must be in the neighborhood */
58  && (x1*x1 + y1*y1 <= SqrRadius)
59  /* (x2,y2) must be in the neighborhood */
60  && (x2*x2 + y2*y2 <= SqrRadius)
61  /* Endpoints must be close to each other */
62  && ((x1 - x2)*(x1 - x2)
63  + (y1 - y2)*(y1 - y2) <= MaxDistSqr)
64  ) ? 1 : 0;
65 }
66 
67 
69 double EdgeLength(edge Edge)
70 {
71  double DiffX = Edge.x1 - Edge.x2;
72  double DiffY = Edge.y1 - Edge.y2;
73  return sqrt(DiffX*DiffX + DiffY*DiffY);
74 }
75 
76 
78 double StencilArcSum(mstencil Stencil)
79 {
80  edge *Edge;
81  double Sum = 0;
82 
83  for(Edge = Stencil.Head; Edge != NULL; Edge = Edge->NextEdge)
84  Sum += Edge->Weight * EdgeLength(*Edge);
85 
86  return Sum;
87 }
88 
89 
91 void FreeStencils(mstencil *Stencils)
92 {
93  int j;
94 
95  if(Stencils)
96  {
97  for(j = 0; j < 4; j++)
98  FreeEdgeList(&Stencils[j]);
99 
100  Free(Stencils);
101  }
102 }
103 
104 
107 {
108  edge *EdgeA = A.Head, *EdgeB = B.Head;
109 
110  while(EdgeA && EdgeB)
111  {
112  if(EdgeA->x1 != EdgeB->x1 || EdgeA->y1 != EdgeB->y1
113  || EdgeA->x2 != EdgeB->x2 || EdgeA->y2 != EdgeB->y2)
114  return 0;
115 
116  EdgeA = EdgeA->NextEdge;
117  EdgeB = EdgeB->NextEdge;
118  }
119 
120  return !(EdgeA || EdgeB) ? 1 : 0;
121 }
122 
123 
129 mstencil *ConstructMosaicedStencils(double Radius, cfa_color CenterPixel)
130 {
131  const int NeighX[4] = { 1, 1, 0, -1};
132  const int NeighY[4] = { 0, -1, -1, -1};
133  mstencil *Stencils;
134  int RedX, RedY;
135  int j, x1, y1, x2, y2, Dist;
136 
137  if(!(Stencils = (mstencil *)Malloc(sizeof(mstencil)*4)))
138  exit(1);
139 
140  switch(CenterPixel)
141  {
142  case COLOR_RED:
143  RedX = 0;
144  RedY = 0;
145  break;
146  case COLOR_GREEN:
147  RedX = 1;
148  RedY = 0;
149  break;
150  case COLOR_BLUE:
151  RedX = 1;
152  RedY = 1;
153  break;
154  default:
155  exit(1);
156  }
157 
158  for(j = 0; j < 4; j++)
159  Stencils[j] = NullEdgeList;
160 
161  /* Fill the stencils */
162  for(j = 0; j < 4; j++)
163  for(y1 = -(int)Radius; y1 <= (int)Radius; y1++)
164  for(x1 = -(int)Radius; x1 <= (int)Radius; x1++)
165  for(Dist = 1; Dist <= 2; Dist++)
166  {
167  x2 = x1 + Dist*NeighX[j];
168  y2 = y1 + Dist*NeighY[j];
169 
170  /* If the edge from (x1,y1) to (x2,y2) is valid, add it
171  to Stencil[j] (edge has weight = 1). */
172  if(IsValidEdge(RedX, RedY, Radius, x1, y1, x2, y2)
173  && !AddEdge(&Stencils[j], x1, y1, x2, y2))
174  exit(1);
175  }
176 
177  return Stencils;
178 }
179 
188 void WriteTVComputation(char **Str, mstencil *Stencils, int j)
189 {
190  edge *Edge = Stencils[j].Head;
191 
192  if(Edge)
193  StringAppend(Str, "TV[%d] = TVEDGE(%2d,%2d, %2d,%2d)",
194  2*j, Edge->x1, Edge->y1, Edge->x2, Edge->y2);
195 
196  for(Edge = Edge->NextEdge; Edge != NULL; Edge = Edge->NextEdge)
197  StringAppend(Str, "\n + TVEDGE(%2d,%2d, %2d,%2d)",
198  Edge->x1, Edge->y1, Edge->x2, Edge->y2);
199 
200  StringAppend(Str, ";");
201 }
202 
203 
204 
205 int main(int argc, char *argv[])
206 {
207  double Radius, AxialSum, DiagonalSum;
208  char *TemplateFilename, *OutputFilename;
209  char **Keys = NULL, **Subs = NULL, **Sub;
210  mstencil *GreenStencils = NULL, *RedBlueStencils = NULL;
211  int Status = 1;
212 
213  if(argc != 4)
214  {
215  fprintf(stderr, "Syntax: gen-mstencil <radius> <template> <output>\n");
216  return 1;
217  }
218  else if((Radius = atof(argv[1])) <= 0)
219  fprintf(stderr, "Radius must be positive.\n");
220 
221  TemplateFilename = argv[2];
222  OutputFilename = argv[3];
223 
224  /* Construct stencils */
225  GreenStencils = ConstructMosaicedStencils(Radius, COLOR_GREEN);
226  RedBlueStencils = ConstructMosaicedStencils(Radius, COLOR_RED);
227 
228  /* Make sure that RedBlue axial stencils are the same as Green versions */
229  if(!StencilEquals(RedBlueStencils[0], GreenStencils[0])
230  || !StencilEquals(RedBlueStencils[2], GreenStencils[2]))
231  {
232  fprintf(stderr, "Assertion failed:\n"
233  "RedBlue axial stencils == Green axial stencils\n");
234  goto Catch;
235  }
236 
237  /* Create the key-substitution pairs for the template */
238  AddPair(&Keys, &Subs, "RADIUS", "%d", (int)floor(Radius));
239 
240  AxialSum = StencilArcSum(GreenStencils[0]);
241  DiagonalSum = StencilArcSum(GreenStencils[1]);
242 
243  Sub = AddPair(&Keys, &Subs, "AXIAL_TVS", "");
244  WriteTVComputation(Sub, GreenStencils, 0);
245  StringAppend(Sub, "\n");
246  WriteTVComputation(Sub, GreenStencils, 2);
247 
248  Sub = AddPair(&Keys, &Subs, "GREEN_DIAGONAL_TVS", "");
249  WriteTVComputation(Sub, GreenStencils, 1);
250  StringAppend(Sub, "\n");
251  WriteTVComputation(Sub, GreenStencils, 3);
252 
253  AddPair(&Keys, &Subs,
254  "WEIGHT_AXIAL", "%.15e", 1/AxialSum);
255  AddPair(&Keys, &Subs,
256  "WEIGHT_PI_8", "%.15e", 1/(AxialSum*WEIGHT_PI_8_FACTOR));
257  AddPair(&Keys, &Subs,
258  "WEIGHT_GREEN_MU", "%.15e", AxialSum/DiagonalSum);
259  AddPair(&Keys, &Subs,
260  "WEIGHT_GREEN_DIAGONAL", "%.15e", 1/DiagonalSum);
261 
262  AxialSum = StencilArcSum(RedBlueStencils[0]);
263  DiagonalSum = StencilArcSum(RedBlueStencils[1]);
264 
265  Sub = AddPair(&Keys, &Subs, "REDBLUE_DIAGONAL_TVS", "");
266  WriteTVComputation(Sub, RedBlueStencils, 1);
267  StringAppend(Sub, "\n");
268  WriteTVComputation(Sub, RedBlueStencils, 3);
269 
270  AddPair(&Keys, &Subs,
271  "WEIGHT_REDBLUE_MU", "%.15e", AxialSum/DiagonalSum);
272  AddPair(&Keys, &Subs,
273  "WEIGHT_REDBLUE_DIAGONAL", "%.15e", 1/DiagonalSum);
274 
275  /* Fill the template */
276  FillTemplate(OutputFilename, TemplateFilename, Keys, Subs);
277 
278  Status = 0;
279 Catch:
280  FreeStringArray(Subs);
281  FreeStringArray(Keys);
282  FreeStencils(GreenStencils);
283  FreeStencils(RedBlueStencils);
284  return Status;
285 }