2015-07-14 3 views
1

Я пытаюсь использовать некоторые алгоритмы для написания метода для удаления значения альфа-значения из цвета и получения его одинаковых значений rgb, но, похоже, мой тест всегда терпит неудачу. Я верю, что это называется альфа-смешением? Я не уверен. Это алгоритм, который я использую для преобразования.Преобразование ARGB в RGB в java

public static int removeAlpha(int foreground, int background) { 
     int redForeground = Color.red(foreground); 
     int redBackground = Color.red(background); 
     int greenForeground = Color.green(foreground); 
     int greenBackground = Color.green(background); 
     int blueForeground = Color.blue(foreground); 
     int blueBackground = Color.blue(background); 
     int alphaForeground = Color.alpha(foreground); 
     int redNew = (redForeground * alphaForeground) + (redBackground * (1 - alphaForeground)); 
     int greenNew = (greenForeground * alphaForeground) + (greenBackground * (1 - alphaForeground)); 
     int blueNew = (blueForeground * alphaForeground) + (blueBackground * (1 - alphaForeground)); 
     return Color.rgb(redNew, greenNew, blueNew); 
    } 

И тест, как этот

@Test 
    public void removeAlpha() { 
     int red = Color.RED; 
     Assert.assertEquals(0xFFFF7F7F, Heatmap.removeAlpha(red, 0xFFFFFFFF)); 
    } 

junit.framework.AssertionFailedError: 
Expected :-32897 
Actual :-258 

когда я рисовать красные в фотошопе и установите непрозрачность на 50%, это дает мне 255,127,127 RGB, который кажется идентичным 50% непрозрачной чистого красного цвета. Я думаю, что алгоритм ложный. Любая помощь будет оценена.

Edit: Вот макет Цвет:

PowerMockito.mockStatic(Color.class); 
     PowerMockito.when(Color.rgb(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyInt())).thenAnswer(new Answer<Object>() { 
      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       int red = (int) invocation.getArguments()[0]; 
       int green = (int) invocation.getArguments()[1]; 
       int blue = (int) invocation.getArguments()[2]; 
       return (0xFF << 24) | (red << 16) | (green << 8) | blue; 
      } 
     }); 
     PowerMockito.when(Color.alpha(Mockito.anyInt())).thenAnswer(new Answer<Object>() { 
      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       return ((int)invocation.getArguments()[0])>>>24; 
      } 
     }); 
     PowerMockito.when(Color.red(Mockito.anyInt())).thenAnswer(new Answer<Object>() { 
      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       return (((int)invocation.getArguments()[0])>>16) & 0xFF; 
      } 
     }); 
     PowerMockito.when(Color.green(Mockito.anyInt())).thenAnswer(new Answer<Object>() { 
      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       return (((int)invocation.getArguments()[0])>>8) & 0XFF; 
      } 
     }); 
     PowerMockito.when(Color.blue(Mockito.anyInt())).thenAnswer(new Answer<Object>() { 
      @Override 
      public Object answer(InvocationOnMock invocation) throws Throwable { 
       return (int)invocation.getArguments()[0] & 0xFF; 
      } 
     }); 
+0

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

+0

Ваш формуляр кажется правильным. Однако я понял, что вы игнорируете 'alphaBackground'. Здесь проблема не в этом, так как ваш тест задает это свойство на 100%. – maja

+0

Вы обрабатываете свои значения цвета как диапазон между '[0, 1]'. Возможно ли, что ваши функции 'Color.xx' возвращают значения' [0, 255] '? – maja

ответ

0

Попробуйте это:

int color = Color.argb(255, 118, 118, 188); 
+0

Я думаю, вы меня неправильно поняли. То, что я пытаюсь сделать, - получить значение rgb цвета с альфой, что означает, что он полностью непрозрачен с разными красными, зелеными и синими значениями. –

+0

@ BarışcanKayaoğlu, извините ... Я просто вижу в имени функции 'removeAlpha', и, как я знаю, это правильный способ удалить альфа – Alexander

+2

@ BarışcanKayaoğlu Чтобы удалить альфу, как правильно показал Александр, просто потяните ее значение до максимальной непрозрачности (255) –

2

Ваша формула лечит 1 как 100%, но ваши цвета функции возвращаются/ожидая значения в диапазоне [0, 255], что означает 255 = 100%.

Вы должны использовать следующую формулу:

newColor = (colorA * opacityA + colorB * (255 - opacityA))/255

Пример:

foreground = 256 
background = 0 
foreground-alpha = 25% 

В диапазоне [0,255], 25% равны 63. T он результат этот пример должен быть 63, так как foreground * 25% + background * 75% - 63.

Так что для того, чтобы получить 75%, вам нужно 100% - 25% = 256 - 63 = 193

Вторая проблема:

Ваш тест неправильно. Вы принимаете 100% red + 100% white, что должно привести к красным 100%, а не 0xFFFF7F7F.

Как сказал @ frarugi87 в своем ответе, вам сначала нужно установить альфа-канал красного на 50%.

+0

Хм .. Да, вы правы, я изменил его, но тест все еще терпит неудачу. Я попытаюсь переформулировать его и повторить попытку. Спасибо –

+0

Это неверно, так как непрозрачность 255 приводит к увеличению цвета. Правильной формулой будет '(colorA * opacityA + colorB * (255 - opacityA))/255', но, на мой взгляд, мое решение (преобразование альфа-канала в 0-1) лучше – frarugi87

+0

Ну, похоже, формула такая же. Но результаты все еще не работают. Ожидаемое: -32897 Актуально: -16711680 –

2

ПРИМЕЧАНИЕ: Я не вхожу в java, поэтому я могу ошибаться. Я просто использую общие понятия программирования, поэтому некоторые настройки могут понадобиться.

Я думаю, что вы возитесь с типами данных ... Вы получаете целочисленное представление своего цвета, то есть 0-255, и умножаете его так, как если бы это было представление 0-1. Попробуйте следующее:

double alphaForeground = ((double)Color.alpha(foreground))/255.0; 
int redNew = ((int)round((redForeground * alphaForeground) + (redBackground * (1 - alphaForeground)))); 
int greenNew = ((int)round((greenForeground * alphaForeground) + (greenBackground * (1 - alphaForeground)))); 
int blueNew = ((int)round((blueForeground * alphaForeground) + (blueBackground * (1 - alphaForeground)))); 

Возможны проблемы с округлением, но ... это должно сработать.

Еще одно замечание: Color.RED имеет 255 альфа-канал. Это означает, что removeAlpha(red, 0xFFFFFFFF) возвращает красный цвет, а не 0xFFFF7F7F.Для того, чтобы получить это значение, вы должны написать

int red = Color.RED; 
red.alpha = 0x80; 

(или какой-то близкое значение)

+0

Я думаю, что в этом случае 255 лучше, так как с 256 у вас никогда не будет 100% непрозрачности ... Однако 255 против 256 составляет менее 0,4% от ошибки;) – frarugi87

+1

Извините, вы правы – maja

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