| Title: | Image Processing for Simulated Cameras |
|---|---|
| Description: | Uses convolution-based techniques to generate simulated camera bokeh, depth of field, and other camera effects, using an image and an optional depth map. Accepts both filename inputs and in-memory array representations of images and matrices, including common raster formats such as 'JPEG', 'PNG', 'TIFF', 'TGA', 'BMP', 'PSD', 'GIF', 'HDR', 'PIC', 'PNM', 'DNG', and 'EXR'. Includes functions to perform 2D convolutions, color correction, colorspace conversion, image/matrix reorientation and resizing, image and text overlays, exposure adjustment, camera vignette effects, and image titles. |
| Authors: | Tyler Morgan-Wall [aut, cph, cre] (ORCID: <https://orcid.org/0000-0002-3131-3814>), Syoyo Fujita [ctb, cph], Sean Barrett [ctb] |
| Maintainer: | Tyler Morgan-Wall <[email protected]> |
| License: | GPL-3 + file LICENSE |
| Version: | 0.26.0 |
| Built: | 2026-06-02 05:31:08 UTC |
| Source: | https://github.com/tylermorganwall/rayimage |
These objects are color space descriptors used by rayimage to tag images
and to convert between RGB spaces. Each descriptor is a named list with:
name: Character. Human-readable name of the space.
primaries: List with r, g, b entries giving xy chromaticities.
rgb_to_xyz: 3x3 numeric matrix (linear RGB -> CIE XYZ, Y=1 white).
xyz_to_rgb: 3x3 numeric matrix (CIE XYZ -> linear RGB).
white_xyz: Length-3 numeric XYZ of the reference white (normalized s.t. Y = 1).
white_name: Character label for the white (e.g., "D60", "D65").
These are used as:
attr(img, "colorspace"): the current working/display space for an image.
attr(img, "white_current"): the current assumed scene/display white (XYZ, Y=1).
CS_ACESCG CS_SRGB CS_P3D65 CS_BT2020 CS_ADOBECS_ACESCG CS_SRGB CS_P3D65 CS_BT2020 CS_ADOBE
Prebuilt RGB Working/Display Color Spaces
CS_ACESCG: ACEScg (AP1 primaries, D60, scene-linear). Recommended working space.
CS_SRGB: sRGB/Rec.709 (D65). Typical display space; used for PNG/JPEG/TIFF output.
CS_P3D65: Display P3 (D65). Wide-gamut display space.
CS_BT2020: BT.2020 (D65). Very wide-gamut; common for HDR mastering.
CS_ADOBE: Adobe RGB (D65). Photo workflows.
render_convert_colorspace() to convert images between spaces.
render_white_balance() for Bradford CAT within a working space.
plot_image(), ray_write_image() for display/output conversion.
# Tag a raw array as sRGB, then convert to ACEScg: arr = array(runif(64*64*4), dim = c(64, 64, 4)) ri = ray_read_image(arr, assume_colorspace = CS_SRGB, assume_white = CS_SRGB$white_xyz) riA = render_convert_colorspace(ri, to_mats = CS_ACESCG) plot_image(riA) # display-converted to sRGB automatically # Convert an sRGB JPEG to ACEScg on ingest: # img = ray_read_image("photo.jpg", normalize = FALSE) # img_aces = render_convert_colorspace(img, to_mats = CS_ACESCG)# Tag a raw array as sRGB, then convert to ACEScg: arr = array(runif(64*64*4), dim = c(64, 64, 4)) ri = ray_read_image(arr, assume_colorspace = CS_SRGB, assume_white = CS_SRGB$white_xyz) riA = render_convert_colorspace(ri, to_mats = CS_ACESCG) plot_image(riA) # display-converted to sRGB automatically # Convert an sRGB JPEG to ACEScg on ingest: # img = ray_read_image("photo.jpg", normalize = FALSE) # img_aces = render_convert_colorspace(img, to_mats = CS_ACESCG)
Dragon Image
dragondragon
An RGB 3-layer HDR rayimg array with 200 rows and 200 columns, generated using the rayrender package, with gamma correction.
Dragon Depthmap
dragondepthdragondepth
An matrix with 200 rows and 200 columns, representing
the depth into the dragon image scene. Generated using the rayrender package.
Distances range from 847 to 1411.
Generates a 2D disk with a gradual falloff.
Disk generated using the following formula:
(-22.35 * cos(1.68 * r2) + 85.91 * sin(1.68 * r2) ) * exp(-4.89 * r2) + (35.91 * cos(4.99 * r2) - 28.87 * sin(4.99 * r2)) * exp(-4.71 * r2) + (-13.21 * cos(8.24 * r2) - 1.57 * sin(8.24 * r2)) * exp(-4.05 * r2) + (0.50 * cos(11.90 * r2) + 1.81 * sin(11.90 * r2)) * exp(-2.92 * r2) + (0.13 * cos(16.11 * r2) - 0.01 * sin(16.11 * r2)) * exp(-1.51 * r2)The origin of the coordinate system is the center of the matrix.
generate_2d_disk(dim = c(11, 11), radius = 1, rescale_unity = FALSE)generate_2d_disk(dim = c(11, 11), radius = 1, rescale_unity = FALSE)
dim |
Default |
radius |
Default |
rescale_unity |
Default |
image(generate_2d_disk(101), asp=1)image(generate_2d_disk(101), asp=1)
Generates a 2D exponential distribution, with an optional argument to take the exponential to a user-defined power.
generate_2d_exponential( falloff = 1, dim = c(11, 11), width = 3, rescale_unity = FALSE )generate_2d_exponential( falloff = 1, dim = c(11, 11), width = 3, rescale_unity = FALSE )
falloff |
Default |
dim |
Default |
width |
Default |
rescale_unity |
Default |
image(generate_2d_exponential(1,31,3), asp=1)image(generate_2d_exponential(1,31,3), asp=1)
Generates a 2D gaussian distribution, with an optional argument to take the gaussian to a user-defined power.
generate_2d_gaussian( sd = 1, power = 1, dim = c(11, 11), width = 3, rescale_unity = FALSE )generate_2d_gaussian( sd = 1, power = 1, dim = c(11, 11), width = 3, rescale_unity = FALSE )
sd |
Default |
power |
Default |
dim |
Default |
width |
Default |
rescale_unity |
Default |
image(generate_2d_gaussian(1,1,31), asp=1)image(generate_2d_gaussian(1,1,31), asp=1)
Calculates font metrics for a specified font, font size, and style.
get_string_dimensions(string, font = "sans", size = 12, align = "center", ...)get_string_dimensions(string, font = "sans", size = 12, align = "center", ...)
string |
The string to be measured. |
font |
Default |
size |
A numeric value specifying the size of the font in points. |
align |
Default '"left"“. The string alignment. |
... |
Other arguments to pass to 'systemfonts::shape_string()“ |
The function renders specific characters ("d" for ascender, "g" for descender, "x" for neutral) using the specified font parameters. It calculates the bounding box of each character to determine the necessary adjustments for accurate text positioning.
A data.frame listing the string dimensions.
# Get height of basic sans font get_string_dimensions("This is a string", size=24)# Get height of basic sans font get_string_dimensions("This is a string", size=24)
Given a series of X and Y coordinates and an array/matrix, interpolates the Z coordinate using bilinear interpolation.
interpolate_array(image, x, y)interpolate_array(image, x, y)
image |
3-layer RGB/4-layer RGBA array, |
x |
X indices (or fractional index) to interpolate. |
y |
Y indices (or fractional index) to interpolate. |
Either a vector of values (if image is a matrix) or a list of interpolated values from each layer.
#if(interactive()){ #Interpolate a matrix interpolate_array(volcano,c(10,10.1,11),c(30,30.5,33)) #Interpolate a 3-layer array (returns list for each channel) interpolate_array(dragon,c(10,10.1,11),c(30,30.5,33)) #end}#if(interactive()){ #Interpolate a matrix interpolate_array(volcano,c(10,10.1,11),c(30,30.5,33)) #Interpolate a 3-layer array (returns list for each channel) interpolate_array(dragon,c(10,10.1,11),c(30,30.5,33)) #end}
Displays the image in the current device.
plot_image( image, draw_grid = FALSE, ignore_alpha = FALSE, asp = 1, new_page = TRUE, return_grob = FALSE, gp = grid::gpar(), angle = 0, show_linear = FALSE )plot_image( image, draw_grid = FALSE, ignore_alpha = FALSE, asp = 1, new_page = TRUE, return_grob = FALSE, gp = grid::gpar(), angle = 0, show_linear = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
draw_grid |
Default |
ignore_alpha |
Default |
asp |
Default |
new_page |
Default |
return_grob |
Default |
gp |
A |
angle |
Default |
show_linear |
Default |
#Plot the dragon array plot_image(dragon) #Make pixels twice as wide as tall plot_image(dragon, asp = 2) #Plot non-square images plot_image(dragon[1:100,,]) #Make pixels twice as tall as wide plot_image(dragon[1:100,,], asp = 1/2)#Plot the dragon array plot_image(dragon) #Make pixels twice as wide as tall plot_image(dragon, asp = 2) #Plot non-square images plot_image(dragon[1:100,,]) #Make pixels twice as tall as wide plot_image(dragon[1:100,,], asp = 1/2)
Displays the image in the current device.
plot_image_grid( input_list, dim = c(1, 1), asp = 1, draw_grid = FALSE, gp = grid::gpar() )plot_image_grid( input_list, dim = c(1, 1), asp = 1, draw_grid = FALSE, gp = grid::gpar() )
input_list |
List of 3-layer RGB/4-layer RGBA array, |
dim |
Default |
asp |
Default |
draw_grid |
Default |
gp |
A |
#Plot the dragon array plot_image_grid(list(dragon, 1-dragon), dim = c(1,2)) plot_image_grid(list(dragon, 1-dragon), dim = c(2,1)) plot_image_grid(list(dragon, NULL, 1-dragon), dim = c(2,2), asp = c(2,1,1/2)) plot_image_grid(list(dragon, NULL, NULL, dragon), dim = c(2,2), asp = c(2,1,1,1/2)) #Plot alongside the depth matrix dragon_depth_reoriented = render_reorient(dragondepth, transpose = TRUE, flipx = TRUE)/2000 plot_image_grid(list(dragondepth/2000, dragon, dragon, dragondepth/2000), dim = c(2,2))#Plot the dragon array plot_image_grid(list(dragon, 1-dragon), dim = c(1,2)) plot_image_grid(list(dragon, 1-dragon), dim = c(2,1)) plot_image_grid(list(dragon, NULL, 1-dragon), dim = c(2,2), asp = c(2,1,1/2)) plot_image_grid(list(dragon, NULL, NULL, dragon), dim = c(2,2), asp = c(2,1,1,1/2)) #Plot alongside the depth matrix dragon_depth_reoriented = render_reorient(dragondepth, transpose = TRUE, flipx = TRUE)/2000 plot_image_grid(list(dragondepth/2000, dragon, dragon, dragondepth/2000), dim = c(2,2))
Displays the working colorspace and non-neutral camera metadata alongside a numeric preview.
## S3 method for class 'rayimg' print(x = NULL, preview_n = 10, decimals = 3, color = TRUE, ...)## S3 method for class 'rayimg' print(x = NULL, preview_n = 10, decimals = 3, color = TRUE, ...)
x |
Default |
preview_n |
Default |
decimals |
Default |
color |
Default |
... |
Default “. Ignored. |
Invisibly returns x.
Reads an image from a file/array/matrix. From files, supports
JPEG, PNG, TIFF, TGA, BMP, PSD, GIF, HDR, PIC, PNM, EXR,
and DNG images.
ray_read_image( image, convert_to_array = FALSE, preview = FALSE, source_linear = NA, normalize = FALSE, dng_normalize = FALSE, normalize_to = CS_ACESCG, normalize_adapt_white = TRUE, assume_colorspace = NULL, assume_white = NULL, reset_camera_settings = FALSE, ... )ray_read_image( image, convert_to_array = FALSE, preview = FALSE, source_linear = NA, normalize = FALSE, dng_normalize = FALSE, normalize_to = CS_ACESCG, normalize_adapt_white = TRUE, assume_colorspace = NULL, assume_white = NULL, reset_camera_settings = FALSE, ... )
image |
3-layer RGB/4-layer RGBA array, |
convert_to_array |
Default |
preview |
Default |
source_linear |
Default |
normalize |
Default |
dng_normalize |
Default |
normalize_to |
Default |
normalize_adapt_white |
Default |
assume_colorspace |
Default |
assume_white |
Default |
reset_camera_settings |
Default |
... |
Arguments to pass to |
A rayimg RGBA array.
#Write as a png tmparr = tempfile(fileext=".png") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image() #Write as a JPEG (passing quality arguments via ...) tmparr = tempfile(fileext=".jpg") ray_read_image(dragon) |> ray_write_image(tmparr, quality = 0.2) ray_read_image(tmparr) |> plot_image() #Write as a tiff tmparr = tempfile(fileext=".tiff") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image() #Write as an exr tmparr = tempfile(fileext=".exr") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image()#Write as a png tmparr = tempfile(fileext=".png") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image() #Write as a JPEG (passing quality arguments via ...) tmparr = tempfile(fileext=".jpg") ray_read_image(dragon) |> ray_write_image(tmparr, quality = 0.2) ray_read_image(tmparr) |> plot_image() #Write as a tiff tmparr = tempfile(fileext=".tiff") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image() #Write as an exr tmparr = tempfile(fileext=".exr") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image()
Takes an RGB array/filename and writes it to file.
ray_write_image(image, filename, clamp = FALSE, write_linear = NA, ...)ray_write_image(image, filename, clamp = FALSE, write_linear = NA, ...)
image |
3-layer RGB/4-layer RGBA array, |
filename |
File to write to, with filetype determined by extension. Filetype can be
|
clamp |
Default |
write_linear |
Default |
... |
Arguments to pass to either |
A rayimg RGBA array.
#Write as a png tmparr = tempfile(fileext=".png") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image() #Write as a JPEG (passing quality arguments via ...) tmparr = tempfile(fileext=".jpg") ray_read_image(dragon) |> ray_write_image(tmparr, quality = 0.2) ray_read_image(tmparr) |> plot_image() #Write as a tiff tmparr = tempfile(fileext=".tiff") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image()#Write as a png tmparr = tempfile(fileext=".png") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image() #Write as a JPEG (passing quality arguments via ...) tmparr = tempfile(fileext=".jpg") ray_read_image(dragon) |> ray_write_image(tmparr, quality = 0.2) ray_read_image(tmparr) |> plot_image() #Write as a tiff tmparr = tempfile(fileext=".tiff") ray_read_image(dragon) |> ray_write_image(tmparr) ray_read_image(tmparr) |> plot_image()
Creates a colored RGBA outline or halo from an image alpha
channel or a supplied mask. When image is supplied, the original image is
composited over the outline by default.
render_alpha_outline( image = NULL, mask = NULL, expand = 0, edge_softness = 0.1, blur = 0, gap_fill = 1, gap_fill_alpha_threshold = 0.25, color = "black", alpha = 1, pad = 0, composite = TRUE, filename = NULL, preview = FALSE )render_alpha_outline( image = NULL, mask = NULL, expand = 0, edge_softness = 0.1, blur = 0, gap_fill = 1, gap_fill_alpha_threshold = 0.25, color = "black", alpha = 1, pad = 0, composite = TRUE, filename = NULL, preview = FALSE )
image |
Default |
mask |
Default |
expand |
Default |
edge_softness |
Default |
blur |
Default |
gap_fill |
Default |
gap_fill_alpha_threshold |
Default |
color |
Default |
alpha |
Default |
pad |
Default |
composite |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA output image with a padding attribute.
txt = render_text_image("\U0001F409", size = 120, background_alpha = 0) render_alpha_outline(txt, expand = 2, blur = 1, color = "purple") |> plot_image() #Make a rainbow outline render_alpha_outline(txt, expand = 2, blur = 0.1, color = "darkgreen") |> render_alpha_outline(expand = 2, blur = 0.1, color = "yellow") |> render_alpha_outline(expand = 2, blur = 0.1, color = "orange") |> render_alpha_outline(expand = 2, blur = 0.1, color = "red") |> render_alpha_outline(expand = 2, blur = 0.1, color = "purple") |> render_alpha_outline(expand = 2, blur = 0.1, color = "blue") |> plot_image()txt = render_text_image("\U0001F409", size = 120, background_alpha = 0) render_alpha_outline(txt, expand = 2, blur = 1, color = "purple") |> plot_image() #Make a rainbow outline render_alpha_outline(txt, expand = 2, blur = 0.1, color = "darkgreen") |> render_alpha_outline(expand = 2, blur = 0.1, color = "yellow") |> render_alpha_outline(expand = 2, blur = 0.1, color = "orange") |> render_alpha_outline(expand = 2, blur = 0.1, color = "red") |> render_alpha_outline(expand = 2, blur = 0.1, color = "purple") |> render_alpha_outline(expand = 2, blur = 0.1, color = "blue") |> plot_image()
Takes an image and a depth map to render the image with depth of field (i.e. similar to "Portrait Mode" in an iPhone). User can specify a custom bokeh shape, or use one of the built-in bokeh types.
render_bokeh( image, depthmap, focus = 0.5, focallength = 100, fstop = 4, filename = NULL, preview = TRUE, preview_focus = FALSE, bokehshape = "circle", bokehintensity = 1, bokehlimit = 0.8, rotation = 0, aberration = 0, progress = interactive(), ... )render_bokeh( image, depthmap, focus = 0.5, focallength = 100, fstop = 4, filename = NULL, preview = TRUE, preview_focus = FALSE, bokehshape = "circle", bokehintensity = 1, bokehlimit = 0.8, rotation = 0, aberration = 0, progress = interactive(), ... )
image |
3-layer RGB/4-layer RGBA array, |
depthmap |
Depth map filename or 1d array. |
focus |
Defaults |
focallength |
Default |
fstop |
Default |
filename |
Default |
preview |
Default |
preview_focus |
Default |
bokehshape |
Default |
bokehintensity |
Default |
bokehlimit |
Default |
rotation |
Default |
aberration |
Default |
progress |
Default |
... |
Additional arguments to pass to |
A rayimg RGBA array.
#Plot the dragon plot_image(dragon) #Plot the depth map plot_image(dragondepth/1500) #Preview the focal plane: render_bokeh(dragon, dragondepth, focus=950, preview_focus = TRUE) #Change the focal length: render_bokeh(dragon, dragondepth, focus=950, focallength=300) #Add chromatic aberration: render_bokeh(dragon, dragondepth, focus=950, focallength=300, aberration = 0.5) #Change the focal distance: render_bokeh(dragon, dragondepth, focus=600, focallength=300) render_bokeh(dragon, dragondepth, focus=1300, focallength=300) #Change the bokeh shape to a hexagon: render_bokeh(dragon, dragondepth, bokehshape = "hex", focallength=300, focus=600) #Change the bokeh intensity: render_bokeh(dragon, dragondepth, focallength=400, focus=900, bokehintensity = 1) render_bokeh(dragon, dragondepth, focallength=400, focus=900, bokehintensity = 3) #Rotate the hexagonal shape: render_bokeh(dragon, dragondepth, bokehshape = "hex", rotation=15, bokehintensity=3, focallength=400, focus=800)#Plot the dragon plot_image(dragon) #Plot the depth map plot_image(dragondepth/1500) #Preview the focal plane: render_bokeh(dragon, dragondepth, focus=950, preview_focus = TRUE) #Change the focal length: render_bokeh(dragon, dragondepth, focus=950, focallength=300) #Add chromatic aberration: render_bokeh(dragon, dragondepth, focus=950, focallength=300, aberration = 0.5) #Change the focal distance: render_bokeh(dragon, dragondepth, focus=600, focallength=300) render_bokeh(dragon, dragondepth, focus=1300, focallength=300) #Change the bokeh shape to a hexagon: render_bokeh(dragon, dragondepth, bokehshape = "hex", focallength=300, focus=600) #Change the bokeh intensity: render_bokeh(dragon, dragondepth, focallength=400, focus=900, bokehintensity = 1) render_bokeh(dragon, dragondepth, focallength=400, focus=900, bokehintensity = 3) #Rotate the hexagonal shape: render_bokeh(dragon, dragondepth, bokehshape = "hex", rotation=15, bokehintensity=3, focallength=400, focus=800)
Takes a logical matrix and returns the nearest distance to each TRUE value.
render_boolean_distance(boolean, rescale = FALSE)render_boolean_distance(boolean, rescale = FALSE)
boolean |
Logical matrix (or matrix of 1s and 0s), where distance will be measured to the |
rescale |
Default |
Matrix of distance values.
#Measure distance to plot_image(render_boolean_distance(t(volcano) > 150)) plot_image(render_boolean_distance(t(volcano) < 150)) #If we want to rescale this to zero to one (to visualize like an image), set rescale=TRUE plot_image(render_boolean_distance(t(volcano) > 150,rescale=TRUE))#Measure distance to plot_image(render_boolean_distance(t(volcano) > 150)) plot_image(render_boolean_distance(t(volcano) < 150)) #If we want to rescale this to zero to one (to visualize like an image), set rescale=TRUE plot_image(render_boolean_distance(t(volcano) > 150,rescale=TRUE))
Transforms an image to black and white, preserving luminance.
render_bw( image, rgb_coef = c(0.2126, 0.7152, 0.0722), filename = NULL, preview = FALSE )render_bw( image, rgb_coef = c(0.2126, 0.7152, 0.0722), filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
rgb_coef |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
#Plot the image with a title dragon |> render_title("Dragon", title_offset=c(10,10), title_bar_color="black", title_size=20, title_color = "white") |> render_bw(preview = TRUE)#Plot the image with a title dragon |> render_title("Dragon", title_offset=c(10,10), title_bar_color="black", title_size=20, title_color = "white") |> render_bw(preview = TRUE)
Clamps an image to a user-specified range, ignoring the alpha channel.
render_clamp( image, min_value = 0, max_value = 1, filename = NA, preview = FALSE, ... )render_clamp( image, min_value = 0, max_value = 1, filename = NA, preview = FALSE, ... )
image |
3-layer RGB/4-layer RGBA array, |
min_value |
Default |
max_value |
Default |
filename |
Default |
preview |
Default |
... |
Arguments to pass to either |
A rayimg RGBA array.
#The image of the unchanged image range(dragon) #Clamp the maximum and minimum values to one and zero render_clamp(dragon) |> range()#The image of the unchanged image range(dragon) #Clamp the maximum and minimum values to one and zero render_clamp(dragon) |> range()
Apply a technical/look 3x3 matrix to an image
render_color_correction( image, matrix = diag(3), filename = NULL, preview = FALSE )render_color_correction( image, matrix = diag(3), filename = NULL, preview = FALSE )
image |
Default |
matrix |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
# We will start with an image that's too warm--we want to correct it to # match the color of the second as closely as possible. dragon_D50 = render_white_balance(dragon, target_white = "D50", bake = TRUE) dragon_D75 = render_white_balance(dragon, target_white = "D75", bake = TRUE) plot_image(dragon_D50) plot_image(dragon_D75) # Fucntion to fit a color correction matrix fit_cc_matrix = function(src, tgt) { stopifnot(ncol(src) == 3, ncol(tgt) == 3, nrow(src) == nrow(tgt)) M_t = apply(tgt, 2, function(y) qr.solve(src, y)) t(M_t) } # Sample N RGBs from an image for fit rand_samples = function(img, n = 5000, seed=1) { set.seed(seed) d = dim(img) ys = sample.int(d[1], n, TRUE); xs = sample.int(d[2], n, TRUE) cbind(img[cbind(ys,xs,1)], img[cbind(ys,xs,2)], img[cbind(ys,xs,3)]) } S = rand_samples(dragon_D50) T = rand_samples(dragon_D75) M = fit_cc_matrix(S, T) # Optionally, regularize toward identity to avoid overfitting # M = 0.8 * M + 0.2 * diag(3) updated_source = render_color_correction(dragon_D50, matrix = M) # Matching the old image (grey) to the target image (orange), # giving a new image (black). plot(S,pch=16,cex=0.5,col="grey") points(T,pch=16,cex=0.5,col="orange") points(rand_samples(updated_source,seed=2),pch=16,cex=0.5,col="black") # Plot the images plot_image(render_title(dragon_D50, "OG Image", title_color = "white", title_size = 12)) plot_image(render_title(dragon_D75, "Target Image", title_color = "white", title_size = 12)) plot_image(render_title(updated_source, "Corrected OG Image", title_color = "white", title_size = 12))# We will start with an image that's too warm--we want to correct it to # match the color of the second as closely as possible. dragon_D50 = render_white_balance(dragon, target_white = "D50", bake = TRUE) dragon_D75 = render_white_balance(dragon, target_white = "D75", bake = TRUE) plot_image(dragon_D50) plot_image(dragon_D75) # Fucntion to fit a color correction matrix fit_cc_matrix = function(src, tgt) { stopifnot(ncol(src) == 3, ncol(tgt) == 3, nrow(src) == nrow(tgt)) M_t = apply(tgt, 2, function(y) qr.solve(src, y)) t(M_t) } # Sample N RGBs from an image for fit rand_samples = function(img, n = 5000, seed=1) { set.seed(seed) d = dim(img) ys = sample.int(d[1], n, TRUE); xs = sample.int(d[2], n, TRUE) cbind(img[cbind(ys,xs,1)], img[cbind(ys,xs,2)], img[cbind(ys,xs,3)]) } S = rand_samples(dragon_D50) T = rand_samples(dragon_D75) M = fit_cc_matrix(S, T) # Optionally, regularize toward identity to avoid overfitting # M = 0.8 * M + 0.2 * diag(3) updated_source = render_color_correction(dragon_D50, matrix = M) # Matching the old image (grey) to the target image (orange), # giving a new image (black). plot(S,pch=16,cex=0.5,col="grey") points(T,pch=16,cex=0.5,col="orange") points(rand_samples(updated_source,seed=2),pch=16,cex=0.5,col="black") # Plot the images plot_image(render_title(dragon_D50, "OG Image", title_color = "white", title_size = 12)) plot_image(render_title(dragon_D75, "Target Image", title_color = "white", title_size = 12)) plot_image(render_title(updated_source, "Corrected OG Image", title_color = "white", title_size = 12))
Convert between two RGB spaces via XYZ, with optional white adaptation. Operates on linear RGB.
render_convert_colorspace( image, from_mats = NA, to_mats = CS_ACESCG, adapt_white = TRUE, from_white = NA, to_white = NA, filename = NULL, preview = FALSE )render_convert_colorspace( image, from_mats = NA, to_mats = CS_ACESCG, adapt_white = TRUE, from_white = NA, to_white = NA, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
from_mats |
Default |
to_mats |
Default |
adapt_white |
Default |
from_white |
Default |
to_white |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array tagged with the target space.
# Read photo, convert to ACEScg with CAT (scene) photo = ray_read_image(sunset_image, normalize = FALSE) photo_aces = render_convert_colorspace( photo, to_mats = CS_ACESCG, adapt_white = TRUE ) tmp_txt = tempfile(fileext = ".png") render_text_image( "Sunset", size = 60, filename = tmp_txt, color = "#c300ffff", background_alpha = 0 ) # Read logo (display-referred), convert primaries only (no CAT) logo = ray_read_image(tmp_txt, normalize = FALSE) # sRGB/D65 logo_aces = render_convert_colorspace( logo, to_mats = CS_ACESCG, adapt_white = FALSE ) # Composite in ACEScg, then display (plot_image converts to sRGB/D65 + OETF) # Here, we also turn overlay conversion in [render_image_overlay()] off, # to show what happens when you don't account for the colorspace difference. # By default [render_image_overlay()] will do this for you. comp1 = render_image_overlay( photo_aces, logo_aces, convert_overlay_colorspace = FALSE ) comp2 = render_image_overlay( photo_aces, logo, convert_overlay_colorspace = FALSE ) #Note the color differences, which arise from the mismatched colorspace on the right. plot_image_grid(list(comp1, comp2), dim = c(1, 2))# Read photo, convert to ACEScg with CAT (scene) photo = ray_read_image(sunset_image, normalize = FALSE) photo_aces = render_convert_colorspace( photo, to_mats = CS_ACESCG, adapt_white = TRUE ) tmp_txt = tempfile(fileext = ".png") render_text_image( "Sunset", size = 60, filename = tmp_txt, color = "#c300ffff", background_alpha = 0 ) # Read logo (display-referred), convert primaries only (no CAT) logo = ray_read_image(tmp_txt, normalize = FALSE) # sRGB/D65 logo_aces = render_convert_colorspace( logo, to_mats = CS_ACESCG, adapt_white = FALSE ) # Composite in ACEScg, then display (plot_image converts to sRGB/D65 + OETF) # Here, we also turn overlay conversion in [render_image_overlay()] off, # to show what happens when you don't account for the colorspace difference. # By default [render_image_overlay()] will do this for you. comp1 = render_image_overlay( photo_aces, logo_aces, convert_overlay_colorspace = FALSE ) comp2 = render_image_overlay( photo_aces, logo, convert_overlay_colorspace = FALSE ) #Note the color differences, which arise from the mismatched colorspace on the right. plot_image_grid(list(comp1, comp2), dim = c(1, 2))
Takes an image and applies a convolution operation to it, using a user-supplied or built-in kernel. Edges are calculated by limiting the size of the kernel to only that overlapping the actual image (renormalizing the kernel for the edges).
render_convolution( image, kernel = "gaussian", kernel_dim = 11, kernel_extent = 3, absolute = TRUE, min_value = NULL, include_alpha = FALSE, filename = NULL, preview = FALSE, progress = FALSE )render_convolution( image, kernel = "gaussian", kernel_dim = 11, kernel_extent = 3, absolute = TRUE, min_value = NULL, include_alpha = FALSE, filename = NULL, preview = FALSE, progress = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
kernel |
Default |
kernel_dim |
Default |
kernel_extent |
Default |
absolute |
Default |
min_value |
Default |
include_alpha |
Default |
filename |
Default |
preview |
Default |
progress |
Default |
A rayimg RGBA array.
#Perform a convolution with the default gaussian kernel plot_image(dragon) #Perform a convolution with the default gaussian kernel render_convolution(dragon, preview = TRUE) #Increase the width of the kernel render_convolution(dragon, kernel = 2, kernel_dim=21,kernel_extent=6, preview = TRUE) #Perform edge detection using an edge detection kernel edge = matrix(c(-1,-1,-1,-1,8,-1,-1,-1,-1),3,3) render_convolution(render_bw(dragon), kernel = edge, preview = TRUE, absolute=FALSE) #Perform edge detection with Sobel matrices sobel1 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3) sobel2 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3,byrow=TRUE) sob1 = render_convolution(render_bw(dragon), kernel = sobel1) sob2 = render_convolution(render_bw(dragon), kernel = sobel2) sob_all = sob1 + sob2 plot_image(sob1) plot_image(sob2) plot_image(sob_all) #Only perform the convolution on bright pixels (bloom) render_convolution(dragon, kernel = 5, kernel_dim=24, kernel_extent=24, min_value=1, preview = TRUE) #Use a built-in kernel: render_convolution(dragon, kernel = generate_2d_exponential(falloff=2, dim=31, width=21), preview = TRUE) #We can also apply this function to matrices: volcano |> image() volcano |> render_convolution(kernel=generate_2d_gaussian(sd=1,dim=31)) |> image() #Use a custom kernel (in this case, an X shape): custom = diag(10) + (diag(10)[,10:1]) plot_image(custom) render_convolution(dragon, kernel = custom, preview = TRUE)#Perform a convolution with the default gaussian kernel plot_image(dragon) #Perform a convolution with the default gaussian kernel render_convolution(dragon, preview = TRUE) #Increase the width of the kernel render_convolution(dragon, kernel = 2, kernel_dim=21,kernel_extent=6, preview = TRUE) #Perform edge detection using an edge detection kernel edge = matrix(c(-1,-1,-1,-1,8,-1,-1,-1,-1),3,3) render_convolution(render_bw(dragon), kernel = edge, preview = TRUE, absolute=FALSE) #Perform edge detection with Sobel matrices sobel1 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3) sobel2 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3,byrow=TRUE) sob1 = render_convolution(render_bw(dragon), kernel = sobel1) sob2 = render_convolution(render_bw(dragon), kernel = sobel2) sob_all = sob1 + sob2 plot_image(sob1) plot_image(sob2) plot_image(sob_all) #Only perform the convolution on bright pixels (bloom) render_convolution(dragon, kernel = 5, kernel_dim=24, kernel_extent=24, min_value=1, preview = TRUE) #Use a built-in kernel: render_convolution(dragon, kernel = generate_2d_exponential(falloff=2, dim=31, width=21), preview = TRUE) #We can also apply this function to matrices: volcano |> image() volcano |> render_convolution(kernel=generate_2d_gaussian(sd=1,dim=31)) |> image() #Use a custom kernel (in this case, an X shape): custom = diag(10) + (diag(10)[,10:1]) plot_image(custom) render_convolution(dragon, kernel = custom, preview = TRUE)
Takes an image and applies a convolution operation to it, using a user-supplied or built-in kernel. This function uses a fast Fourier transform and does the convolution in the frequency domain, so it should be faster for much larger kernels.
render_convolution_fft( image, kernel = "gaussian", kernel_dim = c(11, 11), kernel_extent = 3, absolute = TRUE, pad = 50, include_alpha = FALSE, filename = NULL, preview = FALSE )render_convolution_fft( image, kernel = "gaussian", kernel_dim = c(11, 11), kernel_extent = 3, absolute = TRUE, pad = 50, include_alpha = FALSE, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
kernel |
Default |
kernel_dim |
Default |
kernel_extent |
Default |
absolute |
Default |
pad |
Default |
include_alpha |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
#Perform a convolution with the default gaussian kernel plot_image(dragon) #Perform a convolution with the default gaussian kernel render_convolution_fft(dragon, kernel=0.1, preview = TRUE) #Increase the width of the kernel render_convolution_fft(dragon, kernel = 2, kernel_dim=21,kernel_extent=6, preview = TRUE) #Use a built-in kernel: render_convolution_fft(dragon, kernel = generate_2d_exponential(falloff=2, dim=31, width=21), preview = TRUE) #Perform edge detection edge = matrix(c(-1,-1,-1,-1,8,-1,-1,-1,-1),3,3) render_convolution_fft(render_bw(dragon), kernel = edge, preview = TRUE) #Perform edge detection with Sobel matrices sobel1 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3) sobel2 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3,byrow=TRUE) sob1 = render_convolution_fft(render_bw(dragon), kernel = sobel1) sob2 = render_convolution_fft(render_bw(dragon), kernel = sobel2) sob_all = sob1 + sob2 plot_image(sob1) plot_image(sob2) plot_image(sob_all) #We can also apply this function to matrices: volcano |> image() volcano |> render_convolution_fft(kernel=generate_2d_gaussian(sd=1,dim=31)) |> image() # Because this function uses the fast Fourier transform, large kernels will be much faster # than the same size kernels in [render_convolution()] render_convolution_fft(dragon, kernel_dim = c(200,200) , preview = TRUE) #Use a custom kernel (in this case, an X shape): custom = diag(10) + (diag(10)[,10:1]) #Normalize custom = custom / 20 plot_image(custom*20) render_convolution_fft(dragon, kernel = custom, preview = TRUE)#Perform a convolution with the default gaussian kernel plot_image(dragon) #Perform a convolution with the default gaussian kernel render_convolution_fft(dragon, kernel=0.1, preview = TRUE) #Increase the width of the kernel render_convolution_fft(dragon, kernel = 2, kernel_dim=21,kernel_extent=6, preview = TRUE) #Use a built-in kernel: render_convolution_fft(dragon, kernel = generate_2d_exponential(falloff=2, dim=31, width=21), preview = TRUE) #Perform edge detection edge = matrix(c(-1,-1,-1,-1,8,-1,-1,-1,-1),3,3) render_convolution_fft(render_bw(dragon), kernel = edge, preview = TRUE) #Perform edge detection with Sobel matrices sobel1 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3) sobel2 = matrix(c(1,2,1,0,0,0,-1,-2,-1),3,3,byrow=TRUE) sob1 = render_convolution_fft(render_bw(dragon), kernel = sobel1) sob2 = render_convolution_fft(render_bw(dragon), kernel = sobel2) sob_all = sob1 + sob2 plot_image(sob1) plot_image(sob2) plot_image(sob_all) #We can also apply this function to matrices: volcano |> image() volcano |> render_convolution_fft(kernel=generate_2d_gaussian(sd=1,dim=31)) |> image() # Because this function uses the fast Fourier transform, large kernels will be much faster # than the same size kernels in [render_convolution()] render_convolution_fft(dragon, kernel_dim = c(200,200) , preview = TRUE) #Use a custom kernel (in this case, an X shape): custom = diag(10) + (diag(10)[,10:1]) #Normalize custom = custom / 20 plot_image(custom*20) render_convolution_fft(dragon, kernel = custom, preview = TRUE)
Crops an image (or matrix) either by specifying axis-aligned limits
(width_limits/height_limits) or by specifying a centered box size via center.
render_crop( image = NULL, width_limits = NULL, height_limits = NULL, center = NULL, filename = NULL, preview = FALSE )render_crop( image = NULL, width_limits = NULL, height_limits = NULL, center = NULL, filename = NULL, preview = FALSE )
image |
Default |
width_limits |
Default |
height_limits |
Default |
center |
Default |
filename |
Default |
preview |
Default |
A rayimg array with the cropped region.
# Left half of the image render_crop(dragon, width_limits = c(0, 0.50), height_limits = c(0, 1)) |> plot_image() # Right half of the image render_crop(dragon, width_limits = c(0.50, 1), height_limits = c(0, 1)) |> plot_image() # Top middle of the image (25%–50% height, 25%–75% width) render_crop(dragon, height_limits = c(0.25, 0.50), width_limits = c(0.25, 0.75)) |> plot_image() # Top middle, explicit pixel coords (for a 200x200 image) render_crop(dragon, height_limits = c(50, 100), width_limits = c(50, 150)) |> plot_image() # Center-crop: 50% height and width of the image render_crop(dragon, center = c(0.5, 0.5)) |> plot_image() # Center-crop: fixed 50x100 pixels render_crop(dragon, center = c(50, 100)) |> plot_image()# Left half of the image render_crop(dragon, width_limits = c(0, 0.50), height_limits = c(0, 1)) |> plot_image() # Right half of the image render_crop(dragon, width_limits = c(0.50, 1), height_limits = c(0, 1)) |> plot_image() # Top middle of the image (25%–50% height, 25%–75% width) render_crop(dragon, height_limits = c(0.25, 0.50), width_limits = c(0.25, 0.75)) |> plot_image() # Top middle, explicit pixel coords (for a 200x200 image) render_crop(dragon, height_limits = c(50, 100), width_limits = c(50, 150)) |> plot_image() # Center-crop: 50% height and width of the image render_crop(dragon, center = c(0.5, 0.5)) |> plot_image() # Center-crop: fixed 50x100 pixels render_crop(dragon, center = c(50, 100)) |> plot_image()
Apply exposure compensation and ISO gain
render_exposure( image, exposure = 0, iso = NA, auto = FALSE, percentile = 0.99, verbose = FALSE, filename = NA, preview = FALSE, ... )render_exposure( image, exposure = 0, iso = NA, auto = FALSE, percentile = 0.99, verbose = FALSE, filename = NA, preview = FALSE, ... )
image |
3-layer RGB/4-layer RGBA array, |
exposure |
Default |
iso |
Default |
auto |
Default |
percentile |
Default |
verbose |
Default |
filename |
Default |
preview |
Default |
... |
Additional args passed to |
A rayimg RGBA array.
# LDR/sRGB (auto): decodes to linear, applies EV, records camera metadata render_exposure(dragon, exposure = +1, preview = TRUE) # Force linear/HDR behavior render_exposure(dragon * 2, exposure = -1, preview = TRUE)# LDR/sRGB (auto): decodes to linear, applies EV, records camera metadata render_exposure(dragon, exposure = +1, preview = TRUE) # Force linear/HDR behavior render_exposure(dragon * 2, exposure = -1, preview = TRUE)
Convert sRGB-encoded color data to linear light (and vice versa).
render_gamma_linear(color, srgb_to_linear = TRUE, as_hex = FALSE)render_gamma_linear(color, srgb_to_linear = TRUE, as_hex = FALSE)
color |
A |
srgb_to_linear |
Default |
as_hex |
Default |
Same shape/type as input unless as_hex = TRUE on matrix/array with srgb_to_linear = FALSE,
in which case a character vector of hex codes is returned.
# Numeric RGB vector (sRGB -> linear -> back to sRGB) srgb_vec = c(0.2, 0.4, 0.6) linear_vec = render_gamma_linear(srgb_vec) render_gamma_linear(linear_vec, srgb_to_linear = FALSE) # Hex input (single color) linear_from_hex = render_gamma_linear("#336699") render_gamma_linear(linear_from_hex, srgb_to_linear = FALSE, as_hex = TRUE) # Greyscale matrix (treated as image plane) grey_image = matrix(c(0.1, 0.5, 0.9, 0.3), nrow = 2) linear_grey = render_gamma_linear(grey_image) render_gamma_linear(linear_grey, srgb_to_linear = FALSE, as_hex = TRUE) # Array with a single greyscale channel grey_pixels = array(c(0.2, 0.7), dim = c(1, 2, 1)) linear_grey_arr = render_gamma_linear(grey_pixels) render_gamma_linear(linear_grey_arr, srgb_to_linear = FALSE, as_hex = TRUE) # Array with greyscale + alpha grey_alpha = array(c(0.3, 0.9, 0.6, 0.4), dim = c(1, 2, 2)) linear_grey_alpha = render_gamma_linear(grey_alpha) render_gamma_linear(linear_grey_alpha, srgb_to_linear = FALSE, as_hex = TRUE) # RGB array (3 channels) rgb_pixels = array( c( 0.2, 0.4, 0.6, 0.7, 0.1, 0.3 ), dim = c(1, 2, 3) ) linear_rgb = render_gamma_linear(rgb_pixels) render_gamma_linear(linear_rgb, srgb_to_linear = FALSE, as_hex = TRUE) # RGBA array (alpha channel preserved) rgba_pixels = array( c( 0.2, 0.4, 0.6, 0.5, 0.7, 0.1, 0.3, 0.8 ), dim = c(1, 2, 4) ) linear_rgba = render_gamma_linear(rgba_pixels) render_gamma_linear(linear_rgba, srgb_to_linear = FALSE, as_hex = TRUE) # rayimg input retains metadata and supports hex conversion linear_img = render_gamma_linear(ray_read_image(rgba_pixels)) render_gamma_linear(linear_img, srgb_to_linear = FALSE, as_hex = TRUE)# Numeric RGB vector (sRGB -> linear -> back to sRGB) srgb_vec = c(0.2, 0.4, 0.6) linear_vec = render_gamma_linear(srgb_vec) render_gamma_linear(linear_vec, srgb_to_linear = FALSE) # Hex input (single color) linear_from_hex = render_gamma_linear("#336699") render_gamma_linear(linear_from_hex, srgb_to_linear = FALSE, as_hex = TRUE) # Greyscale matrix (treated as image plane) grey_image = matrix(c(0.1, 0.5, 0.9, 0.3), nrow = 2) linear_grey = render_gamma_linear(grey_image) render_gamma_linear(linear_grey, srgb_to_linear = FALSE, as_hex = TRUE) # Array with a single greyscale channel grey_pixels = array(c(0.2, 0.7), dim = c(1, 2, 1)) linear_grey_arr = render_gamma_linear(grey_pixels) render_gamma_linear(linear_grey_arr, srgb_to_linear = FALSE, as_hex = TRUE) # Array with greyscale + alpha grey_alpha = array(c(0.3, 0.9, 0.6, 0.4), dim = c(1, 2, 2)) linear_grey_alpha = render_gamma_linear(grey_alpha) render_gamma_linear(linear_grey_alpha, srgb_to_linear = FALSE, as_hex = TRUE) # RGB array (3 channels) rgb_pixels = array( c( 0.2, 0.4, 0.6, 0.7, 0.1, 0.3 ), dim = c(1, 2, 3) ) linear_rgb = render_gamma_linear(rgb_pixels) render_gamma_linear(linear_rgb, srgb_to_linear = FALSE, as_hex = TRUE) # RGBA array (alpha channel preserved) rgba_pixels = array( c( 0.2, 0.4, 0.6, 0.5, 0.7, 0.1, 0.3, 0.8 ), dim = c(1, 2, 4) ) linear_rgba = render_gamma_linear(rgba_pixels) render_gamma_linear(linear_rgba, srgb_to_linear = FALSE, as_hex = TRUE) # rayimg input retains metadata and supports hex conversion linear_img = render_gamma_linear(ray_read_image(rgba_pixels)) render_gamma_linear(linear_img, srgb_to_linear = FALSE, as_hex = TRUE)
Takes an RGB array/filename and composites an image overlay over
the full image. For pixel-positioned sprite, label, glyph, or billboard
overlays, use render_sprite_overlay().
render_image_overlay( image, image_overlay = NULL, rescale_original = FALSE, convert_overlay_colorspace = TRUE, alpha = NA, filename = NULL, preview = FALSE )render_image_overlay( image, image_overlay = NULL, rescale_original = FALSE, convert_overlay_colorspace = TRUE, alpha = NA, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
image_overlay |
Default |
rescale_original |
Default |
convert_overlay_colorspace |
Default |
alpha |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
#Plot the dragon plot_image(dragon) #Add an overlay of a red semi-transparent circle: circlemat = generate_2d_disk(min(dim(dragon)[1:2])) circlemat = circlemat/max(circlemat) #Create RGBA image, with a transparency of 0.5 rgba_array = array(1, dim=c(nrow(circlemat),ncol(circlemat),4)) rgba_array[,,1] = circlemat rgba_array[,,2] = 0 rgba_array[,,3] = 0 dragon_clipped = dragon dragon_clipped[dragon_clipped > 1] = 1 render_image_overlay(dragon_clipped, image_overlay = rgba_array, alpha=0.5, preview = TRUE) # Read photo, convert to ACEScg with CAT (scene) photo = ray_read_image(sunset_image, normalize = FALSE) photo_aces = render_convert_colorspace( photo, to_mats = CS_ACESCG, adapt_white = TRUE ) tmp_txt = tempfile(fileext = ".png") render_text_image( "Sunset", size = 60, filename = tmp_txt, color = "#c300ff", background_alpha = 0 ) # Read logo (display-referred), convert primaries only (no CAT) logo = ray_read_image(tmp_txt, normalize = FALSE) # sRGB/D65 logo_aces = render_convert_colorspace( logo, to_mats = CS_ACESCG, adapt_white = FALSE ) # Composite in ACEScg, then display (plot_image converts to sRGB/D65 + OETF) # Here, we also turn overlay conversion in [render_image_overlay()] off, # to show what happens when you don't account for the colorspace difference. # By default [render_image_overlay()] will do this for you. comp1 = render_image_overlay( photo_aces, logo_aces, convert_overlay_colorspace = FALSE ) |> render_title(title_text = "#c300ff: Match", title_bar_color = "white", title_color = "#c300ff", title_bar_alpha=1) comp2 = render_image_overlay( photo_aces, logo, convert_overlay_colorspace = FALSE ) |> render_title(title_text = "#c300ff: Incorrect", title_bar_color = "white", title_color = "#c300ff", title_bar_alpha=1) plot_image_grid(list(comp1, comp2), dim = c(1, 2))#Plot the dragon plot_image(dragon) #Add an overlay of a red semi-transparent circle: circlemat = generate_2d_disk(min(dim(dragon)[1:2])) circlemat = circlemat/max(circlemat) #Create RGBA image, with a transparency of 0.5 rgba_array = array(1, dim=c(nrow(circlemat),ncol(circlemat),4)) rgba_array[,,1] = circlemat rgba_array[,,2] = 0 rgba_array[,,3] = 0 dragon_clipped = dragon dragon_clipped[dragon_clipped > 1] = 1 render_image_overlay(dragon_clipped, image_overlay = rgba_array, alpha=0.5, preview = TRUE) # Read photo, convert to ACEScg with CAT (scene) photo = ray_read_image(sunset_image, normalize = FALSE) photo_aces = render_convert_colorspace( photo, to_mats = CS_ACESCG, adapt_white = TRUE ) tmp_txt = tempfile(fileext = ".png") render_text_image( "Sunset", size = 60, filename = tmp_txt, color = "#c300ff", background_alpha = 0 ) # Read logo (display-referred), convert primaries only (no CAT) logo = ray_read_image(tmp_txt, normalize = FALSE) # sRGB/D65 logo_aces = render_convert_colorspace( logo, to_mats = CS_ACESCG, adapt_white = FALSE ) # Composite in ACEScg, then display (plot_image converts to sRGB/D65 + OETF) # Here, we also turn overlay conversion in [render_image_overlay()] off, # to show what happens when you don't account for the colorspace difference. # By default [render_image_overlay()] will do this for you. comp1 = render_image_overlay( photo_aces, logo_aces, convert_overlay_colorspace = FALSE ) |> render_title(title_text = "#c300ff: Match", title_bar_color = "white", title_color = "#c300ff", title_bar_alpha=1) comp2 = render_image_overlay( photo_aces, logo, convert_overlay_colorspace = FALSE ) |> render_title(title_text = "#c300ff: Incorrect", title_bar_color = "white", title_color = "#c300ff", title_bar_alpha=1) plot_image_grid(list(comp1, comp2), dim = c(1, 2))
Expands an image or matrix canvas by adding constant-value padding around the original image.
render_padding( image, pad = 10, color = "black", alpha = NULL, filename = NULL, preview = FALSE )render_padding( image, pad = 10, color = "black", alpha = NULL, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
pad |
Default |
color |
Default |
alpha |
Default |
filename |
Default |
preview |
Default |
A padded rayimg image or matrix.
render_padding(dragon, pad = 20) |> plot_image()render_padding(dragon, pad = 20) |> plot_image()
Reorients an image or matrix. Transformations are applied in this order: x, y, and transpose.
render_reorient( image, flipx = FALSE, flipy = FALSE, transpose = FALSE, filename = NULL, preview = FALSE )render_reorient( image, flipx = FALSE, flipy = FALSE, transpose = FALSE, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
flipx |
Default |
flipy |
Default |
transpose |
Default |
filename |
Default |
preview |
Default |
3-layer RGB reoriented array or matrix.
#Original orientation plot_image(dragon) #Flip the dragon image horizontally dragon |> render_reorient(flipx = TRUE) |> plot_image() #Flip the dragon image vertically dragon |> render_reorient(flipy = TRUE) |> plot_image() #Transpose the dragon image dragon |> render_reorient(transpose = TRUE) |> plot_image()#Original orientation plot_image(dragon) #Flip the dragon image horizontally dragon |> render_reorient(flipx = TRUE) |> plot_image() #Flip the dragon image vertically dragon |> render_reorient(flipy = TRUE) |> plot_image() #Transpose the dragon image dragon |> render_reorient(transpose = TRUE) |> plot_image()
Resizes an image or a matrix, using bilinear interpolation.
render_resized( image, mag = 1, dims = NULL, filename = NULL, preview = FALSE, method = "tri" )render_resized( image, mag = 1, dims = NULL, filename = NULL, preview = FALSE, method = "tri" )
image |
3-layer RGB/4-layer RGBA array, |
mag |
Default |
dims |
Default |
filename |
Default |
preview |
Default |
method |
Default |
A rayimg RGBA array.
#Plot the image with a title dragon |> render_title("Dragon", title_offset=c(10,10), title_bar_color="black", title_size=20, title_color = "white") |> plot_image() #Half of the resolution render_resized(dragon, mag = 1/2) |> render_title("Dragon (half res)", title_offset=c(5,5), title_bar_color="black", title_size=10, title_color = "white") |> plot_image() #Double the resolution render_resized(dragon, mag = 2) |> render_title("Dragon (2x res)", title_offset=c(20,20), title_bar_color="black", title_size=40, title_color = "white") |> plot_image() #Specify the exact resulting dimensions render_resized(dragon, dim = c(160,320)) |> render_title("Dragon (custom size)", title_offset=c(10,10), title_bar_color="black", title_size=20, title_color = "white") |> plot_image()#Plot the image with a title dragon |> render_title("Dragon", title_offset=c(10,10), title_bar_color="black", title_size=20, title_color = "white") |> plot_image() #Half of the resolution render_resized(dragon, mag = 1/2) |> render_title("Dragon (half res)", title_offset=c(5,5), title_bar_color="black", title_size=10, title_color = "white") |> plot_image() #Double the resolution render_resized(dragon, mag = 2) |> render_title("Dragon (2x res)", title_offset=c(20,20), title_bar_color="black", title_size=40, title_color = "white") |> plot_image() #Specify the exact resulting dimensions render_resized(dragon, dim = c(160,320)) |> render_title("Dragon (custom size)", title_offset=c(10,10), title_bar_color="black", title_size=20, title_color = "white") |> plot_image()
Places an image overlay at a pixel location without resizing it to the full destination image. This is intended for sprite-like or billboard-like overlays such as labels, icons, glyphs, and screen-space annotations.
render_sprite_overlay( image, image_overlay = NULL, convert_overlay_colorspace = TRUE, alpha = NA, overlay_coords = c(1, 1), overlay_dims = NULL, overlay_anchor = "nw", overlay_just = NULL, hjust = NULL, vjust = NULL, preserve_channels = TRUE, filename = NULL, preview = FALSE )render_sprite_overlay( image, image_overlay = NULL, convert_overlay_colorspace = TRUE, alpha = NA, overlay_coords = c(1, 1), overlay_dims = NULL, overlay_anchor = "nw", overlay_just = NULL, hjust = NULL, vjust = NULL, preserve_channels = TRUE, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
image_overlay |
Default |
convert_overlay_colorspace |
Default |
alpha |
Default |
overlay_coords |
Default |
overlay_dims |
Default |
overlay_anchor |
Default |
overlay_just |
Default |
hjust |
Default |
vjust |
Default |
preserve_channels |
Default |
filename |
Default |
preview |
Default |
A rayimg array.
dragon_clipped = dragon dragon_clipped[dragon_clipped > 1] = 1 # Render a transparent dragon emoji and center it on a pixel with hjust/vjust: dragon_emoji = render_text_image( "\U0001F409", size = 80, background_alpha = 0, use_ragg = TRUE, trim = TRUE, trim_padding = 8 ) render_sprite_overlay( dragon_clipped, image_overlay = dragon_emoji, overlay_coords = c(ncol(dragon_clipped) / 2, nrow(dragon_clipped) / 2), hjust = 0.5, vjust = 0.5, preview = TRUE ) # The same justification can be supplied as overlay_just = c(hjust, vjust): render_sprite_overlay( dragon_clipped, image_overlay = dragon_emoji, overlay_coords = c(ncol(dragon_clipped), nrow(dragon_clipped)), overlay_just = c(1, 1), preview = TRUE )dragon_clipped = dragon dragon_clipped[dragon_clipped > 1] = 1 # Render a transparent dragon emoji and center it on a pixel with hjust/vjust: dragon_emoji = render_text_image( "\U0001F409", size = 80, background_alpha = 0, use_ragg = TRUE, trim = TRUE, trim_padding = 8 ) render_sprite_overlay( dragon_clipped, image_overlay = dragon_emoji, overlay_coords = c(ncol(dragon_clipped) / 2, nrow(dragon_clipped) / 2), hjust = 0.5, vjust = 0.5, preview = TRUE ) # The same justification can be supplied as overlay_just = c(hjust, vjust): render_sprite_overlay( dragon_clipped, image_overlay = dragon_emoji, overlay_coords = c(ncol(dragon_clipped), nrow(dragon_clipped)), overlay_just = c(1, 1), preview = TRUE )
Stacks a list of images vertically or horizontally into a single image.
render_stack( input_list, stack = c("v", "h", "vertical", "horizontal"), align = c("center", "start", "end", "left", "right", "top", "bottom"), background = c(0, 0, 0, 0), convert_colorspace = TRUE, filename = NULL, preview = FALSE )render_stack( input_list, stack = c("v", "h", "vertical", "horizontal"), align = c("center", "start", "end", "left", "right", "top", "bottom"), background = c(0, 0, 0, 0), convert_colorspace = TRUE, filename = NULL, preview = FALSE )
input_list |
List of 3-layer RGB/4-layer RGBA array, |
stack |
Default |
align |
Default |
background |
Default |
convert_colorspace |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
render_stack(list(dragon, 1 - dragon), stack = "h") |> plot_image() render_stack(list(dragon, render_bw(dragon)), stack = "v") |> plot_image()render_stack(list(dragon, 1 - dragon), stack = "h") |> plot_image() render_stack(list(dragon, render_bw(dragon)), stack = "v") |> plot_image()
Generates an image which tightly fits text.
render_text_image( text, lineheight = 1, color = "black", size = 12, font = "sans", just = "left", background_color = "white", background_alpha = 1, use_ragg = TRUE, width = NA, height = NA, filename = NULL, check_text_width = TRUE, check_text_height = TRUE, trim = FALSE, trim_padding = 0, preview = FALSE )render_text_image( text, lineheight = 1, color = "black", size = 12, font = "sans", just = "left", background_color = "white", background_alpha = 1, use_ragg = TRUE, width = NA, height = NA, filename = NULL, check_text_width = TRUE, check_text_height = TRUE, trim = FALSE, trim_padding = 0, preview = FALSE )
text |
Text to turn into an image. |
lineheight |
Default |
color |
Default |
size |
Default |
font |
Default |
just |
Default |
background_color |
Default |
background_alpha |
Default |
use_ragg |
Default |
width |
Default |
height |
Default |
filename |
Default |
check_text_width |
Default |
check_text_height |
Default |
trim |
Default |
trim_padding |
Default |
preview |
Default |
A 3-layer RGB array of the processed image if filename = NULL and preview = FALSE.
Otherwise, writes the image to the specified file or displays it if preview = TRUE.
#Generate an image of some text render_text_image("Some text", preview = TRUE) #Change the font size render_text_image("Some text", size = 100, preview = TRUE) #Change the font color render_text_image("Some text", size = 100, color="red",preview = TRUE) #Change the background color and transparency render_text_image("Some text", size = 50, color="purple", background_color="purple", background_alpha = 0.5, preview = TRUE) # Plot an emoji with the agg device. render_text_image("\U0001F600\U0001F680", size = 50, color = "purple", use_ragg = TRUE, background_alpha = 0, preview = TRUE) # Plot an emoji with the agg device and adjust the height and width (which # is on by default) to be a tight fit. render_text_image("\U0001F600\U0001F680", size = 50, color = "purple", use_ragg = TRUE, background_alpha = 0, check_text_width = TRUE, check_text_height = TRUE, preview = TRUE) # Trim the image to the rendered glyphs and then add transparent padding. render_text_image("\U0001F409", size = 80, use_ragg = TRUE, background_alpha = 0, trim = TRUE, trim_padding = 8, preview = TRUE)#Generate an image of some text render_text_image("Some text", preview = TRUE) #Change the font size render_text_image("Some text", size = 100, preview = TRUE) #Change the font color render_text_image("Some text", size = 100, color="red",preview = TRUE) #Change the background color and transparency render_text_image("Some text", size = 50, color="purple", background_color="purple", background_alpha = 0.5, preview = TRUE) # Plot an emoji with the agg device. render_text_image("\U0001F600\U0001F680", size = 50, color = "purple", use_ragg = TRUE, background_alpha = 0, preview = TRUE) # Plot an emoji with the agg device and adjust the height and width (which # is on by default) to be a tight fit. render_text_image("\U0001F600\U0001F680", size = 50, color = "purple", use_ragg = TRUE, background_alpha = 0, check_text_width = TRUE, check_text_height = TRUE, preview = TRUE) # Trim the image to the rendered glyphs and then add transparent padding. render_text_image("\U0001F409", size = 80, use_ragg = TRUE, background_alpha = 0, trim = TRUE, trim_padding = 8, preview = TRUE)
Adds a title with optional styling and a title bar to an image.
The image can be previewed or saved to a file. Supports both the grid-based
method and (deprecated) magick package for rendering the title.
render_title( image, title_text = "", title_size = 30, title_offset = rep(title_size/2, 2), title_lineheight = 1, title_color = "black", title_font = "Arial", title_style = "plain", title_bar_color = NA, title_bar_alpha = 0.5, title_bar_width = NULL, title_position = NA, title_just = "left", use_magick = FALSE, filename = NULL, preview = FALSE )render_title( image, title_text = "", title_size = 30, title_offset = rep(title_size/2, 2), title_lineheight = 1, title_color = "black", title_font = "Arial", title_style = "plain", title_bar_color = NA, title_bar_alpha = 0.5, title_bar_width = NULL, title_position = NA, title_just = "left", use_magick = FALSE, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
title_text |
Default |
title_size |
Default |
title_offset |
Default |
title_lineheight |
Default |
title_color |
Default |
title_font |
Default |
title_style |
Default |
title_bar_color |
Default |
title_bar_alpha |
Default |
title_bar_width |
Default |
title_position |
Default |
title_just |
Default |
use_magick |
Default |
filename |
Default |
preview |
Default |
A 3-layer RGB array of the processed image if filename = NULL and preview = FALSE.
Otherwise, writes the image to the specified file or displays it if preview = TRUE.
The use_magick parameter and all functionality tied to the magick package are
planned for deprecation. It is recommended to use the grid-based method for
future compatibility.
#Plot the dragon render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20) #That's hard to see--let's add a title bar: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_color="white") #Change the width of the bar: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_color="white", title_offset = c(8,8)) #The width of the bar will also automatically adjust for newlines: render_title(dragon, preview = TRUE, title_text = "Dragon\n(Blue)", title_size=20, title_bar_color="white") #Change the color and title color: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_color="red", title_color = "white") #Change the transparency: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_alpha = 0.8, title_bar_color="red", title_color = "white") #Read directly from a file temp_image = tempfile(fileext = ".png") ray_write_image(dragon, temp_image) render_title(temp_image, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_alpha = 0.8, title_bar_color="red", title_color = "white")#Plot the dragon render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20) #That's hard to see--let's add a title bar: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_color="white") #Change the width of the bar: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_color="white", title_offset = c(8,8)) #The width of the bar will also automatically adjust for newlines: render_title(dragon, preview = TRUE, title_text = "Dragon\n(Blue)", title_size=20, title_bar_color="white") #Change the color and title color: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_color="red", title_color = "white") #Change the transparency: render_title(dragon, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_alpha = 0.8, title_bar_color="red", title_color = "white") #Read directly from a file temp_image = tempfile(fileext = ".png") ray_write_image(dragon, temp_image) render_title(temp_image, preview = TRUE, title_text = "Dragon", title_size=20, title_bar_alpha = 0.8, title_bar_color="red", title_color = "white")
Convert an image from its working space to a display space, and optionally apply sRGB OETF for viewing.
render_to_display(image, display = CS_SRGB, encode = TRUE, adapt_white = TRUE)render_to_display(image, display = CS_SRGB, encode = TRUE, adapt_white = TRUE)
image |
A |
display |
Default |
encode |
Default |
adapt_white |
Default |
A rayimg when encode=FALSE, or a rayimg with sRGB-encoded RGB when encode=TRUE.
Reinhard / Uncharted(Hable) / HBD operators in linear
render_tonemap( image, method = c("raw", "reinhard", "uncharted", "hbd"), exposure_bias = 2, W = 11.2, filename = NULL, preview = FALSE )render_tonemap( image, method = c("raw", "reinhard", "uncharted", "hbd"), exposure_bias = 2, W = 11.2, filename = NULL, preview = FALSE )
image |
Default |
method |
Default |
exposure_bias |
Default |
W |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
# Plot unchanged image render_tonemap(dragon, preview = TRUE) # Plot Reinhard tonemapped image render_tonemap(dragon, method = "reinhard", preview = TRUE) # Plot Uncharted/Hable tonemapped image render_tonemap(dragon, method = "uncharted",preview = TRUE) # Plot Uncharted/Hable tonemapped image, white point adjusted render_tonemap(dragon, method = "uncharted", W=11.4, preview = TRUE) # Plot Uncharted/Hable tonemapped image, exposure adjusted render_tonemap(dragon, method = "uncharted", exposure_bias = 1,preview = TRUE) # Plot Hejl-Burgess-Dawson tonemapped image, exposure adjusted render_tonemap(dragon, method = "hbd",preview = TRUE)# Plot unchanged image render_tonemap(dragon, preview = TRUE) # Plot Reinhard tonemapped image render_tonemap(dragon, method = "reinhard", preview = TRUE) # Plot Uncharted/Hable tonemapped image render_tonemap(dragon, method = "uncharted",preview = TRUE) # Plot Uncharted/Hable tonemapped image, white point adjusted render_tonemap(dragon, method = "uncharted", W=11.4, preview = TRUE) # Plot Uncharted/Hable tonemapped image, exposure adjusted render_tonemap(dragon, method = "uncharted", exposure_bias = 1,preview = TRUE) # Plot Hejl-Burgess-Dawson tonemapped image, exposure adjusted render_tonemap(dragon, method = "hbd",preview = TRUE)
Adjusts image vibrance (adaptive saturation), similar in spirit to the iPhone "Vibrance" control: it boosts muted colors more than already-saturated colors, and reduces saturation more strongly in already-saturated regions when negative. Works on HDR arrays as well (values can exceed 1).
render_vibrance( image, vibrance = 0, protect_luminance = 0.25, filename = NULL, preview = FALSE )render_vibrance( image, vibrance = 0, protect_luminance = 0.25, filename = NULL, preview = FALSE )
image |
Image filename, 3-layer RGB array, 4-layer RGBA array, or matrix. If a filename,
it will be read via |
vibrance |
Default |
protect_luminance |
Default |
filename |
Default |
preview |
Default |
4-layer RGBA array (or matrix if passed a matrix and ray_read_image() is not used).
dragon |> render_vibrance(vibrance = 0.4, preview = TRUE)dragon |> render_vibrance(vibrance = 0.4, preview = TRUE)
Takes an RGB array/filename and adds a camera vignette effect.
render_vignette( image, vignette = 0.5, color = "#000000", radius = 1.1, filename = NULL, preview = FALSE )render_vignette( image, vignette = 0.5, color = "#000000", radius = 1.1, filename = NULL, preview = FALSE )
image |
3-layer RGB/4-layer RGBA array, |
vignette |
Default |
color |
Default |
radius |
Default |
filename |
Default |
preview |
Default |
A rayimg RGBA array.
#Plot the dragon plot_image(dragon) #Add a vignette effect: render_vignette(dragon, preview = TRUE, vignette = 1, radius=1.1) #Lighten the vignette effect: render_vignette(dragon, preview = TRUE, vignette = 0.5) #Change the radius: render_vignette(dragon, preview = TRUE, vignette = 1, radius=1.5) render_vignette(dragon, preview = TRUE, vignette = 0.1, radius=0.8) #Change the color: render_vignette(dragon, preview = TRUE, vignette = 1, color="white") #Increase the width of the blur by 50%: render_vignette(dragon, preview = TRUE, vignette = c(1,1.5))#Plot the dragon plot_image(dragon) #Add a vignette effect: render_vignette(dragon, preview = TRUE, vignette = 1, radius=1.1) #Lighten the vignette effect: render_vignette(dragon, preview = TRUE, vignette = 0.5) #Change the radius: render_vignette(dragon, preview = TRUE, vignette = 1, radius=1.5) render_vignette(dragon, preview = TRUE, vignette = 0.1, radius=0.8) #Change the color: render_vignette(dragon, preview = TRUE, vignette = 1, color="white") #Increase the width of the blur by 50%: render_vignette(dragon, preview = TRUE, vignette = c(1,1.5))
Chromatic-adapt an image from reference_white to target_white in its working RGB space.
When bake = FALSE (the default), this should not result in any visible changes to the image when
plotted in rayimage via plot_image(), as that function then corrects the white balance for
display. Set
render_white_balance( image, reference_white = NA, target_white = "D60", bake = FALSE, filename = NULL, preview = FALSE )render_white_balance( image, reference_white = NA, target_white = "D60", bake = FALSE, filename = NULL, preview = FALSE )
image |
Default |
reference_white |
Default |
target_white |
Default |
bake |
Default |
filename |
Default |
preview |
Default |
# Not specifying a target white balance returns an unchanged image render_white_balance(dragon, preview = TRUE) # Default white "D60", converting to D50 produces a warmer image render_white_balance(dragon, preview = TRUE, target_white = "D50", bake = TRUE) # Default white "D60", converting to "D75" produces a cooler image render_white_balance(dragon, preview = TRUE, target_white = "D75", bake = TRUE) # Set reference white to colder "D75", converting to "D50" produces a very warm image render_white_balance(dragon, preview = TRUE, reference_white= "D75", target_white = "D50", bake = TRUE) # With a real, non-rendered image: render_white_balance(sunset_image, preview=TRUE) # Cooler render_white_balance(sunset_image, preview=TRUE, target_white = "D75", bake = TRUE) # Warmer render_white_balance(sunset_image, preview=TRUE, target_white = "D50", bake = TRUE)# Not specifying a target white balance returns an unchanged image render_white_balance(dragon, preview = TRUE) # Default white "D60", converting to D50 produces a warmer image render_white_balance(dragon, preview = TRUE, target_white = "D50", bake = TRUE) # Default white "D60", converting to "D75" produces a cooler image render_white_balance(dragon, preview = TRUE, target_white = "D75", bake = TRUE) # Set reference white to colder "D75", converting to "D50" produces a very warm image render_white_balance(dragon, preview = TRUE, reference_white= "D75", target_white = "D50", bake = TRUE) # With a real, non-rendered image: render_white_balance(sunset_image, preview=TRUE) # Cooler render_white_balance(sunset_image, preview=TRUE, target_white = "D75", bake = TRUE) # Warmer render_white_balance(sunset_image, preview=TRUE, target_white = "D50", bake = TRUE)
Sunset Image
sunset_imagesunset_image
An RGBA 4-layer LDR rayimg array from a JPEG image with 400 rows and 400 columns.
Tyler Morgan-Wall