The Average filter predicts each byte from the average of its left and above neighbors. Today you reverse it, combining both directions and pinning the integer-floor rule that makes it exact.
Reconstruct a scanline filtered with type 3 (Average) from its left and above neighbors.
Average (filter type 3) predicts a byte from the mean of its left and above neighbors and stores the difference. Reconstruction adds that predicted mean back: recon[x] = raw[x] + floor((left + above) / 2). The one detail that must be exact is the floor: the sum of the two neighbors is divided by two and truncated toward zero before adding, with no rounding. With left 8 and above 4 the mean is 6, so a stored 10 reconstructs to 16.
As always, missing neighbors are 0 - the left neighbor is 0 for the first pixel of a row, the above neighbor is 0 for the first row - and the final addition wraps modulo 256. Average is the first filter to mix both directions, so it needs the reconstructed left neighbor and the finished row above at once. It is also a stepping stone to Paeth, which uses the same two neighbors plus a third and a smarter rule. Pin the floor and the zero-neighbor cases here and Paeth is a short hop.
// recon[x] = raw[x] + floor((left + above) / 2)// left = recon[x-bpp] or 0 if x < bpp// above = prevRow[x] or 0 on the first row// the average uses the FLOOR of the integer sum (no rounding).func unAverage(raw, above []byte, bpp int) []byte { }