CreateImage with background alpha

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

CreateImage with background alpha

Post by kenmo »

Not an urgent request! Just please consider for convenience.

CreateImage() has a BackColor parameter, but currently:
- It only allows a 24-bit RGB color, or #PB_Image_Transparent = -1 (which makes black, with alpha=0 for 32-bit)
- If you pass RGBA to a 24-bit image, the Alpha is ignored (good!) unless it is 255 then it makes the color black (bad!)
- If you pass RGBA to a 32-bit image, the Alpha is ignored (inconvenient!)
- If you pass RGBA(255, 255, 255, 255) = -1, it makes a black image (transparent if 32-bit) instead of what the user might expect (opaque white) (see thread here)

Proposed change:
- 32-bit images use a 32-bit RGBA back color
- 24-bit images use a 24-bit RGB back color (if the user passes a RGBA value, Alpha is just ignored or masked out)
- #PB_Image_Transparent is set to RGBA(0, 0, 0, 0) = 0 (so it still creates a black, transparent background)

These changes would be backwards compatible except:
- In existing code that creates 32-bit images by passing a 24-bit BackColor...

Code: Select all

; in existing programs
CreateImage(... myColor)
; would have to become
CreateImage(... myColor | $FF000000)
; or
CreateImage(... Opaque(myColor))

Some example code for testing 24 and 32-bit CreateImage...

Code: Select all

UsePNGImageEncoder()

LoadFont(0, "Arial", 20)

Procedure TestImage(Path.s, Depth.i, BackColor.i)
  If CreateImage(0, 128, 128, Depth, BackColor)
    If StartDrawing(ImageOutput(0))
      DrawingFont(FontID(0))
      DrawingMode(#PB_2DDrawing_Transparent)
      DrawText(16, 16, Str(Depth) + "-bit", $FF0000)
      DrawText(16, 16 + TextHeight("0"), "a = " + Str(Alpha(BackColor)), $FF0000)
      StopDrawing()
    EndIf
    SaveImage(0,
        Path + Str(Depth) + "_" + RSet(Hex(BackColor, #PB_Long), 8, "0") + ".png",
        #PB_ImagePlugin_PNG)
    FreeImage(0)
  EndIf
EndProcedure

Path.s = GetTemporaryDirectory() + "CreateImage" + Right(GetTemporaryDirectory(), 1)
CreateDirectory(Path)
RunProgram(Path)

; Test 32-bit images
TestImage(Path, 32, RGBA($00, $FF, $80, $00)) ; green, 0 alpha
TestImage(Path, 32, RGBA($00, $FF, $80, $40)) ; green, 64 alpha
TestImage(Path, 32, RGBA($00, $FF, $80, $FF)) ; green, 255 alpha
TestImage(Path, 32, RGBA($FF, $FF, $FF, $00)) ; white, 0 alpha
TestImage(Path, 32, RGBA($FF, $FF, $FF, $40)) ; white, 64 alpha
TestImage(Path, 32, RGBA($FF, $FF, $FF, $FF)) ; white, 255 alpha

; Test 24-bit images
TestImage(Path, 24, RGBA($00, $FF, $80, $00)) ; green, 0 alpha
TestImage(Path, 24, RGBA($00, $FF, $80, $40)) ; green, 64 alpha
TestImage(Path, 24, RGBA($00, $FF, $80, $FF)) ; green, 255 alpha
TestImage(Path, 24, RGBA($FF, $FF, $FF, $00)) ; white, 0 alpha
TestImage(Path, 24, RGBA($FF, $FF, $FF, $40)) ; white, 64 alpha
TestImage(Path, 24, RGBA($FF, $FF, $FF, $FF)) ; white, 255 alpha
User avatar
kenmo
Addict
Addict
Posts: 2033
Joined: Tue Dec 23, 2003 3:54 am

Re: CreateImage with background alpha

Post by kenmo »

Of course, there are many workarounds such as drawing a simple RGBA background box:

Code: Select all

#PB_Image_TransparentEx = $00000000

Procedure.i Transparent(Color.i)
  ProcedureReturn (Color & $00FFFFFF)
EndProcedure

Procedure.i Opaque(Color.i)
  ProcedureReturn (Color | $FF000000)
EndProcedure

Procedure.i SetAlpha(Color.i, Alpha.i)
  ProcedureReturn ((Color & $00FFFFFF) | ((Alpha & $FF) << 24))
EndProcedure

Procedure.i CreateImageEx(Image.i, Width.i, Height.i, Depth.i = 32, BackColor.i = $FF000000)
  Protected Result.i 
  If (Depth = 24)
    BackColor = BackColor & $00FFFFFF
  EndIf
  Result = CreateImage(Image, Width, Height, Depth, BackColor)
  If (Result)
    If (Depth = 32)
      If (Image = #PB_Any)
        Image = Result
      EndIf
      If (StartDrawing(ImageOutput(Image)))
        DrawingMode(#PB_2DDrawing_AllChannels)
        Box(0, 0, Width, Height, BackColor)
        StopDrawing()
      EndIf
    EndIf
  EndIf
  ProcedureReturn (Result)
EndProcedure
Post Reply