Atkinson dither algorithm

2017-10-19 Thread Alejandro Tejada via use-livecode
Tom Glod wrote:
> wow! my brain hurts.

Still pending:
1) creating a command line application
2) compiling an external
3) building a widget

In the forum thread, Hermann already demonstrated
how to apply this algorithm using Javascript within
the browser widget.

But creating each one of these would be topic
for another thread! :-)

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-19 Thread Tom Glod via use-livecode
wow! my brain hurts.

On Tue, Oct 17, 2017 at 2:13 PM, Alejandro Tejada via use-livecode <
use-livecode@lists.runrev.com> wrote:

> Hermann, your script version won the
> LiveCode Script speed contest! :-)
>
> I feel humbled and grateful that many of you
> have taken time to look at this. Although an
> image dithering algorithm seems trivial an
> barely useful, the fact is that in this thread,
> we have pushed Livecode script almost to
> it's speed limits.
>
> After we reach Livecode scripts natural limits,
> the next step is
> 1) creating a command line application, or
> 2) building an external, or (like Hermann demonstrated)
> 3) using Javascript within the browser widget or
> 4) the next frontier: Livecode widgets.
>
> This platform does not lack options to get the job
> done. It just require time and expertise to select
> the best options for each phase of a particular project.
>
> Later today, after I finished testing an application in
> different computers, will update the forum final's
> stack version with Alex and Hermann scripts.
>
> Thanks a lot again! :-D
>
> Al
> ___
> use-livecode mailing list
> use-livecode@lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your
> subscription preferences:
> http://post.spmailt.com/f/a/V6GU5lCriQ9t-bb23opSXg~~/AAGp3AA~/RgRbylESP0EIACz0hNEHMqNXA3NwY1gEAFkGc2hhcmVkYQdoZWxsb18xYA01Mi4zOS4xODIuMjQ4QgoAAJId6VlTFUhaUh11c2UtbGl2ZWNvZGVAbGlzdHMucnVucmV2LmNvbQlRBABENWh0dHA6Ly9saXN0cy5ydW5yZXYuY29tL21haWxtYW4vbGlzdGluZm8vdXNlLWxpdmVjb2RlRwJ7fQ~~
>
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-17 Thread Alejandro Tejada via use-livecode
Hermann, your script version won the
LiveCode Script speed contest! :-)

I feel humbled and grateful that many of you
have taken time to look at this. Although an
image dithering algorithm seems trivial an
barely useful, the fact is that in this thread,
we have pushed Livecode script almost to
it's speed limits.

After we reach Livecode scripts natural limits,
the next step is
1) creating a command line application, or
2) building an external, or (like Hermann demonstrated)
3) using Javascript within the browser widget or
4) the next frontier: Livecode widgets.

This platform does not lack options to get the job
done. It just require time and expertise to select
the best options for each phase of a particular project.

Later today, after I finished testing an application in
different computers, will update the forum final's
stack version with Alex and Hermann scripts.

Thanks a lot again! :-D

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-17 Thread hh via use-livecode
@Alejandro and Alex.

All that limit checking is not needed here. It is much faster,
especially for fast images,to do a few unneeded additions than
to do all these checks for each pixel.

I translated my js-function into LC Script, using Alejandro's
variable names and (inline) Alex's array creation method. See
http://forums.livecode.com/viewtopic.php?p=159244#p159244

You certainly can improve this LCS script even more. In javascript
this is so fast that even for large images there is no gain by
'optimization'.

p.s. Al, you don't need a "try". Just use (where 3 = step-1)
repeat with i = 1 to the number of bytes in tempVar - 3 step 4


___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-16 Thread Alejandro Tejada via use-livecode
Hi Alex,

This is Amazing! :-D
Alex, your function saved another 34%
in the running time of this handler!

In retrospect, only now it seems very obvious
that merging two functions could save more
running time in this handler... but
I just keep wondering: How far can we go
merging functions to save milliseconds
in our LiveCode handlers? This is an interesting
question that could be answered exactly
in milliseconds.

By the way, I have to add a try structure to dismiss
an error message:

Function ImgToChToArrayNum2 tImageData, tChannel
-- extract a single channel's data, and convert
-- to sequential array of numbers by Alex Tweedly

put tImageData into tempVar
delete byte 1 to tChannel of tempVar
put empty into tResult
put 0 into tCounter
repeat with i = 1 to the number of bytes in tempVar step 4
   add 1 to tCounter
   try
  put bytetonum(byte i of tempVar) into tResult[tCounter]
  end try
end repeat
return tResult
end ImgTochToArrayNum2

Alex Tweedly wrote:
> I haven't tackled the second half (i.e. the actual dithering bit yet -
> maybe tomorrow).

Excellent! Thanks a lot for your time, Alex.

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-16 Thread Alex Tweedly via use-livecode



On 17/10/2017 00:21, Alex Tweedly via use-livecode wrote:

Sorry about the horrible formatting on the last post... I'll try to find 
my Forum password and post the modified version there 


I haven't tackled the second half (i.e. the actual dithering bit yet - 
maybe tomorrow).

I can trim a few ms off this, but it's really not significant.

Change the checks for being near the right hand side of the image from 
'if's to a switch.


Then,  after you've calculated and used tNewKey, change following lines 
like :


*if* tPixelPosition modtImageWidth <> 1*then**
    put (tPixelPosition + tImageWidth - 1) into tNewKey**
   add*(tDifusionError) totArray2[tNewKey]*
end* *if*


to


*if* tPixelPosition modtImageWidth <> 1*then**
    add*(tDifusionError) totArray2[tNewKey-1]*
end* *if*


but it really is nit-picking - only a tine saving.

-- Alex.

___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode

Re: Atkinson dither algorithm

2017-10-16 Thread Alex Tweedly via use-livecode


On 16/10/2017 19:37, Alejandro Tejada via use-livecode wrote:

Hi Bob,

Bob Sneidar wrote:

I didn't post any code I don't think, but I will certainly
take some credit for having done so! ;-)

In fact, you are not late! :-D

But I am too late - the file is called "...Final Version ..." :-) :-)
Let's have a look anyway

