Image Interpolation with Contour Stencils
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
fitsten.c
Go to the documentation of this file.
1 
16 #include <stdlib.h>
17 #include "fitsten.h"
18 
19 
20 #define PIXEL_STRIDE 3
21 
22 /* Constants related to stencil edge weights */
23 /* mu = 3/4 * sqrt(2) */
24 #define W_MU (1.060660171779821)
25 /* Divisor for axial stencils = 6 */
26 #define W_PI_2 (6.0)
27 /* Divisor for diagonal stencils = 4 sqrt(2) */
28 #define W_PI_4 (5.656854249492381)
29 /* Divisor for pi/8 stencils = 6(1 + sqrt(2))sqrt(2 - sqrt(2)) + 12 */
30 #define W_PI_8 (23.086554390135440)
31 
32 
33 
35 static int Dist(int32_t *A, int32_t *B)
36 {
37  int iDistR = A[0] - B[0];
38  int iDistG = A[1] - B[1];
39  int iDistB = A[2] - B[2];
40  register int iDistY = 2*iDistR + 4*iDistG + iDistB;
41  register int iDistU = -iDistR - 2*iDistG + 3*iDistB;
42  register int iDistV = 4*iDistR - 3*iDistG - iDistB;
43  return (abs(iDistY) + abs(iDistU) + abs(iDistV)) >> 4;
44 }
45 
46 
70 int FitStencils(int *Stencil, int32_t *Image, int Width, int Height, int StencilMul)
71 {
72  const int Stride = PIXEL_STRIDE*Width;
73  const int TVStride = 8*Width;
74  int *StencilTv; /* Contour stencil total variations estimates TV[S] */
75  int Dh[3][2]; /* Horizontal differences computed over the current 3x3 window */
76  int Dv[2][3]; /* Vertical differences */
77  int Da[2][2]; /* Diagonal differences |Image(m,n) - Image(m+1,n+1)| */
78  int Db[2][2]; /* Diagonal differences |Image(m+1,n) - Image(m,n+1)| */
79  int *TvPtr, TvMin, Temp;
80  int x, y, k, S;
81 
82 
83  if(!(StencilTv = (int *)malloc(sizeof(int)*8*Width*Height)))
84  return 0;
85 
86  TvPtr = StencilTv;
87 
88  for(y = 0; y < Height; y++)
89  {
90  Dh[0][1] = 0;
91  Dh[1][1] = 0;
92  Dh[2][1] = 0;
93 
94  Dv[0][1] = 0;
95  Dv[1][1] = 0;
96  Dv[0][2] = (y > 0) ? Dist(Image - Stride, Image) : 0;
97  Dv[1][2] = (y < Height-1) ? Dist(Image + Stride, Image) : 0;
98 
99  Da[0][1] = 0;
100  Da[1][1] = 0;
101  Db[0][1] = 0;
102  Db[1][1] = 0;
103 
104  for(x = 0; x < Width; x++, Image += PIXEL_STRIDE, TvPtr += 8)
105  {
106  Dh[0][0] = Dh[0][1];
107  Dh[1][0] = Dh[1][1];
108  Dh[2][0] = Dh[2][1];
109 
110  Dv[0][0] = Dv[0][1];
111  Dv[1][0] = Dv[1][1];
112  Dv[0][1] = Dv[0][2];
113  Dv[1][1] = Dv[1][2];
114 
115  Da[0][0] = Da[0][1];
116  Da[1][0] = Da[1][1];
117 
118  Db[0][0] = Db[0][1];
119  Db[1][0] = Db[1][1];
120 
121  if(x < Width-1)
122  {
123  Dh[1][1] = Dist(Image, Image+PIXEL_STRIDE);
124 
125  if(y > 0)
126  {
127  Dh[0][1] = Dist(Image-Stride, Image-Stride+PIXEL_STRIDE);
128  Dv[0][2] = Dist(Image-Stride+PIXEL_STRIDE, Image+PIXEL_STRIDE);
129  Da[0][1] = Dist(Image-Stride, Image+PIXEL_STRIDE);
130  Db[0][1] = Dist(Image-Stride+PIXEL_STRIDE, Image);
131  }
132 
133  if(y < Height-1)
134  {
135  Dh[2][1] = Dist(Image+Stride, Image+Stride+PIXEL_STRIDE);
136  Dv[1][2] = Dist(Image+PIXEL_STRIDE, Image+Stride+PIXEL_STRIDE);
137  Da[1][1] = Dist(Image, Image+Stride+PIXEL_STRIDE);
138  Db[1][1] = Dist(Image+PIXEL_STRIDE, Image+Stride);
139  }
140  }
141  else
142  {
143  Dh[0][1] = 0;
144  Dh[1][1] = 0;
145  Dh[2][1] = 0;
146 
147  Dv[0][2] = 0;
148  Dv[1][2] = 0;
149 
150  Da[0][1] = 0;
151  Da[1][1] = 0;
152 
153  Db[0][1] = 0;
154  Db[1][1] = 0;
155  }
156 
157  TvPtr[1] = (Db[1][0] + Db[0][1]) + Db[0][0] + Db[1][1];
158  TvPtr[3] = (Dh[1][0] + Dh[1][1]) + Dh[0][0] + Dh[0][1] + Dh[2][0] + Dh[2][1];
159  TvPtr[5] = (Da[0][0] + Da[1][1]) + Da[1][0] + Da[0][1];
160  TvPtr[7] = (Dv[0][1] + Dv[1][1]) + Dv[0][0] + Dv[1][0] + Dv[0][2] + Dv[1][2];
161 
162  TvPtr[0] = (int)((TvPtr[7] + TvPtr[1]*W_MU) / W_PI_8 + 0.5);
163  TvPtr[2] = (int)((TvPtr[1]*W_MU + TvPtr[3]) / W_PI_8 + 0.5);
164  TvPtr[4] = (int)((TvPtr[3] + TvPtr[5]*W_MU) / W_PI_8 + 0.5);
165  TvPtr[6] = (int)((TvPtr[5]*W_MU + TvPtr[7]) / W_PI_8 + 0.5);
166 
167  TvPtr[1] = (int)(TvPtr[1] / W_PI_4 + 0.5);
168  TvPtr[3] = (int)(TvPtr[3] / W_PI_2 + 0.5);
169  TvPtr[5] = (int)(TvPtr[5] / W_PI_4 + 0.5);
170  TvPtr[7] = (int)(TvPtr[7] / W_PI_2 + 0.5);
171  }
172  }
173 
174  TvPtr = StencilTv;
175 
176  for(y = 0; y < Height; y++)
177  {
178  for(x = 0; x < Width; x++, TvPtr += 8, Stencil++)
179  {
180  if(1 <= x && x < Width - 1 && 1 <= y && y < Height - 1)
181  {
182  /* Filter the TV estimates by [1,2,1; 2,4,2; 1,2,1] */
183  TvMin = TvPtr[-TVStride - 8] + TvPtr[-TVStride + 8]
184  + TvPtr[TVStride - 8] + TvPtr[TVStride + 8]
185  + ((TvPtr[-TVStride] + TvPtr[-8]
186  + TvPtr[8] + TvPtr[TVStride]) << 1)
187  + (TvPtr[0] << 2);
188  S = 0;
189 
190  for(k = 1; k < 8; k++)
191  {
192  Temp = TvPtr[k - TVStride - 8] + TvPtr[k - TVStride + 8]
193  + TvPtr[k + TVStride - 8] + TvPtr[k + TVStride + 8]
194  + ((TvPtr[k - TVStride] + TvPtr[k - 8]
195  + TvPtr[k + 8] + TvPtr[k + TVStride]) << 1)
196  + (TvPtr[k] << 2);
197 
198  if(Temp < TvMin)
199  {
200  TvMin = Temp;
201  S = k;
202  }
203 
204  }
205  }
206  else
207  {
208  TvMin = TvPtr[0];
209  S = 0;
210 
211  for(k = 1; k < 8; k++)
212  if(TvPtr[k] < TvMin)
213  TvMin = TvPtr[S = k];
214  }
215 
216  *Stencil = StencilMul * S;
217  }
218  }
219 
220  free(StencilTv);
221  return 1;
222 }