Combining Red, Green and Blue parts of an image in PB.

Just starting out? Need help? Post your questions and find answers here.
matalog
Enthusiast
Enthusiast
Posts: 165
Joined: Tue Sep 05, 2017 10:07 am

Combining Red, Green and Blue parts of an image in PB.

Post by matalog »

Would PB allow you to have Red, Green and Blue images and stack them on top of each other in what Photoshop calls Screen blending mode (or lighten) to result in an image with its RGB elements being taken from the 3 images and ending up on one image?

This is the technique that NASA use to colour black and white images from space, that have been taken with colour filters.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8433
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Combining Red, Green and Blue parts of an image in PB.

Post by netmaestro »

Start with a transparent image and draw each image on it in succession using 2DDrawingMode #PB_2DDrawing_AlphaBlend and see what you end up with.
BERESHEIT
User avatar
STARGÅTE
Addict
Addict
Posts: 2084
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: Combining Red, Green and Blue parts of an image in PB.

Post by STARGÅTE »

You can use the CustomFilterCallback() for this drawing.
In your custom filter callback you can extract the color channel (R, G, B) from the source image and insert them in the final result as you can see in the example in the documentation.

Code: Select all

Procedure FilterCallback(x, y, SourceColor, TargetColor)
  ; Take only the Red component from the Source, do not modify the others
  ProcedureReturn RGBA(Red(SourceColor), Green(TargetColor), Blue(TargetColor), Alpha(TargetColor))
EndProcedure
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
User avatar
Demivec
Addict
Addict
Posts: 4090
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Combining Red, Green and Blue parts of an image in PB.

Post by Demivec »

Here's a demo of the technique STARGÅTE suggested:

Code: Select all

;Project Name: RGB Image combine Demo
;Author: Demivec
;Created: 10/11/2021
;Version: v1.00
;Compiler: PureBasic v5.73 LTS x64
;License: Free to use, abuse or modify.
;Forum: https://www.purebasic.fr/english/viewtopic.php?p=575766#p575766
;Description: Creates three images containing separate data for blue, red or
;  green elements only and then creates a composite of them.  The composite
;  is displayed along with thumbnails of the source images.  The source images
;  are purposely generated to resemble images of star clusters.

EnableExplicit
InitSprite()

#iw = 600 ;test image width & height
#ih = 600
#soCount = 100000 ;object count

Enumeration windows
  #win_main
EndEnumeration

Enumeration gadgets
  #g_composite_img
EndEnumeration

Enumeration images
  #img_composite
  #img_blueFilter
  #img_greenFilter
  #img_redFilter
EndEnumeration

Enumeration menu
  #men_exitProgram
  #men_generateImage
EndEnumeration

Procedure fc_merge_red(x, y, SourceColor, TargetColor)
  ; Take only the Red component from the Source, do not modify the others
  ProcedureReturn RGBA(Red(SourceColor), Green(TargetColor), Blue(TargetColor), Alpha(TargetColor))
EndProcedure

Procedure fc_merge_blue(x, y, SourceColor, TargetColor)
  ; Take only the Blue component from the Source, do not modify the others
  ProcedureReturn RGBA(Red(TargetColor), Green(TargetColor), Blue(SourceColor), Alpha(TargetColor))
EndProcedure

Procedure fc_merge_green(x, y, SourceColor, TargetColor)
  ; Take only the Green component from the Source, do not modify the others
  ProcedureReturn RGBA(Red(TargetColor), Green(SourceColor), Blue(TargetColor), Alpha(TargetColor))
EndProcedure

Procedure fc_random_alpha(x, y, SourceColor, TargetColor)
  ;vary value for each pixel drawn as a pseudo alpha
  ProcedureReturn RGBA(Red(SourceColor) * Random(255, 1), Green(SourceColor) * Random(255, 1), Blue(SourceColor) * Random(255, 1), Alpha(TargetColor))
EndProcedure