Please, take a look at the script of
Atkinson Dither 04 (Fastest Version)
and make it faster.

OK, did that :-)

I've been aware of this interesting discussion, but had no time to look 
at it at all (until tonight). Sorry to be late to the party.


I made a few changes, as follows:

1. (Just on principle).
I would change all these reference to "char" to "byte" when we are 
really talking about bytes in binary data.


Probably doesn't make any difference to performance - the engine will 
most likely realize that there aren't any Unicode strings involved - but 
it's just "right" to call them bytes, and to use the byte functions to 
manipulate them :-)


2. there's a function ImgToCh which extracts a single channel of data 
out the image data.
It does this with a cute 'delete' method - but that is over-thinking the 
problem.
You can (i.e. the engine can) access a single byte within a byte string 
in constant time (it's surely a single offset in the C library).


so instead of


repeat untiltempVar isempty
  putchar1oftempVar aftertResult
  deletechar1to4oftempVar
end repeat


we can simply do


*repeat* withi = 1tothenumberofcharsintempVar step4*
  put*bytei oftempVar aftertemp*
end* *repeat*

(I kept the initial delete to select which channel, just because it's so 
clever :-) - but that could have been removed and the repeat changed to

*   repeat* withi = tChannel+1tothenumberofcharsintempVar step4*
*

3. The result of that function is then passed to another function that 
converts the byte string into a sequential array of numbers (and that's 
all that's done with the byte string).

So those two should be combined into a single pass - to get :


Function ImgToChToArrayNum2 tImageData, tChannel
   -- extract a single channel's data, and convert to sequential array 
of numbers

   puttImageData intotempVar
   deletebyte1totChannel oftempVar
   putemptyintotResult
put0intotCounter
   repeat withi = 1tothenumberofbytesintempVar step4
  add1totCounter
  putbytetonum(bytei oftempVar) intotResult[tCounter]
   end repeat
   returntResult
end ImgTochToArrayNum2

This takes the time for this part of the whole process down from 250ms 
to about 75ms, and therefore the total process time down from around 
750-800ms to 600-650ms (on my aging MBP).


Trying repeated runs, the times do seem to vary more than usual - not 
sure why.


I haven't tackled the second half (i.e. the actual dithering bit yet - 
maybe tomorrow).


-- Alex.

___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode

Atkinson dither algorithm

2017-10-16 Thread Alejandro Tejada via use-livecode
Hi Bob,

Bob Sneidar wrote:
> I didn't post any code I don't think, but I will certainly
> take some credit for having done so! ;-)

In fact, you are not late! :-D
Please, take a look at the script of
Atkinson Dither 04 (Fastest Version)
and make it faster.

How would you do this?

Making the Functions Private (so they are not
available in the message path)?

Converting some variables to constants?
(like the black and white pixels and many
other variables that do not change at all
inside the handler)

The main difference between V04 and V03
of this handler is a single modification:

An arithmetic operation like ADD:
> add (tDifusionError) to tArray2[tNewKey]
replaced all instances of PUT
variable + variable into array
like in this line:
> put (tDifusionError) + tArray2[tNewKey] into tArray2[tNewKey]

This single change speed the handler (in my own setup)
by a whopping 33%. Just replacing "put" with "add"

Please take a look! :-)
(Download only the stack at the end of this thread)
https://forums.livecode.com/viewtopic.php?f=10=159173#p159173

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-16 Thread Bob Sneidar via use-livecode
I didn't post any code I don't think, but I will certainly take some credit for 
having done so! ;-)

Bob S


> On Oct 14, 2017, at 21:57 , Alejandro Tejada via use-livecode 
>  wrote:
> 
> Hi All,
> 
> This forum message contains the final version of this stack.
> It includes a Color version of this algorithm.
> 
> https://forums.livecode.com/viewtopic.php?f=10=159173#p159173
> 
> Thanks again to Malte Brill, Richard Gaskin, Hermann Hoch, Mark Waddingham,
> Peter Reid, Ben Rubinstein, Bob Sneidar and Lagi Pittas for posting scripts
> and
> writing ideas to improve this handler.
> 
> Al


___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-14 Thread Alejandro Tejada via use-livecode
Hi All,

This forum message contains the final version of this stack.
It includes a Color version of this algorithm.

https://forums.livecode.com/viewtopic.php?f=10=159173#p159173

Thanks again to Malte Brill, Richard Gaskin, Hermann Hoch, Mark Waddingham,
Peter Reid, Ben Rubinstein, Bob Sneidar and Lagi Pittas for posting scripts
and
writing ideas to improve this handler.

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-13 Thread Lagi Pittas via use-livecode
HI All

Hoping I'm not teaching my granny to suck eggs ... Here is a great article
I remembered reading  from a few years ago. It's easy to find on google so
you probably know of it ...

http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/

In any case his projects and how he writes about them are interesting

 http://www.tannerhelland.com/programming-directory/

Lagi

On 12 October 2017 at 12:05, Peter Reid via use-livecode <
use-livecode@lists.runrev.com> wrote:

