Example #1
0
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
}
Example #2
0
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"]))
			}
		}
	}
}