Code archives/Graphics/Ultra Fast Draw Pixmap on Pixmap
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This is the fastest method I could come up with to draw a pixmap onto another pixmap. On a 2.4Ghz its about 7-8ms for 1000x1000px per pixmap (no debug). (ReadPixel and WritePixel are a little slower than using this direct memory method.) The caveats are you are using only RGBA, and you are plotting a source alpha pixmap onto a static alpha-ignored pixmap. It's best to convert RGBA before sending your pixmaps to this function. Additionally, this is unmultiplied alpha. If anyone needs multiplied alpha, I can offer some code assistance (may be even faster). Added an x,y offset and opacity when applying the source pixmap to destination. Big thanks to ImaginaryHuman for starting this out. Optimized alpha-blending code found on various places with Google. Edit: use at your own risk, but let me know if there are problems, I'd be happy to help. Also, I experienced a wrap-around defect or large vaules of x offset, but easily fixed-- but let me know if anyone gets this problem. | |||||
Function UltraDrawPixmapOnPixmap(spix:TPixmap, pixmap:TPixmap, x:Int, y:Int, opacity:Int = $ff) NoDebug '' if your pixmaps are rgba8888 then it will work faster '' ARGB is byte order '' non-multiplied alpha Local sourcepixel:Int Ptr, osp:Int Ptr Local destpixel:Int Ptr, dsp:Int Ptr Local sAlpha:Int If (Not spix Or Not pixmap) Then Return If spix.format<>PF_RGBA8888 spix = ConvertPixmap(spix, PF_RGBA8888 ) If pixmap.format<>PF_RGBA8888 pixmap = ConvertPixmap(pixmap, PF_RGBA8888 ) Local sWidth:Int=spix.Width Local sHeight:Int=spix.Height Local dWidth:Int=pixmap.Width Local dHeight:Int=pixmap.Height sourcepixel=Int Ptr(PixmapPixelPtr(spix,0,0)) destpixel=Int Ptr(PixmapPixelPtr(pixmap,0,0)) Local sRowInts:Int= spix.pitch Shr 2 '' 4 bytes to int Local dRowInts:Int= pixmap.pitch Shr 2 ''crop the image If ( (x+sWidth)>=dWidth) Then sWidth=dWidth-x '-2 'if you get wraparound issues If ( (y+sHeight)>=dHeight) Then sHeight=dHeight-y If(y<0) y = Abs(y) sourcepixel :+(y*sRowInts) sHeight :-y y=0 EndIf If(x<0) sourcepixel :+(-x) sWidth :+x x=0 EndIf destpixel = destpixel + x +(y*dRowInts) dsp = destpixel osp = sourcepixel Local Mask:Int=$000000FF For Local j:Int=0 To (sHeight) For Local i:Int =0 To (sWidth) Step 2 'dRowInts Local sPixel:Int sPixel = sourcepixel[i] sAlpha=(sPixel Shr 24) & $000000ff & opacity Local dPixel:Int = destpixel[i] ''''straight alpha (unmultiplied) 'Local dAlpha:Int = dPixel Shr 24 & Mask ''untested: alpha onto alpha 'Local fa:Int = sAlpha + ((256-sAlpha)*dAlpha) Shr 8 ''untested: alpha onto alpha Local srb:Int = sPixel & $00ff00ff Local sg:Int = sPixel & $0000ff00 Local drb:Int = dPixel & $00ff00ff Local dg:Int = dPixel & $0000ff00 Local orb:Int = (drb + (((srb - drb) * sAlpha + $00800080) Shr 8)) & $00ff00ff Local og:Int = (dg + (((sg - dg ) * sAlpha + $00008000) Shr 8)) & $0000ff00 destPixel[i] = orb | og | $ff000000 ''no need for alpha blending if its on static bg ''lets do it again If ( i >= dWidth And (sWidth & 1)) ''odd length, dont draw Else sPixel = sourcepixel[i+1] sAlpha=(sPixel Shr 24) & $000000ff & opacity dPixel:Int = destpixel[i+1] srb:Int = sPixel & $00ff00ff sg:Int = sPixel & $0000ff00 drb:Int = dPixel & $00ff00ff dg:Int = dPixel & $0000ff00 orb:Int = (drb + (((srb - drb) * sAlpha + $00800080) Shr 8)) & $00ff00ff og:Int = (dg + (((sg - dg ) * sAlpha + $00008000) Shr 8)) & $0000ff00 destPixel[i+1] = orb | og | $ff000000 EndIf Next sourcepixel= osp + sRowInts*j ''need these to truncate off any extra bytes destpixel = dsp + dRowInts*j Next End Function |
Comments
None.
Code Archives Forum