Photoshop Levels filter
Posted: Sat Feb 12, 2022 12:55 pm
Photoshop has a filter called "Levels" for adjusting the contrast range in an image. Based on this pseudocode, I have written this emulation of it. The procedure operates on a specified rectangular area of the image.
The input parameters which would result in no change to the image are:
ShadowValue = 0
MidtoneValue = 128
HighlightValue = 255
Increasing the ShadowValue will emphasise the darks in the image. Decreasing the HighlightValue will emphasise the brights. Altering the MidtoneValue will affect the mid tones.
PhotoshopLevelsHSL() is an alternative version which uses the HSL colour space instead of RGB:
There's also this procedure, for increasing/decreasing alpha gradients:
The input parameters which would result in no change to the image are:
ShadowValue = 0
MidtoneValue = 128
HighlightValue = 255
Increasing the ShadowValue will emphasise the darks in the image. Decreasing the HighlightValue will emphasise the brights. Altering the MidtoneValue will affect the mid tones.
Code: Select all
Macro ContainThis(num,min,max)
If num<min
num=min
EndIf
If num>max
num=max
EndIf
EndMacro
Macro ApplyPhotoshopLevelsToChannel(ChannelValueVar)
; apply input levels
ChannelValueVar = 255 * ( ( ChannelValueVar - ShadowValue ) / ( HighlightValue - ShadowValue ) )
; apply midtones
If MidtoneValue <> 128
ChannelValueVar = 255 * ( Pow( ( ChannelValueVar / 255 ), GammaCorrection ) )
EndIf
; apply output levels
ChannelValueVar = ( ChannelValueVar / 255 ) * ( OutHighlightValue - OutShadowValue ) + OutShadowValue
ContainThis(ChannelValueVar,0,255)
EndMacro
Procedure.b PhotoshopLevels(x,y,w,h,ShadowValue.d,MidtoneValue.d,HighlightValue.d,OutShadowValue.d=0,OutHighlightValue.d=255)
DrawingMode(#PB_2DDrawing_AllChannels)
GammaCorrection.d = 1
For dx = x To x+w
For dy = y To y+h
clr = Point(dx,dy)
ChannelValueR.d = Red(clr)
ApplyPhotoshopLevelsToChannel(ChannelValueR)
ChannelValueG.d = Green(clr)
ApplyPhotoshopLevelsToChannel(ChannelValueG)
ChannelValueB.d = Blue(clr)
ApplyPhotoshopLevelsToChannel(ChannelValueB)
ChannelValueA.i = Alpha(clr)
clr = RGBA(ChannelValueR,ChannelValueG,ChannelValueB,ChannelValueA)
Plot(dx,dy,clr)
Next dy
Next dx
ProcedureReturn #True
EndProcedure
Code: Select all
Procedure.b PhotoshopLevelsHSL(x,y,w,h,ShadowValue.d=0,MidtoneValue.d=128,HighlightValue.d=255,OutShadowValue.d=0,OutHighlightValue.d=255)
DrawingMode(#PB_2DDrawing_AllChannels)
GammaCorrection.d = 1
minlum.d = 500
maxlum.d = -500
NewMap converted.i()
For dx = x To x+w
For dy = y To y+h
clr = Point(dx,dy)
key.s = Str(clr)
If FindMapElement(converted(),key)
Plot(dx,dy,converted(key))
Continue
EndIf
CheckHSLAMem(key)
ChannelValueL.d = hsla_rem(key)\lum
DefeatThis(minlum,ChannelValueL)
BeatThis(maxlum,ChannelValueL)
ApplyPhotoshopLevelsToChannel(ChannelValueL)
ChannelValueA.i = Alpha(clr)
converted(key) = HSL(hsla_rem(key)\hue,hsla_rem(key)\sat,ChannelValueL,ChannelValueA)
Plot(dx,dy,converted(key))
Next dy
Next dx
ProcedureReturn #True
EndProcedure
Code: Select all
Procedure.b PhotoshopLevelsAlpha(x,y,w,h,ShadowValue.d,MidtoneValue.d,HighlightValue.d,OutShadowValue.d=0,OutHighlightValue.d=255)
DrawingMode(#PB_2DDrawing_AlphaChannel)
GammaCorrection.d = 1
For dx = x To x+w
For dy = y To y+h
ChannelValueA.d = Alpha(Point(dx,dy))
ApplyPhotoshopLevelsToChannel(ChannelValueA)
clr = RGBA(0,0,0,ChannelValueA)
Plot(dx,dy,clr)
Next dy
Next dx
ProcedureReturn #True
EndProcedure