(edit by king)由于性能测试需要,需要准备大量不相同的图片(图片md5值不同),为了方便的创建这些图片,写了个小程序来完成这个工作。
这个程序最初的算法是生成一张指定长和宽的图片,然后一个个像素置成特定的颜色。因为最终要生成jpg文件,这样的做法,会导致生成的图片普遍比较小,最终确定为从参数中获得一个种子文件,然后对每个像素进行反色处理。
主要的计算方法如下:
jpgInFile = fopen(param_p->fileName, "rb");
if(jpgInFile == NULL)
{
perror("open seed file");
return NULL;
}
im = gdImageCreateFromJpeg(jpgInFile);
fclose(jpgInFile);
width = gdImageSX(im);
height = gdImageSY(im);
pch = strrchr(param_p->fileName, '.');
strncpy(fileBase, param_p->fileName, pch - param_p->fileName);
for(n = param_p->start; n < param_p->end; ++n)
{
color = gdImageGetPixel(im, n % width, (n / width) % height);
revertColor = gdImageColorAllocate(im, 0xFF - gdImageRed(im, color),
0xFF - gdImageGreen(im, color), 0xFF - gdImageBlue(im, color));
gdImageSetPixel(im, n % width, (n / width) % height, revertColor);
sprintf(fileName, "%s%d.jpg", fileBase, n);
jpgOutFile = fopen(fileName, "wb");
gdImageJpeg(im, jpgOutFile, 60);
fclose(jpgOutFile);
}
反色的方法很简单,分别用0xFF减去像素点的RGB分色就可以了。这里使用了gd库来操作图片,具体gd库的API,可以看http://www.libgd.org/Reference 。
还有个问题,就是“大量”。刚开始还在纠结于用多线程还是多进程,看了下发现多进程非常不便于任务分派,最后还是决定是用多线程来加快图片的创建。
先定义一个结构来保存传递给线程函数的参数:
typedef struct
{
char *fileName;
int start;
int end;
}param;
分别代表种子图片文件名、开始像素点和结束像素点。
for(n = 0; n < threadCount; ++n)
{
paramArray[n].fileName = fileName;
paramArray[n].start = createPerThread * n;
paramArray[n].end = createPerThread * (n + 1);
ret = pthread_create(&threads[n], &attr, &do_create_image, ¶mArray[n]);
if(ret != 0)
{
perror("thread create");
exit(EXIT_FAILURE);
}
}
for(n = 0; n < threadCount; ++n)
{
ret = pthread_join(threads[n], NULL);
if(ret != 0)
{
perror("thread join");
exit(EXIT_FAILURE);
}
}
是用pthread_create和pthread_join进行线程的创建和等待结束,是用多线程的方式大大增加了图片创建的速度,采用O2优化程度编译的代码,可以在13分钟创建1万张图片。
最后,还是用了getopt函数来获得从命令行传入的参数。while((ret = getopt(argc, argv, "s:t:f:")) != -1)
while((ret = getopt(argc, argv, "s:t:f:")) != -1)
{
switch(ret)
{
case 's':
totalCount = atoi(optarg);
break;
case 't':
threadCount = atoi(optarg);
break;
case 'f':
strncpy(fileName, optarg, 256);
break;
default:
fprintf(stderr, "usage: %s [-s SUM] [-t THREAD_COUNT] [-f SEED_FILE]\n", argv[0]);
exit(EXIT_FAILURE);
}
}
因为这个小程序使用了gd库、pthread库,因此在编译的时候,需要连接着两个库。
CC = gcc FLAGS = -O2 LIBS = -lpthread -lgd EXE = jpg all: $(EXE) jpg: jpg_creator.c $(CC) $(FLAGS) -o $@ $? $(LIBS) clean: rm $(EXE)
752

被折叠的 条评论
为什么被折叠?



