github.com/pdfcpu/pdfcpu@v0.11.1/pkg/filter/filter.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 contains PDF filter implementations.
    18  package filter
    19  
    20  import (
    21  	"bytes"
    22  	"io"
    23  
    24  	"github.com/pdfcpu/pdfcpu/pkg/log"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  // PDF defines the following filters. See also 7.4 in the PDF spec.
    29  const (
    30  	ASCII85   = "ASCII85Decode"
    31  	ASCIIHex  = "ASCIIHexDecode"
    32  	RunLength = "RunLengthDecode"
    33  	LZW       = "LZWDecode"
    34  	Flate     = "FlateDecode"
    35  	CCITTFax  = "CCITTFaxDecode"
    36  	JBIG2     = "JBIG2Decode"
    37  	DCT       = "DCTDecode"
    38  	JPX       = "JPXDecode"
    39  )
    40  
    41  // ErrUnsupportedFilter signals unsupported filter encountered.
    42  var ErrUnsupportedFilter = errors.New("pdfcpu: filter not supported")
    43  
    44  // Filter defines an interface for encoding/decoding PDF object streams.
    45  type Filter interface {
    46  	Encode(r io.Reader) (io.Reader, error)
    47  	Decode(r io.Reader) (io.Reader, error)
    48  	// DecodeLength will decode at least maxLen bytes. For filters where decoding
    49  	// parts doesn't make sense (e.g. DCT), the whole stream is decoded.
    50  	// If maxLen < 0 is passed, the whole stream is decoded.
    51  	DecodeLength(r io.Reader, maxLen int64) (io.Reader, error)
    52  }
    53  
    54  // NewFilter returns a filter for given filterName and an optional parameter dictionary.
    55  func NewFilter(filterName string, parms map[string]int) (filter Filter, err error) {
    56  	switch filterName {
    57  
    58  	case ASCII85:
    59  		filter = ascii85Decode{baseFilter{}}
    60  
    61  	case ASCIIHex:
    62  		filter = asciiHexDecode{baseFilter{}}
    63  
    64  	case RunLength:
    65  		filter = runLengthDecode{baseFilter{parms}}
    66  
    67  	case LZW:
    68  		filter = lzwDecode{baseFilter{parms}}
    69  
    70  	case Flate:
    71  		filter = flate{baseFilter{parms}}
    72  
    73  	case CCITTFax:
    74  		filter = ccittDecode{baseFilter{parms}}
    75  
    76  	case DCT:
    77  		filter = dctDecode{baseFilter{parms}}
    78  
    79  	case JBIG2:
    80  		// Unsupported
    81  		fallthrough
    82  
    83  	case JPX:
    84  		// Unsupported
    85  		if log.InfoEnabled() {
    86  			log.Info.Printf("Filter not supported: <%s>", filterName)
    87  		}
    88  		err = ErrUnsupportedFilter
    89  
    90  	default:
    91  		err = errors.Errorf("Invalid filter: <%s>", filterName)
    92  	}
    93  
    94  	return filter, err
    95  }
    96  
    97  // List return the list of all supported PDF filters.
    98  func List() []string {
    99  	// Exclude CCITTFax, DCT, JBIG2 & JPX since they only makes sense in the context of image processing.
   100  	return []string{ASCII85, ASCIIHex, RunLength, LZW, Flate}
   101  }
   102  
   103  type baseFilter struct {
   104  	parms map[string]int
   105  }
   106  
   107  func SupportsDecodeParms(f string) bool {
   108  	return f == CCITTFax || f == LZW || f == Flate
   109  }
   110  
   111  func getReaderBytes(r io.Reader) ([]byte, error) {
   112  	var bb []byte
   113  	if buf, ok := r.(*bytes.Buffer); ok {
   114  		bb = buf.Bytes()
   115  	} else {
   116  		var buf bytes.Buffer
   117  		if _, err := io.Copy(&buf, r); err != nil {
   118  			return nil, err
   119  		}
   120  
   121  		bb = buf.Bytes()
   122  	}
   123  
   124  	return bb, nil
   125  }