Add proper predictor, switch between up/sub, fix up sub

This commit is contained in:
Jeroen Bobbeldijk
2017-09-17 11:15:42 +02:00
parent e9e71178d7
commit fa31007f97

View File

@@ -6,6 +6,7 @@ import (
"encoding/hex" "encoding/hex"
"compress/zlib" "compress/zlib"
"bytes" "bytes"
"log"
) )
func (context *SignContext) writeXref() error { func (context *SignContext) writeXref() error {
@@ -78,8 +79,8 @@ func (context *SignContext) writeXrefTable() error {
} }
func (context *SignContext) writeXrefStream() error { func (context *SignContext) writeXrefStream() error {
// @todo: DO NOT FORGET TO ADD SELF REFERENCE!!! // @todo: add self reference.
// @todo: fix format (columns) for stream // @todo: fix format (columns) for stream, first column is 1 (sub) or 2 (up)
buffer := bytes.NewBuffer(nil) buffer := bytes.NewBuffer(nil)
// Create the new catalog xref line. // Create the new catalog xref line.
@@ -118,11 +119,26 @@ func (context *SignContext) writeXrefStream() error {
return err return err
} }
streamBytes, err := EncodePNGUPBytes(5, buffer.Bytes()) predictor := context.PDFReader.Trailer().Key("DecodeParms").Key("Predictor").Int64()
if err != nil {
return err streamBytes := []byte{}
err := errors.New("")
// If original uses PNG Sub, use that.
if predictor == 11 {
streamBytes, err = EncodePNGSUBBytes(5, buffer.Bytes())
if err != nil {
return err
}
} else {
// Do PNG - Up by default.
streamBytes, err = EncodePNGUPBytes(5, buffer.Bytes())
if err != nil {
return err
}
} }
new_info := "Info " + strconv.FormatInt(int64(context.InfoData.ObjectId), 10) + " 0 R" new_info := "Info " + strconv.FormatInt(int64(context.InfoData.ObjectId), 10) + " 0 R"
new_root := "Root " + strconv.FormatInt(int64(context.CatalogData.ObjectId), 10) + " 0 R" new_root := "Root " + strconv.FormatInt(int64(context.CatalogData.ObjectId), 10) + " 0 R"
@@ -152,8 +168,7 @@ func (context *SignContext) writeXrefStream() error {
return nil return nil
} }
func EncodePNGUPBytes(columns int, data []byte) ([]byte, error) { func EncodePNGSUBBytes(columns int, data []byte) ([]byte, error) {
// @todo: this is PNG SUB, we need PNG UP.
rowCount := len(data) / columns rowCount := len(data) / columns
if len(data)%columns != 0 { if len(data)%columns != 0 {
return nil, errors.New("Invalid row/column length") return nil, errors.New("Invalid row/column length")
@@ -179,5 +194,45 @@ func EncodePNGUPBytes(columns int, data []byte) ([]byte, error) {
w.Write(data) w.Write(data)
w.Close() w.Close()
return b.Bytes(), nil
}
func EncodePNGUPBytes(columns int, data []byte) ([]byte, error) {
rowCount := len(data) / columns
if len(data)%columns != 0 {
return nil, errors.New("Invalid row/column length")
}
prevRowData := make([]byte, columns)
// Initially all previous data is zero.
for i := 0; i < columns; i++ {
prevRowData[i] = 0
}
buffer := bytes.NewBuffer(nil)
tmpRowData := make([]byte, columns)
for i := 0; i < rowCount; i++ {
rowData := data[columns*i : columns*(i+1)]
tmpRowData[0] = rowData[0]
for j := 1; j < columns; j++ {
tmpRowData[j] = byte(int(rowData[j]-prevRowData[j]) % 256)
}
// Save the previous row for prediction.
prevRowData = tmpRowData
buffer.WriteByte(1)
buffer.Write(tmpRowData)
}
data = buffer.Bytes()
var b bytes.Buffer
w := zlib.NewWriter(&b)
w.Write(data)
w.Close()
return b.Bytes(), nil return b.Bytes(), nil
} }