2011-12-09 2 views
3

두 가지 색상을 평균화하려고합니다.두 개의 32 비트 색상을 평균으로 정수로 채우시겠습니까?

내 원래 (끔찍한)를 구현 다음과 같습니다 (이 약의 그러나

int ColorAverage(int c1, int c2) { 
    unsigned char* b1 = reinterpret_cast<unsigned char*>(&c1); 
    unsigned char* b2 = reinterpret_cast<unsigned char*>(&c2); 
    int value; 
    unsigned char* bv = reinterpret_cast<unsigned char*>(&value); 
    bv[0] = (b1[0] + b2[0])/2; 
    bv[1] = (b1[1] + b2[1])/2; 
    bv[2] = (b1[2] + b2[2])/2; 
    bv[3] = (b1[3] + b2[3])/2; 
    return(value); 
} 

, 그것은 여전히 ​​매우 느린 다음과 같이

//color is a union 
int ColorAverage(int c1, int c2) { 
    color C1(c1); 
    color C2(c2); 
    return color(
     (unsigned char)(0.5f * C1.a + 0.5f * C2.a), 
     (unsigned char)(0.5f * C1.r + 0.5f * C2.r), 
     (unsigned char)(0.5f * C1.g + 0.5f * C2.g), 
     (unsigned char)(0.5f * C1.b + 0.5f * C2.b) 
    ).c; 
} 

나의 현재 솔루션 (이 상당히 잘 수행)입니다 내 프레임 시간의 3 %).

나는 24 비트에 대한 해결책을 발견했다, 그러나 그것은 (알파가 손실) 32 비트에 적용되지 않습니다

#define AVERAGE(a, b) (((((a)^(b)) & 0xfffefefeL) >> 1) + ((a) & (b))) 

http://www.compuphase.com/graphic/scale3.htm#HSIEH1

답변

5

이 같은 32 비트 마스크를 확장하십시오 :

#define AVERAGE(a, b) (((((a)^(b)) & 0xfefefefeL) >> 1) + ((a) & (b))) 

편집 : 빠른 검사를 수행했는데 테스트 케이스가 제대로 작동하는 것 같습니다. 그런데 좋은 공식!

4

목표는 다음과 같은 동작을 수행한다 :

(a + b)/2 = ((A^B) >> 1) + (a & b)

및 그것을 정수의 4 바이트 모두에 적용하십시오. 이것이 단지 1 바이트라면 1 비트 씩 오른쪽으로 이동하면 가장 오른쪽 비트는 무시됩니다. 그러나이 경우 맨 앞의 3 바이트 중 맨 오른쪽 비트는 버려지지 않고 인접 바이트로 이동합니다. 염두에 두어야 할 아이디어는 각 바이트의 마지막 비트 마스크가 필요하므로 이동 중에 인접 바이트를 '오염'시키지 않아야합니다.

XOR의 B = 1,011 1,101 1,110 1,001

마스크없이 1 비트의 우측 시프트가, 다음과 같을 것이다 :

예를 들어,^b는 본이라고 말할 1,110 1,111 0,100 잘못

= 0101

(a XOR의 b) >> 1.마스크 제로의 각 바이트의 마지막 비트 아웃이 발생하지 않도록 :

(A XOR 나)와 0xfefefefe = 1010 1100 1110 1000

그럼 당신은 안전이 값을 전환 할 수 있습니다

((a XOR의 b) AND 0xfefefefe) = 0101 0110 0111 0100 그래서

:

오른쪽
#define AVERAGE(a, b) (((((a)^(b)) & 0xfefefefeL) >> 1) + ((a) & (b))) 

C는 논리 오른쪽 시프트와 산술 오른쪽 시프트를 해당 연산자와 구별하지 않는다는 점을 명심해야합니다. 이동하려는 정수가 부호가 없는지 확인하려면 prevent implementation-specific signed-integer shift voodoo으로 지정해야합니다.

수정 : @dasblinkenlight가이 대답을 저주했을 수도 있습니다. 부호가있는 정수를 이동하는 것을주의하면 좋을 것입니다.

관련 문제