2014-12-07 7 views
0

Я работаю над программой C++/Allegro, которая имитирует предоставление кому-то макияжа. Есть возможность изменить цвет кожи, и у меня есть этот код прямо сейчас.Как заполнить область определенным цветом

аннулируются doMakeup :: Фонд (MakeupMap * основа, ALLEGRO_BITMAP * вд) {

al_lock_bitmap(bg, al_get_bitmap_format(bg), ALLEGRO_LOCK_READWRITE); 
ALLEGRO_BITMAP* bmp = al_get_target_bitmap(); 
al_set_target_bitmap(bg); 

int w = al_get_bitmap_width(bg); 
int h = al_get_bitmap_height(bg); 

//ALLEGRO_COLOR c = al_get_pixel(bg, state.x, state.y); 
ALLEGRO_COLOR c2 = al_map_rgb(249, 230, 206); 

for (int i = 0; i < w; i++) 
{ 
    for (int j = 0; j < h; j++) 
    { 
     ALLEGRO_COLOR c = al_get_pixel(bg, i, j); 
     if (SameColour(c, c2)) 
      al_put_pixel(i, j, foundation->colour); 
    } 

} 

al_set_target_bitmap(bmp); 
//move bitmap back to video memory 
al_unlock_bitmap(bg); 

}

код несколько делает то, что я хочу, в том, что в изменении цвета, но всякий раз, когда это приближается к краю, он не меняет цвет. Пожалуйста, помогите мне!

This is what it looks like when I call the function

+0

Любой конкретный язык/окружающей среды? –

+0

Yea C++ и Allegro – Claudia

ответ

1

Как отмечает Кеногу Лабз в другом ответе, ваша проблема в том, что совпадение цвета совпадает с тоном, но цвета по краям изображения сглажены или деградированы кодеком исходного изображения (общая проблема с системами сжатия изображений с потерями таких как JPEG).

Вместо того, чтобы выполнять точное совпадение цвета, вам необходимо соответствовать цвету диапазону.

Лучший способ добиться этого - это, как правило, установить допустимость того, насколько близко Цвета должны быть друг к другу. Вы не указали свой код для SameColor(), но вы, вероятно, можете получить результаты, которые вы хотите, изменяя SameColor() в SimilarColor() с чем-то вроде реализации так:

bool SimilarColor(color c1, color c2, int tolerance) 
{ 
    int rDiff = std::abs(c1.r - c2.r); 
    int gDiff = std::abs(c1.g - c2.g); 
    int bDiff = std::abs(c1.b - c2.b); 

    return (rDiff < tolerance && gDiff < tolerance && bDiff < tolerance); 
} 

NB. Это псевдокод. Теперь я добавил совместимую реализацию ALLEGRO в свой ответ внизу.

Общий принцип заключается в том, что вы вычисляете разницу в красном, зеленую разницу и синюю разницу и убедитесь, что она ниже вашего значения допуска. Если это так, вы возвращаете true и выполняете замену цвета, если нет, то замена не выполняется.

Дополнительно для специалистов:

Чтобы получить еще лучшие результаты, вы можете рассмотреть непосредственно не заменяя цвета совпадают, но вместо изменения цветового тона пикселей совпавших (сохраняя их насыщенность и значение), так что ваше изображение с измененным цветом не упрощается. Для этого потребуются значения H, S, V для цвета 1 и цвета 2, которые могут поддерживаться непосредственно в ALLEGRO или могут потребовать настраиваемый код.

Некоторые дополнительные комментарии

Обратите внимание, что ваш текущий код посещения каждый пиксель в изображении. Возможно, что некоторые непреднамеренные произвольные пиксели в изображении могут входить в ваш перенос и непреднамеренно перекрашиваться.

Чтобы избежать этого, вы можете заменить совпадение цветов с помощью метода повторного окрашивания FloodFill (т. Е. Paintbucket) (хотя это сложнее и ограничивает перекрашивание в смежные области), или вы можете работать с изображением в памяти где каждая перекрашиваемая секция предварительно подготовлена, чтобы иметь уникальный цвет с псевдонимом. Например, у вас может быть исходное изображение с зеленой гранью rgb (0,255,0) в буфере памяти, но отобразите цвет лица на выбранный оттенок.И когда пользователь выбирает изменить цвет, повторно переориентируйте исходное зеленое изображение снова. Надеюсь, это имеет смысл. Вот пример внеэкранного исходного изображения я описываю:

sample color key image

Примечание стороны: всегда предпочитают .png файлов .jpg, если вы хотите, чтобы избежать ухудшения качества изображения из-за формат файл изображения.

Для получения наилучших результатов я полностью рекомендую использовать цветное ключевое изображение, описанное выше. Он имеет дополнительное преимущество в том, что вы можете манипулировать исходным изображением и сохранять в виде формата без потерь, например .png, чтобы вы могли выполнять точное сопоставление цветов в соответствии с вашим исходным кодом и не должны пытаться соответствовать цветовой гамме. У вас также никогда не будет ситуации, когда цвета фона слишком близки к вашему допуску и не будут случайно заменены цветом.

Тем не менее, я также внимательно рассмотрел документацию ALLEGRO для ALLEGRO_COLOR и следующий метод должен выполнить описанный выше метод SimilarColor с использованием этой библиотеки. В Allegro в этом случае вы не можете получить доступ отдельные компоненты ALLEGRO_COLOR непосредственно, так что вы должны выполнить al_unmap_rgb первый:

bool SimilarColor(ALLEGRO_COLOR c1, ALLEGRO_COLOR c2, int tolerance) 
{ 
    // unpack the colors into their r,g,b components: 
    unsigned char c1R, c1G, c1B, c2R, c2G, c2B; 
    al_unmap_rgb(c1, &c1R, &c1G, &c1B); 
    al_unmap_rgb(c2, &c2R, &c2G, &c2B); 

    // calculate the absolute red, green and blue differences: 
    int rDiff = std::abs((int)c1R - (int)c2R); 
    int gDiff = std::abs((int)c1G - (int)c2G); 
    int bDiff = std::abs((int)c1B - (int)c2B); 

    // return true only if ALL color channel diffs are below tolerance. 
    // NB. tolerance needs to be between 1 and 254, and a value of 35 
    // is probably a good start point for testing purposes 

    return (rDiff < tolerance && gDiff < tolerance && bDiff < tolerance); 
} 
+0

Приветствую вас, я добавил немного кода, показывающего возможную совместимость с Allegro в подпрограмме SimilarColor и попытался объяснить несколько вещей более четко. Как уже упоминалось, если вы можете очистить исходное изображение и использовать кодек без потерь изображения, то работа с исходным кодом, возможно, является самым простым подходом. –

0

Пиксели на краю базового изображения не тот же цвет из-за anti-aliasing.

+0

Каков хороший способ борьбы с сглаживанием? – Claudia

Смежные вопросы