func decodeStream(dic DictionaryT, data []byte) []byte { if f, ok := dic["/Filter"]; ok { filter := ForcedArray(f) var decos [][]byte if d, ok := dic["/DecodeParms"]; ok { decos = ForcedArray(d) } else { decos = make([][]byte, len(filter)) } for ff := range filter { // XXX: if there are multiple filters but only one DecodeParams, // it should be used for all filters deco := Dictionary(decos[ff]) switch string(filter[ff]) { case "/FlateDecode": data = fancy.ReadAndClose(zlib.NewReader(fancy.SliceReader(data))) case "/LZWDecode": early := true if deco != nil { if s, ok := deco["/EarlyChange"]; ok { early = num(s) == 1 } } data = lzw.Decode(data, early) case "/ASCII85Decode": ds := data for len(ds) > 1 && ds[len(ds)-1] < 33 { ds = ds[0 : len(ds)-1] } if len(ds) >= 2 && ds[len(ds)-1] == '>' && ds[len(ds)-2] == '~' { ds = ds[0 : len(ds)-2] } data = fancy.ReadAll(ascii85.NewDecoder(fancy.SliceReader(ds))) case "/ASCIIHexDecode": data, _ = hex.DecodeString(string(data)) default: util.Log("Unsupported filter", string(filter[ff])) data = []byte{} } if s, ok := deco["/Predictor"]; ok { pred := num(s) switch { case pred == 1: // no predictor case pred > 10: colors := numdef(deco["/Colors"], 1) columns := numdef(deco["/Columns"], 1) bitspercomponent := numdef(deco["/BitsPerComponent"], 8) util.Log("applying predictor", pred, colors, columns, bitspercomponent) data = util.ApplyPNGPredictor(pred, colors, columns, bitspercomponent, data) default: util.Log("Unsupported predictor", pred) return nil } } } } return data }
func extract(pd *pdfread.PdfReaderT, page int, t *TiffBuilder, next bool) { pg := pd.Pages()[page-1] mbox := util.StringArray(pd.Arr(pd.Att("/MediaBox", pg))) fmt.Println("Page", page) fmt.Println(" MediaBox", mbox) resources := pd.Dic(pd.Att("/Resources", pg)) if xo := pd.Dic(resources["/XObject"]); xo != nil { for name, ref := range xo { dic, data := pd.Stream(ref) printdic(dic, name, " ") if string(dic["/Subtype"]) != "/Image" { continue } switch string(dic["/Filter"]) { case "/CCITTFaxDecode": // TIFF if string(dic["/ColorSpace"]) != "/DeviceGray" { log.Fatal("cannot convert /CCITTFaxDecode ", string(pd.Obj(dic["/ColorSpace"]))) } dparms := pd.Dic(dic["/DecodeParms"]) width := pd.Num(dparms["/Columns"]) height := pd.Num(dparms["/Rows"]) k := pd.Num(dparms["/K"]) bpc := pd.Num(dic["/BitsPerComponent"]) if k >= 0 { // can't do this right now log.Fatal("can't do encoding with K=", k) } t.AddLong(TAG_IMAGE_WIDTH, uint32(width)) t.AddLong(TAG_IMAGE_LENGTH, uint32(height)) t.AddShort(TAG_BITS_PER_SAMPLE, uint16(bpc)) t.AddShort(TAG_COMPRESSION, 4) // CCITT Group 4 t.AddShort(TAG_PHOTOMETRIC_INTERPRETATION, 0) // white is zero t.AddLong(TAG_STRIP_OFFSETS, 0) //t.AddShort(TAG_ORIENTATION, 1) //t.AddShort(TAG_SAMPLES_PER_PIXEL, 1) t.AddLong(TAG_ROWS_PER_STRIP, uint32(height)) t.AddLong(TAG_STRIP_BYTE_COUNTS, uint32(len(data))) //t.AddRational(TAG_X_RESOLUTION, 300, 1) // 300 dpi (300/1) //t.AddRational(TAG_Y_RESOLUTION, 300, 1) // 300 dpi (300/1) //t.AddShort(TAG_RESOLUTION_UNIT, 2) // pixels/inch t.WriteIFD(data, next) case "/DCTDecode": // JPEG /* width := pd.Num(dic["/Width"]) height := pd.Num(dic["/Height"]) bpc := pd.Num(dic["/BitsPerComponent"]) */ f, err := os.Create("test.jpg") if err != nil { log.Fatal(err) } f.Write(data) f.Close() case "/FlateDecode": // compressed bitmap data = fancy.ReadAndClose(zlib.NewReader(fancy.SliceReader(data))) width := pd.Num(dic["/Width"]) height := pd.Num(dic["/Height"]) bpc := pd.Num(dic["/BitsPerComponent"]) if bpc != 8 { log.Fatal("cannot convert /FlateDecode bpc:", bpc) } if string(dic["/ColorSpace"]) != "/DeviceRGB" { log.Fatal("cannot convert /FlateDecode ", string(pd.Obj(dic["/ColorSpace"]))) } ima := image.NewRGBA(image.Rect(0, 0, width, height)) for y := 0; y < height; y++ { for x := 0; x < width; x++ { ima.Set(x, y, color.RGBA{R: data[0], G: data[1], B: data[2], A: 255}) data = data[3:] } } f, err := os.Create("test.png") if err != nil { log.Fatal(err) } png.Encode(f, ima) f.Close() default: log.Fatal("cannot decode ", string(dic["/Filter"])) } } } }