github.com/pdfcpu/pdfcpu@v0.11.1/pkg/filter/paeth.go (about) 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 // The code to compute Paeth is borrowed from image/png in the stdlib because it is internal over there to the png reader. 6 // The PNG Paeth filter is documented here: www.w3.org/TR/PNG-Filters.html 7 8 package filter 9 10 // intSize is either 32 or 64. 11 // Disabled intSize 64 for govet. 12 const intSize = 32 //<< (^uint(0) >> 63) 13 14 func abs(x int) int { 15 // m := -1 if x < 0. m := 0 otherwise. 16 m := x >> (intSize - 1) 17 18 // In two's complement representation, the negative number 19 // of any number (except the smallest one) can be computed 20 // by flipping all the bits and add 1. This is faster than 21 // code with a branch. 22 // See Hacker's Delight, section 2-4. 23 return (x ^ m) - m 24 } 25 26 // paeth implements the Paeth filter function, as per the PNG specification. 27 func paeth(a, b, c uint8) uint8 { 28 // This is an optimized version of the sample code in the PNG spec. 29 // For example, the sample code starts with: 30 // p := int(a) + int(b) - int(c) 31 // pa := abs(p - int(a)) 32 // but the optimized form uses fewer arithmetic operations: 33 // pa := int(b) - int(c) 34 // pa = abs(pa) 35 pc := int(c) 36 pa := int(b) - pc 37 pb := int(a) - pc 38 pc = abs(pa + pb) 39 pa = abs(pa) 40 pb = abs(pb) 41 if pa <= pb && pa <= pc { 42 return a 43 } else if pb <= pc { 44 return b 45 } 46 return c 47 } 48 49 // filterPaeth applies the Paeth filter to the cdat slice. 50 // cdat is the current row's data, pdat is the previous row's data. 51 func filterPaeth(cdat, pdat []byte, bytesPerPixel int) { 52 var a, b, c, pa, pb, pc int 53 for i := 0; i < bytesPerPixel; i++ { 54 a, c = 0, 0 55 for j := i; j < len(cdat); j += bytesPerPixel { 56 b = int(pdat[j]) 57 pa = b - c 58 pb = a - c 59 pc = abs(pa + pb) 60 pa = abs(pa) 61 pb = abs(pb) 62 if pa <= pb && pa <= pc { 63 // No-op. 64 } else if pb <= pc { 65 a = b 66 } else { 67 a = c 68 } 69 a += int(cdat[j]) 70 a &= 0xff 71 cdat[j] = uint8(a) 72 c = b 73 } 74 } 75 }