OpenWindow(#win_main, 0, 0, #iw, #ih + (#ih / 3), "RGB Image combine Demo; [Space} to generate new image, [Esc] to exit", #PB_Window_SystemMenu)

CreateImage(#img_composite, #iw, #ih + (#ih / 3), 32)

ImageGadget(#g_composite_img, 0, 0, #iw, #ih, ImageID(#img_composite))

Procedure generate_data()
  ;random data
  Protected x, y, attraction.f, radius, r, ang.f, i
  Dim sc(#soCount, 3) ;x, y, r
  
  x = Random(#iw - 20, 20)
  y = Random(#ih - 20, 20)
  attraction = 3
  radius = Random(#iw / 8, 20)
  For i = 1 To #soCount
    ang = Random(360)
    If Random(#soCount / 5) = 0
      x = Random(#iw - 20, 20)
      y = Random(#ih - 20, 20)
      attraction = Random(8, 1) / 2
    EndIf
    radius = Random(#iw / 8, 1)
    
    r = Pow(Random(10), attraction) * radius
    sc(i, 1) = x + r * Cos(Radian(ang)) ;x
    sc(i, 2) = y + r * Sin(Radian(ang)) ;y 
    sc(i, 3) = Random(#iw / (Random(100, 40))) ;radius
  Next
  
  CreateImage(#img_redFilter, #iw, #ih, 32)
  CreateImage(#img_greenFilter, #iw, #ih, 32)
  CreateImage(#img_blueFilter, #iw, #ih, 32)
  
  StartDrawing(ImageOutput(#img_composite))
    Box(0, 0, OutputWidth(), OutputHeight(), RGB(0, 0, 0))
  StopDrawing()
    
    
  ;use generated data to create filtered images
  StartDrawing(ImageOutput(#img_blueFilter))
    For i = 1 To #soCount
      DrawingMode(#PB_2DDrawing_CustomFilter)
      CustomFilterCallback(@fc_random_alpha())
      Circle(sc(i, 1), sc(i, 2), sc(i, 3) * 0.25, RGB(0, 0, 1))
      i + Random(2, 1)
    Next
  StopDrawing()
  
  StartDrawing(ImageOutput(#img_greenFilter))
    For i = 1 To #soCount
      DrawingMode(#PB_2DDrawing_CustomFilter)
      CustomFilterCallback(@fc_random_alpha())
      Circle(sc(i, 1), sc(i, 2), sc(i, 3) * 1, RGB(0, 1, 0))
      i + Random(8, 4)
    Next
  StopDrawing()
  
  StartDrawing(ImageOutput(#img_redFilter))
    For i = 1 To #soCount
      DrawingMode(#PB_2DDrawing_CustomFilter)
      CustomFilterCallback(@fc_random_alpha())
      Circle(sc(i, 1), sc(i, 2), sc(i, 3) * 1.25 , RGB(1, 0, 0))
      i + Random(12, 6)
    Next
  StopDrawing()
  
  ;combine images for display
  StartDrawing(ImageOutput(#img_composite))
    DrawingMode(#PB_2DDrawing_CustomFilter)
    For i = #img_blueFilter To #img_redFilter
      Select i
        Case 1: CustomFilterCallback(@fc_merge_blue())
        Case 2: CustomFilterCallback(@fc_merge_green())
        Case 3: CustomFilterCallback(@fc_merge_red())
      EndSelect
      
      DrawImage(ImageID(i), 0, 0)
    Next
    
    ;draw thumbnails of filters
    DrawingMode(#PB_2DDrawing_Default)
    For i = #img_blueFilter To #img_redFilter
      DrawImage(ImageID(i), (i - #img_blueFilter) * (#iw / 3), #ih, #iw / 3, #ih / 3)
    Next
  StopDrawing()
  
  SetGadgetState(0, ImageID(#img_composite))
EndProcedure

generate_data()

AddKeyboardShortcut(#win_main, #PB_Shortcut_Escape, #men_exitProgram)
AddKeyboardShortcut(#win_main, #PB_Shortcut_Space, #men_generateImage)
Define event, quit = #False
Repeat
  event = WaitWindowEvent()
  Select event 
    Case #PB_Event_CloseWindow
      quit = 1
    Case #PB_Event_Menu
      Select EventMenu()
        Case #men_exitProgram
          quit = #True
        Case #men_generateImage
          generate_data()
      EndSelect
  EndSelect
Until quit = 1
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4661
Joined: Sun Apr 12, 2009 6:27 am

Re: Combining Red, Green and Blue parts of an image in PB.

Post by RASHAD »

Tested with Demivec captured the 3 colored images and I came to same conclusion

Code: Select all

; UsePNGImageDecoder()
; UsePNGImageEncoder()

; LoadImage(0,GetTemporaryDirectory()+"Image_000.png")
; LoadImage(1,GetTemporaryDirectory()+"Image_001.png")
; LoadImage(2,GetTemporaryDirectory()+"Image_002.png")

CreateImage(0,600,600,32)
StartDrawing(ImageOutput(0))
For i = 0 To 100
  DrawingMode(#PB_2DDrawing_AllChannels )
  alpha = Random(255,0)
  Circle(Random(600,10),Random(600,10),Random(50,10),RGBA(255,0,0,alpha))
Next
StopDrawing()

CreateImage(1,600,600,32)
StartDrawing(ImageOutput(1))
For i = 0 To 100
  DrawingMode(#PB_2DDrawing_AllChannels )
  alpha = Random(255,0)
  Circle(Random(600,10),Random(600,10),Random(50,10),RGBA(0,255,0,alpha))
Next
StopDrawing()

CreateImage(2,600,600,32)
StartDrawing(ImageOutput(2))
For i = 0 To 100
  DrawingMode(#PB_2DDrawing_AllChannels )
  alpha = Random(255,0)
  Circle(Random(600,10),Random(600,10),Random(50,10),RGBA(0,0,255,alpha))
Next
StopDrawing()

OpenWindow(0, 0, 0, 600, 600, "2D Drawing Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If CreateImage(100, 1200, 1200 ,32,$FFFFFF)
  If StartDrawing(ImageOutput(100))
    DrawImage(ImageID(0),0,0,600,600)
    DrawImage(ImageID(1),600,0,600,600)
    For x = 0 To 599
      For y = 0 To 599
        color = Point(x,y) | Point(x+600,y)
        Plot(x,y+600,color)            
      Next
    Next
    GrabDrawingImage(3,0,600,600,600)
    StopDrawing()
  EndIf
EndIf
If CreateImage(100, 1200, 1200 ,32,$FFFFFF)
  If StartDrawing(ImageOutput(100))
    DrawImage(ImageID(3),0,0,600,600)
    DrawImage(ImageID(2),600,0,600,600)
    For x = 0 To 599
      For y = 0 To 599
        color = Point(x,y) | Point(x+600,y)
        Plot(x,y+600,color)            
      Next
    Next
    GrabDrawingImage(4,0,600,600,600)
    StopDrawing()
  EndIf
EndIf

ImageGadget(0, 0, 0, 600,600, ImageID(4))

Repeat
  Event = WaitWindowEvent() 
Until Event = #PB_Event_CloseWindow

End 
Egypt my love
infratec
Always Here
Always Here
Posts: 6869
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Combining Red, Green and Blue parts of an image in PB.

Post by infratec »

Hi,

the following code can combine 3 pictures to a RGB picture

I grabbed the 3 bw pictures (left side pictures of the USA flag R, G, B from top to down) from:

https://petapixel.com/2015/11/23/how-to ... -bw-shots/

and stored them as BMP.

I used them for testing this code:

Code: Select all

Enumeration
  #RedColorImage
  #GreenColorImage
  #BlueColorImage
  #RGBImage
EndEnumeration



Procedure GrayFilterCallback(x, y, SourceColor, TargetColor)
  
  Protected Red.i, Green.i, Blue.i
  
  
  Color = 0.2126*Red(SourceColor) + 0.7152*Green(SourceColor) + 0.0722*Blue(SourceColor)
  
  ProcedureReturn RGBA(Color, Color, Color, $FF)
  
EndProcedure



Procedure RedFilterCallback(x, y, SourceColor, TargetColor)
  
  ProcedureReturn RGBA(Red(SourceColor), Green(TargetColor), Blue(TargetColor), $FF)
  
EndProcedure


Procedure GreenFilterCallback(x, y, SourceColor, TargetColor)
  
  ProcedureReturn RGBA(Red(TargetColor), Green(SourceColor), Blue(TargetColor), $FF)
  
EndProcedure


Procedure BlueFilterCallback(x, y, SourceColor, TargetColor)
  
  ProcedureReturn RGBA(Red(TargetColor), Green(TargetColor), Blue(SourceColor), $FF)
  
EndProcedure


Procedure ConvertToBW(Image.i)
  
  If StartDrawing(ImageOutput(Image))
    DrawingMode(#PB_2DDrawing_CustomFilter)
    CustomFilterCallback(@GrayFilterCallback())
    DrawImage(ImageID(Image), 0, 0)
    StopDrawing()
  EndIf
  
EndProcedure




Filename$ = OpenFileRequester("Choose the red color image", "", "BMP|*.bmp", 0)
If Filename$
  If LoadImage(#RedColorImage, Filename$)
    ConvertToBW(#RedColorImage)
  EndIf
EndIf

Filename$ = OpenFileRequester("Choose the green color image", "", "BMP|*.bmp", 0)
If Filename$
  LoadImage(#GreenColorImage, Filename$)
  ConvertToBW(#GreenColorImage)
EndIf

Filename$ = OpenFileRequester("Choose the blue color image", "", "BMP|*.bmp", 0)
If Filename$
  LoadImage(#BlueColorImage, Filename$)
  ConvertToBW(#BlueColorImage)
EndIf

If Not IsImage(#RedColorImage) Or Not IsImage(#GreenColorImage) Or Not IsImage(#BlueColorImage)
  MessageRequester("Error", "3 images are needed")
  End
EndIf

ImageWidth = ImageWidth(#RedColorImage)
If ImageWidth < ImageWidth(#GreenColorImage)
  ImageWidth = ImageWidth(#GreenColorImage)
EndIf
If ImageWidth < ImageWidth(#BlueColorImage)
  ImageWidth = ImageWidth(#BlueColorImage)
EndIf

ImageHeight = ImageHeight(#RedColorImage)
If ImageHeight < ImageHeight(#GreenColorImage)
  ImageHeight = ImageHeight(#GreenColorImage)
EndIf
If ImageHeight < ImageHeight(#BlueColorImage)
  ImageHeight = ImageHeight(#BlueColorImage)
EndIf


CreateImage(#RGBImage, ImageWidth, ImageHeight)
If StartDrawing(ImageOutput(#RGBImage))
  
  DrawingMode(#PB_2DDrawing_CustomFilter)
  
  CustomFilterCallback(@RedFilterCallback())
  DrawImage(ImageID(#RedColorImage), 0, 0)
  
  CustomFilterCallback(@GreenFilterCallback())
  DrawImage(ImageID(#GreenColorImage), 0, 0)
  
  CustomFilterCallback(@BlueFilterCallback())
  DrawImage(ImageID(#BlueColorImage), 0, 0)
  
  StopDrawing()
EndIf



OpenWindow(0, 0, 0, 800, 600, "RGB Layer Test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)

ImageGadget(0, 0, 0, 800, 600, ImageID(#RGBImage))

Repeat
  Event = WaitWindowEvent()
  
  
Until Event = #PB_Event_CloseWindow
Last edited by infratec on Mon Oct 11, 2021 7:17 pm, edited 3 times in total.
juergenkulow
Enthusiast
Enthusiast
Posts: 556
Joined: Wed Sep 25, 2019 10:18 am

Re: Combining Red, Green and Blue parts of an image in PB.

Post by juergenkulow »

Hallo matalog

Photoshop calculates two images together when lighten them.
Here is an example:
Image Image Image
Do you have an example with formula how three images are calculated together?
Please ask your questions, because switch on the cognition apparatus decides on the only known life in the universe.Wersten :DDüsseldorf NRW Germany Europe Earth Solar System Flake Bubble Orionarm
Milky Way Local_Group Virgo Supercluster Laniakea Universe
Post Reply