Atkinson dither algorithm & 'for each' loop

Alejandro Tejada capellan2000 at gmail.com
Fri Oct 13 05:53:51 EDT 2017


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



More information about the use-livecode mailing list