...
1
16
17 package gofpdf
18
19 import (
20 "bytes"
21 "fmt"
22 "strings"
23 )
24
25 func (f *Fpdf) pngColorSpace(ct byte) (colspace string, colorVal int) {
26 colorVal = 1
27 switch ct {
28 case 0, 4:
29 colspace = "DeviceGray"
30 case 2, 6:
31 colspace = "DeviceRGB"
32 colorVal = 3
33 case 3:
34 colspace = "Indexed"
35 default:
36 f.err = fmt.Errorf("unknown color type in PNG buffer: %d", ct)
37 }
38 return
39 }
40
41 func (f *Fpdf) parsepngstream(buf *bytes.Buffer, readdpi bool) (info *ImageInfoType) {
42 info = f.newImageInfo()
43
44 if string(buf.Next(8)) != "\x89PNG\x0d\x0a\x1a\x0a" {
45 f.err = fmt.Errorf("not a PNG buffer")
46 return
47 }
48
49 _ = buf.Next(4)
50 if string(buf.Next(4)) != "IHDR" {
51 f.err = fmt.Errorf("incorrect PNG buffer")
52 return
53 }
54 w := f.readBeInt32(buf)
55 h := f.readBeInt32(buf)
56 bpc := f.readByte(buf)
57 if bpc > 8 {
58 f.err = fmt.Errorf("16-bit depth not supported in PNG file")
59 }
60 ct := f.readByte(buf)
61 var colspace string
62 var colorVal int
63 colspace, colorVal = f.pngColorSpace(ct)
64 if f.err != nil {
65 return
66 }
67 if f.readByte(buf) != 0 {
68 f.err = fmt.Errorf("'unknown compression method in PNG buffer")
69 return
70 }
71 if f.readByte(buf) != 0 {
72 f.err = fmt.Errorf("'unknown filter method in PNG buffer")
73 return
74 }
75 if f.readByte(buf) != 0 {
76 f.err = fmt.Errorf("interlacing not supported in PNG buffer")
77 return
78 }
79 _ = buf.Next(4)
80 dp := sprintf("/Predictor 15 /Colors %d /BitsPerComponent %d /Columns %d", colorVal, bpc, w)
81
82 pal := make([]byte, 0, 32)
83 var trns []int
84 data := make([]byte, 0, 32)
85 loop := true
86 for loop {
87 n := int(f.readBeInt32(buf))
88
89 switch string(buf.Next(4)) {
90 case "PLTE":
91
92
93 pal = buf.Next(n)
94 _ = buf.Next(4)
95 case "tRNS":
96
97
98 t := buf.Next(n)
99 switch ct {
100 case 0:
101 trns = []int{int(t[1])}
102 case 2:
103 trns = []int{int(t[1]), int(t[3]), int(t[5])}
104 default:
105 pos := strings.Index(string(t), "\x00")
106 if pos >= 0 {
107 trns = []int{pos}
108 }
109 }
110 _ = buf.Next(4)
111 case "IDAT":
112
113
114 data = append(data, buf.Next(n)...)
115 _ = buf.Next(4)
116 case "IEND":
117
118 loop = false
119 case "pHYs":
120
121
122
123
124
125 x := int(f.readBeInt32(buf))
126 y := int(f.readBeInt32(buf))
127 units := buf.Next(1)[0]
128
129
130
131 if x == y && readdpi {
132 switch units {
133
134 case 1:
135 info.dpi = float64(x) / 39.3701
136 default:
137 info.dpi = float64(x)
138 }
139 }
140 _ = buf.Next(4)
141 default:
142
143 _ = buf.Next(n + 4)
144 }
145 if loop {
146 loop = n > 0
147 }
148 }
149 if colspace == "Indexed" && len(pal) == 0 {
150 f.err = fmt.Errorf("missing palette in PNG buffer")
151 }
152 info.w = float64(w)
153 info.h = float64(h)
154 info.cs = colspace
155 info.bpc = int(bpc)
156 info.f = "FlateDecode"
157 info.dp = dp
158 info.pal = pal
159 info.trns = trns
160
161 if ct >= 4 {
162
163 var err error
164 data, err = sliceUncompress(data)
165 if err != nil {
166 f.err = err
167 return
168 }
169 var color, alpha bytes.Buffer
170 if ct == 4 {
171
172 width := int(w)
173 height := int(h)
174 length := 2 * width
175 var pos, elPos int
176 for i := 0; i < height; i++ {
177 pos = (1 + length) * i
178 color.WriteByte(data[pos])
179 alpha.WriteByte(data[pos])
180 elPos = pos + 1
181 for k := 0; k < width; k++ {
182 color.WriteByte(data[elPos])
183 alpha.WriteByte(data[elPos+1])
184 elPos += 2
185 }
186 }
187 } else {
188
189 width := int(w)
190 height := int(h)
191 length := 4 * width
192 var pos, elPos int
193 for i := 0; i < height; i++ {
194 pos = (1 + length) * i
195 color.WriteByte(data[pos])
196 alpha.WriteByte(data[pos])
197 elPos = pos + 1
198 for k := 0; k < width; k++ {
199 color.Write(data[elPos : elPos+3])
200 alpha.WriteByte(data[elPos+3])
201 elPos += 4
202 }
203 }
204 }
205 data = sliceCompress(color.Bytes())
206 info.smask = sliceCompress(alpha.Bytes())
207 if f.pdfVersion < "1.4" {
208 f.pdfVersion = "1.4"
209 }
210 }
211 info.data = data
212 return
213 }
214
View as plain text