Mutta sitten Niko taas laittoi koodia minulle ja kyseli, että miksi ei toimi. Muuttujat olivat sellaisia, että en tajunnut koodista mitään. Sain kuitenkin Nikolta blendaukseen tarvittavan koodin (pikselimanipulaation) sekä idean kahdesta kuvasta. En kuitenkaan pitänyt Nikon (mielestäni) tökeröstä tavasta tallentaa alpha blendattu kuva käsittelyn jälkeen ja ladata se uudestaan (ainakin näin koodin tulkitsin). Mutta nyt kaikki ideat oli kasassa, ja siitä se ajatus sitten lähti!
Eli tekemäni kaksi funktiota mahdollistavat portaattoman alpha blendauksen. Siihen tarvitaan kaksi kuvaa: blendattava, aivan tavallinen kuva SEKÄ mustavalkoinen blendattavan kuvan kokoinen alpha-arvot sisältävä kuva. Tässä "alpha-kuvassa" musta on täysin läpinäkyvä ja valkoinen on täysin näkyvä pikseli. Seuraavassa funtioiden esittelyt:
Code: Select all
// lataa alpha blendattavan kuvan muistiin ja palauttaa osoittiminen kuvamuuttujaan
' image = luodun alpha blendatun kuvan indeksi
' imagePath$ = blendattavan kuvan polku
' alphaPath$ = alpha-kanavat sisältävän kuvan polku
image = LoadABImage(imagePath$, alphaPath$)
// piirtää muistiin ladatun blendattavan kuvan haluttuihin koordinaatteihin
' img = piirrettävä kuva, ladattu funktiolla "LoadABImage"
' x = x-koordinaatti näytöllä
' y = y-koordinaatti näytöllä
DrawABImage(img, x, y)
// luo muistiin uuden alpha blendatun imagen jo ohjelmaan ladatuista TAVALLISISTA kuvista (eli ei siis ab-kuvista)
' sImg = alpha blendattava kuva
' aImg = alpha-kanavan sisältävä kuva
img = MakeABImage(sImg, aImg)
// palauttaa AB-kuvan (HUOM! vain AB-kuva) leveyden
ABImageWidth(img)
// palauttaa AB-kuvan (HUOM! vain AB-kuva) korkeuden
ABImageHeight(img)
Code: Select all
// *********************** AlphaBlended Image ******************************
// *********************** (c) Matti 'Dibalo' Lankinen *********************
Const cMAX_AB_DATA = 400000 // maksimimäärä pikseleitä, joihin voidaan ladata alpha-tietoa
Const cMAX_AB_IMAGES = 100 // maksimimäärä alpha-blendattuja kuvia
// kuvien data taulukossa (1-3 = RGB, 0 = alpha)
Dim AB_IMAGE_DATA(cMAX_AB_DATA, 3) As Byte
// datan sijainti kuvassa (0 = x, 1 = y)
Dim AB_IMAGE_DATA_POS(cMAX_AB_DATA,1) As Short
// tärkeät tiedot AB-kuvista, luetaan indeksiluvulla
// jonka LoadABImage() luo
' 0 = sijainti IMAGE_DATASSA
' 1 = pointteri non-alpha kuvaan
' 2 = kuvan koko
Dim AB_IMAGE_INFO(cMAX_AB_IMAGES,2)
Global pImageCount // laskuri kuinka monta alpha-kuvaa on luotu
Global imageDataPointer // laskuri missä kohtaa on viimeinen kirjoitettu alpha-kuvan data
pImageCount = 0
imageDataPointer = 0
//////////////////////////////////////////////////////////////////
Function LoadABImage(imagePath$, alphaPath$)
sImg = LoadImage(imagePath) // stantardi image (ilman a-kanavaa)
aImg = LoadImage(alphaPath) // kuva, joka sisältää a-kanavan (mustavalkoinen)
iW = ImageWidth(sImg)
iH = ImageHeight(sImg)
// tarkistetaan, onko alpha blendaus mahdollista
If ImageWidth(aImg) <> iW Or ImageHeight(aImg) <> iH Then MakeError "Image sizes don´t match!"
AB_IMAGE_INFO(pImageCount,0) = imageDataPointer
AB_IMAGE_INFO(pImageCount,1) = sImg
pCount = 0
For x = 0 To iW-1
For y = 0 To iH-1
Lock Image(sImg)
p1 = GetPixel2(x, y, Image(sImg))
Unlock Image(sImg)
Lock Image(aImg)
a = ((GetPixel2(x, y, Image(aImg)) Shl 8) Shr 24)
Unlock Image(aImg)
p1R = ((p1 Shl 8) Shr 24)
p1G = ((p1 Shl 16) Shr 24)
p1B = ((p1 Shl 24) Shr 24)
If p1R Or p1G Or p1B Then
Lock Image(sImg)
If a And a <> 255 Then
AB_IMAGE_DATA(imageDataPointer, 0) = a
AB_IMAGE_DATA(imageDataPointer, 1) = p1R
AB_IMAGE_DATA(imageDataPointer, 2) = p1G
AB_IMAGE_DATA(imageDataPointer, 3) = p1B
AB_IMAGE_DATA_POS(imageDataPointer, 0) = x
AB_IMAGE_DATA_POS(imageDataPointer, 1) = y
pCount+1
imageDataPointer+1
PutPixel2 x, y, (0 + (0 Shl 8) + (0 Shl 16) + (255 Shl 24)), Image(sImg)
EndIf
If a = 0 Then PutPixel x, y, (0 + (0 Shl 8) + (0 Shl 16) + (255 Shl 24)), Image(sImg)
Unlock Image(sImg)
EndIf
Next y
Next x
AB_IMAGE_INFO(pImageCount,2) = pCount
pImageCount+1
DeleteImage aImg
Return (pImageCount-1)
End Function
///////////////////////////////////////////
Function DrawABImage(img, x, y)
DrawImage AB_IMAGE_INFO(img, 1), x, y
sW = ScreenWidth()
sH = ScreenHeight()
Lock SCREEN()
For i = AB_IMAGE_INFO(img,0) To AB_IMAGE_INFO(img,0)+AB_IMAGE_INFO(img,2)
xx = AB_IMAGE_DATA_POS(i,0)+x
yy = AB_IMAGE_DATA_POS(i,1)+y
If 0 =< xx And xx <= sW And 0 <= yy And yy <= sH Then
p = GetPixel2( xx, yy)
pros# = AB_IMAGE_DATA(i,0) / 255.0
bR = ((p Shl 8) Shr 24)
bG = ((p Shl 16) Shr 24)
bB = ((p Shl 24) Shr 24)
PutPixel2 xx, yy, (Int(bB+((AB_IMAGE_DATA(i,3)-bB)*pros)) + (Int(bG+((AB_IMAGE_DATA(i,2)-bG)*pros)) Shl 8) + (Int(bR+((AB_IMAGE_DATA(i,1)-bR)*pros)) Shl 16) + (255 Shl 24))
EndIf
Next i
Unlock SCREEN()
End Function
Ja sitten pieni esimerkkikoodi. Muistattehan ladata alla olevat mediat.
Code: Select all
SCREEN 640,480,0
Include "ABImage.cb"
ClsColor 255,255,255
Cls
img = LoadABImage("face_original.png", "face_alpha.png")
Repeat
DrawABImage(img, MouseX(), MouseY())
DrawScreen
Forever