Skip to content

Channel Composition

Purpose and expected result

Channel Composition creates a new three-channel RGB view from up to three open monochrome views. It is for users who already have registered component masters or normalized color-space component planes and need direct assignment rather than calibration, registration, or stacking.

Choose RGB for ordinary red, green, and blue masters. The seven other modes interpret the three scalar planes as encoded XYZ, Lab, LCh, HSL, HSV, HSI, or YCbCr components and convert them to RGB. A successful run closes the process and opens a new pending-changes image or sequence; it does not replace or modify the chosen views. Optional Linear Match creates matched working copies of later selected components before composition.

At a glance

Item Current behavior
Menu path Process > Color Spaces > Channel Composition
Enabled when The registered top-level action is available even with no open image. The dialog lists open monochrome views. OK is enabled only when the first selector is not <--NO IMAGE-->.
Inputs One required first component and up to two optional later components from open one-channel stills or sequences. Use all-still or all-sequence sources with equal width/height; for sequences, the first component's frame count decides the output's.
Outputs One new three-channel still in the highest of the components' representations, or a new sequence written in the session's temporary directory in the first component's container. Selected views remain unchanged, including when Linear Match is enabled. No component maps, coefficients, or report are produced.
Recommended image state RGB: registered, cropped, calibrated linear masters with comparable background/scale. Other modes: component planes produced with AfterNight's matching normalized encoding; their RGB result is treated as nonlinear.
Preview support None. There is no preview pane or preview action; OK runs the full composition.
Sequence support Implemented for compatible grayscale sequences, frame by frame on a worker, with a progress dialog whose Cancel stops the run; a frame missing from a shorter sequence is a zero plane; the sequence is published whole or not at all.
Mask support Unsupported. Active view masks are neither read nor blended.
External dependencies None. Conversion uses the engine's colour transforms; Linear Match is the engine's normalization scaling match.

Before you start

  • Register and crop the component images first. Channel Composition compares dimensions, but does not align, resample, rotate, or use WCS to reconcile geometry.
  • Keep every selected view monochrome. RGB views do not appear in the source selectors.
  • Select the first displayed component. OK remains disabled for a second- or third-only assignment, and execution validates the first source again before starting its worker.
  • Prefer all three components. A missing selector is replaced by numeric zero, which is black only for direct RGB. In Lab, for example, zero in a* or b* means the minimum encoded chroma coordinate rather than neutral 0.5.
  • Use Linear Match only as a scalar intensity match, not registration or color calibration. It matches temporary working images and leaves selected source buffers unchanged.
  • For Lab/LCh/XYZ, use planes generated by the same AfterNight encoding. The process assumes sRGB-like D65 conversions and does not inspect or apply ICC profiles.

Procedure

  1. Open the registered monochrome channel masters. Verify equal pixel dimensions. For sequences, put the sequence whose frame count and container the output should have first: the output has its number of frames and its container (SER, image list, AVI, MP4, or another video container).
  2. Open Process > Color Spaces > Channel Composition. The source selectors contain <--NO IMAGE--> plus each currently open monochrome view.
  3. Choose Color Space. Confirm that the three labels change to the expected assignment, such as Red / Green / Blue, L / a / b, or Y / Cb / Cr.
  4. Select the first source and then the second and third sources. Reusing one view is allowed, but its exposure is counted once per assignment when output metadata is built.
  5. Leave Linear Match off for already normalized channels and for hue/chroma component maps. Enable it only when comparable RGB intensity masters need scalar level/spread matching.
  6. Click OK. A sequence shows a progress dialog with Cancel; a still has no progress dialog. The components, Color Space, and Linear Match are read when OK is pressed, so a later change reaches the next run only.
  7. On success, inspect the new RGB view's channel balance, clipping, dimensions, processing-state marker, and history description. Save it explicitly when ready; the new view starts as pending changes.

Complete parameter and action reference

