private void FindColorspace(PdfObject colorspace, bool allowIndexed) { if (PdfName.DEVICEGRAY.Equals(colorspace)) { stride = (width * bpc + 7) / 8; pngColorType = 0; } else if (PdfName.DEVICERGB.Equals(colorspace)) { if (bpc == 8 || bpc == 16) { stride = (width * bpc * 3 + 7) / 8; pngColorType = 2; } } else if (colorspace is PdfArray) { PdfArray ca = (PdfArray)colorspace; PdfObject tyca = ca.GetDirectObject(0); if (PdfName.CALGRAY.Equals(tyca)) { stride = (width * bpc + 7) / 8; pngColorType = 0; } else if (PdfName.CALRGB.Equals(tyca)) { if (bpc == 8 || bpc == 16) { stride = (width * bpc * 3 + 7) / 8; pngColorType = 2; } } else if (PdfName.ICCBASED.Equals(tyca)) { PRStream pr = (PRStream)ca.GetDirectObject(1); int n = pr.GetAsNumber(PdfName.N).IntValue; if (n == 1) { stride = (width * bpc + 7) / 8; pngColorType = 0; icc = PdfReader.GetStreamBytes(pr); } else if (n == 3) { stride = (width * bpc * 3 + 7) / 8; pngColorType = 2; icc = PdfReader.GetStreamBytes(pr); } } else if (allowIndexed && PdfName.INDEXED.Equals(tyca)) { FindColorspace(ca.GetDirectObject(1), false); if (pngColorType == 2) { PdfObject id2 = ca.GetDirectObject(3); if (id2 is PdfString) { palette = ((PdfString)id2).GetBytes(); } else if (id2 is PRStream) { palette = PdfReader.GetStreamBytes(((PRStream)id2)); } stride = (width * bpc + 7) / 8; pngColorType = 3; } } } }
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()); }
/** * 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(); } }