2014-12-07 3 views
0

저는 누군가에게 화장을하는 것을 시뮬레이트하는 C++/Allegro 프로그램에서 작업 해 왔습니다. 피부색을 변경하는 옵션이 있으며 지금 당장이 코드를 가지고 있습니다.특정 색으로 영역을 채우는 방법

무효 doMakeup :: 재단 (MakeupMap * 기초, ALLEGRO_BITMAP * BG) 변화한다는 점에서 {

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

예 C++ 및 Allegro – Claudia

답변

1

Kenogu Labz이 다른 답변에서 언급했듯이 색상 일치는 정확하지만 이미지 가장자리 주변의 색상이 원본 이미지 코덱에 의해 앤티 엘리 어싱되거나 저하됩니다 (손실 이미지 압축 시스템의 일반적인 문제). JPEG와 같은).

정확한 색상 일치를 수행하는 대신 색상 범위과 일치해야합니다.

이 작업을 수행하는 가장 좋은 방법은 대개 색상이 얼마나 가까이 있어야하는지에 대한 허용 오차를 설정하는 것입니다. 당신은 SameColor()에 대한 코드를 나열하지 않은하지만 당신은 아마 지금과 같은 구현 뭔가 SimilarColor()SameColor()을 변경하여 원하는 결과를 얻을 수 있습니다 :

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를 리턴하고 색상 대체를 수행하고, 대체가 수행되지 않으면 대체가 수행됩니다. 전문가를위한

추가 :

하는 것이 더 좋은 결과를 얻으려면, 당신은 수 있도록 (자신의 채도 값을 유지)를 직접 일치하는 색상을 교체하는 대신 일치하는 픽셀의 색상을 변경하지 않는 것을 고려할 수 있습니다 색상이 바뀐 이미지가 지나치게 단순화되지 않습니다. 이 경우 색상 1과 색상 2에 H, S, V 값이 필요하며 이는 ALLEGRO에서 직접 지원되거나 사용자 정의 코드가 필요할 수 있습니다.

일부 추가 의견

주 당신의 현재 코드 방문 이미지의 모든 픽셀. 이미지의 일부 의도하지 않은 임의의 픽셀이 허용치 내에서 의도하지 않게 색칠 될 수 있습니다.

피하기 위해 FloodFill (즉, 페인트 킷) 유형의 색 재현을 대체 할 수 있습니다 (더 복잡하고 재색 영역을 연속 영역으로 제한 함). 또는 메모리 이미지에서 작업 할 수도 있습니다 여기서 각각의 재현 가능한 섹션은 고유 한 앨리어싱되지 않은 픽셀 색상을 갖도록 미리 준비되어 있습니다. 예를 들어 메모리 내 버퍼에 rgb (0,255,0) 녹색면이있는 소스 이미지를 가질 수 있지만 선택한 색조로 다시 칠해진 얼굴을 표시 할 수 있습니다.그리고 사용자가 색상을 변경하기로 선택하면 원래의 녹색 이미지를 다시 색칠하십시오. 희망은 그 말이 맞습니다.

sample color key image

사이드 참고 : 당신이 때문에 이미지의 파일 형식으로 사진 저하를 방지하려면 항상 .jpg.png 파일을 선호 여기에 내가 설명하고있는 오프 스크린 소스 이미지의 예입니다.

최상의 결과를 얻으려면 위에서 설명한 색상 키 이미지를 사용하는 것이 좋습니다. 원본 이미지를 조작하고 .png과 같은 무손실 파일 형식으로 저장할 수 있으므로 원본 코드와 똑같은 색상 일치를 수행 할 수 있고 색상 범위를 시도하거나 일치시킬 필요가 없다는 장점이 있습니다. 또한 배경색이 허용치에 너무 가까워서 실수로 색상이 바뀌는 상황이 발생하지 않습니다.

그러나 ALLEGRO_COLOR에 대한 ALLEGRO 설명서를 살펴 보았으며 다음 방법은 해당 라이브러리를 사용하여 위에 표시된 SimilarColor 메서드를 수행해야합니다. 알레그로에서 당신이 직접 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

관련 문제