UI label/action Type and unit Runtime default Persisted-default exception Valid values, step, or constraints Effect of increasing, decreasing, or selecting Dependencies and enable/visibility rules Quality, artifact, runtime, memory, or disk trade-off Scope: preview/apply, channel, mask, still/sequence Persistence
Color Space Selector RGB None RGB, CIE XYZ, CIE L*a*b*, CIE L*c*h*, HSL, HSV, HSI, YCbCr Selects direct assignment or an encoded-component-to-RGB conversion and relabels all three selectors. Always enabled, including during execution. It is read when OK is pressed, so a change during a run reaches the next run only. Non-RGB modes add conversion and clipping risk; hue/chroma modes are not interchangeable with intensity planes. Full still or each sequence frame; no preview/mask Window lifetime; every new dialog starts at RGB.
Red / X / L / H / Y First monochrome source selector <--NO IMAGE--> None Open grayscale still/sequence view; label is Red (RGB), X (XYZ), L (Lab/LCh), H (HSL/HSV/HSI), or Y (YCbCr) Supplies component 0 and determines the guide/reference. List follows view creation, update, rename, and close. OK requires this selector, and execution validates it again before worker launch. A wrong first plane changes the entire result; its geometry seeds missing planes and its metadata leads the metadata built for the result. Component 0; full Apply; still/sequence Window lifetime; returns to <--NO IMAGE--> if its view closes or ceases to be grayscale.
Green / Y / a / c / S / Cb Second monochrome source selector <--NO IMAGE--> None Open grayscale still/sequence view; label follows the chosen mode Supplies component 1: Green, Y, a*, c*, HSL/HSV/HSI saturation, or blue-difference chroma. Omission supplies zero. Same dynamic list. It must match the first source's still/sequence class and final dimensions. Zero is not neutral for Lab a* or YCbCr Cb; Linear Match uses a temporary fitted copy and does not alter this source. Component 1; full Apply; still/sequence Window lifetime.
Blue / Z / b / h / L / V / I / Cr Third monochrome source selector <--NO IMAGE--> None Open grayscale still/sequence view; label follows the chosen mode Supplies component 2: Blue, Z, b*, LCh hue, HSL lightness, HSV value, HSI intensity, or red-difference chroma. Omission supplies zero. Same dynamic list and compatibility requirements. Zero can mean minimum lightness/value/intensity or non-neutral chroma; Linear Match likewise uses a temporary fitted copy. Component 2; full Apply; still/sequence Window lifetime.
Linear Match Checkbox Off None Off/On On treats the first selected component as reference and applies output = a × source + b to temporary copies of each later selected component before composition: a is the ratio of the two planes' robust scales (median absolute deviation), always positive, and b moves the component's median onto the reference's, both measured where both planes hold a sample inside the normalized limits [1e-7, 0.875]. Always editable, including while running; it is read when OK is pressed. It does not align geometry and is unaware of circular hue or centered chroma semantics. Can reduce RGB level/spread differences, but can destroy meaningful component encodings in the output and write outside normalized float range. A pair with no sample inside the limits fails the run. Adds scans and per-pixel work without modifying sources. Pre-composition; selected later components; each sequence frame; no mask Window lifetime; always off in a new dialog.
OK Action Disabled until the first selector is valid None One detached operation at a time Captures the components' images, Color Space, and Linear Match, disables OK/Close, validates the required first source, and starts still or sequence composition. Success opens a new view and closes this window. Source selectors, Color Space, and Linear Match remain enabled while running; the run uses what was captured. Full-resolution work and possible temporary disk for sequences. Linear Match transformations are isolated working copies. Full still/sequence Apply Output/history persist when saved; dialog settings do not.
Close Action Enabled while idle None Click action Closes without starting composition. Disabled after OK until failure/cancel or successful close. It is not the sequence cancellation control. Discards pending choices. Title-bar closing during detached execution is not a substitute for cancellation. Dialog only Not persisted.
Sequence progress/status Read-only progress Hidden for stills None 0–100 percent; title/text Channel Composition / Executing Channel Composition Reports the share of the first component's frames written. Created when any selected source is a sequence; a mix of stills and sequences is refused before it appears. Main OK/Close are disabled. Updates after each frame is written; output consumes temporary disk. Sequence Apply Not persisted.
Cancel (sequence progress) Action Available in progress dialog None Cooperative request Stops the run and leaves the composition dialog open; the unfinished sequence leaves no file and nothing is opened. The stop reaches the current frame's engine work as well as the frame loop. Nothing is published. Sequence Apply only Request only.

How the algorithm works

Conceptual pipeline

  1. Resolve each selected view. Missing components become zero-filled grayscale images or dummy sequences with the first selected source's geometry, type, and frame count.
  2. Per still or per sequence frame, read every plane as a fraction of its own full scale. The result is written in the highest of the components' representations, in the order signed 8-bit, unsigned 8-bit, signed 16-bit, unsigned 16-bit, signed 32-bit, unsigned 32-bit, float32, then float64.
  3. If Linear Match is on, keep the first selected plane unchanged and match every later selected plane to it by the scaling match described below.
  4. Require equal width and height, then either copy RGB planes directly or interpret the normalized planes in the selected color model and reconstruct RGB, the CIE models through the engine's colour transforms in double precision.
  5. Build the result's metadata from the actual selected sources, state its processing state, create a new view next to the first selected source, and record a history description containing the assignments.

