What is the correct way to do alpha blending? (WITH)

I am writing a very simple graphics library and I am trying to figure out how to do alpha blending. I tried this several times, but my results were less than satisfactory. According to Wikipedia, I have to do:

Value = (1-alpha) Value0 + alphavalue1

This, however, does not work at all. Maybe I'm doing something wrong?

The code that I included draws a colorful picture (the proximity function), then tries to draw a partially transparent box (100 100). However, instead of a white translucent box, I get a strange image distortion (I will try to keep them at the bottom of my message). Any suggestions? Here is my code:

#include "hgl.h"

void proximity()
{
    int x = 0, y = 0, d1, d2, d3, dcenter;

    while(x < WIDTH){
        while(y < HEIGHT){
            d1 = distance(x, y, (WIDTH/2) - 200, (HEIGHT/2) + 200);
            d2 = distance(x, y, (WIDTH/2) + 200, (HEIGHT/2) + 200);
            d3 = distance(x, y, (WIDTH/2), (HEIGHT/2) - 150);
            dcenter = distance(x, y, WIDTH/2, HEIGHT/2);
            putpixel(x, y, d1, d2, d3);
            y++;
        }
        y = 0;
        x++;
    }
}

int alpha_transparency(float alpha, float value1, float value2)
{
    return (1-alpha) * value1 + alpha * value2;
}

void transparent_box(int pos_x, int pos_y, int width, int height, float alpha, char r, char g, char b)
{
    int x = 0, y = 0;
    while(x < width)
    {
        while(y < height)
        {
            int rr, rg, rb;
            rr = alpha_transparency(alpha, p.bitmap[x+pos_x][y+pos_y].r, r);
            rg = alpha_transparency(alpha, p.bitmap[x+pos_x][y+pos_y].g, g);
            rb = alpha_transparency(alpha, p.bitmap[x+pos_x][y+pos_y].b, b);
            putpixel(pos_x + x, pos_y + y, rr, rg, rb);
            y++;
        }
        x++;
        y = 0;
    }
}

int main()
{
    fp = fopen("out.bmp","wb");

    set_dimensions(1440, 900);
    insert_header();

    white_screen();

    proximity();
    transparent_box(100, 100, 500, 500, .9, 255, 255, 255);

    insert_image();
    fclose(fp);
    return 0;
}

Sorry, I couldn’t turn on the output because I am a new user. However, here are the links:

Original image

+3
3

- ; - , , [0, 1].

char, . unsigned char, . , , 255, , -1.

, unsigned char, , shenanigans (. EDIT2).

EDIT: , [0, 255], [0, 1], -.

EDIT2: , char unsigned char, , :

alpha_transparency(0.9, (char)255, (char)255)
== alpha_transparency(0.9f, -1.0f, -1.0f)
== -1.0f
== 0xff (cast to char)

alpha_transparency(0.9, (char)128, (char)255)
== alpha_transparency(0.9f, -128.0f, -1.0f)
== -13.7f
== 0xf3

alpha_transparency(0.9, (char)127, (char)255)
== alpha_transparency(0.9f, 127.0f, -1.0f)
== -11.80f
== 0x0b

alpha_transparency(0.9, (char)0, (char)255)
== alpha_transparency(0.9f, 0.0f, -1.0f)
== -0.9f
== 0x00
+2

, , , . , , , 0 , 1 - , 0,5 - . ints, , 0 , 255 - .

, :

return (255-alpha)*value1+alpha*value2;

, , , . :

float result = (255.0f-alpha)*value1+alpha*value2;
return (int) result;

, float int. , , . .

0

, : , ; .

ints , :

int alpha_transparency(int alpha, int value1, int value2) {
  int unscaled= (255-alpha)*value1 + alpha*value2;
  return unscaled / 255;  /* integer division */
}

all-float [0..255] ( - ) float [0.0.. 1.0], , .

float input_raw_value(unsigned char value)  { return value/255.0; }
...
float alpha_transparency(float alpha, float value1, float value2) {
  return (1.0-alpha)*value1 + alpha*value2;
}
...
unsigned char output_raw_value(float value) { return value*255.0; }

Note that I ignored rounding issues in each method; once you have basic math, you should pay some attention to this. In addition, there are various tricks for replacing divisions (which can be relatively slow) by multiplying or bit-tinkering.

0
source

Source: https://habr.com/ru/post/1752538/


All Articles