Page 1 of 1

Image gamma correction

Posted: Tue Dec 20, 2016 4:29 pm
by Keya
I'll just give a brief description of Gamma because its pretty new to me, and no doubt many here already have a firm grasp on it (ive seen some sRGB snippets for example). Gamma basically affects how bright or dark an image appears (the 'exposure' level), and for example if you plot RGB squares of all colors and compare the screenshots from Windows and Mac youll see theyre slightly different even though the code generating them was the same. Using Gamma correction you can ensure the image looks the same on all devices.

Applied to each RGB channel...
Gamma encoding:
Pseudocode: encoded = ((original / 255) ^ (1 / gamma)) * 255
In Purebasic: encoded = Pow((original / 255), (1 / gamma)) * 255
[Feature Request: ^ Operator]

Gamma decoding:
original = ((encoded / 255) ^ gamma) * 255

Gamma in Photoshop:
Image menu -> Adjustments -> Exposure -> Gamma Correction
The output of this appears to match that of Photoshop.

Code: Select all

Procedure GammaCorrectImage(hImg, Gamma.d)
  Protected *drawbuf, *red.Ascii, *green.Ascii, *blue.Ascii, x,y
  Protected ipixfmt, irowlen, steprow, width, height, bytesperpixel, GammaCorrect.d
  width = ImageWidth(hImg)
  height = ImageHeight(hImg)
  If width < 1 Or height < 1
    MessageRequester("Error", "Invalid dimensions " + Str(width) + " x " + Str(height)): End
  EndIf
  bytesperpixel = ImageDepth(hImg) >> 3  
  If StartDrawing(ImageOutput(hImg))       
    *drawbuf = DrawingBuffer()    
    irowlen = DrawingBufferPitch()
    ipixfmt = DrawingBufferPixelFormat()    
    If ipixfmt & #PB_PixelFormat_ReversedY  ;start from the bottom and work upwards
      steprow = (0-irowlen-irowlen) + (irowlen - (width * bytesperpixel))
      *drawbuf + (irowlen * height) - irowlen
    Else  ;start from the top and work down
      steprow = (irowlen - (width * bytesperpixel)) 
    EndIf         
    *red = *drawbuf: *green=*red+1: *blue=*green+1
    If (ipixfmt & #PB_PixelFormat_32Bits_BGR) Or (ipixfmt & #PB_PixelFormat_24Bits_BGR)
      Swap *red, *blue
    EndIf
    
    
GammaCorrect = 1 / Gamma ;### Calculate gamma correction
    
    For y = 1 To height
      For x = 1 To width        
        
;### Gamma correction        
        *red\a = Pow((*red\a / 255), GammaCorrect) * 255
        *green\a = Pow((*green\a / 255), GammaCorrect) * 255
        *blue\a = Pow((*blue\a / 255), GammaCorrect) * 255        
;### End gamma correction        
        
        *red+bytesperpixel: *green+bytesperpixel: *blue+bytesperpixel        
      Next x
      *red+steprow: *green+steprow: *blue+steprow
    Next y    
    StopDrawing()
    
  EndIf  
EndProcedure

;### Example
sFile.s = "C:\merryxmas.png"
UsePNGImageDecoder()
hImg = LoadImage(#PB_Any, sFile)
If hImg = 0: MessageRequester("Error","LoadImage fail"): End: EndIf

GAMMA.d = 0.5    ;0.0 - 10.0
GammaCorrectImage(hImg, GAMMA)

OpenWindow(0,0,0,ImageWidth(hImg),ImageHeight(hImg),"Gamma",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ImageGadget(0,0,0,ImageWidth(hImg),ImageHeight(hImg),ImageID(hImg))    
Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow