Image Interpolation with Contour Stencils
|
00001 00016 #include <stdlib.h> 00017 #include "fitsten.h" 00018 00019 00020 #define PIXEL_STRIDE 3 00021 00022 /* Constants related to stencil edge weights */ 00023 /* mu = 3/4 * sqrt(2) */ 00024 #define W_MU (1.060660171779821) 00025 /* Divisor for axial stencils = 6 */ 00026 #define W_PI_2 (6.0) 00027 /* Divisor for diagonal stencils = 4 sqrt(2) */ 00028 #define W_PI_4 (5.656854249492381) 00029 /* Divisor for pi/8 stencils = 6(1 + sqrt(2))sqrt(2 - sqrt(2)) + 12 */ 00030 #define W_PI_8 (23.086554390135440) 00031 00032 00033 00035 static int Dist(int32_t *A, int32_t *B) 00036 { 00037 int iDistR = A[0] - B[0]; 00038 int iDistG = A[1] - B[1]; 00039 int iDistB = A[2] - B[2]; 00040 register int iDistY = 2*iDistR + 4*iDistG + iDistB; 00041 register int iDistU = -iDistR - 2*iDistG + 3*iDistB; 00042 register int iDistV = 4*iDistR - 3*iDistG - iDistB; 00043 return (abs(iDistY) + abs(iDistU) + abs(iDistV)) >> 4; 00044 } 00045 00046 00070 int FitStencils(int *Stencil, int32_t *Image, int Width, int Height, int StencilMul) 00071 { 00072 const int Stride = PIXEL_STRIDE*Width; 00073 const int TVStride = 8*Width; 00074 int *StencilTv; /* Contour stencil total variations estimates TV[S] */ 00075 int Dh[3][2]; /* Horizontal differences computed over the current 3x3 window */ 00076 int Dv[2][3]; /* Vertical differences */ 00077 int Da[2][2]; /* Diagonal differences |Image(m,n) - Image(m+1,n+1)| */ 00078 int Db[2][2]; /* Diagonal differences |Image(m+1,n) - Image(m,n+1)| */ 00079 int *TvPtr, TvMin, Temp; 00080 int x, y, k, S; 00081 00082 00083 if(!(StencilTv = (int *)malloc(sizeof(int)*8*Width*Height))) 00084 return 0; 00085 00086 TvPtr = StencilTv; 00087 00088 for(y = 0; y < Height; y++) 00089 { 00090 Dh[0][1] = 0; 00091 Dh[1][1] = 0; 00092 Dh[2][1] = 0; 00093 00094 Dv[0][1] = 0; 00095 Dv[1][1] = 0; 00096 Dv[0][2] = (y > 0) ? Dist(Image - Stride, Image) : 0; 00097 Dv[1][2] = (y < Height-1) ? Dist(Image + Stride, Image) : 0; 00098 00099 Da[0][1] = 0; 00100 Da[1][1] = 0; 00101 Db[0][1] = 0; 00102 Db[1][1] = 0; 00103 00104 for(x = 0; x < Width; x++, Image += PIXEL_STRIDE, TvPtr += 8) 00105 { 00106 Dh[0][0] = Dh[0][1]; 00107 Dh[1][0] = Dh[1][1]; 00108 Dh[2][0] = Dh[2][1]; 00109 00110 Dv[0][0] = Dv[0][1]; 00111 Dv[1][0] = Dv[1][1]; 00112 Dv[0][1] = Dv[0][2]; 00113 Dv[1][1] = Dv[1][2]; 00114 00115 Da[0][0] = Da[0][1]; 00116 Da[1][0] = Da[1][1]; 00117 00118 Db[0][0] = Db[0][1]; 00119 Db[1][0] = Db[1][1]; 00120 00121 if(x < Width-1) 00122 { 00123 Dh[1][1] = Dist(Image, Image+PIXEL_STRIDE); 00124 00125 if(y > 0) 00126 { 00127 Dh[0][1] = Dist(Image-Stride, Image-Stride+PIXEL_STRIDE); 00128 Dv[0][2] = Dist(Image-Stride+PIXEL_STRIDE, Image+PIXEL_STRIDE); 00129 Da[0][1] = Dist(Image-Stride, Image+PIXEL_STRIDE); 00130 Db[0][1] = Dist(Image-Stride+PIXEL_STRIDE, Image); 00131 } 00132 00133 if(y < Height-1) 00134 { 00135 Dh[2][1] = Dist(Image+Stride, Image+Stride+PIXEL_STRIDE); 00136 Dv[1][2] = Dist(Image+PIXEL_STRIDE, Image+Stride+PIXEL_STRIDE); 00137 Da[1][1] = Dist(Image, Image+Stride+PIXEL_STRIDE); 00138 Db[1][1] = Dist(Image+PIXEL_STRIDE, Image+Stride); 00139 } 00140 } 00141 else 00142 { 00143 Dh[0][1] = 0; 00144 Dh[1][1] = 0; 00145 Dh[2][1] = 0; 00146 00147 Dv[0][2] = 0; 00148 Dv[1][2] = 0; 00149 00150 Da[0][1] = 0; 00151 Da[1][1] = 0; 00152 00153 Db[0][1] = 0; 00154 Db[1][1] = 0; 00155 } 00156 00157 TvPtr[1] = (Db[1][0] + Db[0][1]) + Db[0][0] + Db[1][1]; 00158 TvPtr[3] = (Dh[1][0] + Dh[1][1]) + Dh[0][0] + Dh[0][1] + Dh[2][0] + Dh[2][1]; 00159 TvPtr[5] = (Da[0][0] + Da[1][1]) + Da[1][0] + Da[0][1]; 00160 TvPtr[7] = (Dv[0][1] + Dv[1][1]) + Dv[0][0] + Dv[1][0] + Dv[0][2] + Dv[1][2]; 00161 00162 TvPtr[0] = (int)((TvPtr[7] + TvPtr[1]*W_MU) / W_PI_8 + 0.5); 00163 TvPtr[2] = (int)((TvPtr[1]*W_MU + TvPtr[3]) / W_PI_8 + 0.5); 00164 TvPtr[4] = (int)((TvPtr[3] + TvPtr[5]*W_MU) / W_PI_8 + 0.5); 00165 TvPtr[6] = (int)((TvPtr[5]*W_MU + TvPtr[7]) / W_PI_8 + 0.5); 00166 00167 TvPtr[1] = (int)(TvPtr[1] / W_PI_4 + 0.5); 00168 TvPtr[3] = (int)(TvPtr[3] / W_PI_2 + 0.5); 00169 TvPtr[5] = (int)(TvPtr[5] / W_PI_4 + 0.5); 00170 TvPtr[7] = (int)(TvPtr[7] / W_PI_2 + 0.5); 00171 } 00172 } 00173 00174 TvPtr = StencilTv; 00175 00176 for(y = 0; y < Height; y++) 00177 { 00178 for(x = 0; x < Width; x++, TvPtr += 8, Stencil++) 00179 { 00180 if(1 <= x && x < Width - 1 && 1 <= y && y < Height - 1) 00181 { 00182 /* Filter the TV estimates by [1,2,1; 2,4,2; 1,2,1] */ 00183 TvMin = TvPtr[-TVStride - 8] + TvPtr[-TVStride + 8] 00184 + TvPtr[TVStride - 8] + TvPtr[TVStride + 8] 00185 + ((TvPtr[-TVStride] + TvPtr[-8] 00186 + TvPtr[8] + TvPtr[TVStride]) << 1) 00187 + (TvPtr[0] << 2); 00188 S = 0; 00189 00190 for(k = 1; k < 8; k++) 00191 { 00192 Temp = TvPtr[k - TVStride - 8] + TvPtr[k - TVStride + 8] 00193 + TvPtr[k + TVStride - 8] + TvPtr[k + TVStride + 8] 00194 + ((TvPtr[k - TVStride] + TvPtr[k - 8] 00195 + TvPtr[k + 8] + TvPtr[k + TVStride]) << 1) 00196 + (TvPtr[k] << 2); 00197 00198 if(Temp < TvMin) 00199 { 00200 TvMin = Temp; 00201 S = k; 00202 } 00203 00204 } 00205 } 00206 else 00207 { 00208 TvMin = TvPtr[0]; 00209 S = 0; 00210 00211 for(k = 1; k < 8; k++) 00212 if(TvPtr[k] < TvMin) 00213 TvMin = TvPtr[S = k]; 00214 } 00215 00216 *Stencil = StencilMul * S; 00217 } 00218 } 00219 00220 free(StencilTv); 00221 return 1; 00222 }