Avatar billede alvion Nybegynder
10. september 2001 - 06:21 Der er 5 kommentarer og
1 løsning

BitBlt til at lave alpha-kanal transparens

Jeg vil tegne et bitmap (bmp_a) oven i et andet (bmp_b) således at bmp_a bliver semi transparent visse steder.

Hvor transparent hver pixels skal være, bestemmes af et gråtone bitmap (bmp_pat), hvor f.eks. hvid er ikke-transparent, sort er fuldt transparent og alle gråtoner ind imellem giver en skala af transparens.

Jeg kan løbe alle pixels igennem på billederne og lave følgende beregning:

rR = pix_rA + ((pix_pat*(pix_rB-pix_rA)) >> 8);
gR = pix_gA + ((pix_pat*(pix_gB-pix_gA) >> 8);
bR = pix_bA + ((pix_pat*(pix_bB-pix_bA)) >> 8);

Men jeg tænkte om ikke den hurtige BitBlt havde en ROPCODE jeg kunne bruge til formålet? Hvor jeg f.eks. definerer mit bmp_pat som pattern.
Avatar billede soepro Nybegynder
10. september 2001 - 09:09 #1
Say what ?
Avatar billede alvion Nybegynder
10. september 2001 - 10:11 #2
Ok lad mig uddybe med et eksempel (lad mig først nævne at jeg med \"BitBlt\" taler Win32 programmering):

Tag Photoshops lag. I dem har du mulighed for at stille \"opacity\" for hvert lag, således at laget bliver mere eller mindre gennemsigtigt.

Dette gøres ved at foretage en \"alphablend\" mellem det billede, der skal tegnes (bmp_a), og det billede som allerede er vist (bmp_b). En alphablend er en beregning på hver enkel pixel i forhold til en alphaværdi (den du sætter som \"opacity).

Det kan som halvt pseudokode illustreres således (vi forudsætter at begge billeder er lige store):

for (y=0; y<bmp_a.Height(); ++y) {
  for (x=0; x<bmp_a.Width(); ++x) {
    screen.SetPixel(x,y) = AlphaBlend(bmp_a.GetPixel(x,y), bmp_b.GetPixel(x,y), alpha);
  }
}

Funktionen AlphaBlend er defineret som

Pixel AlphaBlend(const Pixel& a, const Pixel& b, const float alpha)
{
  int rA,gA,bA,rB,gB,bB,rR,gR,bR;

  rR = (int)(rA + alpha*(rB - rA));
  gR = (int)(gA + alpha*(gB - gA));
  bR = (int)(bA + alpha*(bB - bA));

  return Pixel(rR, gR, bR);
}

alpha er en float mellem 0 og 1 (0=bmp_a\'s pixel vises, 1=bmp_b\'s pixel vises, alle værdier derimellem laver en blend af begge pixels)


Jeg har så optimeret rutinen til kun at bruge integers (af hensyn til hastighed). alpha skal nu indeholde en værdi mellem 0 og 255 (0=bmp_a, 255=bmp_b)

Pixel AlphaBlend(const Pixel& a, const Pixel& b, const int alpha)
{
  int rA,gA,bA,rB,gB,bB,rR,gR,bR;

  rR = rA + ((alpha*(rB-rA)) >> 8);
  gR = gA + ((alpha*(gB-gA) >> 8);
  bR = bA + ((alpha*(bB-bA)) >> 8);

  return Pixel(rR, gR, bR);
}

Godt det var teorien. Nu vil jeg så ikke længere kun bruge én alpha værdi. Nu vil jeg istedet definere en \"alpha-maske\" dvs. et bitmap på størrelse med bmp_a kun i gråtoner. Disse gråtoner definerer så ved hver enkelt pixel, hvordan den skal blendes mellem bmp_a og bmp_b. Koden fra før er nem at omskrive:

for (y=0; y<bmp_a.Height(); ++y) {
  for (x=0; x<bmp_a.Width(); ++x) {
    screen.SetPixel(x,y) = AlphaBlend(bmp_a.GetPixel(x,y), bmp_b.GetPixel(x,y), bmp_alpha.GetPixel(x,y));
  }
}

Nu er det jo bare sådan, at ovenstående kode er MEGET langsom i forhold til f.eks. en BitBlt. BitBlt har forskellige ROPCODEs som kan får blitteren til at behandle source-bitmap, dest-bitmap og pattern på forskellige måder. Mit spørgsmål er så:

Kan ovenstående laves med BitBlt?
Avatar billede soepro Nybegynder
10. september 2001 - 13:02 #3
Ok ... spændende !
Avatar billede moykal Nybegynder
14. september 2001 - 11:00 #4
Har selv leget lidt med det.... men fandt ud af at det var for besværligt. Check GDIPlus. Der er alt meget enklere.
Avatar billede alvion Nybegynder
14. september 2001 - 12:36 #5
moykal -> Det ser meget godt ud, men det supporteres jo kun af Win2k og fremefter...
Avatar billede alvion Nybegynder
10. oktober 2001 - 11:34 #6
Nå ingen svar...
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester