I tried to speed bump the autobrighten handler
Code: Select all
function addFilter_AutoBrighten pImage,pStyle,pStyle2,tAmount
if pImage is empty then exit to top
put the imageData of pImage into tData
put the width of pImage into pWidth
put the height of pImage into pHeight
put pWidth * pHeight * 4 into tHowOften
repeat with tCounter = 2 to tHowOften step 4
put charToNum(char tCounter of tData) into tRed
put charToNum(char tCounter + 1 of tData) into tGreen
put charToNum(char tCounter + 2 of tData) into tBlue
-- -- see below for compounded formula
-- put (tRed + tGreen + tBlue)/3 into pHold
-- put pHold/255 into tPercent
-- put (tAmount*2) * tPercent into pHold
-- subtract tAmount from pHold
-- replaces above blocked code
put ((tAmount*2) * (((tRed + tGreen + tBlue)/3)/255))-tAmount into pHold
if pStyle is "1" then
-- Adjust High & Low Levels
-- put pHold into pHold -- not necessary
else if pStyle is "2" then
--Adjust High Levels Only
if (pHold < 0) then
put 0 into pHold
end if
else if pStyle is "3" then
--Adjust Low Levels only
if (pHold > 0) then
put 0 into pHold
end if
end if
put (16 + ((.183 * tRed) + (.614 * tGreen) + (.062 * tBlue))) into tY
put (128 + (((-.101) * tRed) + ((-.339) * tGreen) + (.439 * tBlue))) into tCb
put (128 + ((.439 * tRed) + ((-.339) * tGreen) + ((-.040) * tBlue))) into tCr
if pStyle2 is 1 then
add pHold to tY
else if pStyle2 is 2 then
subtract pHold from tY
end if
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (0.000 * (tCb - 128)) + (1.793 * (tCr - 128))),255),0)) into char tCounter of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + ((-0.213) * (tCb - 128)) + ((-0.533) * (tCr - 128))),255),0)) into char tCounter + 1 of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (2.112 * (tCb - 128)) + (0.000 * (tCr - 128))),255),0)) into char tCounter + 2 of tData
end repeat
set the imageData of pImage to tData
return "Render Complete!"
end addFilter_AutoBrighten
The speed increase comes at a cost: the code is hardly legible, would need commenting for maintenance. You can compare it to the current version of PhotoRoom. Just paste this code into the script of card main and block the current handler.
here is one version that takes out the conditionals of the inner repeat loop at the cost of being a lot longer, this one saves another 80 milliseconds on said dimensions.
Code: Select all
function addFilter_AutoBrighten pImage,pStyle,pStyle2,tAmount
if pImage is empty then exit to top
put the imageData of pImage into tData
put the width of pImage into pWidth
put the height of pImage into pHeight
if pStyle2 is 1 then
put 1 into tMultiply
else
put - 1 into tMultiply
end if
put pWidth * pHeight * 4 into tHowOften
if pStyle is 1 then
repeat with tCounter = 2 to tHowOften step 4
put charToNum(char tCounter of tData) into tRed
put charToNum(char tCounter + 1 of tData) into tGreen
put charToNum(char tCounter + 2 of tData) into tBlue
-- -- see below for compounded formula
-- put (tRed + tGreen + tBlue)/3 into pHold
-- put pHold/255 into tPercent
-- put (tAmount*2) * tPercent into pHold
-- subtract tAmount from pHold
-- replaces above blocked code
put ((tAmount*2) * (((tRed + tGreen + tBlue)/3)/255))-tAmount into pHold
--
put (16 + ((.183 * tRed) + (.614 * tGreen) + (.062 * tBlue))) into tY
put (128 + (((-.101) * tRed) + ((-.339) * tGreen) + (.439 * tBlue))) into tCb
put (128 + ((.439 * tRed) + ((-.339) * tGreen) + ((-.040) * tBlue))) into tCr
add (pHold * tMultiply) to tY
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (0.000 * (tCb - 128)) + (1.793 * (tCr - 128))),255),0)) into char tCounter of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + ((-0.213) * (tCb - 128)) + ((-0.533) * (tCr - 128))),255),0)) into char tCounter + 1 of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (2.112 * (tCb - 128)) + (0.000 * (tCr - 128))),255),0)) into char tCounter + 2 of tData
end repeat
end if
if pStyle is 2 then
repeat with tCounter = 2 to tHowOften step 4
put charToNum(char tCounter of tData) into tRed
put charToNum(char tCounter + 1 of tData) into tGreen
put charToNum(char tCounter + 2 of tData) into tBlue
-- -- see below for compounded formula
-- put (tRed + tGreen + tBlue)/3 into pHold
-- put pHold/255 into tPercent
-- put (tAmount*2) * tPercent into pHold
-- subtract tAmount from pHold
-- replaces above blocked code
put ((tAmount*2) * (((tRed + tGreen + tBlue)/3)/255))-tAmount into pHold
put max(pHold,0) into pHold
put (16 + ((.183 * tRed) + (.614 * tGreen) + (.062 * tBlue))) into tY
put (128 + (((-.101) * tRed) + ((-.339) * tGreen) + (.439 * tBlue))) into tCb
put (128 + ((.439 * tRed) + ((-.339) * tGreen) + ((-.040) * tBlue))) into tCr
add (pHold * tMultiply) to tY
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (0.000 * (tCb - 128)) + (1.793 * (tCr - 128))),255),0)) into char tCounter of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + ((-0.213) * (tCb - 128)) + ((-0.533) * (tCr - 128))),255),0)) into char tCounter + 1 of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (2.112 * (tCb - 128)) + (0.000 * (tCr - 128))),255),0)) into char tCounter + 2 of tData
end repeat
end if
if pStyle is 3 then
repeat with tCounter = 2 to tHowOften step 4
put charToNum(char tCounter of tData) into tRed
put charToNum(char tCounter + 1 of tData) into tGreen
put charToNum(char tCounter + 2 of tData) into tBlue
-- -- see below for compounded formula
-- put (tRed + tGreen + tBlue)/3 into pHold
-- put pHold/255 into tPercent
-- put (tAmount*2) * tPercent into pHold
-- subtract tAmount from pHold
-- replaces above blocked code
put ((tAmount*2) * (((tRed + tGreen + tBlue)/3)/255))-tAmount into pHold
--
put min(pHold,0) into pHold
put (16 + ((.183 * tRed) + (.614 * tGreen) + (.062 * tBlue))) into tY
put (128 + (((-.101) * tRed) + ((-.339) * tGreen) + (.439 * tBlue))) into tCb
put (128 + ((.439 * tRed) + ((-.339) * tGreen) + ((-.040) * tBlue))) into tCr
add (pHold * tMultiply) to tY
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (0.000 * (tCb - 128)) + (1.793 * (tCr - 128))),255),0)) into char tCounter of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + ((-0.213) * (tCb - 128)) + ((-0.533) * (tCr - 128))),255),0)) into char tCounter + 1 of tData
put numToChar(max(min(the round of ((1.164 * (tY - 16)) + (2.112 * (tCb - 128)) + (0.000 * (tCr - 128))),255),0)) into char tCounter + 2 of tData
end repeat
end if
set the imageData of pImage to tData
return "Render Complete!"
end addFilter_AutoBrighten
For each will probably not make it faster since Livecode is very fast at getting a char = byte. The reason I suppose is that it accesses individual bytes by some pointer arithmetic. For each is a lot faster for chunks greater than bytes e.g. words, lines, items because Livecode does a lot less counting compared to repeat with i = x to the number of words of y. Additionally you have to maintain your own counter to know what byte you are accessing since you don't want every byte sequentially. And if you want them sequentially you need triplets of chars for red, green and blue. (tried it but it gets a bit messy and is slower than above handlers.)
Timing is not accurate since it varies from run to run a bit, times in milliseconds are roundabout times but give a feeling for the relative speed of different handlers.
LIveCode is not fast enough to make image manipulation a real joy. But then consider the computation needed for an image 640 by 480 px. = 640*480 =307200 px =1228800 bytes. And you have to access them to read them, convert them with charToNum, do your computation and convert them back with numToChar and write them to the imageData. Unless Livecode provides a faster means of accessing imageData it is all we have.
Kind regards
Bernd