C,429(定义标志为391 + 38)
i,R,G,B,q;char*c,t[99];main(r,a,b,k,z,p){scanf("%*[^ ]%d%*6s%d%[^N]%*[^R]R\n",&a,&b,t);int j=a*b,d[j],e[j];F(c=d;c<d+j;*c++=getchar());F(;i<j;e[i++]=X<<24|B/q<<16|G/q<<8|R/q,R=G=B=q=0)F(k=0;k<j;)p=d[k++],D<r&&(++q,R+=p&X,G+=p>>8&X,B+=p>>16&X);F(i=!printf("P7\nWIDTH %d\nHEIGHT %d%sNDHDR\n",a,b,t);i<j;d[i++]=e[k])F(;k=rand()%j,D>r/2;);F(c=d;q<j*4;i=(q%4-2?2:3)*c[q]/2,putchar(i>X?X:i),++q);}
输入格式:pam
文件中没有注释或标题中有多余的空格,内容通过STDIN传递。
n
参数是必需的(它们可以是任何东西)。
输出格式:pam
STDOUT中的文件。
编译:
gcc -DX=255 -DF=for "-DD=z=abs(k-i),z/b+z%a" -Wl,--stack,33554432 -funsigned-char icyavatars.c -o icyavatars
-Wl,--stack,33554432
增加堆栈大小;可以更改或删除它,具体取决于所处理图片的大小(程序要求的堆栈大小大于像素数的两倍乘以4)。
-funsigned-char
使用gcc unsigned char
代替signed char
for char
。C标准允许使用这些选项中的任何一个,并且仅在此处需要此选项,因为signed char
默认情况下gcc使用。
要运行(n = 5):
./icyavatars random argument here fourth fifth < image.pam > output.pam
注:如果在Windows上编译,stdio.h
,fcntl.h
和io.h
必须被包括在内,并添加到开始下面的代码main()
,以使程序读取/写入标准输入/输出为二进制,而不是文本,流(这是在Linux上不相关的,但Windows使用\r\n
而不是\n
用于文本流)。
setmode(fileno(stdin), _O_BINARY);
setmode(fileno(stdout), _O_BINARY);
评论版本
int i,R,G,B,q;
char *c,t[99];
main(r,a,b,k,z,p){
// read all of header
// save a large chunk to t, save width to a, save height to b
scanf("%*[^ ]%d%*6s%d%[^N]%*[^R]R\n", &a, &b, t);
// create arrays for holding the pixels
int j = a * b, d[j], e[j];
// each pixel is 4 bytes, so we just read byte by byte to the int arrays
for(c = d; c < d + j; ++c)
*c=getchar();
// calculating average rgb
for(i = 0; i < j; ++i){
// check every pixel; add r/g/b values to R/G/B if manhattan distance < r-1
for(k = 0; k < j; ++k){
// pixel being checked
p = d[k];
// manhattan distance
z = abs(k - i)/b + abs(k - i)%a;
if(z < r){
// extract components and add
++q;
R += p & 255;
G += p >> 8 & 255;
B += p >> 16 & 255;
}
}
// set pixel in e (not d) to average RGB and 255 alpha
e[i]= 255<<24 | B/q<<16 | G/q<<8 | R/q;
// clear temporary variables
R = G = B = q = 0;
}
// print header
printf("P7\nWIDTH %d\nHEIGHT %d%sNDHDR\n",a,b,t);
// choose random pixels
for(i = 0; i < j; ++i){
// loop until randomly generated integer represents a pixel that is close enough
do{
k = rand() % j;
// manhattan distance
z = abs(k - i)/b + abs(k - i)%a;
}while(z > r/2);
// set d to the new pixel value
d[i] = e[k];
}
// apply blue scaling and output
for(c = d, q = 0; q < j * 4; ++q){
// 3/2 if blue component, 1 otherwise
i = (q % 4 - 2 ? 2 : 3)*c[q]/2;
// cap components at 255
putchar(i > 255 ? 255 : i);
}
}
马丁(n = 10):
马丁(n = 20):
马丁(n = 100):