github.com/pdfcpu/pdfcpu@v0.11.1/pkg/filter/runLengthDecode.go (about) 1 /* 2 Copyright 2018 The pdfcpu Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package filter 18 19 import ( 20 "bytes" 21 "io" 22 ) 23 24 type runLengthDecode struct { 25 baseFilter 26 } 27 28 func (f runLengthDecode) decode(w io.ByteWriter, src []byte, maxLen int64) { 29 var written int64 30 31 for i := 0; i < len(src); { 32 b := src[i] 33 if b == 0x80 { 34 // eod 35 break 36 } 37 i++ 38 if b < 0x80 { 39 c := int(b) + 1 40 for j := 0; j < c; j++ { 41 if maxLen >= 0 && maxLen == written { 42 break 43 } 44 45 w.WriteByte(src[i]) 46 written++ 47 i++ 48 } 49 continue 50 } 51 c := 257 - int(b) 52 for j := 0; j < c; j++ { 53 if maxLen >= 0 && maxLen == written { 54 break 55 } 56 57 w.WriteByte(src[i]) 58 written++ 59 } 60 i++ 61 } 62 } 63 64 func (f runLengthDecode) encode(w io.ByteWriter, src []byte) { 65 66 const maxLen = 0x80 67 const eod = 0x80 68 69 i := 0 70 b := src[i] 71 start := i 72 73 for { 74 75 // Detect constant run eg. 0x1414141414141414 76 for i < len(src) && src[i] == b && (i-start < maxLen) { 77 i++ 78 } 79 c := i - start 80 if c > 1 { 81 // Write constant run with length=c 82 w.WriteByte(byte(257 - c)) 83 w.WriteByte(b) 84 if i == len(src) { 85 w.WriteByte(eod) 86 return 87 } 88 b = src[i] 89 start = i 90 continue 91 } 92 93 // Detect variable run eg. 0x20FFD023335BCC12 94 for i < len(src) && src[i] != b && (i-start < maxLen) { 95 b = src[i] 96 i++ 97 } 98 if i == len(src) || i-start == maxLen { 99 c = i - start 100 w.WriteByte(byte(c - 1)) 101 for j := 0; j < c; j++ { 102 w.WriteByte(src[start+j]) 103 } 104 if i == len(src) { 105 w.WriteByte(eod) 106 return 107 } 108 } else { 109 c = i - 1 - start 110 // Write variable run with length=c 111 w.WriteByte(byte(c - 1)) 112 for j := 0; j < c; j++ { 113 w.WriteByte(src[start+j]) 114 } 115 i-- 116 } 117 b = src[i] 118 start = i 119 } 120 121 } 122 123 // Encode implements encoding for a RunLengthDecode filter. 124 func (f runLengthDecode) Encode(r io.Reader) (io.Reader, error) { 125 126 b1, err := getReaderBytes(r) 127 if err != nil { 128 return nil, err 129 } 130 131 var b2 bytes.Buffer 132 f.encode(&b2, b1) 133 134 return &b2, nil 135 } 136 137 // Decode implements decoding for an RunLengthDecode filter. 138 func (f runLengthDecode) Decode(r io.Reader) (io.Reader, error) { 139 return f.DecodeLength(r, -1) 140 } 141 142 func (f runLengthDecode) DecodeLength(r io.Reader, maxLen int64) (io.Reader, error) { 143 144 b1, err := getReaderBytes(r) 145 if err != nil { 146 return nil, err 147 } 148 149 var b2 bytes.Buffer 150 f.decode(&b2, b1, maxLen) 151 152 return &b2, nil 153 }