Image gamma correction
Posted: Tue Dec 20, 2016 4:29 pm
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.
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