2014-11-16 2 views
0

Я пытаюсь создать алгоритм для наложения изображения с прозрачными пленками поверх полностью непрозрачного изображения. На следующем образце у меня есть обратное полностью непрозрачное изображение, а переднее изображение - синяя рамка с рассеянными краями. Проблема, с которой я сталкиваюсь, заключается в том, что моя реализация неправильно перекрывает полупрозрачные области, создающие темные пиксели.Оверлейные пиксели с альфа-значением в C/C++

enter image description here

Вот моя реализация:

#define OPAQUE 0xFF 
#define TRANSPARENT 0 
#define ALPHA(argb) (uint8_t)(argb >> 24) 
#define RED(argb) (uint8_t)(argb >> 16) 
#define GREEN(argb) (uint8_t)(argb >> 8) 
#define BLUE(argb) (uint8_t)(argb) 
#define ARGB(a, r, g, b) (a << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff) 
#define BLEND(a, b, alpha) ((a * alpha) + (b * (255 - alpha)))/255 

void ImageUtil::overlay(const uint32_t* front, uint32_t* back, const unsigned int width, const unsigned int height) 
{ 
    const size_t totalPixels = width * height; 

    for (unsigned long index = 0; index < totalPixels; index++) 
    { 
     const uint32_t alpha = ALPHA(*front); 

     const uint32_t R = BLEND(RED(*front), RED(*back), alpha); 
     const uint32_t G = BLEND(GREEN(*front), GREEN(*back), alpha); 
     const uint32_t B = BLEND(BLUE(*front), BLUE(*back), alpha); 

     *backPixels++ = ARGB(OPAQUE, R , G, B); 
     *frontPixels++; 
    } 
} 

UPDATE:

Тестовые Изображения файлы

DOWNLOAD

+0

Что вы открыли для себя, когда вы отлажены это? –

+2

как вы загрузили свое изображение? возможно ли, что ваш загрузчик изображений предварительно умножил это изображение? – gman

+0

Изображения загружаются правильно. Я пробовал это, загружая и сохраняя их снова отдельно без слияния, что создает те же исходные изображения. Я думаю, что проблема может быть в формуле, смешивающей пиксели, но я не могу определить проблему. – PerracoLabs

ответ

0

Follow советы по комментариям от gman и interjay, я исследовал дальше и да, данные загружаются с предварительно умноженной альфой. Это создает затемнение при смешивании. Решение заключалось в том, чтобы не размножать передние пиксели, и, наконец, я получил ожидаемый результат.

Unmultiply формула:

((0xFF * color)/alpha) 

Окончательный код:

#define OPAQUE 0xFF; 
#define TRANSPARENT 0; 

#define ALPHA(rgb) (uint8_t)(rgb >> 24) 
#define RED(rgb) (uint8_t)(rgb >> 16) 
#define GREEN(rgb) (uint8_t)(rgb >> 8) 
#define BLUE(rgb) (uint8_t)(rgb) 

#define UNMULTIPLY(color, alpha) ((0xFF * color)/alpha) 
#define BLEND(back, front, alpha) ((front * alpha) + (back * (255 - alpha)))/255 
#define ARGB(a, r, g, b) (a << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF) 

void ImageUtil::overlay(const uint32_t* front, uint32_t* back, const unsigned int width, const unsigned int height) 
{ 
    const size_t totalPixels = width * height; 

    for (unsigned long index = 0; index < totalPixels; index++) 
    { 
     const uint32_t frontAlpha = ALPHA(*front); 

     if (frontAlpha == TRANSPARENT) 
     { 
      *back++; 
      *front++; 
      continue; 
     } 

     if (frontAlpha == OPAQUE) 
     { 
      *back++ = *front++; 
      continue; 
     } 

     const uint8_t backR = RED(*back); 
     const uint8_t backG = GREEN(*back); 
     const uint8_t backB = BLUE(*back); 

     const uint8_t frontR = UNMULTIPLY(RED(*front), frontAlpha); 
     const uint8_t frontG = UNMULTIPLY(GREEN(*front), frontAlpha); 
     const uint8_t frontB = UNMULTIPLY(BLUE(*front), frontAlpha); 

     const uint32_t R = BLEND(backR, frontR, frontAlpha); 
     const uint32_t G = BLEND(backG, frontG, frontAlpha); 
     const uint32_t B = BLEND(backB, frontB, frontAlpha); 

     *back++ = ARGB(OPAQUE, R , G, B); 
     *front++; 
    } 
} 
Смежные вопросы