CrImage::Transform
Image transformation and filtering operations.
Provides a comprehensive set of image manipulation functions including:
- Resizing with multiple interpolation algorithms (nearest, bilinear, bicubic, Lanczos)
- Rotation (arbitrary angles and optimized 90°/180°/270°)
- Flipping (horizontal and vertical)
- Cropping to rectangles
- Filters (blur, sharpen, Gaussian blur)
- Adjustments (brightness, contrast, grayscale, inversion)
- Edge detection (Sobel, Prewitt, Roberts, Scharr)
- Visual effects (sepia, emboss, vignette, temperature)
- In-place operations for memory efficiency
Example:
img = CrImage.read("input.png")
# Resize with high quality
resized = img.resize(800, 600, method: :lanczos)
# Rotate 45 degrees
rotated = img.rotate(45.0)
# Apply filters
blurred = img.blur_gaussian(radius: 5)
sharpened = img.sharpen(amount: 1.5)
# Adjust colors
brighter = img.brightness(50)
contrasted = img.contrast(1.2)
# Edge detection
edges = img.sobel
# Visual effects
vintage = img.sepia
embossed = img.emboss
Class methods
Applies EXIF orientation transform using integer value.
Convenience overload that accepts raw orientation value (1-8).
Applies EXIF orientation transform to correct image rotation.
Digital cameras store orientation information in EXIF metadata to indicate how the image should be displayed. This method applies the necessary rotation and/or flip to display the image correctly.
Parameters:
src: The source image to orientorientation: EXIF orientation value (1-8)
Returns: A new Image with correct orientation, or copy if no transform needed
Orientation values:
- 1: Normal (no transform)
- 2: Flip horizontal
- 3: Rotate 180°
- 4: Flip vertical
- 5: Transpose (flip horizontal + rotate 270°)
- 6: Rotate 90° clockwise
- 7: Transverse (flip horizontal + rotate 90°)
- 8: Rotate 270° clockwise (90° counter-clockwise)
Example:
img = CrImage::JPEG.read("photo.jpg")
exif = CrImage::EXIF.read("photo.jpg")
if exif
oriented = CrImage::Transform.auto_orient(img, exif.orientation)
end
Applies box blur in-place without creating a new image.
Modifies the image directly, which is much faster and more memory-efficient than the non-mutating version. Uses a temporary buffer internally but still more efficient than creating a full copy. The original image data is permanently modified.
Parameters:
img: The RGBA image to modify (must be RGBA type)radius: Blur radius in pixels (must be positive)
Returns: Nil (modifies image in-place)
Raises: ArgumentError if radius is not positive or image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.blur!(img, 5)
Applies a box blur filter to an image.
Box blur is a simple averaging filter that blurs by averaging all pixels within a square kernel. Fast but produces lower quality blur compared to Gaussian. Edge pixels are clamped to image boundaries.
Parameters:
src: The source image to blurradius: Blur radius in pixels (must be positive)
Returns: A new blurred Image
Raises: ArgumentError if radius is not positive
Example:
img = CrImage::PNG.read("photo.png")
blurred = CrImage::Transform.blur_box(img, 5)
Applies Gaussian blur to an image.
Gaussian blur uses a weighted average based on the Gaussian distribution, producing natural-looking blur. Implemented as separable convolution for efficiency. If sigma is not provided, it defaults to radius/3.
Parameters:
src: The source image to blurradius: Blur radius in pixels (must be non-negative, 0 returns a copy)sigma: Standard deviation of Gaussian kernel (optional, defaults to radius/3)
Returns: A new blurred Image
Raises: ArgumentError if radius is negative
Example:
img = CrImage::PNG.read("photo.png")
blurred = CrImage::Transform.blur_gaussian(img, 10)
custom_blur = CrImage::Transform.blur_gaussian(img, 10, sigma: 5.0)
Applies Gaussian blur in-place without creating a new image.
Modifies the image directly, which is much faster and more memory-efficient than the non-mutating version. Uses a temporary buffer internally but still more efficient than creating a full copy. The original image data is permanently modified.
Parameters:
img: The RGBA image to modify (must be RGBA type)radius: Blur radius in pixels (must be non-negative)sigma: Standard deviation of Gaussian kernel (optional, defaults to radius/3)
Returns: Nil (modifies image in-place)
Raises: ArgumentError if radius is negative or image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.blur_gaussian!(img, 10)
Adjusts the brightness of an image.
Adds a constant value to all RGB channels. Positive values brighten, negative values darken. Values are clamped to 0-255 range. Alpha channel is preserved.
Parameters:
src: The source image to adjustadjustment: Brightness adjustment value (-255 to 255)
Returns: A new Image with adjusted brightness
Raises: ArgumentError if adjustment is outside valid range
Example:
img = CrImage::PNG.read("photo.png")
brighter = CrImage::Transform.brightness(img, 50)
darker = CrImage::Transform.brightness(img, -30)
Adjusts brightness in-place without creating a new image.
Modifies the image directly, which is much faster and more memory-efficient than the non-mutating version. The original image data is permanently modified.
Parameters:
img: The RGBA image to modify (must be RGBA type)adjustment: Brightness adjustment value (-255 to 255)
Returns: Nil (modifies image in-place)
Raises: ArgumentError if image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.brightness!(img, 50)
CrImage::PNG.write("brighter.png", img)
Adjusts the contrast of an image.
Scales RGB values around the midpoint (128). Values greater than 1.0 increase contrast, values less than 1.0 decrease contrast. Alpha channel is preserved.
Parameters:
src: The source image to adjustfactor: Contrast factor (0.0 to 2.0, where 1.0 is no change)
Returns: A new Image with adjusted contrast
Raises: ArgumentError if factor is outside valid range
Example:
img = CrImage::PNG.read("photo.png")
high_contrast = CrImage::Transform.contrast(img, 1.5)
low_contrast = CrImage::Transform.contrast(img, 0.7)
Adjusts contrast in-place without creating a new image.
Modifies the image directly, which is much faster and more memory-efficient than the non-mutating version. The original image data is permanently modified.
Parameters:
img: The RGBA image to modify (must be RGBA type)factor: Contrast factor (0.0 to 2.0, where 1.0 is no change)
Returns: Nil (modifies image in-place)
Raises: ArgumentError if image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.contrast!(img, 1.5)
Crops an image to the specified rectangle.
Extracts a rectangular region from the source image. The crop rectangle is automatically clipped to the source image bounds.
Parameters:
src: The source image to croprect: The rectangle defining the crop region
Returns: A new Image containing only the cropped region
Raises: ArgumentError if the crop rectangle is completely outside image bounds
Example:
img = CrImage::PNG.read("photo.png")
crop_rect = CrImage.rect(100, 100, 300, 300)
cropped = CrImage::Transform.crop(img, crop_rect)
Applies edge detection to an image using the specified operator.
Edge detection highlights areas of rapid intensity change, useful for finding object boundaries, features, and structural information.
Parameters:
src: The source imageoperator: Edge detection operator to use (default: Sobel)threshold: Optional threshold for binary edge map (0-255, nil for gradient magnitude)
Returns: A new grayscale Image showing detected edges
Example:
img = CrImage::PNG.read("photo.png")
edges = CrImage::Transform.detect_edges(img)
binary_edges = CrImage::Transform.detect_edges(img, threshold: 50)
Applies an emboss effect to an image.
Emboss creates a 3D raised appearance by emphasizing edges and converting the image to grayscale with directional lighting.
Parameters:
src: The source imageangle: Light direction angle in degrees (default: 45.0)depth: Effect strength (default: 1.0, range: 0.5-2.0)
Returns: A new Image with emboss effect
Example:
img = CrImage::PNG.read("photo.png")
embossed = CrImage::Transform.emboss(img)
strong_emboss = CrImage::Transform.emboss(img, depth: 2.0)
Flips an image horizontally (mirror effect).
Creates a mirror image by reversing pixels along the horizontal axis. The output dimensions remain the same as the input.
Parameters:
src: The source image to flip
Returns: A new Image flipped horizontally
Example:
img = CrImage::PNG.read("face.png")
mirrored = CrImage::Transform.flip_horizontal(img)
Flips an image vertically (upside down).
Reverses pixels along the vertical axis, turning the image upside down. The output dimensions remain the same as the input.
Parameters:
src: The source image to flip
Returns: A new Image flipped vertically
Example:
img = CrImage::PNG.read("photo.png")
upside_down = CrImage::Transform.flip_vertical(img)
Converts an image to grayscale.
Uses the luminosity method with standard weights (R: 0.299, G: 0.587, B: 0.114)
to convert color images to grayscale. Returns a Gray image.
Parameters:
src: The source image to convert
Returns: A new Gray image
Example:
img = CrImage::PNG.read("color_photo.png")
gray = CrImage::Transform.grayscale(img)
CrImage::PNG.write("gray_photo.png", gray)
Converts image to grayscale in-place (modifies the image directly). Only works on RGBA images for performance. Uses ITU-R BT.709 luminance formula: Y = 0.2126R + 0.7152G + 0.0722*B
Parameters:
img: The RGBA image to modify
Returns: Nil (modifies image in-place)
Raises: ArgumentError if image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.grayscale!(img)
Inverts the colors of an image (negative effect).
Subtracts each RGB channel value from 255 to create a color negative. Alpha channel is preserved.
Parameters:
src: The source image to invert
Returns: A new Image with inverted colors
Example:
img = CrImage::PNG.read("photo.png")
negative = CrImage::Transform.invert(img)
Inverts colors in-place without creating a new image.
Modifies the image directly, which is much faster and more memory-efficient than the non-mutating version. The original image data is permanently modified.
Parameters:
img: The RGBA image to modify (must be RGBA type)
Returns: Nil (modifies image in-place)
Raises: ArgumentError if image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.invert!(img)
Applies Prewitt edge detection (convenience method).
Prewitt operator is similar to Sobel but with equal weighting.
Example:
edges = CrImage::Transform.prewitt(img)
Resizes an image using bicubic (Catmull-Rom) interpolation.
Uses a 4x4 pixel neighborhood for interpolation, producing high quality results with good sharpness. Faster than Lanczos while maintaining excellent quality. Uses separable convolution for efficiency.
Parameters:
src: The source image to resizenew_width: Target width in pixels (must be positive)new_height: Target height in pixels (must be positive)
Returns: A new Image with the specified dimensions
Raises: ArgumentError if width or height is not positive
Example:
img = CrImage::JPEG.read("photo.jpg")
high_quality = CrImage::Transform.resize_bicubic(img, 1920, 1080)
# Or use the chainable API:
high_quality = img.resize(1920, 1080, method: :bicubic)
Resizes an image using bilinear interpolation.
Provides better quality than nearest neighbor by interpolating between the four nearest pixels. Good balance between speed and quality for most uses.
Parameters:
src: The source image to resizenew_width: Target width in pixels (must be positive)new_height: Target height in pixels (must be positive)
Returns: A new Image with the specified dimensions
Raises: ArgumentError if width or height is not positive
Example:
img = CrImage::PNG.read("photo.png")
resized = CrImage::Transform.resize_bilinear(img, 800, 600)
# Or use the chainable API:
resized = img.resize(800, 600, method: :bilinear)
Resizes an image using Lanczos-3 interpolation.
Provides the highest quality resizing with excellent detail preservation and minimal aliasing artifacts. Uses a 3-lobe windowed sinc filter. Best for professional photo editing and when quality is paramount. Slower than other methods due to larger kernel size.
Parameters:
src: The source image to resizenew_width: Target width in pixels (must be positive)new_height: Target height in pixels (must be positive)
Returns: A new Image with the specified dimensions
Raises: ArgumentError if width or height is not positive
Example:
img = CrImage::PNG.read("artwork.png")
print_quality = CrImage::Transform.resize_lanczos(img, 3000, 2000)
# Or use the chainable API:
print_quality = img.resize(3000, 2000, method: :lanczos)
Resizes an image using nearest neighbor interpolation.
This is the fastest resizing algorithm but produces lower quality results, especially when upscaling. Best used for pixel art or when speed is critical.
Parameters:
src: The source image to resizenew_width: Target width in pixels (must be positive)new_height: Target height in pixels (must be positive)
Returns: A new Image with the specified dimensions
Raises: ArgumentError if width or height is not positive
Example:
img = CrImage::PNG.read("input.png")
thumbnail = CrImage::Transform.resize_nearest(img, 100, 100)
# Or use the chainable API:
thumbnail = img.resize(100, 100, method: :nearest)
Applies Roberts cross edge detection (convenience method).
Roberts cross uses 2x2 kernels, faster but more sensitive to noise.
Example:
edges = CrImage::Transform.roberts(img)
Rotates an image by an arbitrary angle (in degrees) clockwise.
The output image is sized to contain the entire rotated image without cropping. Empty areas are filled with the specified background color (default: transparent). For 90°, 180°, 270° rotations, uses optimized fast paths.
Parameters:
src: The source image to rotateangle_degrees: Rotation angle in degrees (positive = clockwise)interpolation: Interpolation method (Nearest or Bilinear)background: Color for empty areas (default: transparent)
Returns: A new Image containing the rotated result
Example:
img = CrImage::PNG.read("photo.png")
# Rotate 45 degrees with bilinear interpolation
rotated = CrImage::Transform.rotate(img, 45.0)
# Rotate with nearest neighbor (faster)
rotated = CrImage::Transform.rotate(img, 30.0,
interpolation: CrImage::Transform::RotationInterpolation::Nearest)
# Rotate with white background
rotated = CrImage::Transform.rotate(img, 15.0,
background: CrImage::Color::WHITE)
Rotates an image 180 degrees.
The output dimensions remain the same as the input. This is a lossless operation that preserves all pixel data.
Parameters:
src: The source image to rotate
Returns: A new Image rotated 180 degrees
Example:
img = CrImage::PNG.read("photo.png")
flipped = CrImage::Transform.rotate_180(img)
Rotates an image 270 degrees clockwise (90 degrees counter-clockwise).
The output dimensions are swapped (width becomes height, height becomes width). This is a lossless operation that preserves all pixel data.
Parameters:
src: The source image to rotate
Returns: A new Image rotated 270 degrees clockwise
Example:
img = CrImage::PNG.read("portrait.png")
landscape = CrImage::Transform.rotate_270(img)
Rotates an image 90 degrees clockwise.
The output dimensions are swapped (width becomes height, height becomes width). This is a lossless operation that preserves all pixel data.
Parameters:
src: The source image to rotate
Returns: A new Image rotated 90 degrees clockwise
Example:
img = CrImage::PNG.read("landscape.png")
portrait = CrImage::Transform.rotate_90(img)
Applies a sepia tone effect to an image.
Sepia creates a warm, brownish tone reminiscent of old photographs. Uses standard sepia transformation matrix.
Parameters:
src: The source image
Returns: A new Image with sepia tone applied
Example:
img = CrImage::PNG.read("photo.png")
vintage = CrImage::Transform.sepia(img)
Applies a sharpening filter to an image.
Enhances edges and details using an unsharp mask technique. Higher amounts produce more pronounced sharpening. Values above 2.0 may produce artifacts.
Parameters:
src: The source image to sharpenamount: Sharpening strength (default: 1.0, typical range: 0.5-2.0)
Returns: A new sharpened Image
Example:
img = CrImage::JPEG.read("photo.jpg")
sharpened = CrImage::Transform.sharpen(img, 1.5)
Applies sharpening filter in-place without creating a new image.
Modifies the image directly, which is much faster and more memory-efficient than the non-mutating version. Uses a temporary buffer internally but still more efficient than creating a full copy. The original image data is permanently modified.
Parameters:
img: The RGBA image to modify (must be RGBA type)amount: Sharpening strength (default: 1.0, typical range: 0.5-2.0)
Returns: Nil (modifies image in-place)
Raises: ArgumentError if image is not RGBA type
Example:
img = CrImage::PNG.read("photo.png").as(CrImage::RGBA)
CrImage::Transform.sharpen!(img, 1.5)
Applies Sobel edge detection (convenience method).
Sobel operator uses 3x3 kernels with smoothing, good for general edge detection.
Example:
edges = CrImage::Transform.sobel(img)
Adjusts color temperature of an image.
Shifts colors toward warm (orange/red) or cool (blue) tones. Useful for correcting white balance or creating mood.
Parameters:
src: The source imagetemperature: Temperature adjustment (-100 to 100, negative=cooler, positive=warmer)
Returns: A new Image with adjusted color temperature
Example:
img = CrImage::PNG.read("photo.png")
warmer = CrImage::Transform.temperature(img, 30)
cooler = CrImage::Transform.temperature(img, -30)
Applies a vignette effect to an image.
Vignette darkens the edges of the image, drawing focus to the center. Common in photography for artistic effect.
Parameters:
src: The source imagestrength: Vignette intensity (default: 0.5, range: 0.0-1.0)radius: Vignette radius as fraction of image size (default: 0.7, range: 0.1-1.0)
Returns: A new Image with vignette effect
Example:
img = CrImage::PNG.read("photo.png")
vignetted = CrImage::Transform.vignette(img)
strong_vignette = CrImage::Transform.vignette(img, strength: 0.8)