/** * decodes the bytes currently captured in the streamBytes and replaces it with an image representation of the bytes * (this will either be a png or a tiff, depending on the color depth of the image) * @throws IOException */ private void DecodeImageBytes() { if (streamContentType != null) throw new ArgumentException(MessageLocalization.GetComposedMessage("Decoding.can't.happen.on.this.type.of.stream.(.1.)", streamContentType.FileExtension)); pngColorType = -1; PdfArray decode = dictionary.GetAsArray(PdfName.DECODE); width = dictionary.GetAsNumber(PdfName.WIDTH).IntValue; height = dictionary.GetAsNumber(PdfName.HEIGHT).IntValue; bpc = dictionary.GetAsNumber(PdfName.BITSPERCOMPONENT).IntValue; pngBitDepth = bpc; PdfObject colorspace = dictionary.GetDirectObject(PdfName.COLORSPACE); if (colorspace is PdfName && colorSpaceDic != null){ PdfObject csLookup = colorSpaceDic.GetDirectObject((PdfName)colorspace); if (csLookup != null) colorspace = csLookup; } palette = null; icc = null; stride = 0; FindColorspace(colorspace, true); MemoryStream ms = new MemoryStream(); if (pngColorType < 0) { if (bpc != 8) throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("the.color.depth.1.is.not.supported", bpc)); if (PdfName.DEVICECMYK.Equals(colorspace)) { } else if (colorspace is PdfArray) { PdfArray ca = (PdfArray)colorspace; PdfObject tyca = ca.GetDirectObject(0); if (!PdfName.ICCBASED.Equals(tyca)) throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("the.color.space.1.is.not.supported", colorspace)); PRStream pr = (PRStream)ca.GetDirectObject(1); int n = pr.GetAsNumber(PdfName.N).IntValue; if (n != 4) { throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("N.value.1.is.not.supported", n)); } icc = PdfReader.GetStreamBytes(pr); } else throw new UnsupportedPdfException(MessageLocalization.GetComposedMessage("the.color.space.1.is.not.supported", colorspace)); stride = 4 * width; TiffWriter wr = new TiffWriter(); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL, 4)); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_BITSPERSAMPLE, new int[]{8,8,8,8})); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_PHOTOMETRIC, TIFFConstants.PHOTOMETRIC_SEPARATED)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_IMAGEWIDTH, width)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_IMAGELENGTH, height)); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_COMPRESSION, TIFFConstants.COMPRESSION_LZW)); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_PREDICTOR, TIFFConstants.PREDICTOR_HORIZONTAL_DIFFERENCING)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP, height)); wr.AddField(new TiffWriter.FieldRational(TIFFConstants.TIFFTAG_XRESOLUTION, new int[]{300,1})); wr.AddField(new TiffWriter.FieldRational(TIFFConstants.TIFFTAG_YRESOLUTION, new int[]{300,1})); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_RESOLUTIONUNIT, TIFFConstants.RESUNIT_INCH)); wr.AddField(new TiffWriter.FieldAscii(TIFFConstants.TIFFTAG_SOFTWARE, Version.GetInstance().GetVersion)); MemoryStream comp = new MemoryStream(); TiffWriter.CompressLZW(comp, 2, imageBytes, height, 4, stride); byte[] buf = comp.ToArray(); wr.AddField(new TiffWriter.FieldImage(buf)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_STRIPBYTECOUNTS, buf.Length)); if (icc != null) wr.AddField(new TiffWriter.FieldUndefined(TIFFConstants.TIFFTAG_ICCPROFILE, icc)); wr.WriteFile(ms); streamContentType = ImageBytesType.CCITT; imageBytes = ms.ToArray(); return; } else { PngWriter png = new PngWriter(ms); if (decode != null){ if (pngBitDepth == 1){ // if the decode array is 1,0, then we need to invert the image if (decode.GetAsNumber(0).IntValue == 1 && decode.GetAsNumber(1).IntValue == 0){ int len = imageBytes.Length; for (int t = 0; t < len; ++t) { imageBytes[t] ^= 0xff; } } else { // if the decode array is 0,1, do nothing. It's possible that the array could be 0,0 or 1,1 - but that would be silly, so we'll just ignore that case } } else { // todo: add decode transformation for other depths } } png.WriteHeader(width, height, pngBitDepth, pngColorType); if (icc != null) png.WriteIccProfile(icc); if (palette != null) png.WritePalette(palette); png.WriteData(imageBytes, stride); png.WriteEnd(); streamContentType = ImageBytesType.PNG; imageBytes = ms.ToArray(); } }
public byte[] GetImageAsBytes() { if (streamBytes == null) return null; if (!decoded) { // if the stream hasn't been decoded, check to see if it is a single stage JPG or JPX encoded stream. If it is, // then we can just use stream as-is PdfName filter = dictionary.GetAsName(PdfName.FILTER); if (filter == null){ PdfArray filterArray = dictionary.GetAsArray(PdfName.FILTER); if (filterArray.Size == 1){ filter = filterArray.GetAsName(0); } else { throw new UnsupportedPdfException("Multi-stage filters not supported here (" + filterArray + ")"); } } if (PdfName.DCTDECODE.Equals(filter)) { fileType = TYPE_JPG; return streamBytes; } else if (PdfName.JPXDECODE.Equals(filter)) { fileType = TYPE_JP2; return streamBytes; } throw new UnsupportedPdfException("Unsupported stream filter " + filter); } pngColorType = -1; width = dictionary.GetAsNumber(PdfName.WIDTH).IntValue; height = dictionary.GetAsNumber(PdfName.HEIGHT).IntValue; bpc = dictionary.GetAsNumber(PdfName.BITSPERCOMPONENT).IntValue; pngBitDepth = bpc; PdfObject colorspace = dictionary.GetDirectObject(PdfName.COLORSPACE); palette = null; icc = null; stride = 0; FindColorspace(colorspace, true); MemoryStream ms = new MemoryStream(); if (pngColorType < 0) { if (bpc != 8) return null; if (PdfName.DEVICECMYK.Equals(colorspace)) { } else if (colorspace is PdfArray) { PdfArray ca = (PdfArray)colorspace; PdfObject tyca = ca.GetDirectObject(0); if (!PdfName.ICCBASED.Equals(tyca)) return null; PRStream pr = (PRStream)ca.GetDirectObject(1); int n = pr.GetAsNumber(PdfName.N).IntValue; if (n != 4) { return null; } icc = PdfReader.GetStreamBytes(pr); } else return null; stride = 4 * width; TiffWriter wr = new TiffWriter(); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL, 4)); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_BITSPERSAMPLE, new int[]{8,8,8,8})); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_PHOTOMETRIC, TIFFConstants.PHOTOMETRIC_SEPARATED)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_IMAGEWIDTH, width)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_IMAGELENGTH, height)); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_COMPRESSION, TIFFConstants.COMPRESSION_LZW)); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_PREDICTOR, TIFFConstants.PREDICTOR_HORIZONTAL_DIFFERENCING)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP, height)); wr.AddField(new TiffWriter.FieldRational(TIFFConstants.TIFFTAG_XRESOLUTION, new int[]{300,1})); wr.AddField(new TiffWriter.FieldRational(TIFFConstants.TIFFTAG_YRESOLUTION, new int[]{300,1})); wr.AddField(new TiffWriter.FieldShort(TIFFConstants.TIFFTAG_RESOLUTIONUNIT, TIFFConstants.RESUNIT_INCH)); wr.AddField(new TiffWriter.FieldAscii(TIFFConstants.TIFFTAG_SOFTWARE, Document.Version)); MemoryStream comp = new MemoryStream(); TiffWriter.CompressLZW(comp, 2, streamBytes, height, 4, stride); byte[] buf = comp.ToArray(); wr.AddField(new TiffWriter.FieldImage(buf)); wr.AddField(new TiffWriter.FieldLong(TIFFConstants.TIFFTAG_STRIPBYTECOUNTS, buf.Length)); if (icc != null) wr.AddField(new TiffWriter.FieldUndefined(TIFFConstants.TIFFTAG_ICCPROFILE, icc)); wr.WriteFile(ms); fileType = TYPE_TIF; return ms.ToArray(); } PngWriter png = new PngWriter(ms); png.WriteHeader(width, height, pngBitDepth, pngColorType); if (icc != null) png.WriteIccProfile(icc); if (palette != null) png.WritePalette(palette); png.WriteData(streamBytes, stride); png.WriteEnd(); fileType = TYPE_PNG; return ms.ToArray(); }