2013-10-16 8 views
3

정수로 코딩 된 두 가지 색상을 혼합하려고합니다. 여기에 내 작은 기능은 다음과 같습니다두 int 색상을 올바르게 혼합하는 방법

int blend (int a, int b, float ratio) { 
    if (ratio > 1f) { 
     ratio = 1f; 
    } else if (ratio < 0f) { 
     ratio = 0f; 
    } 
    float iRatio = 1.0f - ratio; 

    int aA = (a >> 24 & 0xff); 
    int aR = ((a & 0xff0000) >> 16); 
    int aG = ((a & 0xff00) >> 8); 
    int aB = (a & 0xff); 

    int bA = (b >> 24 & 0xff); 
    int bR = ((b & 0xff0000) >> 16); 
    int bG = ((b & 0xff00) >> 8); 
    int bB = (b & 0xff); 

    int A = ((int)(aA * iRatio) + (int)(bA * ratio)); 
    int R = ((int)(aR * iRatio) + (int)(bR * ratio)); 
    int G = ((int)(aG * iRatio) + (int)(bG * ratio)); 
    int B = ((int)(aB * iRatio) + (int)(bB * ratio)); 

    return A << 24 | R << 16 | G << 8 | B; 
} 

모든 것이 잘 작동하는 것 같다,하지만 특정 인수는 잘못된 색상을 생산하고 있습니다. 예를 들어 :

int a = 0xbbccdd; 
    int b = 0xbbccdd; 
    int c = blend(a, b, 0.5f); // gives 0xbaccdc, although it should be 0xbbccdd 

내 생각 엔

그래서 올바른 방법은 무엇입니까 ... 유동 비율 또는 주조에 의해 곱셈 중 하나가 여기 비난,하지만 난 그들과 함께 무엇이 잘못되었는지 알아낼 수 있다는 것입니다 Java에서 두 가지 색상을 혼합하는 방법은 무엇입니까?

+0

은 왜 당신이'바이트 []'배열하고, 생성 int 값을 얻기 위해'ByteBuffer'을 사용하지 마십시오
귀하의 의견을 바탕으로 나는 동일한 비율로 n 개의 색상을 혼합 다음과 같은 기능을 만들었습니다 'byte []'배열에서? –

+0

성능 향상을 위해. 내가 틀렸다고 정정 해 주겠지 만 원시물을 만드는 것은 객체를 인스턴스화하는 것보다 훨씬 빠릅니다. 이 코드는 초당 수백 번 실행해야합니다. –

+0

bitwise 작업을 사용하여 찾은 최고의 대답은 여기에 있습니다 : http://stackoverflow.com/a/4787257/303612 –

답변

4

내 생각 엔 int에 대한 캐스팅은 추가 후에 수행되어야합니다. 이처럼

int a = (int)((aA * iRatio) + (bA * ratio)); 

또한 변수를 사용할 때 Java 명명 규칙을 사용하는 것이 좋습니다. 상수 만 대문자 여야합니다.

+0

도움이되었습니다. 어리석은 나, 왜 그런 식으로 던지지 않았어 :/ –

+0

BTW. 변수의 이름을 어떻게 지정 하시겠습니까? 나는 대문자가 최종적인 정적 변수만을위한 것이라는 것을 안다. 이것은 단지 SOOOO이며 읽기 쉽다. –

+0

'redHex ','greenHex ','blueHex '와 같은 것은 아마도 각 색상의 16 진수 값을 나타 내기 때문일 것이다. :) – dARKpRINCE

1

감사합니다. JuliusB 및 dARKpRINCE. 필자는 java.awt.Color를 수용하고 캐스트를 수정하고 Java 표준과 같은 변수 이름을 변경했습니다. 잘 작동한다. 다시 한 번 감사드립니다! dARKpRINCE의 대답 @

Color blend(Color c1, Color c2, float ratio) { 
    if (ratio > 1f) ratio = 1f; 
    else if (ratio < 0f) ratio = 0f; 
    float iRatio = 1.0f - ratio; 

    int i1 = c1.getRGB(); 
    int i2 = c2.getRGB(); 

    int a1 = (i1 >> 24 & 0xff); 
    int r1 = ((i1 & 0xff0000) >> 16); 
    int g1 = ((i1 & 0xff00) >> 8); 
    int b1 = (i1 & 0xff); 

    int a2 = (i2 >> 24 & 0xff); 
    int r2 = ((i2 & 0xff0000) >> 16); 
    int g2 = ((i2 & 0xff00) >> 8); 
    int b2 = (i2 & 0xff); 

    int a = (int)((a1 * iRatio) + (a2 * ratio)); 
    int r = (int)((r1 * iRatio) + (r2 * ratio)); 
    int g = (int)((g1 * iRatio) + (g2 * ratio)); 
    int b = (int)((b1 * iRatio) + (b2 * ratio)); 

    return new Color(a << 24 | r << 16 | g << 8 | b); 
} 
1

는 정확하지만 나는 몇 가지 사소한 조언을 : 그것은 모든 개체 필드에 의존하지 않기 때문에

  1. 함수는 정적이어야한다.

  2. (x >> 24) & 0xFF 대신 x >>> 24을 수행하여 색상의 알파 성분을 추출 할 때 한 번의 작업을 저장할 수 있습니다.

  3. 형태의 아무것도 : 당신이 필요로 곱셈의 수를 반으로

    a + (b - a) * ratio 
    

    :

    (a * (1 - ratio)) + (b * ratio) 
    

    는 다음과 같이 쓸 수 있습니다.

1

감사합니다. JuliusB, dARKpRINCE 및 bmauter.

public static Color blend(Color... c) { 
    if (c == null || c.length <= 0) { 
     return null; 
    } 
    float ratio = 1f/((float) c.length); 

    int a = 0; 
    int r = 0; 
    int g = 0; 
    int b = 0; 

    for (int i = 0; i < c.length; i++) { 
     int rgb = c[i].getRGB(); 
     int a1 = (rgb >> 24 & 0xff); 
     int r1 = ((rgb & 0xff0000) >> 16); 
     int g1 = ((rgb & 0xff00) >> 8); 
     int b1 = (rgb & 0xff); 
     a += ((int) a1 * ratio); 
     r += ((int) r1 * ratio); 
     g += ((int) g1 * ratio); 
     b += ((int) b1 * ratio); 
    } 

    return new Color(a << 24 | r << 16 | g << 8 | b); 
}