internal/png/stdlibwriter.go
func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
	// We try all five filter types, and pick the one that minimizes the sum of absolute differences.
	// This is the same heuristic that libpng uses, although the filters are attempted in order of
	// estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than
	// in their enumeration order (ftNone, ftSub, ftUp, ftAverage, ftPaeth).
	cdat0 := cr[0][1:]
	cdat1 := cr[1][1:]
	cdat2 := cr[2][1:]
	cdat3 := cr[3][1:]
	cdat4 := cr[4][1:]
	pdat := pr[1:]
	n := len(cdat0)

	// The up filter.
	sum := 0
	for i := 0; i < n; i++ {
		cdat2[i] = cdat0[i] - pdat[i]
		sum += abs8(cdat2[i])
	}
	best := sum
	filter := ftUp

	// The Paeth filter.
	sum = 0
	for i := 0; i < bpp; i++ {
		cdat4[i] = cdat0[i] - pdat[i]
		sum += abs8(cdat4[i])
	}
	for i := bpp; i < n; i++ {
		cdat4[i] = cdat0[i] - paeth(cdat0[i-bpp], pdat[i], pdat[i-bpp])
		sum += abs8(cdat4[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftPaeth
	}

	// The none filter.
	sum = 0
	for i := 0; i < n; i++ {
		sum += abs8(cdat0[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftNone
	}

	// The sub filter.
	sum = 0
	for i := 0; i < bpp; i++ {
		cdat1[i] = cdat0[i]
		sum += abs8(cdat1[i])
	}
	for i := bpp; i < n; i++ {
		cdat1[i] = cdat0[i] - cdat0[i-bpp]
		sum += abs8(cdat1[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftSub
	}

	// The average filter.
	sum = 0
	for i := 0; i < bpp; i++ {
		cdat3[i] = cdat0[i] - pdat[i]/2
		sum += abs8(cdat3[i])
	}
	for i := bpp; i < n; i++ {
		cdat3[i] = cdat0[i] - uint8((int(cdat0[i-bpp])+int(pdat[i]))/2)
		sum += abs8(cdat3[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftAverage
	}

	return filter
}
func filter(cr *[nFilter][]byte, pr []byte, bpp int) int {
	// We try all five filter types, and pick the one that minimizes the sum of absolute differences.
	// This is the same heuristic that libpng uses, although the filters are attempted in order of
	// estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than
	// in their enumeration order (ftNone, ftSub, ftUp, ftAverage, ftPaeth).
	cdat0 := cr[0][1:]
	cdat1 := cr[1][1:]
	cdat2 := cr[2][1:]
	cdat3 := cr[3][1:]
	cdat4 := cr[4][1:]
	pdat := pr[1:]
	n := len(cdat0)

	// The up filter.
	sum := 0
	for i := 0; i < n; i++ {
		cdat2[i] = cdat0[i] - pdat[i]
		sum += abs8(cdat2[i])
	}
	best := sum
	filter := ftUp

	// The Paeth filter.
	sum = 0
	for i := 0; i < bpp; i++ {
		cdat4[i] = cdat0[i] - pdat[i]
		sum += abs8(cdat4[i])
	}
	for i := bpp; i < n; i++ {
		cdat4[i] = cdat0[i] - paeth(cdat0[i-bpp], pdat[i], pdat[i-bpp])
		sum += abs8(cdat4[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftPaeth
	}

	// The none filter.
	sum = 0
	for i := 0; i < n; i++ {
		sum += abs8(cdat0[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftNone
	}

	// The sub filter.
	sum = 0
	for i := 0; i < bpp; i++ {
		cdat1[i] = cdat0[i]
		sum += abs8(cdat1[i])
	}
	for i := bpp; i < n; i++ {
		cdat1[i] = cdat0[i] - cdat0[i-bpp]
		sum += abs8(cdat1[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftSub
	}

	// The average filter.
	sum = 0
	for i := 0; i < bpp; i++ {
		cdat3[i] = cdat0[i] - pdat[i]/2
		sum += abs8(cdat3[i])
	}
	for i := bpp; i < n; i++ {
		cdat3[i] = cdat0[i] - uint8((int(cdat0[i-bpp])+int(pdat[i]))/2)
		sum += abs8(cdat3[i])
		if sum >= best {
			break
		}
	}
	if sum < best {
		best = sum
		filter = ftAverage
	}

	return filter
}
func filter ( cr * [ nFilter ] [ ] byte , pr [ ] byte , bpp int ) int { // We try all five filter types, and pick the one that minimizes the sum of absolute differences. // This is the same heuristic that libpng uses, although the filters are attempted in order of // estimated most likely to be minimal (ftUp, ftPaeth, ftNone, ftSub, ftAverage), rather than // in their enumeration order (ftNone, ftSub, ftUp, ftAverage, ftPaeth). cdat0 := cr [ 0 ] [ 1 : ] cdat1 := cr [ 1 ] [ 1 : ] cdat2 := cr [ 2 ] [ 1 : ] cdat3 := cr [ 3 ] [ 1 : ] cdat4 := cr [ 4 ] [ 1 : ] pdat := pr [ 1 : ] n := len ( cdat0 ) // The up filter. sum := 0 for i := 0 ; i < n ; i ++ { cdat2 [ i ] = cdat0 [ i ] - pdat [ i ] sum += abs8 ( cdat2 [ i ] ) } best := sum filter := ftUp // The Paeth filter. sum = 0 for i := 0 ; i < bpp ; i ++ { cdat4 [ i ] = cdat0 [ i ] - pdat [ i ] sum += abs8 ( cdat4 [ i ] ) } for i := bpp ; i < n ; i ++ { cdat4 [ i ] = cdat0 [ i ] - paeth ( cdat0 [ i - bpp ] , pdat [ i ] , pdat [ i - bpp ] ) sum += abs8 ( cdat4 [ i ] ) if sum >= best { break } } if sum < best { best = sum filter = ftPaeth } // The none filter. sum = 0 for i := 0 ; i < n ; i ++ { sum += abs8 ( cdat0 [ i ] ) if sum >= best { break } } if sum < best { best = sum filter = ftNone } // The sub filter. sum = 0 for i := 0 ; i < bpp ; i ++ { cdat1 [ i ] = cdat0 [ i ] sum += abs8 ( cdat1 [ i ] ) } for i := bpp ; i < n ; i ++ { cdat1 [ i ] = cdat0 [ i ] - cdat0 [ i - bpp ] sum += abs8 ( cdat1 [ i ] ) if sum >= best { break } } if sum < best { best = sum filter = ftSub } // The average filter. sum = 0 for i := 0 ; i < bpp ; i ++ { cdat3 [ i ] = cdat0 [ i ] - pdat [ i ] / 2 sum += abs8 ( cdat3 [ i ] ) } for i := bpp ; i < n ; i ++ { cdat3 [ i ] = cdat0 [ i ] - uint8 ( ( int ( cdat0 [ i - bpp ] ) + int ( pdat [ i ] ) ) / 2 ) sum += abs8 ( cdat3 [ i ] ) if sum >= best { break } } if sum < best { best = sum filter = ftAverage } return filter }
// Chooses the filter to use for encoding the current row, and applies it.
// The return value is the index of the filter and also of the row in cr that has had it applied.
Chooses the filter to use for encoding the current row and applies it . The return value is the index of the filter and also of the row in cr that has had it applied .