Image Demosaicking with Contour Stencils
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
mstencils.c
Go to the documentation of this file.
1 /* Generated 2013-07-05 17:41:32 */
2 
9 #include <math.h>
10 
12 #define TVEDGE(x1,y1,x2,y2) \
13  fabs(Input[HorizontalOffset[x1] + VerticalOffset[y1]] \
14  - Input[HorizontalOffset[x2] + VerticalOffset[y2]])
15 
17 #define NUMSTENCILS 8
18 
20 #define NEIGHRADIUS 2
21 
22 /* Contour stencil weights */
23 #define WEIGHT_AXIAL 4.545454545454546e-02
24 #define WEIGHT_PI_8 1.181325147609750e-02
25 #define WEIGHT_GREEN_MU 1.111167799007432e+00
26 #define WEIGHT_GREEN_DIAGONAL 5.050762722761053e-02
27 #define WEIGHT_REDBLUE_MU 1.111167799007432e+00
28 #define WEIGHT_REDBLUE_DIAGONAL 5.050762722761053e-02
29 
51 void FitMosaicedStencils(int *Stencil, const float *Input,
52  int Width, int Height, int RedX, int RedY)
53 {
54  const int Green = 1 - ((RedX + RedY) & 1);
55  double TV[NUMSTENCILS], MinTV;
56  int Offsets[2*(2*NEIGHRADIUS + 1)];
57  int *HorizontalOffset = Offsets + NEIGHRADIUS;
58  int *VerticalOffset = Offsets + (3*NEIGHRADIUS + 1);
59  int x, y, k, S;
60 
61  if(!Stencil || !Input
62  || Width < NEIGHRADIUS + 1 || Height < NEIGHRADIUS + 1)
63  return;
64 
65  HorizontalOffset[0] = VerticalOffset[0] = 0;
66 
67  for(y = 0; y < Height; y++)
68  {
69  for(k = 1; k <= NEIGHRADIUS; k++)
70  {
71  VerticalOffset[-k] = (y >= k) ? -k*Width : (k - 2*y)*Width;
72  VerticalOffset[k] = (y < Height - k) ?
73  k*Width : 2*(Height - k - y)*Width;
74  }
75 
76  for(x = 0; x < Width; x++, Input++, Stencil++)
77  {
78  for(k = 1; k <= NEIGHRADIUS; k++)
79  {
80  HorizontalOffset[-k] = (x >= k) ? -k : (k - 2*x);
81  HorizontalOffset[k] = (x < Width - k) ?
82  k : 2*(Width - k - x);
83  }
84 
85  TV[0] = TVEDGE(-1,-2, 1,-2)
86  + TVEDGE(-2,-1, 0,-1)
87  + TVEDGE(-1,-1, 1,-1)
88  + TVEDGE( 0,-1, 2,-1)
89  + TVEDGE(-2, 0, 0, 0)
90  + TVEDGE(-1, 0, 1, 0)
91  + TVEDGE( 0, 0, 2, 0)
92  + TVEDGE(-2, 1, 0, 1)
93  + TVEDGE(-1, 1, 1, 1)
94  + TVEDGE( 0, 1, 2, 1)
95  + TVEDGE(-1, 2, 1, 2);
96  TV[4] = TVEDGE(-1, 0, -1,-2)
97  + TVEDGE( 0, 0, 0,-2)
98  + TVEDGE( 1, 0, 1,-2)
99  + TVEDGE(-2, 1, -2,-1)
100  + TVEDGE(-1, 1, -1,-1)
101  + TVEDGE( 0, 1, 0,-1)
102  + TVEDGE( 1, 1, 1,-1)
103  + TVEDGE( 2, 1, 2,-1)
104  + TVEDGE(-1, 2, -1, 0)
105  + TVEDGE( 0, 2, 0, 0)
106  + TVEDGE( 1, 2, 1, 0);
107 
108  if(((x + y) & 1) == Green) /* Center pixel is green */
109  {
110  TV[2] = TVEDGE(-1,-1, 0,-2)
111  + TVEDGE(-2, 0, -1,-1)
112  + TVEDGE(-1, 0, 1,-2)
113  + TVEDGE( 0, 0, 1,-1)
114  + TVEDGE(-2, 1, 0,-1)
115  + TVEDGE(-1, 1, 0, 0)
116  + TVEDGE( 0, 1, 2,-1)
117  + TVEDGE( 1, 1, 2, 0)
118  + TVEDGE(-1, 2, 1, 0)
119  + TVEDGE( 0, 2, 1, 1);
120  TV[6] = TVEDGE( 1,-1, 0,-2)
121  + TVEDGE( 0, 0, -1,-1)
122  + TVEDGE( 1, 0, -1,-2)
123  + TVEDGE( 2, 0, 1,-1)
124  + TVEDGE(-1, 1, -2, 0)
125  + TVEDGE( 0, 1, -2,-1)
126  + TVEDGE( 1, 1, 0, 0)
127  + TVEDGE( 2, 1, 0,-1)
128  + TVEDGE( 0, 2, -1, 1)
129  + TVEDGE( 1, 2, -1, 0);
130 
131  /* Compute TVs for odd multiples of pi/8 as linear
132  combinations of axial and diagonal TVs. */
133  TV[1] = TV[0] + WEIGHT_GREEN_MU*TV[2];
134  TV[3] = TV[4] + WEIGHT_GREEN_MU*TV[2];
135  TV[5] = TV[4] + WEIGHT_GREEN_MU*TV[6];
136  TV[7] = TV[0] + WEIGHT_GREEN_MU*TV[6];
137 
138  TV[2] *= WEIGHT_GREEN_DIAGONAL;
139  TV[6] *= WEIGHT_GREEN_DIAGONAL;
140  }
141  else /* Center pixel is red or blue */
142  {
143  TV[2] = TVEDGE(-2,-1, -1,-2)
144  + TVEDGE( 0,-1, 1,-2)
145  + TVEDGE(-2, 0, 0,-2)
146  + TVEDGE(-1, 0, 0,-1)
147  + TVEDGE( 1, 0, 2,-1)
148  + TVEDGE(-2, 1, -1, 0)
149  + TVEDGE(-1, 1, 1,-1)
150  + TVEDGE( 0, 1, 1, 0)
151  + TVEDGE(-1, 2, 0, 1)
152  + TVEDGE( 0, 2, 2, 0)
153  + TVEDGE( 1, 2, 2, 1);
154  TV[6] = TVEDGE( 0,-1, -1,-2)
155  + TVEDGE( 2,-1, 1,-2)
156  + TVEDGE(-1, 0, -2,-1)
157  + TVEDGE( 1, 0, 0,-1)
158  + TVEDGE( 2, 0, 0,-2)
159  + TVEDGE( 0, 1, -1, 0)
160  + TVEDGE( 1, 1, -1,-1)
161  + TVEDGE( 2, 1, 1, 0)
162  + TVEDGE(-1, 2, -2, 1)
163  + TVEDGE( 0, 2, -2, 0)
164  + TVEDGE( 1, 2, 0, 1);
165 
166  TV[1] = TV[0] + WEIGHT_REDBLUE_MU*TV[2];
167  TV[3] = TV[4] + WEIGHT_REDBLUE_MU*TV[2];
168  TV[5] = TV[4] + WEIGHT_REDBLUE_MU*TV[6];
169  TV[7] = TV[0] + WEIGHT_REDBLUE_MU*TV[6];
170 
171  TV[2] *= WEIGHT_REDBLUE_DIAGONAL;
172  TV[6] *= WEIGHT_REDBLUE_DIAGONAL;
173  }
174 
175  TV[0] *= WEIGHT_AXIAL;
176  TV[1] *= WEIGHT_PI_8;
177  TV[3] *= WEIGHT_PI_8;
178  TV[4] *= WEIGHT_AXIAL;
179  TV[5] *= WEIGHT_PI_8;
180  TV[7] *= WEIGHT_PI_8;
181 
182  /* Select the best-fitting stencil */
183  MinTV = TV[S = 0];
184 
185  for(k = 1; k < NUMSTENCILS; k++)
186  if(TV[k] < MinTV)
187  {
188  MinTV = TV[k];
189  S = k;
190  }
191 
192  /* Store the selected stencil for the current pixel */
193  *Stencil = S;
194  }
195  }
196 }