Model and equations

Let c0, c1, and c2 be normalized samples from the first, second, and third selectors. Integer samples are normalized across their full type range; float and double samples are used directly.

Mode Component interpretation and RGB reconstruction
RGB R = c0, G = c1, B = c2. Samples are copied into the result's representation; there is no gamut clamp in this path.
CIE XYZ X = 95.047 c0, Y = 100 c1, Z = 108.883 c2. The D65 XYZ-to-linear-sRGB matrix is followed by the sRGB transfer function and an RGB [0,1] clamp.
CIE L*a*b* L* = 100 c0, a* = 255 c1 - 128, b* = 255 c2 - 128. CIELAB is converted through D65 XYZ to sRGB and clamped. Neutral a* and b* are therefore near 0.502, not zero.
CIE L*c*h* L* = 100 c0, C* = 200 c1, h = 360 c2 - 180 degrees; a* = C* cos(h) and b* = C* sin(h). The Lab/XYZ/sRGB route then clamps RGB.
HSL c0, c1, and c2 are normalized hue, saturation, and lightness. The standard six-sector implementation reconstructs stored RGB values. Hue 1 wraps once to 0.
HSV c0, c1, and c2 are normalized hue, saturation, and value. A six-sector conversion reconstructs stored RGB values.
HSI c0, c1, and c2 are normalized hue, saturation, and intensity, where forward HSI intensity is (R+G+B)/3. The three 120-degree inverse sectors are clamped to [0,1].
YCbCr Y=c0, Cb=c1, Cr=c2, with neutral chroma at 0.5, by the exact BT.601 full-range coefficients: R=Y+1.402(Cr-0.5), B=Y+1.772(Cb-0.5), and G=(Y-0.299R-0.114B)/0.587, that is G=Y-0.344136(Cb-0.5)-0.714136(Cr-0.5). RGB is clamped.

For Linear Match, the first selected plane is reference r and a later plane is target x. Linear Match is the normalization stage's scaling match:

x' = a x + b, with a = MAD(r) / MAD(x) and b = median(r) - a median(x),

where the medians and median absolute deviations are measured over the positions at which both planes hold a sample inside the inclusive interval [1e-7, 0.875], so zeros and samples above seven eighths of full scale take no part. The slope a is always positive, so a plane that runs against the reference is scaled, never turned over. The match is applied to every sample of the plane, those outside the limits included.

Linear Match operates on scalar encoded values. It does not understand hue wrap, neutral chroma, filters, exposure, WCS, or astronomical color response.

Boundary and failure behavior

  • A missing first selector keeps OK disabled. If execution is invoked through another path, it reports The first channel component is required rather than starting the worker.
  • All selected sources must be either stills or sequences. A mixed selection raises All the selected images must be either sequences or images.
  • Stills, and the frames of sequences, must have the same width and height or the run fails with All the images must have the same size. Sequences need not have the same number of frames: the output has the first component's frame count, a frame missing from a shorter later component is a zero plane, and frames of a longer later component beyond the first's are not read.
  • There is no registration, resampling, WCS comparison, crop, or edge policy. Pixels are combined at identical array coordinates.
  • A Linear Match the engine cannot measure - a pair with no sample inside the limits - fails the run with the engine's reason; it does not leave a black component. Floating output is not clamped by the match.
  • CIE, HSI, and YCbCr reconstruction clamp RGB gamut. Direct RGB does not; HSL/HSV assume valid normalized components. An integer result is rounded to the nearest code of the result's representation in every mode.
  • A sequence output is written in the first component's container - SER, image list, AVI, MP4, or another video container (Matroska) - each frame converted for it as the sequence writer converts every frame: SER at 8 or 16 bits, AVI and video at 8 bits, a video at an even width and height. The sequence is published whole, once every frame is written, or not at all.
  • Cancellation stops the run, inside the current frame's work as well as between frames; an unfinished sequence leaves no file.

Parameter interactions and starting points

