2016-02-20 3 views
4

У меня проблема с отображением альфа-прозрачности с использованием GTK и Каира. Я пытаюсь показать это изображение 1Альфа прозрачность в Каире

Если я делаю альфа-смешение себя, все работает.

Manual alpha blending

Если я передать значения альфа непосредственно в Каир, тень, кажется, делают хорошо, но эффект свечения поврежден.

Cairo alpha rendering

Является ли это ошибка в Каире 1.14.2, или я что-то отсутствует?

//Need deprecated API to get background color 
GdkColor color = gtk_widget_get_style(widget)->bg[GTK_STATE_NORMAL]; 
Pixel color_blend 
    { 
    uint8_t(255*color.red/65535.0f) 
    ,uint8_t(255*color.green/65535.0f) 
    ,uint8_t(255*color.blue/65535.0f) 
    ,255 
    }; 
while(ptr!=ptr_end) 
    { 
// TODO: Interpolate 
    auto row_src=size_t(row*factor); 
    auto col_src=size_t(col*factor); 

    auto alpha=ptr_src[row_src*width_in + col_src].v3/255.0f; 
    *ptr= 
     { 
    // Using manual alpha blend works 
     uint8_t(alpha*ptr_src[row_src*width_in + col_src].v2 + (1-alpha)*color_blend.v2) 
     ,uint8_t(alpha*ptr_src[row_src*width_in + col_src].v1 + (1-alpha)*color_blend.v1) 
     ,uint8_t(alpha*ptr_src[row_src*width_in + col_src].v0 + (1-alpha)*color_blend.v0) 
     ,255 
    /* This appears to be broken 
     ptr_src[row_src*width_in + col_src].v2 
     ,ptr_src[row_src*width_in + col_src].v1 
     ,ptr_src[row_src*width_in + col_src].v0 
     ,ptr_src[row_src*width_in + col_src].v3*/ 
     }; 

    ++col; 
    if(col==width_out) 
     { 
     col=0; 
     ++row; 
     } 
    ++ptr; 
    } 

Я толкаю пиксели с помощью

auto surface=cairo_image_surface_create_for_data((uint8_t*)pixels.begin(),CAIRO_FORMAT_ARGB32,width_out,height_out,width_out*sizeof(Pixel)); 

cairo_set_source_surface(cr, surface, 0.5*(width-width_out), 0.0); 
cairo_paint(cr); 

cairo_surface_destroy(surface); 

Явной установки оператору CAIRO_OPERATOR_OVER не помогает, результат все тот же.

+0

Вы используете правильный оператор, т. Е. CAIRO_OPERATOR_OVER вместо CAIRO_OPERATOR_SOURCE? –

+0

@ H. Guijt CAIRO_OPERATOR_OVER по умолчанию, и указание его явно дает тот же результат. Однако изменение в CAIRO_OPERATOR_SOURCE имеет правильное поведение, то есть я получаю полупрозрачное окно. – user877329

+0

Это не имеет никакого смысла ... Uhm, как насчет формата поверхности адресата: это RGB или ARGB? –

ответ

3

Как вы отметили в своем комментарии выше, ваши значения пикселей неверны. Вам нужно использовать заранее умноженную альфу. Возвращаясь к моему примеру из вопроса (и игнорируя его), полностью красный с прозрачностью 50% - 0x7f << 24 | 0x7f в Каире. Пиксели с недопустимыми значениями (какой-то компонент цвета больше альфа-значения) дают неопределенные результаты, а ваш 0xff << 24 | 0x7f относится к этой категории.

См http://www.cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t:

Предварительно умноженный альфа используется. (То есть, 50% прозрачный красный 0x80800000, а не 0x80ff0000.)

P.S .: На мой взгляд, правильный способ доступа к данным пикселя осуществляется через uint32_t и смещение, например, uint32_t pixel = (r << 24) | (g << 16) | (b << 8) | a;. Таким образом, вам вообще не нужно беспокоиться о контенте.

P.P.S .: Для OVER и полностью непрозрачной цели формула Cairo используется для упрощения до source_color + target_color * (1 - source_alpha), в то время как ваш код использует source_color * source_alpha + target_color * (1 - source_alpha). См. http://www.cairographics.org/operators/. Эти две формулы явно не эквивалентны.

Редактировать: Хорошо, возможно, они эквивалентны при использовании pre-multiplie alpha. Извините за путаницу.

+0

Они * эквивалентны при использовании предварительно умноженной альфы. И формула Каира использует только в этом случае. Таким образом, вы можете удалить * возможно *. – user877329

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