Fast Algorithm to Determine Average Brightness of an Image
Sannyasin Brahmanathaswami
brahma at hindu.org
Tue Sep 20 21:52:17 EDT 2016
@ HH
OK I will "bite" on your idea. but I have never examined or processed the imagedata. Please scrutinize my code below. But there is a major caveat with your original code (see below)
I think I got it correct.
but there is a huge difference on the result between the 1 X 1 and the 12 X 9
I have a late afternoon shot of the sun setting over the ocean. your original function returns
148.981481 # which seems too low…
But if I did this correctly (I may not have)
I get
192.333333 # which seems a lot more correct visually because this is bright image.
average across 12x 9 = 108 px = 432 bytes of image data.
did I do something wrong here. (disclaimer… this could probably be optimized…but still very fast)
function avgBrightness theImage
--lock screen; lock messages
if there is no img ii then create img ii
set resizeQuality of img ii to "best"
put the width of img 1 into tOrigWidth
put the height of img 1 into tOrigHeight
set width of img ii to tOrigWidth
set height of img ii to tOrigHeight
set imagedata of img ii to the imagedata of img theImage
put 12 into tNewWidth
# Scale down proportinally
set the width of img ii to tNewWidth
put round ( (tOrigHeight*tNewWidth)/tOrigWidth) into tNewHeight
set height of img ii to tNewHeight
--set width of img ii to 1
--set height of img ii to 1
put the imagedata of img ii into iData
put tNewWidth * tNewHeight * 4 into tNoPixelBytes
delete img ii
# get beyond first byte otherwise mod 4 returns bogus value
put (byteToNum(byte 2 of iData) & "," &\
byteToNum(byte 3 of iData) & "," &\
byteToNum(byte 4 of iData) & ",") into tAllPixelColorValues
repeat with x = 5 to tNoPixelBytes
if x mod 4 = 1 then next repeat # skip this one, all zeros here.
put byteToNum(byte x of iData) &"," after tAllPixelColorValues
end repeat
put empty into item -1 of tAllPixelColorValues # remove last empty itm
return avg (tAllPixelColorValues)
unlock screen; unlock messages
end avgBrightness
BR
But if you use your original code and do not delete img ii, a different value is returned than if you uncomment that line.. if you delete img ii you get a different value.
function avgBrightness1 theImage
--lock screen; lock messages
if there is no img ii then create img ii
set resizeQuality of img ii to "best"
put the width of img 1 into tOrigWidth
put the height of img 1 into tOrigHeight
set imagedata of img ii to the imagedata of img theImage
set width of img ii to 1
set height of img ii to 1
put the imagedata of img ii into iData
--delete img ii
return avg (byteToNum(byte 2 of iData), \
byteToNum(byte 3 of iData), \
byteToNum(byte 4 of iData))
--unlock screen; unlock messages
end avgBrightness1
On 9/20/16, 1:31 PM, "use-livecode on behalf of hh" <use-livecode-bounces at lists.runrev.com on behalf of hh at hyperhh.de> wrote:
There is still one option that uses a weighted grayLevel-mean
(I use these weights in imageJIT). This would reflect more
than simple averaging that one wants a dark/light decision.
return (0.1*byteToNum(byte 2 of iData) \
+ 0.6*byteToNum(byte 3 of iData) \
+ 0.3*byteToNum(byte 4 of iData))
Also, what will be still fast enough, you could think about
scaling down _proportional_ to 3x2 pixels (or 12x8 pixels)
and then applying the above weighted mean on these few pixels.
p.s. I checked: The one-pixel color is by LC built from the
arithmetic mean of the color channels, nearly as fast as an external!
More information about the use-livecode
mailing list