L'intérêt ?
c'est de supprimer les bords noirs (bugs) qu'on peut avoir avec certaines images, par exemple lors d'un ResizeImage() ou avec un SaveImage() et la lib vectordrawing !
Voici le lien vers le code de Wilbert :
Voici son code (en ASM, donc hyper optimisé) :
Code : Tout sélectionner
DeclareModule Premultiply
; 32 bits RGBA or BGRA pixel buffer
Declare PremultiplyPixels(*PixelBuffer32, NumPixels)
Declare UnpremultiplyPixels(*PixelBuffer32, NumPixels)
EndDeclareModule
Module Premultiply
EnableASM
DisableDebugger
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rax : eax : EndMacro
Macro rbx : ebx : EndMacro
Macro rcx : ecx : EndMacro
Macro rdx : edx : EndMacro
Macro rsi : esi : EndMacro
CompilerEndIf
Procedure PremultiplyPixels(*PixelBuffer32, NumPixels)
lea rax, [premultiply.l_premultiplyTable]
mov rdx, *PixelBuffer32
mov rcx, NumPixels
push rbx
push rsi
mov rsi, rax
!premultiply.l_premul0:
movzx eax, word [rdx + 2]
cmp ah, 255
!je premultiply.l_premul1
movzx ebx, byte [rsi + rax]
mov [rdx + 2], bl
mov al, [rdx + 1]
movzx ebx, byte [rsi + rax]
mov [rdx + 1], bl
mov al, [rdx]
movzx ebx, byte [rsi + rax]
mov [rdx], bl
!premultiply.l_premul1:
add rdx, 4
sub rcx, 1
!jnz premultiply.l_premul0
pop rsi
pop rbx
EndProcedure
Procedure UnpremultiplyPixels(*PixelBuffer32, NumPixels)
lea rax, [premultiply.l_premultiplyTable + 0x10000]
mov rdx, *PixelBuffer32
mov rcx, NumPixels
push rbx
push rsi
mov rsi, rax
!premultiply.l_unpremul0:
movzx eax, word [rdx + 2]
cmp ah, 255
!je premultiply.l_unpremul1
cmp ah, 0
!je premultiply.l_unpremul1
movzx ebx, byte [rsi + rax]
mov [rdx + 2], bl
mov al, [rdx + 1]
movzx ebx, byte [rsi + rax]
mov [rdx + 1], bl
mov al, [rdx]
movzx ebx, byte [rsi + rax]
mov [rdx], bl
!premultiply.l_unpremul1:
add rdx, 4
sub rcx, 1
!jnz premultiply.l_unpremul0
pop rsi
pop rbx
EndProcedure
Procedure FillTable()
lea rdx, [premultiply.l_premultiplyTable]
push rbx
mov ebx, 255
sub ecx, ecx
!premultiply.l_filltable0:
movzx eax, ch
mul cl
add eax, 127
div bl
mov [rdx + rcx], al
add cx, 1
!jnz premultiply.l_filltable0
add rdx, 0x10000
mov ecx, 0x100
sub bx, bx
!premultiply.l_filltable1:
mov eax, 255
cmp cl, ch
!jae premultiply.l_filltable2
mul cl
add ax, bx
div ch
!premultiply.l_filltable2:
mov [rdx + rcx], al
add cl, 1
!jnz premultiply.l_filltable1
movzx bx, ch
add bx, 1
shr bx, 1
add ch, 1
!jnz premultiply.l_filltable1
pop rbx
EndProcedure
FillTable()
DataSection
!premultiply.l_premultiplyTable: times 131072 db 0
EndDataSection
EndModule
Code : Tout sélectionner
rocedure PreMultiplyAlpha(image)
StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
For y=0 To ImageHeight(image)-1
For x=0 To ImageWidth(image)-1
color = Point(x, y)
Plot(x, y, RGBA( (Red(color) * Alpha(color) + 127) /255, (Green(color) * Alpha(color) + 127) /255, (Blue(color) * Alpha(color) + 127) /255, Alpha(color)))
Next
Next
StopDrawing()
ProcedureReturn image
EndProcedure
Procedure UnPreMultiplyAlpha(image)
StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
For y=0 To ImageHeight(image)-1
For x=0 To ImageWidth(image)-1
color = Point(x, y)
alpha = Alpha(color)
If alpha=0 : alpha=1 : EndIf
Plot(x, y, RGBA( (255 * Red(color) + (Alpha(color) /2)) /alpha, (255 * Green(color) + (Alpha(color) /2)) /alpha, (255 * Blue(color) + (Alpha(color) /2)) /alpha, Alpha(color)))
Next
Next
StopDrawing()
ProcedureReturn image
EndProcedure
Un de mes anciens codes qui montrait le bug des images prémultipliées créées avec la lib vectordrawing :
Code : Tout sélectionner
; infos : to see the bug with vector drawing saving, now fixed with premultiply procedure :) (code de 2015)
Procedure PreMultiplyAlpha(image)
If StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
For y=0 To ImageHeight(image)-1
For x=0 To ImageWidth(image)-1
color = Point(x, y)
Plot(x, y, RGBA( (Red(color) * Alpha(color) + 127) /255, (Green(color) * Alpha(color) + 127) /255, (Blue(color) * Alpha(color) + 127) /255, Alpha(color)))
Next
Next
StopDrawing()
EndIf
ProcedureReturn image
EndProcedure
Procedure UnPreMultiplyAlpha(image)
If StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
For y=0 To ImageHeight(image)-1
For x=0 To ImageWidth(image)-1
color = Point(x, y)
alpha = Alpha(color)
If alpha=0 : alpha=1 : EndIf
Plot(x, y, RGBA( (255 * Red(color) + (Alpha(color) /2)) /alpha, (255 * Green(color) + (Alpha(color) /2)) /alpha, (255 * Blue(color) + (Alpha(color) /2)) /alpha, Alpha(color)))
Next
Next
StopDrawing()
EndIf
ProcedureReturn image
EndProcedure
Procedure DrawVector()
AddPathCircle(75, 100, 60)
VectorSourceColor(RGBA(255, 240, 200, 255))
FillPath()
AddPathCircle(125, 100, 60)
VectorSourceColor(RGBA(210, 250, 255, 207))
FillPath()
; Dessin opaque sur une couche semi-transparente
BeginVectorLayer(240)
AddPathCircle(275, 100, 60)
VectorSourceColor(RGBA(255, 240, 240, 255))
FillPath()
AddPathCircle(325, 100, 60)
VectorSourceColor(RGBA(200,255, 240, 255))
FillPath()
EndVectorLayer()
EndProcedure
UsePNGImageEncoder()
UsePNGImageDecoder()
If OpenWindow(0, 0, 0, 400, 400, "VectorDrawing", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 0, 0, 400, 420)
; first, we save an image in vectordrawing
If CreateImage(0, GadgetWidth(0), GadgetHeight(0), 32,#PB_Image_Transparent)
; same with or without those line
; --- you can comment those lines, but the result is the same.
If StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AllChannels)
Box(0,0,GadgetWidth(0),GadgetHeight(0),RGBA(0,0,0,0))
StopDrawing()
EndIf
; -----
If StartVectorDrawing(ImageVectorOutput(0))
DrawVector()
StopVectorDrawing()
EndIf
file$ = "image09E9E8Z7.png"
; tempimg = UnPreMultiplyAlpha(0) ; <----------------------- uncomment this line to see the good result !
If SaveImage(tempimg, File$, #PB_ImagePlugin_PNG) = 0
MessageRequester("CanvasGadget", "Cannot save image: " + File$)
EndIf
FreeImage(0)
; the load the image saved, to see the result
If LoadImage(0, file$)
EndIf
EndIf
; the we draw the 2 images : the vectordrawing and the loaded image :
If StartVectorDrawing(CanvasVectorOutput(0))
DrawVector()
MovePathCursor(0, 210)
DrawVectorImage(ImageID(0))
StopVectorDrawing()
EndIf
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
DeleteFile( file$)
EndIf
- bug avec ResizeImage()
- bug avec SaveImage() via la lib vectordrawing
etc...
J'espère que ça sera utile à certains d'entre vous .
Pour moi, avoir trouvé cette procédure, ça me corrige des bugs dans 4 de mes logiciels de création d'images ^^ (qui me sortaient parfois des images avec un bord noir.
A+ les amis