2016-07-09 14:09:27 +00:00
|
|
|
/*
|
|
|
|
* This file is subject to the terms and conditions defined in
|
2016-07-29 17:23:39 +00:00
|
|
|
* file 'LICENSE.md', which is part of this source code package.
|
2016-07-09 14:09:27 +00:00
|
|
|
*/
|
|
|
|
|
2016-09-08 17:53:45 +00:00
|
|
|
package core
|
2016-07-09 14:09:27 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2016-07-17 19:59:17 +00:00
|
|
|
|
|
|
|
"github.com/unidoc/unidoc/common"
|
2016-07-09 14:09:27 +00:00
|
|
|
)
|
|
|
|
|
2017-08-02 18:01:31 +00:00
|
|
|
// NewEncoderFromStream creates a StreamEncoder based on the stream's dictionary.
|
2017-02-13 15:30:36 +00:00
|
|
|
func NewEncoderFromStream(streamObj *PdfObjectStream) (StreamEncoder, error) {
|
2017-08-04 17:47:55 +10:00
|
|
|
filterObj := TraceToDirectObject(streamObj.PdfObjectDictionary.Get("Filter"))
|
2017-07-08 21:04:13 +00:00
|
|
|
if filterObj == nil {
|
2017-02-12 21:37:07 +00:00
|
|
|
// No filter, return raw data back.
|
2017-02-13 15:30:36 +00:00
|
|
|
return NewRawEncoder(), nil
|
2017-02-12 21:37:07 +00:00
|
|
|
}
|
|
|
|
|
2017-05-10 10:21:46 +00:00
|
|
|
if _, isNull := filterObj.(*PdfObjectNull); isNull {
|
|
|
|
// Filter is null -> raw data.
|
|
|
|
return NewRawEncoder(), nil
|
|
|
|
}
|
|
|
|
|
2017-02-12 21:37:07 +00:00
|
|
|
// The filter should be a name or an array with a list of filter names.
|
|
|
|
method, ok := filterObj.(*PdfObjectName)
|
|
|
|
if !ok {
|
|
|
|
array, ok := filterObj.(*PdfObjectArray)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Filter not a Name or Array object")
|
|
|
|
}
|
2017-02-13 20:35:42 +00:00
|
|
|
if len(*array) == 0 {
|
|
|
|
// Empty array -> indicates raw filter (no filter).
|
|
|
|
return NewRawEncoder(), nil
|
|
|
|
}
|
|
|
|
|
2017-02-12 21:37:07 +00:00
|
|
|
if len(*array) != 1 {
|
2017-02-13 20:35:42 +00:00
|
|
|
menc, err := newMultiEncoderFromStream(streamObj)
|
2017-02-22 21:10:57 +00:00
|
|
|
if err != nil {
|
|
|
|
common.Log.Error("Failed creating multi encoder: %v", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2017-02-28 12:16:46 +00:00
|
|
|
common.Log.Trace("Multi enc: %s\n", menc)
|
2017-02-22 21:10:57 +00:00
|
|
|
return menc, nil
|
2017-02-12 21:37:07 +00:00
|
|
|
}
|
2017-02-13 20:35:42 +00:00
|
|
|
|
|
|
|
// Single element.
|
2017-02-12 21:37:07 +00:00
|
|
|
filterObj = (*array)[0]
|
|
|
|
method, ok = filterObj.(*PdfObjectName)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Filter array member not a Name object")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-13 20:35:42 +00:00
|
|
|
if *method == StreamEncodingFilterNameFlate {
|
|
|
|
return newFlateEncoderFromStream(streamObj, nil)
|
|
|
|
} else if *method == StreamEncodingFilterNameLZW {
|
|
|
|
return newLZWEncoderFromStream(streamObj, nil)
|
2017-02-24 17:38:41 +00:00
|
|
|
} else if *method == StreamEncodingFilterNameDCT {
|
2017-03-05 22:41:38 +00:00
|
|
|
return newDCTEncoderFromStream(streamObj, nil)
|
2017-08-04 17:47:55 +10:00
|
|
|
} else if *method == StreamEncodingFilterNameRunLength {
|
|
|
|
return newRunLengthEncoderFromStream(streamObj, nil)
|
2017-02-24 17:38:41 +00:00
|
|
|
} else if *method == StreamEncodingFilterNameASCIIHex {
|
|
|
|
return NewASCIIHexEncoder(), nil
|
2017-02-23 15:25:23 +00:00
|
|
|
} else if *method == StreamEncodingFilterNameASCII85 {
|
|
|
|
return NewASCII85Encoder(), nil
|
2017-08-07 13:34:19 +10:00
|
|
|
} else if *method == StreamEncodingFilterNameCCITTFax {
|
|
|
|
return NewCCITTFaxEncoder(), nil
|
|
|
|
} else if *method == StreamEncodingFilterNameJBIG2 {
|
|
|
|
return NewJBIG2Encoder(), nil
|
|
|
|
} else if *method == StreamEncodingFilterNameJPX {
|
|
|
|
return NewJPXEncoder(), nil
|
2017-02-23 15:25:23 +00:00
|
|
|
} else {
|
|
|
|
common.Log.Debug("ERROR: Unsupported encoding method!")
|
|
|
|
return nil, fmt.Errorf("Unsupported encoding method (%s)", *method)
|
2016-07-09 14:09:27 +00:00
|
|
|
}
|
|
|
|
}
|
2017-02-13 15:30:36 +00:00
|
|
|
|
2017-08-02 18:01:31 +00:00
|
|
|
// DecodeStream decodes the stream data and returns the decoded data.
|
|
|
|
// An error is returned upon failure.
|
2017-02-13 15:30:36 +00:00
|
|
|
func DecodeStream(streamObj *PdfObjectStream) ([]byte, error) {
|
2017-02-28 12:16:46 +00:00
|
|
|
common.Log.Trace("Decode stream")
|
2017-02-13 15:30:36 +00:00
|
|
|
|
|
|
|
encoder, err := NewEncoderFromStream(streamObj)
|
|
|
|
if err != nil {
|
|
|
|
common.Log.Debug("Stream decoding failed: %v", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-07-08 21:04:13 +00:00
|
|
|
common.Log.Trace("Encoder: %#v\n", encoder)
|
2017-02-13 15:30:36 +00:00
|
|
|
|
|
|
|
decoded, err := encoder.DecodeStream(streamObj)
|
|
|
|
if err != nil {
|
|
|
|
common.Log.Debug("Stream decoding failed: %v", err)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return decoded, nil
|
|
|
|
}
|
2017-02-24 17:38:41 +00:00
|
|
|
|
2017-08-02 18:01:31 +00:00
|
|
|
// EncodeStream encodes the stream data using the encoded specified by the stream's dictionary.
|
2017-02-24 17:38:41 +00:00
|
|
|
func EncodeStream(streamObj *PdfObjectStream) error {
|
2017-02-28 12:16:46 +00:00
|
|
|
common.Log.Trace("Encode stream")
|
2017-02-24 17:38:41 +00:00
|
|
|
|
|
|
|
encoder, err := NewEncoderFromStream(streamObj)
|
|
|
|
if err != nil {
|
|
|
|
common.Log.Debug("Stream decoding failed: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if lzwenc, is := encoder.(*LZWEncoder); is {
|
|
|
|
// If LZW:
|
|
|
|
// Make sure to use EarlyChange 0.. We do not have write support for 1 yet.
|
|
|
|
lzwenc.EarlyChange = 0
|
2017-07-08 21:04:13 +00:00
|
|
|
streamObj.PdfObjectDictionary.Set("EarlyChange", MakeInteger(0))
|
2017-02-24 17:38:41 +00:00
|
|
|
}
|
|
|
|
|
2017-02-28 12:16:46 +00:00
|
|
|
common.Log.Trace("Encoder: %+v\n", encoder)
|
2017-02-24 17:38:41 +00:00
|
|
|
encoded, err := encoder.EncodeBytes(streamObj.Stream)
|
|
|
|
if err != nil {
|
|
|
|
common.Log.Debug("Stream encoding failed: %v", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
streamObj.Stream = encoded
|
|
|
|
|
|
|
|
// Update length
|
2017-07-08 21:04:13 +00:00
|
|
|
streamObj.PdfObjectDictionary.Set("Length", MakeInteger(int64(len(encoded))))
|
2017-02-24 17:38:41 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|