less..
Alpha-blend의 기본중의 기본인 Half and Half 메소드.
말 그대로 반투명이다.
foreground와 background의 색을 반반씩 섞는(평균값을 구하는) 방법이다.
F = foreground color
B = backgound color
n = pixel index
f(n) = (Fn + Bn) / 2
위와 같은 아주 간단한 식이다.
2의 자승은 shift연산으로 표현할 수 있으므로, 좀더 빠르게 처리하려면 다음과 같이 바꿀 수 있다.
f(n) = (Fn + Bn) >> 1
...너무 간단해서 별로 설명할것도 없음.
예제 코드는 24bit bitmap이미지를 이용하여 테스트 했다.
1. 윗식 그대로 1바이트 단위로 처리한 결과.
[Alpha_HalfAndHalf]
 |
| Half and Half |
2. 아무래도 1바이트씩 처리하는것은 속도면에서 무리가 있다.
그러니 4바이트씩 처리하도록 바꿔보자.
먼저 1바이트에 대해 생각해 보면, Fn과 Bn이 가질수 있는 최대 크기는 0xFF이다.
연산식 (Fn + Bn) / 2에서, Fn + Bn의 최대값은 0x1FE가된다.
따라서 f(n)의 최대값은 0xFF, 즉 1바이트의 최대값과 같게 된다.
(두 수의 평균은 두 수를 초과할수 없음을 생각해보면 쉽다.)
이제 4바이트씩 처리를 한다고 생각해보자.
Fn과 Bn의 최대값은 0xFF FF FF FF가 된다.
만약 이대로 Fn + Bn을 수행하게 된다면 오버플로가 발생하게 된다.
따라서 덧셈연산을 먼저해서는 우리가 원하는 평균값은 도출할 수 없게 된다.
나눗셈은 분배법칙이 성립하므로 나눗셈을 먼저 해보자.
f(n) = Fn/2 + Bn/2
Fn/2와 Bn/2의 최대값은 0x7F이므로 f(n)의 최대값은 0xFE가 된다.
위 식을 이용하면 1의 오차가 있지만 근사한 결과를 도출할 수 있다.
그럼 4바이트를 대상으로 나눗셈을 수행해야한다.
만약 4바이트에 대해 일반적인 나눗셈을 수행할경우, 0x7F FF FF FF가 되어, 우리가 원하는 0x7F 7F 7F 7F와는 다른값이 된다.
이렇게 다른 값이 나오는 이유는, 상위 바이트에서 버려져야할 가장 하위 비트가 최상위 비트에 오기때문이다,
따라서 0x7F 7F 7F 7F와 And연산 하여 최상위 1비트를 버리게 되면 우리가 원하는 결과를 얻을수 있다.
그러므로 식은 다음과 같게 된다.
f(n) = (Fn>>1)&0x7F7F7F7F + (Bn>>1)&0x7F7F7F7F
 |
| Half and Half - 32bit Transfer A |
확연히 속도가 향상되었음을 알 수 있다.
3. 분명히 속도는 향상 되었으나, 1의 오차가 있다.
만약 정확한 값을 구하고자 한다면 보정해야할것이다.
오차는 두번의 나눗셈이 수행되면서 버려지는 1비트에 기인하게 된다.
만약 덧셈을 수행한 후 나눗셈을 수행하게 된다면, Fn과 Bn의 최하위 비트가 모두 1일때 캐리가 발생하게 된다.
하지만 나눗셈을 수행하고 덧셈을 수행하는 경우, 최하위 1비트가 버려지므로 캐리는 발생하지 않게 된다.
따라서 Fn과 Bn의 최하위 1비트가 모두 1이라면 결과에 1을 더해서 캐리를 보정해야한다.
이를 4바이트에 대해 모두 적용해야 하므로 식은 다음과 같이 되게 된다.
f(n) = (Fn>>1)&0x7F7F7F7F + (Bn>>1)&0x7F7F7F7F + (Fn&Bn&0x01010101)
 |
| Half and Half - 32bit Transfer B |
속도는 약간 느려졌지만 정확한 결과를 도출할 수 있다.
*1바이트 처리에 비해 4바이트 처리에서 비약적으로 속도가 향상되는것은, 우리가 현재 사용하고 있는 CPU가 32bit기반이기 때문이다.
32bitCPU에서는 1바이트로 덧셈을 하든, 2바이트로 덧셈을 하든, 4바이트로 덧셈을 하든 1클럭을 소모하게 된다.
따라서 한번에 4바이트 단위로 처리하여 인스트럭션 수를 줄여주는것이 속도 향상에 도움이된다.
*나눗셈을 Shift연산으로 치환하는 이유는 Shift연산은 Bitwise Operation이므로 보다 적은 클럭으로 계산할 수 있기때문이다.
단, 2의 자승수에만 사용할 수 있다.
*속도 향상을 시킴에 있어, 인스트럭션을 줄이고 적은 클럭을 소모하는 연산으로 바꾸는것 외에도 I/O접근, 메모리 접근을 최소화 하는 방법도 있다.
메모리 버스는 4바이트 이상의 크기를 가지기 때문에, 1바이트를 4번 가져오는것보다 4바이트를 한번에 가져오는것이 빠르다.