> One note of caution regarding the use of the "repeat for each" loop,
> whilst you will get a loop iteration for every value in the collection
> (fldhexa3 in your example), you are not guaranteed the order in which they
> will occur.  This doesn't matter in a lot of cases but does matter when the
> sequence is significant.  In the case of your example I believe sequence is
> critical, otherwise the pixels might appear to be scrambled!
>
> The following adjusted loop guarantees the sequence at the expense of
> speed:
>
>   put 1 into i
>   repeat for each word theWord in fldhexa3
>  put word i of fldhexa3 into theWord
>  put 00 & theword & theword & theword after tVar2
>  add 1 to i
>   end repeat
>
> The original "improved" loop reduces the run-time to 25%.  However, the
> "modified improved" loop only manages to reduce the original run-time to
> 50%.
>
> The suggested loop above takes advantage of the "for each" mechanism to
> produce a set of iterations very rapidly but gets slowed by the need to
> guarantee sequence. I wonder whether the LC engine could impose strict
> sequence more effectively with a variant of the "for each" loop such as
>
>   repeat for each sequenced word x in theCollection
>  ...
>   end repeat
>
> My own tests, comparing the speed of the 4 common repeat loops, imply that
> the current "for each" form is hugely faster than the others.  I tested
> "repeat for each...", "repeat while...", "repeat until...", "repeat
> with..." and a simulated "repeat for each sequenced..." forms using a
> simple loop body that added lines of text one after another, e.g.
>
>   put empty into tData
>   repeat with i = 1 to tMaxI
> put line i of tList & return after tData
>   end repeat
>
> I ran this test for 250,000 iterations for each type of loop, which
> produced the following timings:
>
>   Starting test for 250,000 iterations...
>   repeat for each... 0 mins 0 secs 111 millisecs
>   repeat while... 0 mins 30 secs 569 millisecs
>   repeat until... 0 mins 30 secs 379 millisecs
>   repeat with... 0 mins 30 secs 341 millisecs
>   repeat for each seq... 0 mins 30 secs 524 millisecs
>
> As you can see, in this test the "repeat for each..." form was approx. 275
> times faster than the other forms.  Also the simulated "repeat for each
> sequenced..." form was no faster than the other forms.  This shows how
> variable the speed will be with the simulated "repeat for each
> sequenced...", depending on the details of the loop body.
>
> If there was a "repeat for each sequenced..." form of loop in LC, any
> speed-up could be very beneficial even if the amount of speed-up was only
> 10 times faster!
>
> Cheers
>
> Peter
> --
> Peter Reid
> Loughborough, UK
>
> > On 9 Oct 2017, at 10:18am, use-livecode-requ...@lists.runrev.com wrote:
> >
> > Message: 12
> > Date: Sat, 7 Oct 2017 15:53:44 +0200
> > From: Malte Pfaff-Brill <revolut...@derbrill.de>
> > To: use-livecode@lists.runrev.com
> > Subject: Re: Atkinson dither algorithm
> > Message-ID: <42023b36-0a4e-4251-bb0c-9cd46de55...@derbrill.de>
> > Content-Type: text/plain; charset=us-ascii
> >
> > Hi Al,
> >
> > I already posted on the forums, but for completeness also here:
> >
> > a lot can be done by replacing repeat with with repeat for each where
> you can.
> >
> > --repeat with i = 1 to the number of words of fldhexa3
> >   --   put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of
> fldhexa3 after tVar2
> >   --end repeat
> >
> >   repeat for each word theWord in fldhexa3
> >  put 00 & theword & theword & theword after tVar2
> >   end repeat
> >
> >
> > A sidenode:
> >
> > I always use strict compile mode, therefore I added the needed variable
> declarations and noticed you use startTime as a variablename, which is a
> reserved keyword. That is not a good idea.  (I noticed, because I managed
> to freeze liveCode where I fixed only half of the use of startTime. Booom.)
> >
> > Cheers,
> >
> > malte
>
>
> ___
> use-livecode mailing list
> use-livecode@lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your
> subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-livecode
>
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Atkinson dither algorithm & 'for each' loop

2017-10-13 Thread Alejandro Tejada via use-livecode
After reading Mark Waddingham explanation, now i am using a sequential
ordered array for this handler. Check this much shorter and faster version:

on mouseUp

   put the millisecs into startTime
   set the cursor to busy

   put the alphadata of img "Image" into tAlphaData
   put the imagedata of img "Image" into tVar
   put the width of img "Image" into tImageWidth
   put the height of img "Image" into tImageHeight
   put the number of chars of tVar into tImgPixels

   if existence(sb the "ThresholdDither") then
  put thumbPos of sb the "ThresholdDither" into tThreshold
   else
  put 127 into tThreshold
   end if

   put numtochar(0) & numtochar(255) & numtochar(255) & numtochar(255) into
tWP
   put numtochar(0) & numtochar(0) & numtochar(0) & numtochar(0) into tBP
   put ((tImageWidth * tImageHeight) - tImageWidth) into tHW

   put ImgToArrayNum(ImgToCh(tVar,1)) into tArray2

   put 0 into tPixelCounter
   put tImgPixels/4 into tPixels
   repeat tPixels

  add 1 to tPixelCounter
  put tPixelCounter into tPixelPosition

  put tArray2[tPixelCounter] into tOldPixelValue

  if round(tOldPixelValue) <= tThreshold then
 put 0 into tNewPixelValue
 put tBP after fldhexa8
 else
 put 255 into tNewPixelValue
 put tWP after fldhexa8
 end if

  put (tOldPixelValue - tNewPixelValue)/8 into tDifusionError

  -- Atkinson dither add the diffusion error
  -- to 6 adjacent pixels
  -- x o o
  --  o o o
  -- o

  if tPixelPosition mod tImageWidth <> 0 then
 -- pixel position is less than image width
 put tPixelCounter + 1 into tNewKey
 put (tDifusionError) + tArray2[tNewKey] into tArray2[tNewKey]

 if tPixelPosition mod (tImageWidth - 1) <> 0 then
-- pixel position is less than image width - 1
put tPixelCounter + 2 into tNewKey
put tDifusionError + tArray2[tNewKey] into tArray2[tNewKey]
 end if
  end if

  if tPixelPosition <= tHW then -- ((tImageWidth * tImageHeight) -
tImageWidth)
 -- pixel position is not in the last line of the image

 if tPixelPosition mod tImageWidth <> 1 then
-- pixel position is not the first pixel in any line of the
image
put (tPixelPosition + tImageWidth - 1) into tNewKey
put (tDifusionError) + tArray2[tNewKey] into tArray2[tNewKey]
 end if

 put (tPixelPosition + tImageWidth) into tNewKey
 put (tDifusionError) + tArray2[tNewKey] into tArray2[tNewKey]

 if tPixelPosition mod tImageWidth <> 0 then
