import '../../../assert/js/assert.js';
import '../../../globals.js';
/**
 * RenderProgram for an image
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { ByteEncoder, ClippableFace, RenderEvaluationContext, RenderExecutionStack, RenderExecutor, RenderExtend, RenderImageable, RenderInstruction, RenderInstructionLocation, RenderProgram, RenderResampleType, SerializedRenderImageable } from '../imports.js';
import Matrix3 from '../../../dot/js/Matrix3.js';
import Vector4 from '../../../dot/js/Vector4.js';
export default class RenderImage extends RenderProgram {
    readonly transform: Matrix3;
    readonly image: RenderImageable;
    readonly extendX: RenderExtend;
    readonly extendY: RenderExtend;
    readonly resampleType: RenderResampleType;
    readonly logic: RenderImageLogic;
    constructor(transform: Matrix3, image: RenderImageable, extendX: RenderExtend, extendY: RenderExtend, resampleType: RenderResampleType, logic?: RenderImageLogic);
    getName(): string;
    withChildren(children: RenderProgram[]): RenderImage;
    transformed(transform: Matrix3): RenderProgram;
    protected equalsTyped(other: this): boolean;
    evaluate(context: RenderEvaluationContext): Vector4;
    writeInstructions(instructions: RenderInstruction[]): void;
    /**
     * 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
     */
    static 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;
    static extend(extend: RenderExtend, t: number): number;
    static extendInteger(i: number, size: number, extend: RenderExtend): number;
    serialize(): SerializedRenderImage;
    static deserialize(obj: SerializedRenderImage): RenderImage;
    static serializeRenderImageable(imageable: RenderImageable): SerializedRenderImageable;
    static deserializeRenderImageable(obj: SerializedRenderImageable): RenderImageable;
}
export declare class RenderImageLogic {
    readonly transform: Matrix3;
    readonly image: RenderImageable;
    readonly extendX: RenderExtend;
    readonly extendY: RenderExtend;
    readonly resampleType: RenderResampleType;
    readonly inverseTransform: Matrix3;
    readonly inverseTransformWithHalfOffset: Matrix3;
    constructor(transform: Matrix3, image: RenderImageable, extendX: RenderExtend, extendY: RenderExtend, resampleType: RenderResampleType);
    equals(other: RenderImageLogic): boolean;
    evaluate(context: RenderEvaluationContext): Vector4;
}
export declare class RenderInstructionImage extends RenderInstruction {
    readonly logic: RenderImageLogic;
    constructor(logic: RenderImageLogic);
    toString(): string;
    equals(other: RenderInstruction, areLocationsEqual: (a: RenderInstructionLocation, b: RenderInstructionLocation) => boolean): boolean;
    execute(stack: RenderExecutionStack, context: RenderEvaluationContext, executor: RenderExecutor): void;
    writeBinary(encoder: ByteEncoder, getOffset: (location: RenderInstructionLocation) => number): void;
    getBinaryLength(): number;
}
export type SerializedRenderImage = {
    type: 'RenderImage';
    transform: number[];
    image: SerializedRenderImageable;
    extendX: RenderExtend;
    extendY: RenderExtend;
    resampleType: RenderResampleType;
};
//# sourceMappingURL=RenderImage.d.ts.map