From b39c7065e8bcace065f6135b1e314fa6d628471f Mon Sep 17 00:00:00 2001 From: Gunnsteinn Hall Date: Wed, 3 Oct 2018 14:56:03 +0000 Subject: [PATCH] Fix for outputing Function type 0 (colorspace) --- pdf/model/colorspace_test.go | 130 ++++++++++++++++++++++++++++ pdf/model/functions.go | 9 +- pdf/model/reader.go | 2 +- pdf/model/testdata/cs_functype0.bin | 1 + pdf/model/testdata/iccstream.bin | Bin 0 -> 3144 bytes 5 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 pdf/model/testdata/cs_functype0.bin create mode 100644 pdf/model/testdata/iccstream.bin diff --git a/pdf/model/colorspace_test.go b/pdf/model/colorspace_test.go index b68f2f9d..823bd48a 100644 --- a/pdf/model/colorspace_test.go +++ b/pdf/model/colorspace_test.go @@ -6,8 +6,13 @@ package model import ( + "bytes" "fmt" + "io/ioutil" "testing" + + "github.com/unidoc/unidoc/pdf/core" + "github.com/unidoc/unidoc/pdf/internal/testutils" ) func TestSeparationCS1(t *testing.T) { @@ -44,3 +49,128 @@ func TestDeviceNCS1(t *testing.T) { //t.Errorf("Test not implemented yet") } + +// Bug with outputing Separation colorspaces using a Function0 function. +func TestColorspaceLoading(t *testing.T) { + rawpdf := []byte(` +10 0 obj +<< + /ColorSpace << + /R99 99 0 R + /R86 86 0 R + /R88 88 0 R + >> +>> +endobj +99 0 obj +[/Separation /All 86 0 R 87 0 R] +endobj +86 0 obj +[/ICCBased 85 0 R] +endobj +88 0 obj +[/Separation /Black 86 0 R 87 0 R] +endobj +85 0 obj +<< + /N 3 + /Alternate /DeviceRGB + /Length 3144 +>> +stream +!!STREAMDATA2!! +endstream endobj +87 0 obj +<< + /Size [255] + /BitsPerSample 8 + /Domain [0 1] + /Length 765 + /Encode [0 254] + /Decode [0 1 0 1 0 1] + /Range [0 1 0 1 0 1] + /FunctionType 0 +>> +stream +!!STREAMDATA1!! +endstream endobj +`) + functype0, err := ioutil.ReadFile(`testdata/cs_functype0.bin`) + if err != nil { + t.Fatalf("Error: %v", err) + } + + iccdata, err := ioutil.ReadFile(`testdata/iccstream.bin`) + if err != nil { + t.Fatalf("Error: %v", err) + } + + rawpdf = bytes.Replace(rawpdf, []byte("!!STREAMDATA1!!"), functype0, 1) + rawpdf = bytes.Replace(rawpdf, []byte("!!STREAMDATA2!!"), iccdata, 1) + //fmt.Printf("%s\n", rawpdf) + + objMap, err := testutils.ParseIndirectObjects(string(rawpdf)) + if err != nil { + t.Fatalf("Error: %v", err) + } + if len(objMap) != 6 { + t.Fatalf("len(objMap) != 6 (%d)", len(objMap)) + } + + resourceDict, ok := core.GetDict(objMap[10]) + if !ok { + t.Fatalf("Resource object missing dictionary") + } + + resources, err := NewPdfPageResourcesFromDict(resourceDict) + if err != nil { + t.Fatalf("Error loading resources: %v", err) + } + + fmt.Printf("Out\n") + fmt.Printf("%s\n", resources.ToPdfObject()) + outDict, ok := core.GetDict(resources.ToPdfObject()) + if !ok { + t.Fatalf("error") + } + fmt.Printf("%s\n", outDict.DefaultWriteString()) + r99, ok := resources.GetColorspaceByName("R99") + if !ok { + t.Fatalf("error") + } + + array, ok := core.GetArray(r99.ToPdfObject()) + if !ok { + t.Fatalf("error") + } + + if array.Len() != 4 { + t.Fatalf("len != 4 (got %d)", array.Len()) + } + + name, ok := core.GetName(array.Get(0)) + if !ok || *name != "Separation" { + t.Fatalf("Unexpected value") + } + + name, ok = core.GetName(array.Get(1)) + if !ok || *name != "All" { + t.Fatalf("Unexpected value") + } + + ind, ok := core.GetIndirect(array.Get(2)) + if !ok { + t.Fatalf("error") + } + if ind.ObjectNumber != 86 { + t.Fatalf("Incorrect obj num") + } + + f, ok := core.GetStream(array.Get(3)) + if !ok { + t.Fatalf("Stream get error") + } + if f.ObjectNumber != 87 { + t.Fatalf("Incorrect function obj number (got %d)", f.ObjectNumber) + } +} diff --git a/pdf/model/functions.go b/pdf/model/functions.go index fc80d051..4d908c4e 100644 --- a/pdf/model/functions.go +++ b/pdf/model/functions.go @@ -229,8 +229,7 @@ func newPdfFunctionType0FromStream(stream *PdfObjectStream) (*PdfFunctionType0, } func (this *PdfFunctionType0) ToPdfObject() PdfObject { - container := this.container - if container != nil { + if this.container == nil { this.container = &PdfObjectStream{} } @@ -267,10 +266,10 @@ func (this *PdfFunctionType0) ToPdfObject() PdfObject { // TODO: Encode. // Either here, or automatically later on when writing out. dict.Set("Length", MakeInteger(int64(len(this.rawData)))) - container.Stream = this.rawData + this.container.Stream = this.rawData - container.PdfObjectDictionary = dict - return container + this.container.PdfObjectDictionary = dict + return this.container } func (this *PdfFunctionType0) Evaluate(x []float64) ([]float64, error) { diff --git a/pdf/model/reader.go b/pdf/model/reader.go index 6a3c4db0..5b38532f 100644 --- a/pdf/model/reader.go +++ b/pdf/model/reader.go @@ -530,7 +530,7 @@ func (this *PdfReader) buildPageList(node *PdfIndirectObject, parent *PdfIndirec if !ok { return errors.New("Node missing Type (Required)") } - common.Log.Trace("buildPageList node type: %s", *objType) + common.Log.Trace("buildPageList node type: %s (%+v)", *objType, node) if *objType == "Page" { p, err := this.newPdfPageFromDict(nodeDict) if err != nil { diff --git a/pdf/model/testdata/cs_functype0.bin b/pdf/model/testdata/cs_functype0.bin new file mode 100644 index 00000000..e5cd6933 --- /dev/null +++ b/pdf/model/testdata/cs_functype0.bin @@ -0,0 +1 @@ +~~}|~~{~}{}|z||y{{x{zxzywyyvyxuxwuwvtvvsvurutrtsqsspsrorqoqpnppmoolonknmkmljllikkhkjhjigihfhheggdgfdfeceebddadc`cb`ba_aa^``]`_]_^\^^[]]Z]\Z\[Y[ZXZZWYYVXXUWWTVVSUURTTQTSPSRORQNQPNPOMONLNMKMLJLKIKJHJIGIIFHHEGGDFFCEEBDDACC@CB@BA?A@>@?=?><>=;==:<<9;:8:9798687566455344233122/11.0/-/.,.-+,,*++)**())'((&''%&&$%%#$$"##!"" !!  \ No newline at end of file diff --git a/pdf/model/testdata/iccstream.bin b/pdf/model/testdata/iccstream.bin new file mode 100644 index 0000000000000000000000000000000000000000..7f9d18d097d1bcccb32e6d5743ac4af593170b6f GIT binary patch literal 3144 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 L{PK7vZD!`*_k{EN literal 0 HcmV?d00001