-- pixel position is less than image width
put (tPixelPosition + tImageWidth + 1) into tNewKey
put (tDifusionError) + tArray2[tNewKey] into tArray2[tNewKey]
 end if

 if tPixelPosition <= (tImageWidth * tImageHeight) - (tImageWidth *
2) then
-- pixel position is less than image width - 1
put (tPixelPosition + tImageWidth * 2) into tNewKey
put (tDifusionError) + tArray2[tNewKey] into tArray2[tNewKey]
 end if
  end if

   end repeat

   create img
   set the height of it to the height of img "Image"
   set the width of it to the width of img "Image"
   set the imagedata of it to fldhexa8
   set the alphaData of it to tAlphaData

   put the millisecs - startTime && "milliseconds to create Atkinson Dither
from image's single channel"

end mouseUp

Function ImgToArrayNum vImageData
   -- This function converts binary imagedata to
   -- integer numbers from 0 to 255 into
   -- an array.
   -- vImageData is a single color channel
   -- stored as binary imagedata.

   put empty into tResult
   put 0 into tCounter
   repeat for each char K in vImageData
  add 1 to tCounter
  put chartonum(K) into tResult[tCounter]
   end repeat
   return tResult
end ImgToArrayNum

Function ImgToCh tImageData tChannel
   -- This function returns binary data.
   --
   -- tImageData is unmodified original imagedata of image
   -- with 4 chars for each pixel: 1 alphadata and 3 color channels.
   --
   -- tChannel is a number from 1 to 3:
   -- 1 is red channel, 2 is green channel and 3 is blue channel

   put tImageData into tempVar

   delete char 1 to tChannel of tempVar
   -- the first char of the imagedata is part
   -- of the alphadata or maskdata, so when
   -- we delete char 1, the next char is part
   -- from red channel... if we delete 2 first
   -- chars, then next char is green channel
   -- if we delete 3 first chars, then we get
   -- the blue channel

  repeat until tempVar is empty
  put char 1 of tempVar after tResult
  delete char 1 to 4 of tempVar
   end repeat

   return tResult

end ImgToCh

Have a nice weekend!

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:

Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread hh via use-livecode
@Al.
For multiples of 1/8 (Atkinson) you need 8*256=2048 integers,
that is 11 Bit.
For multiples of 1/16 (Floyd-Steinberg) you need 16*256=4096
integers, that is 12 Bit.
In 2 chars = 16 Bit fit even multiples of 1/256.
No dither-algorithm uses such tiny diffusion-errors.

___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Alejandro Tejada via use-livecode
Hi Hermann,

Hermann Hoch wrote:
> So all considerations to improve the LCS script are,
> TMHO, of rather theoretical value. Here are some more:
> The Atkinson algorithm uses multiples of 1/8 = 0.125 for
> the diffusion-error, the Floyd-Steinberg algorithm uses
> multiples of 1/16 = 0.0625.
> And have this in mind:
> Whenever you use numToChar(Number) in your script you
> are wrong by Number - round(Number) of the accumulated
> pixel value ...

This is correct, for this reason, in the most recent version of
this handler, I am using 2 chars to store the new pixel value.
first char is a whole number from 0 to 255 and the second
char represent a decimal part from 0 to 99.

I will test if using 5 chars for storing the new pixel value.
In this way, the new pixel could store values of
.00 that should be enough for this task...

After reading Mark's answer, I learned that using a numerical
ordered array to store pixel values could be really fast too.
This is another path to explore.

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread hh via use-livecode
> Al wrote:
> Please, check this new handler in the forum and suggest how to
> make this faster and more precise.

I already gave you a method that is, with a 500x500 image, at
least 1000 (thousand) times faster than your script.

Of course this is not due my special skills but the ability of
javascript (used via a browser widget) to let the GPU/graphic
card do the essential job of pixel manipulation.

So all considerations to improve the LCS script are, TMHO, of
rather theoretical value. Here are some more:

> Al wrote:
> ... the result STILL is not visually identical to that handler.
> My educated guess is that Atkinson dither algorithm requires
> numbers with more than 2 numbers after the decimal point.
> That is: 243.643578 instead of just 243.64

Conclude from the following:
The Atkinson algorithm uses multiples of 1/8 = 0.125 for the
diffusion-error, the Floyd-Steinberg algorithm uses multiples
of 1/16 = 0.0625. 

And have this in mind:
Whenever you use numToChar(Number) in your script you are wrong by
Number - round(Number) of the accumulated pixel value ...

___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Mark Waddingham via use-livecode

On 2017-10-12 19:35, Alejandro Tejada via use-livecode wrote:

Peter Read wrote:

One note of caution regarding the use of the "repeat for each" loop,
whilst you will get a loop iteration for every value in the collection
(fldhexa3 in your example), you are not guaranteed the order in
which they will occur. This doesn't matter in a lot of cases but
does matter when the sequence is significant.  In the case of your
example I believe sequence is critical, otherwise the pixels might
appear to be scrambled!


Prior to 7, you had to be careful not to modify either the container 
being iterated over *or* the var holding the chunk for the current 
iteration as it could cause issues as described (actually, it was 
fundamentally unsafe to do that, as it could result in a crash). i.e.


  repeat for each item tItem in tContainer
replace "Foo" with "B" in tContainer -- BAD - MIGHT CAUSE PROBLEMS
put "a' into char 2 of tItem -- BAD - MIGHT CAUSE PROBLEMS
  end repeat

From 7 onwards, this is no longer the case. You can do whatever you want 
with either the container. Indeed, in 7, the engine essentially operates 
as if it was iterating over a copy of the container and with a copy of 
the chunk (i.e. tItem and tContainer in the above snippet).


Upshot - you can do whatever you want with your variables - the engine 
ensures that what you do won't affect what you asked for to begin with 
(in particular, if you asked to iterate over tContainer, then it will 
iterate over tContainer as it was at the point you first asked - any 
changes to tContainer after the initial repeat for each line will have 
no effect on the repeat for each clause).


Warmest Regards,

Mark.

--
Mark Waddingham ~ m...@livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps

___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Alejandro Tejada via use-livecode
A few hours ago, I send a message to the mail list, a message that vanish
without trace. Now I am resending parts of that message. The rest of the
message is in the forum...