Combination Conservative starting point Too weak looks like Too strong looks like Adjustment order
Registered R/G/B + Linear Match off Use three equal-size calibrated linear masters from the same geometry Existing level/spread differences remain visible in statistics Not applicable; assignment itself has no amount Register/crop, normalize upstream if justified, assign R/G/B, compose, then color-calibrate.
Comparable R/G/B + Linear Match on Use broad, varying, unclipped content and the first selected channel as the intended reference Channel backgrounds/spreads remain unequal Clipped/out-of-range color or a black component Verify alignment and sample support, enable once, compose, then inspect the output.
Lab/LCh/XYZ component planes Use all three planes extracted with AfterNight's corresponding encoding; keep Linear Match off Missing/incorrect component produces implausible color or luminance Gamut clipping and extreme color from non-neutral or mismapped chroma Verify mode and plane order, confirm neutral encodings, compose, inspect gamut.
HSL/HSV/HSI/YCbCr component planes Use normalized maps from one compatible conversion and all three assignments Wrong value/lightness or neutral chroma leaves output dark or tinted Saturated sectors, hue discontinuity, or channel clipping Confirm hue/chroma normalization first, assign intensity/value/luma last, keep matching off.
Partial assignment Prefer all three; use omission only for a deliberate zero component in RGB Expected color is absent Non-RGB zero component has unintended semantic meaning Select the first component, fill all remaining components, then choose deliberate omissions.

These are source-derived starting points, not executed visual prescriptions.

Inputs, outputs, and metadata

  • The output is a new three-channel RGB view in the highest of the selected components' representations. Source geometry is unchanged; no alpha channel is produced.
  • Still image names are RGB, CIE XYZ, CIE L*a*b, CIE L*c*h, HSL, HSV, HSI, or YCbCr before the view factory makes the name unique. Sequence names retain the displayed Lab/LCh asterisks.
  • History records the selected mode's three source names, using - for an omitted source. It does not record Linear Match coefficients, accepted sample counts, sample type conversions, clipping counts, or alignment evidence.
  • The result's metadata is built from the assigned sources. Its exposure is the sum of the exposures they state, recorded once; assigning the same source repeatedly counts it repeatedly. The object, instrument, telescope, observer, filter, sensor temperature, gain, binning, and exposure start are kept when every assigned source states the same value and dropped otherwise.
  • The result keeps the header cards every assigned component states identically, but no exposure, processing-state or identity card of a component; a card the components state differently, or only some state, is dropped. It keeps the first component's plate solution with its world coordinate (WCS/SIP) cards, so the viewer, the astrometry window and a new plate solve find that solution on the composed image.
  • The inherited processing state is cleared. RGB is marked linear only when every valid selected input is explicitly declared linear; it is marked nonlinear if any input is declared nonlinear, otherwise it stays unknown. Every non-RGB composition is marked nonlinear because reconstruction uses encoded color-space behavior.
  • Linear Match preserves metadata/name state in its fitted outputs, and Channel Composition substitutes those outputs only in its local working list. Selected stills and decoded source frames are not swapped or written in place.
  • A sequence output is written as SEQ_SWAP<token> in the session's temporary directory, in the first component's container family and at its nominal frame rate (one frame per second when it states none), and opens beside the first component once every frame is written. Save/export any wanted result.

Performance

Direct RGB assignment is linear in pixel count and allocates a three-channel output plus any type-conversion or missing-plane buffers. Color-space modes add per-pixel conversion; CIE and HSI paths use powers/trigonometry and are more expensive than direct copies or simple matrix/sector conversions. Engine loops use oneTBB.

Linear Match adds full-plane scans, the robust statistics of each pair, and an output buffer per matched component. Sequences decode all input frames, compose one output frame at a time, and write a complete temporary sequence. Prototype the assignment on duplicated crops when checking semantics, but use the full registered geometry for the final composition.

Worked example

  • Evidence mode: Source-and-test-derived.
  • Input condition/provenance and settings: the behavior records (src/AfterNightTests/fixtures/common/expectations/behavior/) hold each space's composition of three planes, and CombinationsRecordTest reproduces them through the window; for CIE Lab, constant normalized a*=0.5, b*=0.5 planes beside a lightness gradient.
  • Expected checkpoint: reconstruction produces a valid three-channel RGB image; the neutral chroma planes map close to gray while lightness follows the input plane. CombinationsProcessCase.CompositionLinearMatchScalesEachComponentOntoTheFirst holds Linear Match.
  • Inspect at 100%/statistics/history: in an actual run, confirm equal geometry, three RGB channels, no unexpected gamut clipping, the intended state marker, and the three assignment names in history.
  • Limitations: the tests run the Channel Composition window over synthetic planes, not an approved astronomical set/sequence. They do not prove visual quality, alignment quality, FPS preservation, production timing, or peak memory.

