Skip to content

RenderImage

Overview

RenderProgram for an image

@author Jonathan Olson <jonathan.olson@colorado.edu>

Class RenderImage

import { RenderImage } from 'scenerystack/alpenglow';

Constructor

new RenderImage( transform : Matrix3, image : RenderImageable, extendX : RenderExtend, extendY : RenderExtend, resampleType : RenderResampleType, logic? : RenderImageLogic )

Instance Methods

getName() : string

withChildren( children : RenderProgram[] ) : RenderImage

transformed( transform : Matrix3 ) : RenderProgram

equalsTyped( other : this ) : boolean

(protected)

evaluate( context : RenderEvaluationContext ) : Vector4

writeInstructions( instructions : RenderInstruction[] )

serialize() : SerializedRenderImage

Instance Properties

logic : RenderImageLogic

(readonly)

Static Methods

evaluateAnalyticFilter( logic : RenderImageLogic, context : RenderEvaluationContext, inverseTransform : Matrix3, minExpand : number, maxExpand : number, boundsShift : number, evaluateFace : ( face: ClippableFace, x: number, y: number, px: number, py: number, area: number ) => number, evaluateFull : ( x: number, y: number, px: number, py: number ) => number ) : Vector4

Evaluates a section of a filter analytically.

Basically, we transform the shape (that is presumably clipped to a user-space "pixel") into our image's coordinate frame. It might overlap one image-coordinate-frame pixel, or many. We'll figure out which pixels it overlaps, clip it to each of those individually, and then we'll evaluate the filter for each of those.

For most filters, the contribution of a single image-pixel (to our user-pixel) will then be determined by convolving the filter with the clipped shape, and summing up the integral. For our filters, we're able to use Green's theorem to evaluate this integral analytically, by doing a line integral along the edges of the indvidual areas.

The filters we are using have piecewise-polynomial functions, and thus their line integrals are similiarly "split in pieces". So for e.g. bilinear, we need to evaluate a 2x2 grid of "clipped" image-pixels individually to figure out the contribution. This means we need to get the clipped path for each image-pixel, and then we evaluate a specific line integral on the outline of that (and sum it up for each image-pixel in the grid).

We'll need to divide out the image-space result by the image-space area at the end

NOTE: we might have a flipped transform, so our signed area might be NEGATIVE in this case, so this code handles positive or negative areas.

NOTE: some filters can result in negative contributions for some pixels, so we need to handle that too!

@param logic @param context @param inverseTransform - The transform to put the face within the image's coordinate frame @param minExpand - How far our filter expands to the min direction (left/top) - 0 box, 1 bilinear, 2 mitchell @param maxExpand - How far our filter expands to the max direction (right/bottom) - 1 box, 1 bilinear, 2 mitchell @param boundsShift - A shift of indices, should be -1 for the box filter (since it is offset) @param evaluateFace - Evaluation function for a partial pixel. Evaluates the filter centered at x,y with the bounds of the clipped pixel in the range of px,py,px+1,py+1 @param evaluateFull - Evaluation function for a full pixel. Evaluates the filter centered at x,y with a full pixel of the bounds px,py,px+1,py+1

extend( extend : RenderExtend, t : number ) : number

extendInteger( i : number, size : number, extend : RenderExtend ) : number

Integer version of extend_mode. Given size=4, provide the following patterns:

input: -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

pad: 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3 repeat: 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1 reflect: 2, 3, 3, 2, 1, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 1

deserialize( obj : SerializedRenderImage ) : RenderImage

serializeRenderImageable( imageable : RenderImageable ) : SerializedRenderImageable

deserializeRenderImageable( obj : SerializedRenderImageable ) : RenderImageable

Class RenderImageLogic

import { RenderImageLogic } from 'scenerystack/alpenglow';

Constructor

new RenderImageLogic( transform : Matrix3, image : RenderImageable, extendX : RenderExtend, extendY : RenderExtend, resampleType : RenderResampleType )

Instance Methods

equals( other : RenderImageLogic ) : boolean

evaluate( context : RenderEvaluationContext ) : Vector4

Instance Properties

inverseTransform : Matrix3

(readonly)

inverseTransformWithHalfOffset : Matrix3

(readonly)

Class RenderInstructionImage

import { RenderInstructionImage } from 'scenerystack/alpenglow';

Constructor

new RenderInstructionImage( logic : RenderImageLogic )

Instance Methods

toString() : string

equals( other : RenderInstruction, areLocationsEqual : ( a: RenderInstructionLocation, b: RenderInstructionLocation ) => boolean ) : boolean

execute( stack : RenderExecutionStack, context : RenderEvaluationContext, executor : RenderExecutor )

writeBinary( encoder : ByteEncoder, getOffset : ( location: RenderInstructionLocation ) => number )

getBinaryLength() : number

Type SerializedRenderImage

import type { SerializedRenderImage } from 'scenerystack/alpenglow';

Source Code

See the source for RenderImage.ts in the alpenglow repository.