Peter Read wrote:
> One note of caution regarding the use of the "repeat for each" loop,
> whilst you will get a loop iteration for every value in the collection
> (fldhexa3 in your example), you are not guaranteed the order in
> which they will occur. This doesn't matter in a lot of cases but
> does matter when the sequence is significant.  In the case of your
> example I believe sequence is critical, otherwise the pixels might
> appear to be scrambled!

In my own setup, the control structure "repeat for each" is caching
the content of the working variable. This means that we could not
modify the content of this variable while the control structure is
working with it.

After reading your message, now I understand why this happens.
If developers are allowed to modify a variable used by a control
structure like "repeat for  each" then we could get unexpected
result as you describe: elements are processed in an out of order
sequence.

Ben Rubinstein wrote in response to Peter Reid:
> Are you sure? My understanding has always been that
> chunk items, e.g.
> repeat for each [ byte | char | word | item | line]  in 
> will always be sequential (indeed that's why this structure is fast)
> - it's only when dealing with hashed arrays that the sequence is
> not reliable, i.e.
> repeat for each key  in 
> repeat for each element  in 
> Do you have experience to the contrary?

As I wrote earlier in this same message, Peter could have found
some way to change the working variable in a repeat for each
control structure and the result is that elements are processed
with an out of order sequence.

By the way, after reading all comments and recommendations
about the atkinson dither algorithm, I wrote a new handler that
is a lot faster that my first handler, but the result STILL is not
visually identical to that handler.

My educated guess is that Atkinson dither algorithm requires
numbers with more than 2 numbers after the decimal point.
That is: 243.643578 instead of just 243.64
Later this week, I will try to discover the minimal number of
decimal numbers that this algorithm requires.

Please, check this new handler in the forum and suggest how to make
this faster and more precise:

https://forums.livecode.com/viewtopic.php?f=10=159078=b46bc56428cb5b0f48d2c6520c107c47#p159078

Have a nice week!

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Richard Gaskin via use-livecode

Peter Reid wrote:

> One note of caution regarding the use of the "repeat for each" loop,
> whilst you will get a loop iteration for every value in the collection
> (fldhexa3 in your example), you are not guaranteed the order in which
> they will occur.

Maybe I misunderstand, but are you thinking of arrays there?

With string containers a "repeat for each" expression should parse from 
beginning to end, sequentially.


Any exception to that would be prohibitively unpredictable, and should 
be reported as a bug.



> The following adjusted loop guarantees the sequence at the expense of
> speed:
>
>   put 1 into i
>   repeat for each word theWord in fldhexa3
>  put word i of fldhexa3 into theWord

The speed lost there appears to be the result of a redundancy, and a 
particularly expensive one:


We love the convenience of chunk expressions, but in loops we want to 
remain mindful of "  of " because satisfying 
such expressions will require the engine to start from the beginning of 
the container, examine every character and counting delimiters, until it 
reaches the number of such delimiters specified in "".


So the "repeat" line above parses the chunk value into theWord, but then 
the next line ignores that that's already happened and reassigns the 
same theWord value using an expression that requires then engine to 
count words from the beginning of fldhexa3 each time through the loop.



With this specific algo I believe there may be further benefits in using 
a chunk type other than word (based on a a hunch derived from word 
chunks being parsed more flexibly than items or lines), and perhaps not 
converting the binary data to hex at all, instead parsing bytes directly 
with a "step 4" option in the loop to keep track of the four components 
that define each pixel.


--
 Richard Gaskin
 Fourth World Systems
 Software Design and Development for the Desktop, Mobile, and the Web
 
 ambassa...@fourthworld.comhttp://www.FourthWorld.com

___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Bob Sneidar via use-livecode
That is correct Ben. It's not the repeat for each that is unreliable (probably 
a bad word to use here) but it is arrays which do not retain the sequence of 
key/values in the order they were put in. 

To get around this, when possible use numbered keys, then:

put  the keys of aMyArray into tKeyList
sort the lines of tKeyList numeric ascending
repeat for each line tKey in tKeyList
...

Bob S


