# LispKit Image

Library `(lispkit image)` provides a comprehensive interface to Apple’s Core Image framework for advanced image processing operations. The library supports creating image processing pipelines using abstract images, applying various filters, and performing coordinate transformations.

The image library is built around three main object types:

- Abstract images: Represent images in Core Image’s processing pipeline, supporting lazy evaluation and efficient composition of operations.
- Image filters: Represent image operations for generating, transforming, or combining abstract images, e.g. to apply effects like blur, color adjustment, distortion, and composition.
- Image coefficients: Represent numeric vectors used as parameters for filters.

All image operations work with abstract images, which can be converted to and from concrete images as defined by library `(lispkit draw)` for display, output, or file I/O operations.

## Filter Categories and Implementations

(available-image-filter-categories) [procedure]
(available-image-filter-categories raw?)

Returns a list of available Core Image filter categories. If raw? is `#t`, returns the raw string names; otherwise returns symbolic identifiers. Categories include:

- `blur`: Image blurring effects
- `sharpen`: Image sharpening effects
- `color-adjustment`, `color-effect`: Color manipulation filters
- `distortion-effect`: Geometric distortion filters
- `composite-operation`: Image blending and composition
- `generator`: Filters that create images from scratch
- `stylize`: Artistic and stylization effects

    (available-image-filter-categories)
    ⇒  (non-square-pixels composite-operation tile-effect interlaced
        color-adjustment reduction generator blur gradient transition
        sharpen builtin high-dynamic-range stylize filter-generator
        still-image halftone-effect video geometry-adjustment
        distortion-effect color-effect)
    (available-image-filter-categories #t)
    ⇒  ("CICategoryFilterGenerator" "CICategoryHighDynamicRange" "CICategoryHalftoneEffect"
        "CICategoryNonSquarePixels" "CICategoryStylize" "CICategoryColorAdjustment"
        "CICategoryStillImage" "CICategoryGenerator" "CICategorySharpen"
        "CICategoryTransition" "CICategoryGeometryAdjustment" "CICategoryDistortionEffect"
        "CICategoryGradient" "CICategoryBuiltIn" "CICategoryInterlaced" "CICategoryVideo"
        "CICategoryCompositeOperation" "CICategoryReduction" "CICategoryTileEffect"
        "CICategoryColorEffect" "CICategoryBlur")

(image-filter-category category) [procedure]
(image-filter-category category raw?)

category is either a string or a symbol. `image-filter-category` returns a symbol matching category if raw? is either not provided or set to `#f`. `image-filter-category` returns a string matching category if raw? is set to `#f`. `image-filter-category` returns `#f` if category is unknown or unsupported.

    (image-filter-category 'distortion-effect)           ⇒  distortion-effect
    (image-filter-category 'distortion-effect #t)        ⇒  "CICategoryDistortionEffect"
    (image-filter-category 'unknown)                     ⇒  #f
    (image-filter-category "CICategoryDistortionEffect") ⇒  distortion-effect

(available-image-filter-implementations) [procedure]
(available-image-filter-implementations categories)
(available-image-filter-implementations categories raw?)

Returns a list of available image filter implementations in the given filter categories. categories is a list of Core Image filter category identifiers. A category identifier is either a symbol or a string. Use boolean argument raw? to get internal Core Image filter implementation names instead of symbolic identifiers.

    ➤(available-image-filter-implementations '(reduction))
    ⇒  (area-alpha-weighted-histogram area-average area-average-maximum-red
        area-bounds-red area-histogram area-logarithmic-histogram area-maximum
        area-maximum-alpha area-minimum area-minimum-alpha area-min-max
        area-min-max-red column-average histogram-display-filter kmeans row-average)
    (available-image-filter-implementations '(reduction high-dynamic-range) #t)
    ⇒  ("CIAreaAverage" "CIAreaAverageMaximumRed" "CIAreaBoundsRed"
        "CIAreaLogarithmicHistogram" "CIAreaMaximum" "CIAreaMaximumAlpha"
        "CIAreaMinimum" "CIAreaMinimumAlpha" "CIAreaMinMax" "CIAreaMinMaxRed"
        "CIColumnAverage" "CIKMeans" "CIRowAverage")

## Abstract Images

(abstract-image? obj) [procedure]

Returns `#t` if obj is an abstract image, `#f` otherwise.

(make-abstract-image) [procedure]
(make-abstract-image source)
(make-abstract-image source flip?)

Creates an abstract image from various sources:

- If source is a string: loads image from the given file path
- If source is a bytevector: decodes image data
- If source is an image: converts to abstract image
- If source is an abstract image: returns the abstract image
- If source is `#f` or omitted: creates an empty abstract image

The boolean argument flip? controls vertical orientation (defaults to `#f`).

    (make-abstract-image)               ⇒ <empty abstract image>
    (make-abstract-image "dir/pt.jpg")  ⇒ <abstract image from file>
    (make-abstract-image image #t)      ⇒ <vertically flipped abstract image>

(image->abstract-image image) [procedure]
(image->abstract-image image flip?)

Converts an image to an abstract image. Use boolean argument flip? to control vertical orientation.

(color->abstract-image color) [procedure]

Creates an infinite abstract image filled with the specified color. This generator is useful for making backgrounds or for color generation filters.

    (color->abstract-image (color 1.0 0.0 0.0))  ⇒ <infinite red image>

(abstract-image->image aimage) [procedure]
(abstract-image->image aimage ppi)
(abstract-image->image aimage ppi flip?)

Renders an abstract image aimage into an image. Argument ppi specifies pixels per inch (default 72, maximum 720). Returns `#f` if rendering fails.

    (abstract-image->image ai)        ⇒ <rendered native image>
    (abstract-image->image ai 144 #t) ⇒ <high-DPI flipped image>

(abstract-image-bounds aimage) [procedure]

Returns the bounding rectangle of an abstract image as `((x . y) . (width . height))`. Returns `#f` for images with infinite bounds. In the Core Image framework, the bounding rectangle is also called the extent of an abstract image.

    (abstract-image-bounds my-image)  ⇒  ((0.0 . 0.0) . (1024.0 . 768.0))

(abstract-image-adjustment-filters aimage) [procedure]
(abstract-image-adjustment-filters aimage options)

Generates adjustment filters for enhancing the given abstract image aimage. Argument options is an association list that can include:

- `(crop . #t)`: Enable automatic cropping
- `(enhance . #t)`: Enable contrast/exposure enhancement
- `(rotate . #t)`: Enable automatic rotation correction
- `(red-eye . #t)`: Enable red-eye reduction

Returns a list of image filters that can be applied to improve the image.

## Image Filters

(image-filter? obj) [procedure]

Returns `#t` if obj is an image filter, `#f` otherwise.

(make-image-filter name) [procedure]
(make-image-filter name input)
(make-image-filter name input args)

Creates an image filter with the specified name. Optionally sets an abstract input image and provides arguments for the specified filter. args is an association list of argument names and values.

    (make-image-filter 'gaussian-blur)
    (make-image-filter 'gaussian-blur img '((input-radius . 5.0)))
    (make-image-filter 'color-controls #f '((input-brightness . 0.1) (input-contrast . 1.2)))

(image-filter-name filter) [procedure]

Returns the localized display name of the image filter as a string.

(image-filter-implementation filter-or-id) [procedure]
(image-filter-implementation filter-or-id raw?)

Returns the filter implementation identifier of the image filter filter-or-id. If raw? is `#t`, returns the Core Image internal name as a string; otherwise returns the symbolic identifier. filter-or-id is either an image filter, a symbolic image filter identifier, or a name of a Core Image filter as a string.

(image-filter-description filter) [procedure]

Returns the localized description of the image filter as a string, or `#f` if no description is available.

(image-filter-categories filter) [procedure]
(image-filter-categories filter raw?)

Returns a list of categories that the image filter belongs to. If raw? is `#t`, returns the raw string names; otherwise returns symbolic identifiers.

(image-filter-available filter) [procedure]

Returns availability information as two string values mac-version and ios-version indicating the minimum OS versions where the image filter is available.

(image-filter-inputs filter) [procedure]
(image-filter-inputs filter raw?)

Returns a list of input argument names for the given image filter.

(image-filter-outputs filter) [procedure]
(image-filter-outputs filter raw?)

Returns a list of output argument names for the filter.

(image-filter-output filter) [procedure]

Returns the primary output image of the filter as an abstract image, or `#f` if no output is available.

(image-filter-argument filter key) [procedure]

Returns metadata about the filter argument key for the given image filter as an association list. Keys include:

- `name`: Name of the argument.
- `display-name`: Human-readable argument name.
- `identity`: An identifier for the argument.
- `description`: Human-readable argument description.
- `reference-documentation`: Reference to documentation.
- `class`: Objective C/Swift class name for representing values of this attribute (e.g. `"NSNumber"`).
- `type`: Argument type. Supported are: `time`, `scalar`, `distance`, `angle`, `boolean`, `integer`, `count`, `color`, `opaque-color`, `gradient`, `point`, `offset`, `coordinate-3d`, `rect`, `abstract-image`, `transformation`, `date`, `styled-text`, `string`, `number`, `bytevector`, `image-coefficients`, `array`, and `color-space`.
- `default`: Default value
- `min`, `max`: Value range limits
- `slider-min`, `slider-max`: UI slider range

(image-filter-argument-ref filter key) [procedure]
(image-filter-argument-ref filter key default)

Returns the current value of the given image filter argument key, or default if the argument is not set.

(image-filter-argument-set! filter key value) [procedure]

Sets the value of the specified image filter argument key to value. This is a mutating operation.

    (define blur (make-image-filter 'gaussian-blur))
    (image-filter-argument-set! blur 'input-radius 10.0)
    (image-filter-argument-ref blur 'input-radius)  ⇒  10.0

## Image Coefficients

Image filters have attributes, which are key value pairs associated with image filter objects. Attributes have types, which can be determined by using the `image-filter-argument` procedure and extracting the `type` property. Here is an example:

    (define f (make-image-filter 'color-cross-polynomial))
    (image-filter-inputs f)
    ⇒  (input-image input-red-coefficients input-green-coefficients input-blue-coefficients)
    (cdr (assoc 'type (image-filter-argument f 'input-red-coefficients)))
    ⇒  image-coefficients

Filter attributes of type `image-coefficients` are represented by `image-coefficients` objects.

(image-coefficients arg …) [procedure]

Creates an image coefficients object from numeric values and sequences of numeric values arg …. Arguments can be numbers, lists of numbers, or vectors of numbers, which are sequentially flattened into a single coefficient vector within a image coefficients object.

    (image-coefficients 1.0 2.0 3.0)       ⇒  #<image-coefficients 98c840750 3:  1.0,  2.0,  3.0>
    (image-coefficients '(1.0 2.0) '(3 4)) ⇒  #<image-coefficients 98c8407b0 4:  1.0,  2.0,  3.0,  4.0>
    (image-coefficients #(1 2) '(3) 4)     ⇒  #<image-coefficients 98c8407e0 4:  1.0,  2.0,  3.0,  4.0>
    (image-coefficients (rect 1 2 3 4))    ⇒  #<image-coefficients 98c847ae0 4:  1.0,  2.0,  3.0,  4.0>

(image-coefficients->vector coeffs) [procedure]

Converts image coefficients coeffs to a vector of flonums.

(image-coefficients->point coeffs) [procedure]

Interprets the first two coefficient values `x` and `y` as a point, returning `(x . y)`. Returns `#f` if fewer than two coefficients coeffs are available.

(image-coefficients->rect coeffs) [procedure]

Interprets the first four coefficient values `x`, `y`, `width`, and `hight` as a rectangle, returning `((x . y) . (width . height))`. Returns `#f` if fewer than four coefficients are available.

    (define r (rect '(1 . 2) '(3 . 4)))
    r  ⇒  ((1.0 . 2.0) 3.0 . 4.0)
    (define c (image-coefficients r))
    c  ⇒  #<image-coefficients 98c847f60 4:  1.0,  2.0,  3.0,  4.0>
    (image-coefficients->rect c)
    ⇒  ((1.0 . 2.0) 3.0 . 4.0)

## Image Processing Pipeline

(apply-image-filter aimage filter …) [procedure]

Applies a sequence of filters to an abstract image aimage, creating an image processing pipeline and returning the resulting abstract image of `#f` if processing fails. Each argument filter is either a filter specifier or a list of filter specifiers. The following two forms of filter specifiers are supported:

- image filter object: A configured image filter that will be applied as is.
- `(filter-identifier (arg1 . value) ...)`: A list whose first element identifies the image filter followed by pairs defining image filter attributes. The image filter identifier is either a symbol or a string.

    ;; Apply gaussian blur with radius 5.0
    (apply-image-filter img '(gaussian-blur (input-radius . 5.0)))
    ⇒  #<abstract-image 9eef6c280: 0×0>

    ;; Apply multiple filters in sequence
    (apply-image-filter img
      '(gaussian-blur (input-radius . 2.0))
      '(color-controls (input-brightness . 0.1) (input-contrast . 1.2))
      (make-image-filter 'vignette))
    ⇒  #<abstract-image 782434020: 0×0>

## Coordinate Mapping

(map-image-point pnt image) [procedure]

Maps the coordinates of a point pnt on image (using points as units) to pixel coordinates on a corresponding abstract image. The point should be in the format `(x . y)`.

(map-image-rect rect image) [procedure]

Maps the representation of a rectangle rect on image (using points as units) to pixel coordinates on a corresponding abstract image. The rect should be in the format `((x . y) . (width . height))`.