The @image
module contains functions and classes for manipulating images.
Functions
:exif(path)
#
Get EXIF metadata from an image file, typically a JPEG.
Parameters
-
path
—
the path of the file
Return
-
an object containing the following fields:
- width — the width of the image in pixels
- height — the height of the image in pixels
- orientation — the orientation of the image:
- 1 or 2 = right side up
- 3 or 4 = upside down
- 5 or 6 = rotated left (counter clockwise)
- 7 or 8 = rotated right (clockwise)
- See diagram
here
- software — the software used to create the image
- copyright — the copyright on the image
- description — the description of the image
-
iso — the
ISO
setting of the camera, which describes the light sensitivity of the sensor; sometimes described as "film speed",
because more sensitive films react faster to light exposure
-
f_stop — the
f-stop setting of the camera, which describes the aperture relative to focal length;
larger numbers indicate a wider
field of view
and shallower
depth of field
-
exposure_secs — the
exposure time in seconds
-
focal_length_mm — the
focal length in millimeters
- flash — a boolean indicating whether flash was used
-
time — an object with various times in string format
- original — when the picture was taken
- changed — when the picture was changed
- digitized — when the picture was digitized
-
camera — an object describing the camera
- make — the make of the camera
- model — the model of the camera
-
lens — an object describing the lens used
- make — the make of the lens
- model — the model of the lens
- f_min — the minimum f-stop of the lens
- f_max — the maximum f-stop of the lens
- focal_min — the minimum focal length of the lens
- focal_max — the maximum focal length of the lens
Notes
A lot of these values assume the use of a professional camera with a detachable lens
(DSLR), and don't really apply to modern cell phone cameras
(although cell phone cameras are getting fancier and some have multiple lenses now).
:plot(data,cols,type)
#
Generate a plot from tabular data.
Parameters
-
data
—
a 2D table of data; first row should be headers
-
cols
—
an array of strings referring to columns within data to examine;
the first column is the x-axis and any subsequent columns are the y-axis
(optional, default is all the columns in order of appearance)
-
type
—
a string referring to the type of plot to generate (optional, default is "line");
should be one of the following:
-
line — generate a line graph (default)
-
bar — generate a bar graph
-
scatter — generate a scatter plot
-
linreg — generate a scatter plot with linear regression lines
-
pie — generate a rectangular pie chart
Return
Notes
This uses the same underlying code as my plot tool, so see that page for output examples.
@surface
Methods
A surface is an image, represented internally as an array of pixels, which can be manipulated.
Each pixel is 32 bits: 8 bits for each of the color components (red, green, blue), and 8 bits for alpha (transparency).
This allows the color of each pixel to be represented as a 32-bit integer.
The order of the pixels is left-to-right, top-to-bottom (just like text).
The order of the components can be changed with :set_color_format().
Most methods return the surface itself so that they they can be chained to save typing.
Most methods can take color as either number or string. When passed as a string, the color is converted to a number using
:color().
:new()
#
:new(path)
:new(width,height)
Create a new surface.
Parameters
-
path
—
the path to a PNG, BMP, or JPEG file
-
width
—
the width in pixels
-
h
—
the height in pixels
Return
Notes
If no parameters are specified, an empty 0 by 0 surface is created.
If path is specified, the surface is loaded from a file.
If width and height are specified, a blank (all black) width by height surface is created.
:load(path)
#
Load data from file into surface.
Parameters
-
path
—
the path to a PNG, BMP, or JPEG file
Return
Notes
If the file fails to load, :data() and :data_ptr() will be null.
:save(path)
#
Save surface to file.
Parameters
-
path
—
the path to a PNG, BMP, or JPEG file
Return
:clear()
#
Clear all data and make the surface 0x0 and empty (no data).
Return
Notes
After calling this, :data() and :data_ptr() will be null.
:allocate(width,height)
#
Allocate data for this surface.
Parameters
-
width
—
the width in pixels
-
height
—
the height in pixels
Return
Notes
After calling, this surface will be a width by height and blank (all black).
:width()
#
Get the width in pixels.
Return
-
a number which is the width in pixels
:height()
#
Get the height in pixels.
Return
-
a number which is the height in pixels
:size()
#
Get the size in pixels, which is equivalent to :width() multiplied by :height().
Return
:data()
#
Get a copy of the surface data as bytes.
Return
-
a string containing a copy of the surface data as bytes
Notes
The length of the string will be :size() multiplied by 4 (since there are 4 bytes per pixel).
Remember that strings in Axiom are just arbitrary bytes (no explicit encoding) and can also hold binary data.
:data_ptr()
#
Get a pointer to the surface data, for use with native code
(@native)
Return
-
a number that is the pointer to the surface data
Notes
The length of the data in bytes is :size() multiplied by 4 (since there are 4 bytes per pixel).
Remember that pointers in Axiom are opaque (incompatible with pointer arithmetic), and are just for interfacing with native code.
:get(x,y)
#
Get the color of a pixel.
Parameters
-
x
—
the x coordinate
-
y
—
the y coordinate
Return
-
a number containing the color of the pixel interpreted as a 32-bit integer
Notes
The method :rgba() can be used to get individual components from the color.
Remember that 0,0 is at the top left.
If the coordinates are out of bounds, the behavior is to return the pixel that would be mirrored from the out-of-bounds edge.
This is for compatibility with image algorithms that use
kernels.
:set(x,y,color)
#
Set the color of a pixel
Parameters
-
x
—
the x coordinate
-
y
—
the y coordinate
-
color
—
the color as a number or string
Return
:rgba(color)
#
Get components of a color.
Parameters
-
color
—
the color as a number
Return
-
an array containing the the color components in [r,g,b,a] order
Notes
All components are unsigned bytes, so they will be in the range [0,255].
:hsl(color)
#
Get the components of a color in HSL (Hue, Saturation, Lightness) color space.
Parameters
-
color
—
the color as a number
Return
-
an array containing the the color components in [h,s,l] order
Notes
Hue will be in the range [0,360):
- 0 = red
- 60 = yellow
- 120 = green
- 180 = cyan
- 240 = blue
- 300 = purple
Saturation will be in the range [0,1], where 0 = grayscale and 1 = pure color.
Lightness will be in the range [0,1], where 0 = black, 1 = white.
:luma(color)
#
Convert a color to grayscale.
Parameters
-
color
—
the color as a number
Return
-
the luma value in range [0,255]
:color(str)
#
Create a color from string.
Parameters
-
str
—
the color as a string; see notes for acceptable formats
Return
Notes
Colors can be specified in one of the following formats:
- RGBA hex: #rrggbbaa
- RGB hex: #rrggbb
- RGBA hex, 16-bit: #rgba
- RGB hex, 16-bit: #rgb
- RGBA tuple: rgba(r,g,b,a)
- RGB tuple: rgb(r,g,b)
- HSLA tuple: hsl(h,s,l,a)
- HSL tuple: hsl(h,s,l)
- Constant: white, black, red, green, blue, orange, purple, yellow
For the tuples, RGB must be [0,255], alpha must be [0,1], hue must be [0,360), saturation [0,1], and lightness [0,1].
If alpha is not specified, it is assumed to be 0xff (255).
If str is actually a number, no processing is done.
:get_color_format()
#
Get the pixel color format.
Return
-
one of the following strings:
:set_color_format(format,convert)
#
Set the pixel color format
Parameters
-
format
—
the format; see acceptable values in
:get_color_format()
-
convert
—
boolean, whether or not to convert existing data in the surface to the new format
Return
:copy(s)
#
Set this surface to a copy of another surface.
Parameters
Return
:swap(s)
#
Swap data with another surface.
Parameters
Return
:crop(x,y,w,h,s)
#
Set this surface to the cropped area of another surface.
Parameters
-
x
—
the x coordinate
-
y
—
the y coordinate
-
w
—
the width of the cropped area
-
h
—
the height of the cropped area
-
s
—
another surface (optional; if not specified, this surface is used)
Return
:fill(color)
#
Fill the surface with a single color.
Parameters
-
color
—
the color as a number or string
Return
:interpolate(s,p)
#
Interpolate this surface with another surface.
Parameters
-
s
—
another surface
-
p
—
the amount, see notes
Return
Notes
Each pixel in both surfaces are blended using the following formula: a*p + b*(1-p),
where a is every pixel in this surface and b is every pixel in the other surface.
If p is greater than 1, then a is "extrapolated" from b.
:blend(s,p,q)
#
Blend this surface with another surface.
Parameters
-
s
—
another surface
-
p
—
the contribution from this surface
-
q
—
the contribution from the other surface
Return
Notes
Each pixel in both surfaces are blended using the following formula: a*p + b*q,
where a is this surface and b is the other surface.
:blur(radius)
#
Blur the image.
Parameters
-
radius
—
the radius in pixels (optional, default=10)
Return
:desaturate()
#
Desaturate the image (convert to grayscale).
Return
:lazy_sharpen(amount)
#
Sharpen the image by extrapolating from the average color.
Parameters
-
amount
—
how much to sharpen the image (optional, default=3.0)
Return
Notes
Faster than :sharpen().
:sharpen(amount,blur_radius)
#
Sharpen the image by extrapolating from a blurred image.
Parameters
-
amount
—
how much to sharpen the image (optional, default=3.0)
-
blur_radius
—
the radius to use when blurring the image (optional, default=2)
Return
Notes
Slower than :lazy_sharpen() but should give a nicer result.
:saturate(amount)
#
Saturate the image by extrapolating from a desaturated image.
Parameters
-
amount
—
how much to saturate the image (optional, default=3.0)
Return
:negate()
#
Negate the image (invert the colors).
Return
:brighten(amount)
#
Brighten the image by extrapolating from black.
Parameters
-
amount
—
how much to brighten the image (optional, default=1.25)
Return
:lazy_resize(scale)
#
:lazy_resize(w,h)
Resize this image using nearest-neighbor for in-between pixels.
Parameters
-
scale
—
how much to scale both width and height
(values <1 shrink the image, and values >1 enlarge the image)
-
w
—
the exact width in pixels to resize to
-
h
—
the exact height in pixels to resize to
Return
:resize(scale)
#
:resize(w,h)
Resize this image with upsampling/downsampling for in-between pixels.
Parameters
-
scale
—
how much to scale both width and height
(values <1 shrink the image, and values >1 enlarge the image)
-
w
—
the exact width in pixels to resize to
-
h
—
the exact height in pixels to resize to
Return
Notes
Slower than :lazy_resize() but gives a better result.
:threshold(luma)
#
Perform a threshold operation on the image, which changes all pixels white if > threshold,
and black if <= threshold.
Parameters
-
luma
—
the luma threshold [0,255]
Return
:average()
#
Get the average color of the image.
Return
-
the average color as a number
:text(x,y,str,color,face,size,transparent)
#
Draw text on this surface.
Parameters
-
x
—
the x coordinate of the top-left of the text
-
y
—
the y coordinate of the top-left of the text
-
str
—
the text to draw
-
color
—
the color of the text
-
face
—
the font face to use (optional, default is "Tahoma")
-
size
—
the font size to use (optional, default is 12)
-
transparent
—
whether or not to use the alpha component of the color when blending with the background
(optional, default is false)
Return
-
the height of the drawn text in pixels
Notes
The text is bound by surface width, and will wrap.
If face is specified, the current directory and the operating system font directories will be searched.
Only TrueType (.ttf) files are supported.
Tahoma is the default because it is already present on most operating systems.
:text_width(str,face,size)
#
Get the width of the text given the font face and size.
Parameters
-
str
—
the text to draw
-
face
—
the font face to use (optional, default is "Tahoma")
-
size
—
the font size to use (optional, default is 12)
Return
-
the width of the text in pixels
Notes
Doesn't actually draw anything on the surface; just used for layout calculations.
:line_height(face,size)
#
Get the line height given the font face and size.
Parameters
-
face
—
the font face to use (optional, default is "Tahoma")
-
size
—
the font size to use (optional, default is 12)
Return
-
the height of a line of text in pixels
Notes
Doesn't actually draw anything on the surface; just used for layout calculations.
:blit(s,x,y,use_alpha)
#
Blit (copy image from) another surface onto this surface.
Parameters
-
s
—
another surface
-
x
—
the x coordinate
-
y
—
the y coordinate
-
use_alpha
—
whether or not to use the alpha channel of s as a mask when blitting
(optional, default=true)
Return
:rect(x,y,w,h,color,filled)
#
Draw a rectangle.
Parameters
-
x
—
the x coordinate of the upper left
-
y
—
the y coordinate of the upper left
-
w
—
the w coordinate
-
h
—
the h coordinate
-
color
—
the color as a number or string
-
filled
—
whether or not to draw the rectangle filled (or just the outline)
(optional, default=false)
Return
:line(x1,y1,x2,y2,color)
#
Draw a line.
Parameters
-
x1
—
the start x coordinate
-
y1
—
the start y coordinate
-
x2
—
the end x coordinate
-
y2
—
the end y coordinate
-
color
—
the color as a number or string
Return
:circle(x,y,radius,color,filled)
#
Draw a circle.
Parameters
-
x
—
the x coordinate of the center
-
y
—
the y coordinate of the center
-
radius
—
the radius of the circle in pixels
-
color
—
the color as a number or string
Return
:rotate_left()
#
Rotate the image left (counter-clockwise).
Return
:rotate_right()
#
Rotate the image right (clockwise).
Return
:flip(x_axis,y_axis)
#
Flip the image across the x-axis, y-axis, or both.
Parameters
-
x_axis
—
boolean, whether or not to flip over the x-axis (flip vertically)
-
y_axis
—
boolean, whether or not to flip over the y-axis (flip horizontally)
Return
:pivot()
#
Flip the image across the diagonal that runs from the top-left to the bottom-right.
Return
:cinema()
#
Enhance the image in a cinema-like manner; increase sharpness and contrast while reducing saturation.
Return
:find_exact(s)
#
Find another surface within this surface.
Parameters
Return
-
an array of coordinate pairs, one for every coordinate where s was found
(or an empty array if not found)
Notes
All pixels must match exactly.
:find_fuzzy(s)
#
Find another surface within this surface using fuzzy matching.
Parameters
Return
-
an array of coordinate pairs, one for every coordinate where s was found
(or an empty array if not found)
Notes
Only a subset of a pixels in s have to match.
:ascii(x,y,str,color,scale)
#
Draw text on this surface using the ASCII 5x7 font which is typically seen on a
Code Page 437 console.
(The font face is pixelated and fixed width).
Parameters
-
x
—
the x coordinate of the top-left of the text
-
y
—
the y coordinate of the top-left of the text
-
str
—
the text to draw
-
color
—
the color as a number or string
-
scale
—
how much to scale up the font; must be a positive integer
(optional, default is 2)
Return
-
the height of the text in pixels
Notes
Each glyph is actually 5 by 8 pixels (the 8th pixel is the descender).
This function leaves a 1 pixel margin around the top and left of the glyph, so the total size is actually 6 by 9 pixels per letter.
(Assuming scale is 1).
The text is bound by surface width, and will wrap.
:ascii_table(scale)
#
Draw all ASCII 5x7 glyphs on this surface.
Parameters
-
scale
—
how much to scale up the font; must be a positive integer
(optional, default is 2)
Return
Notes
This is so you can view the entire font (since unlike TrueType fonts which typically have a viewer built into the operating system,
there is no other way to view the embedded 5x7 font). You can also view the image
here.
The replaces whatever was in the surface with an entirely new image.
:dither(bits)
#
Reduce the bit depth of each color component, and compensate for the loss in color accuracy by
dithering.
Parameters
-
bits
—
the number of bits to reduce the bit depth to for each component (original depth is 8)
(optional, default is 2)
Return
Notes
This truncates each color components of each pixel so that instead of being 8 bits, the most significant [8 - bits] bits are zeroed.
This is used within :hide() for preprocessing.
:hide(s,bits)
#
Hide an image within the most significant bits of this surface, also known as
steganography
Parameters
-
s
—
another surface
-
bits
—
the number of significant bits to use
Return
Notes
The image within s is dithered and has its bit depth reduced to bits.
It is then hidden in the most significant bits bits of the image within this surface, which makes it hard to detect.
:unhide(bits)
#
Reveal the image hidden within the most significant bits of this surface.
Parameters
-
bits
—
the number of significant bits to extract the image from
Return
Notes
Replaces this surface with the hidden image, if any. This is the opposite of :hide().