> On Oct 12, 2017, at 04:48 , Ben Rubinstein via use-livecode 
>  wrote:
> 
> Hi Peter,
> 
>> One note of caution regarding the use of the "repeat for each" loop, whilst 
>> you will get a loop iteration for every value in the collection
>> (fldhexa3 in your example), you are not guaranteed the order in which they
>> will occur.
> 
> Are you sure? My understanding has always been that chunk items, e.g.
>   repeat for each [ byte | char | word | item | line]  in 
> 
> will always be sequential (indeed that's why this structure is fast) - it's 
> only when dealing with hashed arrays that the sequence is not reliable, i.e.
>   repeat for each key  in 
>   repeat for each element  in 
> 
> Do you have experience to the contrary?
> 
> best regards,
> 
> Ben


___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Ben Rubinstein via use-livecode

Hi Peter,

One note of caution regarding the use of the "repeat for each" loop, 
whilst you will get a loop iteration for every value in the collection

(fldhexa3 in your example), you are not guaranteed the order in which they
will occur.


Are you sure? My understanding has always been that chunk items, e.g.
repeat for each [ byte | char | word | item | line]  in 

will always be sequential (indeed that's why this structure is fast) - it's 
only when dealing with hashed arrays that the sequence is not reliable, i.e.

repeat for each key  in 
repeat for each element  in 

Do you have experience to the contrary?

best regards,

Ben

On 12/10/2017 12:05, Peter Reid via use-livecode wrote:

One note of caution regarding the use of the "repeat for each" loop, whilst you 
will get a loop iteration for every value in the collection (fldhexa3 in your example), 
you are not guaranteed the order in which they will occur.  This doesn't matter in a lot 
of cases but does matter when the sequence is significant.  In the case of your example I 
believe sequence is critical, otherwise the pixels might appear to be scrambled!

The following adjusted loop guarantees the sequence at the expense of speed:

   put 1 into i
   repeat for each word theWord in fldhexa3
  put word i of fldhexa3 into theWord
  put 00 & theword & theword & theword after tVar2
  add 1 to i
   end repeat

The original "improved" loop reduces the run-time to 25%.  However, the "modified 
improved" loop only manages to reduce the original run-time to 50%.

The suggested loop above takes advantage of the "for each" mechanism to produce a set of 
iterations very rapidly but gets slowed by the need to guarantee sequence. I wonder whether the LC 
engine could impose strict sequence more effectively with a variant of the "for each" 
loop such as

   repeat for each sequenced word x in theCollection
  ...
   end repeat

My own tests, comparing the speed of the 4 common repeat loops, imply that the current "for each" form is hugely faster than the 
others.  I tested "repeat for each...", "repeat while...", "repeat until...", "repeat with..." and 
a simulated "repeat for each sequenced..." forms using a simple loop body that added lines of text one after another, e.g.

   put empty into tData
   repeat with i = 1 to tMaxI
 put line i of tList & return after tData
   end repeat

I ran this test for 250,000 iterations for each type of loop, which produced 
the following timings:

   Starting test for 250,000 iterations...
   repeat for each... 0 mins 0 secs 111 millisecs
   repeat while... 0 mins 30 secs 569 millisecs
   repeat until... 0 mins 30 secs 379 millisecs
   repeat with... 0 mins 30 secs 341 millisecs
   repeat for each seq... 0 mins 30 secs 524 millisecs

As you can see, in this test the "repeat for each..." form was approx. 275 times faster than the 
other forms.  Also the simulated "repeat for each sequenced..." form was no faster than the other 
forms.  This shows how variable the speed will be with the simulated "repeat for each 
sequenced...", depending on the details of the loop body.

If there was a "repeat for each sequenced..." form of loop in LC, any speed-up 
could be very beneficial even if the amount of speed-up was only 10 times faster!

Cheers

Peter
--
Peter Reid
Loughborough, UK


On 9 Oct 2017, at 10:18am, use-livecode-requ...@lists.runrev.com wrote:

Message: 12
Date: Sat, 7 Oct 2017 15:53:44 +0200
From: Malte Pfaff-Brill <revolut...@derbrill.de>
To: use-livecode@lists.runrev.com
Subject: Re: Atkinson dither algorithm
Message-ID: <42023b36-0a4e-4251-bb0c-9cd46de55...@derbrill.de>
Content-Type: text/plain; charset=us-ascii

Hi Al,

I already posted on the forums, but for completeness also here:

a lot can be done by replacing repeat with with repeat for each where you can.

--repeat with i = 1 to the number of words of fldhexa3
   --   put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of 
fldhexa3 after tVar2
   --end repeat

   repeat for each word theWord in fldhexa3
  put 00 & theword & theword & theword after tVar2
   end repeat


A sidenode:

I always use strict compile mode, therefore I added the needed variable 
declarations and noticed you use startTime as a variablename, which is a 
reserved keyword. That is not a good idea.  (I noticed, because I managed to 
freeze liveCode where I fixed only half of the use of startTime. Booom.)

Cheers,

malte



___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode



___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm & 'for each' loop

2017-10-12 Thread Peter Reid via use-livecode
One note of caution regarding the use of the "repeat for each" loop, whilst you 
will get a loop iteration for every value in the collection (fldhexa3 in your 
example), you are not guaranteed the order in which they will occur.  This 
doesn't matter in a lot of cases but does matter when the sequence is 
significant.  In the case of your example I believe sequence is critical, 
otherwise the pixels might appear to be scrambled!

The following adjusted loop guarantees the sequence at the expense of speed:

  put 1 into i
  repeat for each word theWord in fldhexa3
 put word i of fldhexa3 into theWord
 put 00 & theword & theword & theword after tVar2
 add 1 to i
  end repeat

The original "improved" loop reduces the run-time to 25%.  However, the 
"modified improved" loop only manages to reduce the original run-time to 50%.

The suggested loop above takes advantage of the "for each" mechanism to produce 
a set of iterations very rapidly but gets slowed by the need to guarantee 
sequence. I wonder whether the LC engine could impose strict sequence more 
effectively with a variant of the "for each" loop such as

  repeat for each sequenced word x in theCollection
 ...
  end repeat

My own tests, comparing the speed of the 4 common repeat loops, imply that the 
current "for each" form is hugely faster than the others.  I tested "repeat for 
each...", "repeat while...", "repeat until...", "repeat with..." and a 
simulated "repeat for each sequenced..." forms using a simple loop body that 
added lines of text one after another, e.g.

  put empty into tData
  repeat with i = 1 to tMaxI
put line i of tList & return after tData
  end repeat

I ran this test for 250,000 iterations for each type of loop, which produced 
the following timings:

  Starting test for 250,000 iterations...
  repeat for each... 0 mins 0 secs 111 millisecs
  repeat while... 0 mins 30 secs 569 millisecs
  repeat until... 0 mins 30 secs 379 millisecs
  repeat with... 0 mins 30 secs 341 millisecs
  repeat for each seq... 0 mins 30 secs 524 millisecs

As you can see, in this test the "repeat for each..." form was approx. 275 
times faster than the other forms.  Also the simulated "repeat for each 
sequenced..." form was no faster than the other forms.  This shows how variable 
the speed will be with the simulated "repeat for each sequenced...", depending 
on the details of the loop body.

If there was a "repeat for each sequenced..." form of loop in LC, any speed-up 
could be very beneficial even if the amount of speed-up was only 10 times 
faster!

Cheers

Peter
--
Peter Reid
Loughborough, UK

> On 9 Oct 2017, at 10:18am, use-livecode-requ...@lists.runrev.com wrote:
> 
> Message: 12
> Date: Sat, 7 Oct 2017 15:53:44 +0200
> From: Malte Pfaff-Brill <revolut...@derbrill.de>
> To: use-livecode@lists.runrev.com
> Subject: Re: Atkinson dither algorithm  
> Message-ID: <42023b36-0a4e-4251-bb0c-9cd46de55...@derbrill.de>
> Content-Type: text/plain; charset=us-ascii
> 
> Hi Al,
> 
> I already posted on the forums, but for completeness also here:
> 
> a lot can be done by replacing repeat with with repeat for each where you can.
> 
> --repeat with i = 1 to the number of words of fldhexa3
>   --   put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of 
> fldhexa3 after tVar2
>   --end repeat
> 
>   repeat for each word theWord in fldhexa3
>  put 00 & theword & theword & theword after tVar2
>   end repeat
> 
> 
> A sidenode:
> 
> I always use strict compile mode, therefore I added the needed variable 
> declarations and noticed you use startTime as a variablename, which is a 
> reserved keyword. That is not a good idea.  (I noticed, because I managed to 
> freeze liveCode where I fixed only half of the use of startTime. Booom.)
> 
> Cheers,
> 
> malte


___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-07 Thread Alejandro Tejada via use-livecode
Hi Malte,

Malte Brill wrote:
> I already posted on the forums, but for completeness also here:
> a lot can be done by replacing repeat with with repeat for each where you
can.
>
> --repeat with i = 1 to the number of words of fldhexa3
> --put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of
fldhexa3 after tVar2
> --end repeat
>
> repeat for each word theWord in fldhexa3
>  put 00 & theword & theword & theword after tVar2
> end repeat

This change reduced the time in a 25%!
Wonderful. Thanks a lot Malte :-D

> I always use strict compile mode, therefore I added the needed variable
> declarations and noticed you use startTime as a variablename, which is a
> reserved keyword. That is not a good idea.  (I noticed, because I managed
to
> freeze liveCode where I fixed only half of the use of startTime. Booom.)

startTime is a property of media players, so I am surprised that
LiveCode do not warn me about this. :-o

Also, I will try others less complex and simpler dithering algorithms as
Floyd-Steinberg and Sierra Lite to measure total time differences.

http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/

Malte, Thanks again for taking a look and improve this code!
Have a nice weekend!

Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-07 Thread Malte Pfaff-Brill via use-livecode
Hi Al,

I already posted on the forums, but for completeness also here:

a lot can be done by replacing repeat with with repeat for each where you can.

 --repeat with i = 1 to the number of words of fldhexa3
   --   put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of 
fldhexa3 after tVar2
   --end repeat

   repeat for each word theWord in fldhexa3
  put 00 & theword & theword & theword after tVar2
   end repeat


A sidenode:

I always use strict compile mode, therefore I added the needed variable 
declarations and noticed you use startTime as a variablename, which is a 
reserved keyword. That is not a good idea.  (I noticed, because I managed to 
freeze liveCode where I fixed only half of the use of startTime. Booom.)

Cheers,

malte
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode


Re: Atkinson dither algorithm

2017-10-07 Thread Alejandro Tejada via use-livecode
I have posted a demo stack in the forums:
https://forums.livecode.com/viewtopic.php?f=10=29935

Have a nice weekend!
Al

On Sat, Oct 7, 2017 at 1:52 AM, Alejandro Tejada 
wrote:

> Hi All,
>
> I am stuck trying to make this code for Bill Atkinson
> dithering algorithm much more faster.
> Any ways to speed this code?
> Follow the recipe and watch out for lines broken
> by mail character length limit.
>
> Recipe:
>
> 1) Import an small image (200x200 pixels) and
> name it as "Image" (you could import a small
> transparent png or a small jpg image)
>
> 2) Optionally, create a scrollbar type slider
> with a range between 0 and 255.
> Set the name of this scrollbar as "ThresholdDither"
> and move the slider to 127 or 0 or 255.
>
> 3) Paste the following script in a button and
> click on it to run this code:
>
> on mouseUp
>
>put the millisecs into startTime
>set the cursor to busy
>
>put the alphadata of img "Image" into tAlphaData
>put the imagedata of img "Image" into tVar
>-- img "Image" could be a grayscale image
>-- where all 3 channels: Red, Green, Blue
>-- are identical or a color image where only
>-- the red channel is used
>
>delete char 1 of tVar
>-- the first char of the imagedata is part
>-- of the alphadata or maskdata
>repeat with i = 1 to length(tVar) step 4
>   put chartonum(char i of tVar) & space after fldhex
>end repeat
>delete last char of fldhex -- a space
>-- fldhex now contains a single channel of the RGB image
>-- converted to numbers between 0 and 255
>
>put the number of words of fldhex into lenghtofldhex
>put the width of img "Image" into tImageWidth
>put the height of img "Image" into tImageHeight
>
>repeat with i = 1 to lenghtofldhex step tImageWidth
>-- We need as many words per line, as pixels contains
>-- the image width (because each pixel is represented
>-- by a word and this word is number between 0 and 255)
>
>put word i to ( i + ((tImageWidth) - 1)) of fldhex & cr after fldhexa2
>end repeat
>
>put empty into fldhex
>delete last char of fldhexa2
>-- deleting the last cr character
>
>put the number of lines of fldhexa2 into sYsize
>put the number of words of line 1 of fldhexa2 into sXsize
>
>// get the scrollbar value
>-- tThreshold is a value between 0 and 255
>if existence(sb the "ThresholdDither") then
>put thumbPos of sb the "ThresholdDither" into tThreshold
>else
>put 127 into tThreshold
>end if
>
>repeat with tY = 1 to sYsize
>   repeat with tX = 1 to sXsize
>
>  put tX into tPixelPosition
>
>  put word (tPixelPosition) of line tY of fldhexa2 into
> tOldPixelValue
>
>  if round(tOldPixelValue) <= tThreshold then
> put 0 into tNewPixelValue
>  else
> put 255 into tNewPixelValue
>  end if
>
>  put (tOldPixelValue - tNewPixelValue)/8 into tDifusionError
>
>  -- Atkinson dither add the diffusion error
>  -- to 6 adjacent pixels
>  -- x o o
>  --  o o o
>  -- o
>
>  put tNewPixelValue & space after fldhexa3
>
>
> if tPixelPosition < sXsize then
>put tDifusionError + word (tPixelPosition + 1) of line tY
> of fldhexa2 into word (tPixelPosition + 1) of line tY of fldhexa2
>
>
>   if tPixelPosition < (sXsize-1) then
>   put tDifusionError + word (tPixelPosition + 2) of line
> tY of fldhexa2 into word (tPixelPosition + 2) of line tY of fldhexa2
>end if
>
>
> end if
>
>
> if tY < sYsize then
>
>
>if tPixelPosition > 1 then
>   put tDifusionError + word (tPixelPosition - 1) of line
> tY + 1 of fldhexa2 into word (tPixelPosition - 1) of line tY + 1 of fldhexa2
>end if
>
>
>put tDifusionError + word (tPixelPosition) of line tY + 1
> of fldhexa2 into word (tPixelPosition) of line tY + 1 of fldhexa2
>
>
>if tPixelPosition < sXsize then
>   put tDifusionError + word (tPixelPosition + 1)  of line
> tY + 1 of fldhexa2 into word (tPixelPosition + 1) of line tY + 1 of fldhexa2
>end if
>
>
>if tY < (sYsize - 1) then
>   put tDifusionError + word (tPixelPosition) of line tY +
> 2 of fldhexa2 into word (tPixelPosition) of line tY + 2 of fldhexa2
>end if
>
>
> end if
>
>   end repeat
>end repeat
>
>replace "0" with "00" in fldhexa3
>replace "255" with "FF" in fldhexa3
>
>repeat with i = 1 to the number of words of fldhexa3
>   put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of
> fldhexa3 after tVar2
>end repeat
>put binaryEncode("H*",tVar2) into tVar3
>
>create img
>set the height of it to the height of img "Image"
>set the width of it to the width of img 

