mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-25 18:47:42 -06:00
A raw whose white balance is only in the vendor's multipliers (CR2, NEF, ARW...) has no AsShotNeutral of its own. Loading a frame dropped the multipliers and stitch copied the first frame's colour tags, so a panorama of frames that reach the stitcher without a neutral wrote a DNG with neither AsShotNeutral nor AsShotWhiteXY, and a viewer had no white to start from (a strong colour cast until White Balance > Auto). Frames now carry the multipliers (Frame::wb_multipliers, filled from the decoded raw; load_frame_with is split so a decoded raw can be tested without a file). stitch takes the median R/G and B/G of the multipliers of the frames that are in the panorama (the mean of the middle two for an even count; frames without multipliers, or with non-finite or non-positive ones, do not vote) and sets the result's AsShotNeutral to their reciprocal, green = 1. The source's AsShotWhiteXY is dropped with it: a reader takes it before the neutral and the DNG spec makes the two exclusive. With no multipliers anywhere (DNG sources) the first frame's tags are kept, as before. In the app and the CLI a raw without colour matrices already gets a neutral from starting_colour_tags (#965). For frames balanced alike the new neutral renders the same (checked in the engine crate); it differs when the camera balanced the frames differently: the panorama follows the median instead of the first frame. Tests: the frame carries the multipliers; the consensus for odd and even counts, with missing and unusable values; stitching raw-style frames gives the median AsShotNeutral, ignores frames outside the panorama and leaves the colour as it was without multipliers; the written DNG, read back with the raw reader, has the reciprocal AsShotNeutral and the white balance the source's multipliers give.