Написал программу, фильтр для изображений (получаются рисунки простым карандашом). Алгоритм такой: если каждый пиксель достаточно сильно отличается от следующего (это отличие указывается с помощью value), то ставится серый пиксель, яркость которого определяется разницей цвета и коэффициентом яркости (brightness_quotient). Но некоторые картинки получаются слишком плохо. На самом деле алгоритма три, но они очень похожи, и результаты не всегда заметно отличаются. Хотелось бы у предложения по усовершенствованию алгоритма.
// pencil.c
#include <stdio.h>
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h>
#include "bmp.h"
#define _GNU_SOURCE
#define DEFAULT 0
#define ADDITION 1
#define MULTIPLICATION 2
BMPHEADER bmp;
char *bits;
struct option long_options[] = {
{"algorithm", 1, 0, 0},
{"value", 1, 0, 0},
{"help", 0, 0, 0},
{"version", 0, 0, 0},
{"direction", 1, 0, 0},
{"brightness", 1, 0, 0},
{0, 0, 0, 0}
};
char algorithm=0;
int value=0;
char *ofile;
int direction=2;
float brightness_quotient=1.0;
int myabs(int val)
{
if (val < 0) return -val; else return val;
}
void help(char *argv0)
{
printf("%s options input_file\n", argv0);
printf("Available options:\n");
printf("\t--algorithm,-a [name] - use optional algorithm from following list:\n");
printf("\t\t0 = default\n");
printf("\t\t1 = addition\n");
printf("\t\t2 = multiplication\n");
printf("\t--value,-v [val]\n");
printf("\t--direction,-d [dir] - possible values:\n");
printf("\t\t0 = horizontal\n");
printf("\t\t1 = vertical\n");
printf("\t\t[other value] = horizontal and vertical\n");
printf("\t--brightness,-b - brightness quotient (default value is 1.0)\n");
printf("\t--help,-h - show help\n");
printf("\t--version - show version\n");
printf("\t-o [file]\n");
exit(0);
}
void version()
{
printf("Pencil version 0.1\n");
exit(0);
}
void check_options(int argc, char **argv)
{
int n;
while(1)
{
int c = getopt_long(argc, argv, "a:v:ho:d:b:", long_options, &n);
if (c == -1) break;
switch(c)
{
case 0:
switch(n)
{
case 0:
algorithm = atoi(optarg);
break;
case 1:
value = atoi(optarg);
break;
case 2:
help(argv[0]);
break;
case 3:
version();
break;
case 4:
direction = atoi(optarg);
break;
case 5:
brightness_quotient = atof(optarg);
break;
}
case 'v':
value = atoi(optarg);
break;
case 'h':
help(argv[0]);
break;
case 'o':
ofile = optarg;
break;
case 'a':
algorithm = atoi(optarg);
break;
case 'd':
direction = atoi(optarg);
break;
case 'b':
brightness_quotient = atof(optarg);
break;
}
}
}
int main(int argc, char **argv)
{
check_options(argc, argv);
if (value == 0 || ofile == NULL || optind >= argc)
{
printf("wrong options\n");
exit(1);
}
if (load_bitmap(argv[argc-1], &bmp) == INVALID_BITMAP)
{
printf("INVALID_BITMAP\n");
exit(2);
}
bits = (char *)malloc(bmp.info.biWidth*bmp.info.biHeight*3);
int i, j;
if (direction != 1)
for(i = 0; i < bmp.info.biHeight; i++)
{
for(j = 0; j < bmp.info.biWidth-1; j++)
{
unsigned char rr, gg, bb;
bb = myabs(bmp.bits[(j*bmp.info.biHeight+i)*3] - bmp.bits[(j*bmp.info.biHeight+i+1)*3]);
gg = myabs(bmp.bits[(j*bmp.info.biHeight+i)*3+1] - bmp.bits[(j*bmp.info.biHeight+i+1)*3 + 1]);
rr = myabs(bmp.bits[(j*bmp.info.biHeight+i)*3+2] - bmp.bits[(j*bmp.info.biHeight+i+1)*3 + 2]);
switch(algorithm)
{
case DEFAULT:
if (rr > value || gg > value || bb > value)
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = (int)(brightness_quotient*((float)rr+(float)gg+(float)bb)*9.0);
else
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = 255;
break;
case ADDITION:
if ((rr + gg + bb) > value)
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = (int)(brightness_quotient*((float)rr+(float)gg+(float)bb)*9.0);
else
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = 255;
break;
case MULTIPLICATION:
if (rr*gg*bb > value)
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = (int)(brightness_quotient*((float)rr+(float)gg+(float)bb)*9.0);
else
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = 255;
break;
}
}
}
if (direction != 0)
for(j = 0; j < bmp.info.biWidth; j++)
{
for(i = 0; i < bmp.info.biHeight-1; i++)
{
unsigned char rr, gg, bb;
bb = myabs(bmp.bits[(j*bmp.info.biHeight+i)*3] - bmp.bits[(j*bmp.info.biHeight+i+bmp.info.biWidth)*3]);
gg = myabs(bmp.bits[(j*bmp.info.biHeight+i)*3+1] - bmp.bits[(j*bmp.info.biHeight+i+bmp.info.biWidth)*3 + 1]);
rr = myabs(bmp.bits[(j*bmp.info.biHeight+i)*3+2] - bmp.bits[(j*bmp.info.biHeight+i+bmp.info.biWidth)*3 + 2]);
switch(algorithm)
{
case DEFAULT:
if (rr > value || gg > value || bb > value)
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = (int)(brightness_quotient*((float)rr+(float)gg+(float)bb)*9.0);
break;
case ADDITION:
if ((rr + gg + bb) > value)
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = (int)(brightness_quotient*((float)rr+(float)gg+(float)bb)*9.0);
break;
case MULTIPLICATION:
if (rr*gg*bb > value)
bits[(j*bmp.info.biHeight+i)*3] = bits[(j*bmp.info.biHeight+i)*3+1] = bits[(j*bmp.info.biHeight+i)*3+2] = (int)(brightness_quotient*((float)rr+(float)gg+(float)bb)*9.0);
break;
}
}
}
bmp_writestd(ofile, bits, bmp.info.biWidth, bmp.info.biHeight);
return 0;
}
Похожие темы
- Форум [C] Параметры, Case (2012)
- Форум getopt_long (2005)
- Форум Ошибка сегментирования (2017)
- Форум Xlib. С ошибками не валится, но не работает. (2012)
- Форум [emacs][cedet] Автодополнение (2010)
- Форум что не так в использовании структуры (2008)
- Форум Что происходит в этом коде (2014)
- Форум Помогите пожалуйста с простейшим калькулятором на языке си (2017)
- Форум Перехват клавиш XGrabKeyboard. (2016)
- Форум Загрузка программы в gdb с параметрами и брейкпоинтами (2019)