Atkinson dither algorithm

2017-10-06 Thread Alejandro Tejada via use-livecode
Hi All,

I am stuck trying to make this code for Bill Atkinson
dithering algorithm much more faster.
Any ways to speed this code?
Follow the recipe and watch out for lines broken
by mail character length limit.

Recipe:

1) Import an small image (200x200 pixels) and
name it as "Image" (you could import a small
transparent png or a small jpg image)

2) Optionally, create a scrollbar type slider
with a range between 0 and 255.
Set the name of this scrollbar as "ThresholdDither"
and move the slider to 127 or 0 or 255.

3) Paste the following script in a button and
click on it to run this code:

on mouseUp

   put the millisecs into startTime
   set the cursor to busy

   put the alphadata of img "Image" into tAlphaData
   put the imagedata of img "Image" into tVar
   -- img "Image" could be a grayscale image
   -- where all 3 channels: Red, Green, Blue
   -- are identical or a color image where only
   -- the red channel is used

   delete char 1 of tVar
   -- the first char of the imagedata is part
   -- of the alphadata or maskdata
   repeat with i = 1 to length(tVar) step 4
  put chartonum(char i of tVar) & space after fldhex
   end repeat
   delete last char of fldhex -- a space
   -- fldhex now contains a single channel of the RGB image
   -- converted to numbers between 0 and 255

   put the number of words of fldhex into lenghtofldhex
   put the width of img "Image" into tImageWidth
   put the height of img "Image" into tImageHeight

   repeat with i = 1 to lenghtofldhex step tImageWidth
   -- We need as many words per line, as pixels contains
   -- the image width (because each pixel is represented
   -- by a word and this word is number between 0 and 255)

   put word i to ( i + ((tImageWidth) - 1)) of fldhex & cr after fldhexa2
   end repeat

   put empty into fldhex
   delete last char of fldhexa2
   -- deleting the last cr character

   put the number of lines of fldhexa2 into sYsize
   put the number of words of line 1 of fldhexa2 into sXsize

   // get the scrollbar value
   -- tThreshold is a value between 0 and 255
   if existence(sb the "ThresholdDither") then
   put thumbPos of sb the "ThresholdDither" into tThreshold
   else
   put 127 into tThreshold
   end if

   repeat with tY = 1 to sYsize
  repeat with tX = 1 to sXsize

 put tX into tPixelPosition

 put word (tPixelPosition) of line tY of fldhexa2 into