Warnings and limitations

  • Channel Composition does not register or align channels. Equal dimensions do not prove equal sky coordinates.
  • The first component is mandatory. OK stays disabled for later-only assignments, and execution rejects a missing/unavailable first view before worker launch.
  • Linear Match operates on temporary fitted copies and leaves selected sources unchanged. It should still stay off for encoded hue/chroma planes.
  • Controls other than OK/Close remain enabled during a run, but the run uses the components, Color Space, and Linear Match captured when OK was pressed.
  • Missing components are literal zeros, not model-specific neutral values.
  • Non-RGB modes assume AfterNight's normalized encoding and sRGB-like D65 model; ICC profiles are not applied. CIE/YCbCr/HSI output can clip out-of-gamut RGB.
  • Active masks are ignored. There is no preview, coefficient report, histogram, clipping diagnostic, or automatic color calibration.
  • A sequence output takes the first component's container and frame count; an AVI or video container holds 8 bits, so a 16-bit composition written into one loses precision. Sequence sources need equal dimensions.
  • The result keeps only the header cards every component states identically and the first component's WCS cards; it does not check that the other components share the first one's geometry. The exposure is summed by assignment.

Troubleshooting

Symptom or exact error Verified cause/validation path Recovery Evidence source
OK is disabled The first selector is <--NO IMAGE-->, or its selected view closed/changed away from grayscale. Later-only selections do not enable execution. Open a monochrome view and select it in the first component. Process selector/update source.
A desired view is absent The view's current image is not grayscale. Extract the intended scalar component or open a monochrome master; do not select RGB directly. View-list filtering source.
All the images must have the same size Selected stills have different width/height. Linear Match does not waive the final composition check. Register/resample and crop all components to exactly matching geometry, then rerun from backups. Process geometry validation.
All the selected images must be either sequences or images At least one selected view is a sequence and another is a still. Use only stills or only compatible sequences. Worker compatibility source.
The output sequence is shorter than a component, or a channel is black at the end The output has the first component's frame count; a shorter later component gives zero planes for its missing frames. Put the sequence with the wanted frame count first and give every component the same frame range. ChannelCompositionProcess::executeChannelComposition frame loop.
A composed 16-bit sequence comes back at 8 bits The first component is an AVI or video sequence, whose container holds 8 bits. Use a SER or image-list sequence as the first component. SequenceWriter (controls/SequenceContainers.h).
Output component is black A component was omitted, so its plane is zero. Assign the intended plane. Dummy-plane source.
Linear Match fails the run A component and the reference share no sample inside [1e-7, 0.875]. Turn matching off or use a broad, varying comparable source/reference pair. measureLinearChannelMatch.
Lab/YCbCr output has a severe cast Missing/wrong component, or chroma was supplied with zero instead of its normalized neutral value near 0.5. Use all correctly ordered planes from the matching extraction/conversion path. Encoding and inverse-conversion source/tests.
Output stars/edges have colored offsets Inputs share dimensions but were not actually registered. Register every channel to one reference and use a common crop before composition. Exact-coordinate composition source.
Sequence Cancel leaves no output Cancel stops the run; an unfinished sequence leaves no file and nothing is opened. Run again when ready. SequenceWriter and the run's stop.

Use Image Registration before composition and Linear Match only when a deliberate scalar normalization is appropriate. Split CFA and Non-Interactive Processes explain ways to create scalar planes; verify their encoding before choosing a non-RGB mode.

After direct RGB composition, use Color Calibration, Photometric Color Calibration, or Spectrophotometric Color Calibration as appropriate. Use LRGB Combination when adding a separate luminance master to an existing RGB target, and the Narrowband Imaging workflow for palette choices and ordering.

References and provenance

  • AfterNight implementation and focused tests are authoritative for selector behavior, normalized encodings, fit boundaries, source non-mutation, metadata, sequence dispatch, and current failure paths.
  • International Color Consortium, How to interpret the sRGB color space, checked 2026-07-14. Used to contextualize the sRGB transfer, D65 white, and RGB/XYZ relationship implemented by AfterNight; the process does not perform ICC color management.
  • CIE, Colorimetry — Part 4: CIE 1976 L*a*b* Colour Space, checked 2026-07-14. Used for CIELAB/LCh terminology; AfterNight's storage normalization and conversion constants remain project implementation details.
  • Linear Match is the engine's normalization scaling match (Algorithms/Normalization/GlobalNormalization.h) inside the limits src/AfterNightProcesses/processes/core/LinearChannelMatch.h states.