Finding the seam between two screenshots
Stitching a scroll capture is a search problem, and the thing being searched for is the amount the page moved between one screenshot and the next. Nobody scrolls by a fixed distance, so that number is different for every pair and cannot be assumed. It has to be measured, and the measurement has to be cheap enough to run on the phone the screenshots came from.
The first step is to throw away almost everything. Each screenshot is squeezed horizontally to thirty-two brightness samples per row, so a picture that is millions of pixels becomes a few tens of thousands of numbers, one thin strip per row of the original. Two rows of a page that look the same have similar strips, and two rows that differ have different ones, which is the only property the search needs. The squeeze is done by the browser image scaler rather than by picking every nth column, because sampling columns would step straight over a one pixel line and call two different rows identical.
Then every possible overlap is scored. For each candidate, a fixed sixty-four rows spread across the overlapping band are compared and the average difference is taken, so a candidate costs the same whether it claims twenty rows in common or two thousand. That fixed cost is what makes it affordable to try every offset instead of a sample of them, and trying every offset turns out to be necessary: a signature misaligned by two rows scores like unrelated content, not like a near miss, so there is no gradient to follow and nothing for a coarse pass to interpolate. The cheapest handful of candidates are then rescored against three times as many rows, which is what separates a real match from sixty-four rows that agreed by luck.
The failure this design is most careful about is the confident wrong answer. A blank margin, an empty chat background or a run of white paper matches itself perfectly at every offset, so a matcher that only minimises difference will report a large overlap wherever the page is empty and silently delete the height in between. So a winning band is also asked whether its own rows differ from each other. A band with no vertical texture is not evidence, whatever it scores, and a pair that produces one is joined end to end and reported as unmatched rather than guessed at.
The other thing that misleads a stitcher is the phone itself. The clock, the battery, the app toolbar and the tab bar do not scroll, so they are printed identically on every screenshot in the set, and those identical rows are exactly what a naive matcher reads as a perfect alignment. They are found first, by taking the number of leading rows that are unchanged across every consecutive pair and keeping the smallest, because that is the only part all of the screenshots agree on. One pair sharing more means the page repeated something there, not that the bar is taller. The result is capped at a quarter of the height, since two barely scrolled screenshots are identical over most of their area and without a ceiling the detector would conclude that almost everything is a status bar and merge the capture down to nothing.
What comes out is a plan rather than a picture: a list of which rows of which screenshot land where. Painting it runs into a limit most people never meet, which is that a browser will not give you a canvas of unlimited size, and Safari in particular hands back a canvas of the size you asked for and then quietly draws nothing into it. So the limit is measured instead of looked up, by writing a pixel into the far corner and reading it back, and a capture too tall for this device is scaled to fit with the amount stated. The PDF is built a page at a time from the same plan, never allocating the full height at once, which is why it keeps every pixel of a capture the single image path has to shrink.