#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef unsigned char byte;
byte q, h, w, th;
byte noised_image[200][200];
byte median_image[200][200];
byte grad_image[200][200];
byte sub_image[200][200];
short levels[256];
#define abs(x) ((x)>0?(x):-(x))
#define in(x, a, b) ((x)>=(a) && (x)<(b))
/*
static const char dirs[][2][2] =
{
{{-1, -1}, {0, 1}}, {{0, -1}, {0, 1}}, {{1, -1}, {0, 1}}, {{-1, -2}, {0, 1}}, {{0, -2}, {0, 1}}, {{1, -2}, {0, 1}},
{{0, -1}, {1, 1}}, {{-1, 0}, {1, 1}}, {{-1, -1}, {1, 1}}, {{-1, -2}, {1, 1}}, {{-2, -1}, {1, 1}}, {{-2, -2}, {1, 1}},
{{0, -1}, {-1, 1}}, {{1, 0}, {-1, 1}}, {{1, -1}, {-1, 1}}, {{1, -2}, {-1, 1}}, {{2, -1}, {-1, 1}}, {{2, -2}, {-1, 1}},
{{-1, 2}, {0, -1}}, {{0, 2}, {0, -1}}, {{1, 2}, {0, -1}},
{{-1, 0}, {1, -1}}, {{-1, 2}, {1, -1}}, {{-2, 1}, {1, -1}}, {{-2, 2}, {1, -1}},
{{1, 0}, {-1, -1}}, {{1, 2}, {-1, -1}}, {{2, 1}, {-1, -1}}, {{2, 2}, {-1, -1}},
-
{{1, 0}, {-1, 0}}, {{2, -1}, {-1, 0}}, {{2, 0}, {-1, 0}}, {{2, 1}, {-1, 0}},
{{-2, -1}, {1, 0}}, {{-2, 0}, {1, 0}}, {{-2, 1}, {1, 0}}
};
*/
static const char dirs[][2][2] =
{
{{-1, -1}, {0, 1}}, {{0, -1}, {0, 1}}, {{1, -1},
{0, 1}},
{{0, -1}, {1, 1}}, {{-1, 0}, {1, 1}}, {{-1, -1}, {1, 1}},
{{0, -1}, {-1, 1}}, {{1, 0}, {-1, 1}}, {{1, -1}, {-1, 1}},
{{-1, 0}, {1, -1}},
{{1, 0}, {-1, -1}},
{{1, 0}, {-1, 0}},
};
#define w_size 4
static const char w_coords[w_size][2] =
{ {-1, 0}, {1, 0}, {0, 1}, {0, -1} };
/*
#define w_size 8
static const char w_coords[w_size][2] =
{ {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1} };
*/
void init()
{
memset(levels, 0, sizeof(levels));
}
void readImage();
void writeImage();
#ifdef ONLINE_JUDGE
void readImage()
{
int i, j;
char str[800], *p;
gets(str);
sscanf(str, "%d%d%d", &q, &h, &w);
for(i = 0; i < h; i++)
{
gets(str);
p = str;
for(j = 0; j < w; j++)
{
noised_image[i][j] = atoi(p);
p++;
while( *p && *(p++) != ' ' );
}
}
}
void writeImage()
{
int i, j;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
printf("%03d ", noised_image
[i
][j
]);
}
}
}
#endif
int btcmp( const void *arg1, const void *arg2 )
{
return *(byte*)arg1<*(byte*)arg2?-1:*(byte*)arg1==*(byte*)arg2?0:1;
}
void simpleInterpolate()
{
int i, j, k;
byte window[w_size+1];
-
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
int l, m;
for(k = 0; k < w_size; k++)
{
l = i + w_coords[k][0];
m = j + w_coords[k][1];
if(l < 0 || l >= h || m < 0 || m >= w)
{
window[k] = noised_image[i][j];
}else
window[k] = noised_image[l][m];
}
window[k] = noised_image[i][j];
qsort(window, w_size+1, sizeof(byte), btcmp);
median_image[i][j] = window[w_size/2];
}
}
}
void findOrthoGrad()
{
int i, j, k;
-
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
byte diff = 255, val = noised_image[i][j];
int x1, y1, x2, y2;
for(k = 0; k < sizeof(dirs)/sizeof(dirs[0]); k++)
{
x1 = j + dirs[k][0][0];
y1 = i + dirs[k][0][1];
x2 = j + dirs[k][1][0];
y2 = i + dirs[k][1][1];
if(!in(x1, 0, w) || !in(x2, 0, w) || !in(y1, 0, h) || !in(y2, 0, h))
continue;
if(abs(noised_image[y1][x1] - noised_image[y2][x2]) < diff)
{
diff = abs(noised_image[y1][x1] - noised_image[y2][x2]);
val = (noised_image[y1][x1] + noised_image[y2][x2])/2;
}
-
}
grad_image[i][j] = val;
}
}
}
void subImage()
{
int i, j, k;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
sub_image[i][j] = abs(noised_image[i][j] - grad_image[i][j]);
if(sub_image[i][j] != 0)
levels[sub_image[i][j]]++;
}
}
}
void selectThreshhold()
{
byte i;
int npoints = (h*w*q
)/70, sum = 0, d = 255*h*w;
for(i=255; i>0; i--)
{
if(abs(levels[i]+sum-npoints) < d)
{
th = i;
sum += levels[i];
d = abs(sum-npoints);
}
}
}
void removeNoise()
{
int i, j;
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
if(sub_image[i][j] >= th)
noised_image[i][j] = median_image[i][j];
}
}
}
int main()
{
int t;
char str[5];
gets(str);
t = atoi(str);
while(t--)
{
init();
readImage();
simpleInterpolate();
findOrthoGrad();
subImage();
selectThreshhold();
removeNoise();
writeImage();
}
return 0;
}