...

Source file src/pkg/image/png/paeth.go

     1	// Copyright 2012 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package png
     6	
     7	// intSize is either 32 or 64.
     8	const intSize = 32 << (^uint(0) >> 63)
     9	
    10	func abs(x int) int {
    11		// m := -1 if x < 0. m := 0 otherwise.
    12		m := x >> (intSize - 1)
    13	
    14		// In two's complement representation, the negative number
    15		// of any number (except the smallest one) can be computed
    16		// by flipping all the bits and add 1. This is faster than
    17		// code with a branch.
    18		// See Hacker's Delight, section 2-4.
    19		return (x ^ m) - m
    20	}
    21	
    22	// paeth implements the Paeth filter function, as per the PNG specification.
    23	func paeth(a, b, c uint8) uint8 {
    24		// This is an optimized version of the sample code in the PNG spec.
    25		// For example, the sample code starts with:
    26		//	p := int(a) + int(b) - int(c)
    27		//	pa := abs(p - int(a))
    28		// but the optimized form uses fewer arithmetic operations:
    29		//	pa := int(b) - int(c)
    30		//	pa = abs(pa)
    31		pc := int(c)
    32		pa := int(b) - pc
    33		pb := int(a) - pc
    34		pc = abs(pa + pb)
    35		pa = abs(pa)
    36		pb = abs(pb)
    37		if pa <= pb && pa <= pc {
    38			return a
    39		} else if pb <= pc {
    40			return b
    41		}
    42		return c
    43	}
    44	
    45	// filterPaeth applies the Paeth filter to the cdat slice.
    46	// cdat is the current row's data, pdat is the previous row's data.
    47	func filterPaeth(cdat, pdat []byte, bytesPerPixel int) {
    48		var a, b, c, pa, pb, pc int
    49		for i := 0; i < bytesPerPixel; i++ {
    50			a, c = 0, 0
    51			for j := i; j < len(cdat); j += bytesPerPixel {
    52				b = int(pdat[j])
    53				pa = b - c
    54				pb = a - c
    55				pc = abs(pa + pb)
    56				pa = abs(pa)
    57				pb = abs(pb)
    58				if pa <= pb && pa <= pc {
    59					// No-op.
    60				} else if pb <= pc {
    61					a = b
    62				} else {
    63					a = c
    64				}
    65				a += int(cdat[j])
    66				a &= 0xff
    67				cdat[j] = uint8(a)
    68				c = b
    69			}
    70		}
    71	}
    72	

View as plain text