tOldPixelValue

 if round(tOldPixelValue) <= tThreshold then
put 0 into tNewPixelValue
 else
put 255 into tNewPixelValue
 end if

 put (tOldPixelValue - tNewPixelValue)/8 into tDifusionError

 -- Atkinson dither add the diffusion error
 -- to 6 adjacent pixels
 -- x o o
 --  o o o
 -- o

 put tNewPixelValue & space after fldhexa3


if tPixelPosition < sXsize then
   put tDifusionError + word (tPixelPosition + 1) of line tY of
fldhexa2 into word (tPixelPosition + 1) of line tY of fldhexa2


  if tPixelPosition < (sXsize-1) then
  put tDifusionError + word (tPixelPosition + 2) of line tY
of fldhexa2 into word (tPixelPosition + 2) of line tY of fldhexa2
   end if


end if


if tY < sYsize then


   if tPixelPosition > 1 then
  put tDifusionError + word (tPixelPosition - 1) of line tY
+ 1 of fldhexa2 into word (tPixelPosition - 1) of line tY + 1 of fldhexa2
   end if


   put tDifusionError + word (tPixelPosition) of line tY + 1 of
fldhexa2 into word (tPixelPosition) of line tY + 1 of fldhexa2


   if tPixelPosition < sXsize then
  put tDifusionError + word (tPixelPosition + 1)  of line
tY + 1 of fldhexa2 into word (tPixelPosition + 1) of line tY + 1 of fldhexa2
   end if


   if tY < (sYsize - 1) then
  put tDifusionError + word (tPixelPosition) of line tY + 2
of fldhexa2 into word (tPixelPosition) of line tY + 2 of fldhexa2
   end if


end if

  end repeat
   end repeat

   replace "0" with "00" in fldhexa3
   replace "255" with "FF" in fldhexa3

   repeat with i = 1 to the number of words of fldhexa3
  put 00 & word i of fldhexa3 & word i of fldhexa3 & word i of fldhexa3
after tVar2
   end repeat
   put binaryEncode("H*",tVar2) into tVar3

   create img
   set the height of it to the height of img "Image"
   set the width of it to the width of img "Image"
   set the imagedata of it to tVar3
   set the alphaData of it to tAlphaData

   put the millisecs - startTime && "milliseconds to create Atkinson Dither"

end mouseUp

Thanks in advance!
Al
___
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode