I think the problem is how PB creates a GDI Plus bitmap from a HBITMAP, because using the api directly works as expected but implies some hacking replacing the pb gdi plus graphics context.
Both examples fixed:
pjay:
Code: Select all
; Adjust pre-multiplied alpha to true Alpha to resolve edge fringing with VDL - PJ 2022.
; - Limited to images with single FG/BG colours - [2024 -> moved to PUDL solution]
EnableExplicit
Import "gdiplus.lib"
GdipCreateBitmapFromScan0(width.l, height.l, stride.l, format.l, scan0.i, bitmap.i)
GdipGetImageGraphicsContext(image.i, graphics.i)
GdipSetSmoothingMode(graphics.i, smoothingMode.l)
GdipDeleteGraphics(graphics.i)
EndImport
;Some pixel formats
#PixelFormatGDI = $00020000
#PixelFormatAlpha = $00040000
#PixelFormatCanonical = $00200000
#PixelFormat24bppRGB = (8 | (24 << 8) | #PixelFormatGDI)
#PixelFormat32bppARGB = (10 | (32 << 8) | #PixelFormatAlpha | #PixelFormatGDI | #PixelFormatCanonical)
;- enum QualityMode
#QualityModeInvalid = -1
#QualityModeDefault = 0
#QualityModeLow = 1 ; Best performance
#QualityModeHigh = 2 ; Best rendering quality
;- enum SmoothingMode
Enumeration
#SmoothingModeInvalid = #QualityModeInvalid
#SmoothingModeDefault = #QualityModeDefault
#SmoothingModeHighSpeed = #QualityModeLow
#SmoothingModeHighQuality = #QualityModeHigh
#SmoothingModeNone
#SmoothingModeAntiAlias
#SmoothingModeAntiAlias8x4 = #SmoothingModeAntiAlias
#SmoothingModeAntiAlias8x8
EndEnumeration
;Creates a gdip bitmap from an hbitmap
Procedure.i gdp_image_from_hbitmap(hbm.i)
Protected.BITMAP bmp
Protected.i gdpBmp
Protected.i dataSize, scan0
Protected.l pixelFormat
GetObject_(hbm, SizeOf(BITMAP), @bmp.BITMAP)
Select bmp\bmBitsPixel
Case 24 : pixelFormat = #PixelFormat24bppRGB
Case 32 : pixelFormat = #PixelFormat32bppARGB
Default : pixelFormat = #PixelFormat32bppARGB
EndSelect
;First scanline is the last in bmBits (bottom to top).
dataSize = (bmp\bmWidthBytes) * bmp\bmHeight
scan0 = bmp\bmBits + dataSize - (bmp\bmWidthBytes)
GdipCreateBitmapFromScan0(bmp\bmWidth, bmp\bmHeight, -bmp\bmWidthBytes, pixelFormat, scan0, @gdpBmp)
ProcedureReturn gdpBmp
EndProcedure
Enumeration ;/ window
#MyWin_Main
EndEnumeration
Enumeration ;/ gadgets
#myGad_Canvas
EndEnumeration
Enumeration ;/ images
#MyImg_Main_Standard
#MyImg_Main_White
#MyImg_Main_Corrected
EndEnumeration
Global myFG.l = RGBA(127,127,127,255)
Global myBg.l = RGBA(0,0,0,0) ; = #PB_Image_Transparent
Procedure Image_CorrectAlpha(img.i, fgCol.i, bgCol.i = -1) ; calculate & correct alpha value for layered drawing
Protected.l x.l, y.l, p.l, r1.a = Red(fgCol), g1.a = Green(fgCol), b1.a = Blue(fgCol), r2.a, g2.a, b2.a
StartDrawing(ImageOutput(img)) : DrawingMode(#PB_2DDrawing_AllChannels)
For y = 0 To OutputHeight() - 1
For x = 0 To OutputWidth() - 1 : p = Point(x,y)
If p <> fgCol And p <> bgCol ; we're in an alpha area, calculate the alpha value based on distance from fgCol...
r2 = Red(p) : g2 = Green(p) : b2 = Blue(p)
Plot(x,y,RGBA(r1, g1, b1, 255.0 * (1.0 - (Sqr((r2-r1) * (r2-r1) + (g2-g1) * (g2-g1) + (b2-b1) * (b2-b1)) / 441.6729559))))
EndIf
Next
Next
StopDrawing()
EndProcedure
#Size = 128 : #hSize = #Size * 0.5
Procedure Init_Main()
Protected.i x, hbm, img, svd, old_gc, gc
CreateImage(#MyImg_Main_Standard, #size, #size, 32, #PB_Image_Transparent)
CreateImage(#MyImg_Main_White, #size, #size, 32, #PB_Image_Transparent)
StartVectorDrawing(ImageVectorOutput(#MyImg_Main_Standard))
VectorSourceColor(myFG) : AddPathCircle(#Size * 0.5, #Size * 0.5, #Size * 0.475) : FillPath()
StopVectorDrawing()
; If StartDrawing(ImageOutput(#MyImg_Main_White))
; DrawingMode(#PB_2DDrawing_AllChannels)
; Box(0,0,OutputWidth(),OutputHeight(),RGBA(255,255,255,0))
; StopDrawing()
; EndIf
;Create a gdip bitmap from a pb image
hbm = ImageID(#MyImg_Main_White)
img = gdp_image_from_hbitmap(hbm)
svd = StartVectorDrawing(ImageVectorOutput(#MyImg_Main_White))
;Delete the old graphics context
old_gc = PeekI(svd)
GdipDeleteGraphics(old_gc)
;Create new graphics context based on gdip bitmap
GdipGetImageGraphicsContext(img, @gc)
GdipSetSmoothingMode(gc, #SmoothingModeHighQuality)
;Set our new graphics context
PokeI(svd, gc)
VectorSourceColor(myFG) : AddPathCircle(#Size * 0.5, #Size * 0.5, #Size * 0.475) : FillPath()
StopVectorDrawing()
;/ create a copy of the main image & apply the alpha correction:
CopyImage(#MyImg_Main_Standard, #MyImg_Main_Corrected)
Image_CorrectAlpha(#MyImg_Main_Corrected, myFG, myBG)
#Width = 1024 : #Height = 768
OpenWindow(#myWin_Main, 0, 0, #width / DesktopResolutionX(), #height / DesktopResolutionY(), "Fix for Edge fringing of VDL Image - PJ2022", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(#myGad_Canvas,0,0,#Width, #Height)
StartDrawing(CanvasOutput(#myGad_Canvas))
Box(0,0,OutputWidth(),OutputHeight(),#Black)
DrawingMode(#PB_2DDrawing_AlphaBlend)
RandomSeed(0) : For x = 1 To 100 : DrawImage(ImageID(#MyImg_Main_Standard),Random(#Width * 0.2), Random(#Height - #Size)) : Next
DrawText(0, 0," Standard (#PB_Image_Transparent) ")
DrawText(0, 20," - Get Dark Fringing ")
RandomSeed(0) : For x = 1 To 100 : DrawImage(ImageID(#MyImg_Main_White), (#Width * 0.333) + Random(#Width * 0.2), Random(#Height - #size)) : Next
DrawText(#Width * 0.333, 0, " GDI PLUS API")
DrawText(#Width * 0.333, 20, " - No Fringing ")
RandomSeed(0) : For x = 1 To 100 : DrawImage(ImageID(#MyImg_Main_Corrected), (#Width * 0.666) + Random(#Width * 0.2), Random(#Height - #size)) : Next
DrawText(#Width * 0.666, 0, " Alpha Corrected ")
DrawText(#Width * 0.666, 20, " No fringing ")
StopDrawing()
EndProcedure
Init_Main()
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Taz:
Code: Select all
EnableExplicit
Import "gdiplus.lib"
GdipCreateBitmapFromScan0(width.l, height.l, stride.l, format.l, scan0.i, bitmap.i)
GdipGetImageGraphicsContext(image.i, graphics.i)
GdipSetSmoothingMode(graphics.i, smoothingMode.l)
GdipDeleteGraphics(graphics.i)
EndImport
;Some pixel formats
#PixelFormatGDI = $00020000
#PixelFormatAlpha = $00040000
#PixelFormatCanonical = $00200000
#PixelFormat24bppRGB = (8 | (24 << 8) | #PixelFormatGDI)
#PixelFormat32bppARGB = (10 | (32 << 8) | #PixelFormatAlpha | #PixelFormatGDI | #PixelFormatCanonical)
;- enum QualityMode
#QualityModeInvalid = -1
#QualityModeDefault = 0
#QualityModeLow = 1 ; Best performance
#QualityModeHigh = 2 ; Best rendering quality
;- enum SmoothingMode
Enumeration
#SmoothingModeInvalid = #QualityModeInvalid
#SmoothingModeDefault = #QualityModeDefault
#SmoothingModeHighSpeed = #QualityModeLow
#SmoothingModeHighQuality = #QualityModeHigh
#SmoothingModeNone
#SmoothingModeAntiAlias
#SmoothingModeAntiAlias8x4 = #SmoothingModeAntiAlias
#SmoothingModeAntiAlias8x8
EndEnumeration
;Creates a gdip bitmap from an hbitmap
Procedure.i gdp_image_from_hbitmap(hbm.i)
Protected.BITMAP bmp
Protected.i gdpBmp
Protected.i dataSize, scan0
Protected.l pixelFormat
GetObject_(hbm, SizeOf(BITMAP), @bmp.BITMAP)
Select bmp\bmBitsPixel
Case 24 : pixelFormat = #PixelFormat24bppRGB
Case 32 : pixelFormat = #PixelFormat32bppARGB
Default : pixelFormat = #PixelFormat32bppARGB
EndSelect
;First scanline is the last in bmBits (bottom to top).
dataSize = (bmp\bmWidthBytes) * bmp\bmHeight
scan0 = bmp\bmBits + dataSize - (bmp\bmWidthBytes)
GdipCreateBitmapFromScan0(bmp\bmWidth, bmp\bmHeight, -bmp\bmWidthBytes, pixelFormat, scan0, @gdpBmp)
ProcedureReturn gdpBmp
EndProcedure
Enumeration
#WIN
#TEXT_CANVAS
#CANVAS
#TEXT_IMAGE
#IMAGE
#TEXT_IMAGE_BG
#IMAGE_WIDTH_BACKGROUND
#IMG_VIEW
#IMG_VIEW_WITH_BG
EndEnumeration
Global width = 600, height = 495, shapeW = 500, shapeH = 100, labelHeight = 25
Procedure _DrawContent(outputW, outputH, fillBackground.b)
Protected x = (outputW - shapeW) / 2
Protected y = (outputH - shapeH) / 2
If fillBackground
VectorSourceColor(RGBA(255, 255, 255, 255))
AddPathBox(0, 0, outputW, outputH)
FillPath()
EndIf
VectorSourceColor(RGBA(173, 209, 243, 100))
MovePathCursor(x + 40, y + 100 - 1)
AddPathArc(x + shapeW, y , x + shapeW, y + shapeH, 40)
AddPathArc(x + shapeW, y + shapeH, x , y + shapeH, 40)
AddPathArc(x , y + shapeH, x , y , 40)
AddPathArc(x , y , x + 40 , y , 40)
ClosePath()
FillPath()
EndProcedure
; Draws onto Canvas or Image, optionally with background fill
Procedure DrawRoundedRect(mode.i, fillBackground = #False)
Protected h = (height - labelHeight * 3) / 3
Select mode
Case #CANVAS
If StartVectorDrawing(CanvasVectorOutput(#CANVAS))
_DrawContent(width, h, fillBackground)
StopVectorDrawing()
EndIf
Case #IMAGE
Protected.i hbm, img, old_gc, gc, svd
If CreateImage(#IMAGE, width, h, 32, #PB_Image_Transparent)
;Create a gdip bitmap from a pb image
hbm = ImageID(#IMAGE)
img = gdp_image_from_hbitmap(hbm)
svd = StartVectorDrawing(ImageVectorOutput(#IMAGE))
If svd
;Delete the old graphics context
old_gc = PeekI(svd)
GdipDeleteGraphics(old_gc)
;Create new graphics context based on gdip bitmap
GdipGetImageGraphicsContext(img, @gc)
GdipSetSmoothingMode(gc, #SmoothingModeHighQuality)
;Set our new graphics context
PokeI(svd, gc)
_DrawContent(width, h, fillBackground)
StopVectorDrawing() ;We assume deletes the new graphics context
EndIf
EndIf
Case #IMAGE_WIDTH_BACKGROUND
If CreateImage(#IMAGE_WIDTH_BACKGROUND, width, h, 32, #PB_Image_Transparent)
If StartVectorDrawing(ImageVectorOutput(#IMAGE_WIDTH_BACKGROUND))
_DrawContent(width, h, fillBackground)
StopVectorDrawing()
EndIf
EndIf
EndSelect
EndProcedure
; Opens window with 3 stacked rendering comparisons
Procedure _Example()
Protected y, rowHeight = (height - labelHeight * 3) / 3
If OpenWindow(#WIN, 0, 0, width, height, "Rendering Comparison", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TextGadget(#TEXT_CANVAS, 0, y, width, labelHeight, "CanvasVectorOutput(#CANVAS)", #PB_Text_Center)
y + labelHeight: CanvasGadget(#CANVAS, 0, y, width, rowHeight): y + rowHeight
TextGadget(#TEXT_IMAGE, 0, y, width, labelHeight, "ImageVectorOutput(#IMAGE) without background", #PB_Text_Center)
y + labelHeight: ImageGadget(#IMG_VIEW, 0, y, width, rowHeight, 0): y + rowHeight
TextGadget(#TEXT_IMAGE_BG, 0, y, width, labelHeight, "ImageVectorOutput(#IMAGE_WIDTH_BACKGROUND)", #PB_Text_Center)
y + labelHeight: ImageGadget(#IMG_VIEW_WITH_BG, 0, y, width, rowHeight, 0)
; Render content
DrawRoundedRect(#CANVAS)
DrawRoundedRect(#IMAGE)
DrawRoundedRect(#IMAGE_WIDTH_BACKGROUND, #True)
; Set image gadgets
SetGadgetState(#IMG_VIEW, ImageID(#IMAGE))
SetGadgetState(#IMG_VIEW_WITH_BG, ImageID(#IMAGE_WIDTH_BACKGROUND))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow: Break
EndSelect
ForEver
EndIf
EndProcedure
_Example()