-- Posterize --
-- This algorithm posterizes an image with results identical to Photoshop's Posterize
command.
-- History --
-- May 5, 2005: Luisa Klose <luisa@axiomx.com>
-- The posterize function takes 4 parameters: an RGB image object, its width, its height,
and the posterize value.
-- This example uses a mouseUp handler to call the function, and gets the posterize value
from a field.
on mouseUp
-- Create a variable representing the posterize value from
the field's contents.
posterizeValue = integer(field
"posterize value")
-- Make sure that the field contains an integer between 2 and
255.
if integerP(posterizeValue)
= 0 or posterizeValue < 2 or posterizeValue > 255 then
-- If not, show an alert.
alert "Enter
an integer between 2 and 255."
else
-- If the value is within range, duplicate a
member's image to create the image object.
myImage = duplicate(member(1).image)
-- Run the function.
posterize(myImage, myImage.width,
myImage.height, posterizeValue)
-- Copy the posterized image object back to the
member's image.
member(1).image.copyPixels(myImage, member(1).rect,
myImage.rect)
end if
end
-- The function works with integers between 2 and 255. Lower numbers produce more dramatic
results.
-- Because it works with an image object, there's no need to use return to pass it back to
the handler that called it.
on posterize thisImage, thisW, thisH, thisValue
-- Show the hourglass cursor.
cursor 4
-- First divide 256 possible values by the posterize value to
get the number of color areas.
numOfAreas = 256.0000 / thisValue
-- Then the number of color values between 0 and 255 that are
defined by the boundaries between the above color areas.
-- To understand how this works, remember that it only takes 1 line to divide a
rectangle into 2 areas.
numOfValues = 255.0000 / (thisValue - 1)
-- Subtract 1 from the width and height because pixel
coordinates start at 0.
thisW = thisW - 1
thisH = thisH - 1
-- Create the repeat loops to analyze and replace pixel
values in the image object.
-- This example processes the image left-to-right and top-to-bottom.
repeat with y = 0 to thisH
repeat with x = 0 to thisW
-- Get the pixel's color and set
variables from its RGB components.
currentcolor = thisImage.getPixel(x,
y)
currentRed = currentcolor.red
currentGreen = currentcolor.green
currentBlue = currentcolor.blue
-- First, we need to find the color
area that the pixel's red value falls within.
-- The result has to be an integer, but it can't be rounded
to the higher value.
-- Since we're working with floating point numbers, there's
no graceful way to convert them to integers without rounding.
-- So we have to create 2 variables and perform a
comparison to get the correct number.
-- Divide the pixel's value by the number of color areas to
get the floating point number.
redAreaFloat = currentRed / numOfAreas
-- Round it to the nearest integer.
redArea = integer(redAreaFloat)
-- If the number was rounded to the
higher value, subtract 1 from it.
if redArea > redAreaFloat then redArea = redArea - 1
-- Now we can find the pixel's new
color value. Again we need to create 2 variables to compare.
-- Multiply the number of color
values by pixel's color area to get the fraction.
newRedFloat = numOfValues * redArea
-- Round it.
newRed = integer(newRedFloat)
-- If the number was rounded to the
higher value, subtract 1 from it.
if newRed > newRedFloat then newRed = newRed - 1
-- Do the same for the pixel's green
and blue values.
greenAreaFloat = currentGreen / numOfAreas
greenArea = integer(greenAreaFloat)
if greenArea >
greenAreaFloat then greenArea = greenArea - 1
newGreenFloat = numOfValues * greenArea
newGreen = integer(newGreenFloat)
if newGreen >
newGreenFloat then newGreen = newGreen - 1
blueAreaFloat = currentBlue / numOfAreas
blueArea = integer(blueAreaFloat)
if blueArea >
blueAreaFloat then blueArea = blueArea - 1
newBlueFloat = numOfValues * blueArea
newBlue = integer(newBlueFloat)
if newBlue > newBlueFloat then newBlue = newBlue - 1
-- Set the pixel to the new color.
thisImage.setPixel(x, y, rgb(newRed, newGreen, newBlue))
end repeat
end repeat
cursor 0
end