public XObjectImage CreateImage(XObjectContentRecord xObject, IPdfTokenScanner pdfScanner, bool isLenientParsing) { if (xObject == null) { throw new ArgumentNullException(nameof(xObject)); } if (xObject.Type != XObjectType.Image) { throw new InvalidOperationException($"Cannot create an image from an XObject with type: {xObject.Type}."); } var width = xObject.Stream.StreamDictionary.Get <NumericToken>(NameToken.Width, pdfScanner).Int; var height = xObject.Stream.StreamDictionary.Get <NumericToken>(NameToken.Height, pdfScanner).Int; var isJpxDecode = xObject.Stream.StreamDictionary.TryGet(NameToken.Filter, out var token) && token is NameToken filterName && filterName.Equals(NameToken.JpxDecode); var isImageMask = xObject.Stream.StreamDictionary.TryGet(NameToken.ImageMask, out var maskToken) && maskToken is BooleanToken maskBoolean && maskBoolean.Data; return(new XObjectImage(width, height, isJpxDecode, isImageMask, xObject.Stream.StreamDictionary, xObject.Stream.Data)); }
public static XObjectImage ReadImage(XObjectContentRecord xObject, IPdfTokenScanner pdfScanner, IFilterProvider filterProvider, IResourceStore resourceStore, bool isLenientParsing) { if (xObject == null) { throw new ArgumentNullException(nameof(xObject)); } if (xObject.Type != XObjectType.Image) { throw new InvalidOperationException($"Cannot create an image from an XObject with type: {xObject.Type}."); } var dictionary = xObject.Stream.StreamDictionary; var bounds = xObject.AppliedTransformation.Transform(new PdfRectangle(new PdfPoint(0, 0), new PdfPoint(1, 1))); var width = dictionary.Get <NumericToken>(NameToken.Width, pdfScanner).Int; var height = dictionary.Get <NumericToken>(NameToken.Height, pdfScanner).Int; var isImageMask = dictionary.TryGet(NameToken.ImageMask, pdfScanner, out BooleanToken isMaskToken) && isMaskToken.Data; var isJpxDecode = dictionary.TryGet(NameToken.Filter, out var token) && token is NameToken filterName && filterName.Equals(NameToken.JpxDecode); int bitsPerComponent = 0; if (!isImageMask && !isJpxDecode) { if (!dictionary.TryGet(NameToken.BitsPerComponent, pdfScanner, out NumericToken bitsPerComponentToken)) { throw new PdfDocumentFormatException($"No bits per component defined for image: {dictionary}."); } bitsPerComponent = bitsPerComponentToken.Int; } else if (isImageMask) { bitsPerComponent = 1; } var intent = xObject.DefaultRenderingIntent; if (dictionary.TryGet(NameToken.Intent, out NameToken renderingIntentToken)) { intent = renderingIntentToken.Data.ToRenderingIntent(); } var interpolate = dictionary.TryGet(NameToken.Interpolate, pdfScanner, out BooleanToken interpolateToken) && interpolateToken.Data; var decodedBytes = new Lazy <IReadOnlyList <byte> >(() => xObject.Stream.Decode(filterProvider)); var decode = EmptyArray <decimal> .Instance; if (dictionary.TryGet(NameToken.Decode, pdfScanner, out ArrayToken decodeArrayToken)) { decode = decodeArrayToken.Data.OfType <NumericToken>() .Select(x => x.Data) .ToArray(); } var colorSpace = default(ColorSpace?); if (!isImageMask) { if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out NameToken colorSpaceNameToken) && TryMapColorSpace(colorSpaceNameToken, resourceStore, out var colorSpaceResult)) { colorSpace = colorSpaceResult; } else if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out ArrayToken colorSpaceArrayToken)) { if (colorSpaceArrayToken.Length == 0) { throw new PdfDocumentFormatException($"Empty ColorSpace array defined for image XObject: {dictionary}."); } var first = colorSpaceArrayToken.Data[0]; if (!(first is NameToken firstColorSpaceName) || !TryMapColorSpace(firstColorSpaceName, resourceStore, out colorSpaceResult)) { throw new PdfDocumentFormatException($"Invalid ColorSpace array defined for image XObject: {colorSpaceArrayToken}."); } colorSpace = colorSpaceResult; } else if (!isJpxDecode) { throw new PdfDocumentFormatException($"No ColorSpace defined for image XObject: {dictionary}."); } } return(new XObjectImage(bounds, width, height, bitsPerComponent, colorSpace, isJpxDecode, isImageMask, intent, interpolate, decode, dictionary, xObject.Stream.Data, decodedBytes)); }
public static XObjectImage ReadImage(XObjectContentRecord xObject, IPdfTokenScanner pdfScanner, ILookupFilterProvider filterProvider, IResourceStore resourceStore) { if (xObject == null) { throw new ArgumentNullException(nameof(xObject)); } if (xObject.Type != XObjectType.Image) { throw new InvalidOperationException($"Cannot create an image from an XObject with type: {xObject.Type}."); } var dictionary = xObject.Stream.StreamDictionary; var bounds = xObject.AppliedTransformation.Transform(new PdfRectangle(new PdfPoint(0, 0), new PdfPoint(1, 1))); var width = dictionary.Get <NumericToken>(NameToken.Width, pdfScanner).Int; var height = dictionary.Get <NumericToken>(NameToken.Height, pdfScanner).Int; var isImageMask = dictionary.TryGet(NameToken.ImageMask, pdfScanner, out BooleanToken isMaskToken) && isMaskToken.Data; var isJpxDecode = dictionary.TryGet(NameToken.Filter, out var token) && token is NameToken filterName && filterName.Equals(NameToken.JpxDecode); int bitsPerComponent = 0; if (!isImageMask && !isJpxDecode) { if (!dictionary.TryGet(NameToken.BitsPerComponent, pdfScanner, out NumericToken bitsPerComponentToken)) { throw new PdfDocumentFormatException($"No bits per component defined for image: {dictionary}."); } bitsPerComponent = bitsPerComponentToken.Int; } else if (isImageMask) { bitsPerComponent = 1; } var intent = xObject.DefaultRenderingIntent; if (dictionary.TryGet(NameToken.Intent, out NameToken renderingIntentToken)) { intent = renderingIntentToken.Data.ToRenderingIntent(); } var interpolate = dictionary.TryGet(NameToken.Interpolate, pdfScanner, out BooleanToken interpolateToken) && interpolateToken.Data; DictionaryToken filterDictionary = xObject.Stream.StreamDictionary; if (xObject.Stream.StreamDictionary.TryGet(NameToken.Filter, out var filterToken) && filterToken is IndirectReferenceToken) { if (filterDictionary.TryGet(NameToken.Filter, pdfScanner, out ArrayToken filterArray)) { filterDictionary = filterDictionary.With(NameToken.Filter, filterArray); } else if (filterDictionary.TryGet(NameToken.Filter, pdfScanner, out NameToken filterNameToken)) { filterDictionary = filterDictionary.With(NameToken.Filter, filterNameToken); } else { filterDictionary = null; } } var supportsFilters = filterDictionary != null; if (filterDictionary != null) { var filters = filterProvider.GetFilters(filterDictionary, pdfScanner); foreach (var filter in filters) { if (!filter.IsSupported) { supportsFilters = false; break; } } } var decodeParams = dictionary.GetObjectOrDefault(NameToken.DecodeParms, NameToken.Dp); if (decodeParams is IndirectReferenceToken refToken) { dictionary = dictionary.With(NameToken.DecodeParms, pdfScanner.Get(refToken.Data).Data); } var streamToken = new StreamToken(dictionary, xObject.Stream.Data); var decodedBytes = supportsFilters ? new Lazy <IReadOnlyList <byte> >(() => streamToken.Decode(filterProvider, pdfScanner)) : null; var decode = EmptyArray <decimal> .Instance; if (dictionary.TryGet(NameToken.Decode, pdfScanner, out ArrayToken decodeArrayToken)) { decode = decodeArrayToken.Data.OfType <NumericToken>() .Select(x => x.Data) .ToArray(); } var colorSpace = default(ColorSpace?); if (!isImageMask) { if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out NameToken colorSpaceNameToken) && TryMapColorSpace(colorSpaceNameToken, resourceStore, out var colorSpaceResult)) { colorSpace = colorSpaceResult; } else if (dictionary.TryGet(NameToken.ColorSpace, pdfScanner, out ArrayToken colorSpaceArrayToken) && colorSpaceArrayToken.Length > 0) { var first = colorSpaceArrayToken.Data[0]; if ((first is NameToken firstColorSpaceName) && TryMapColorSpace(firstColorSpaceName, resourceStore, out colorSpaceResult)) { colorSpace = colorSpaceResult; } } else if (!isJpxDecode) { colorSpace = xObject.DefaultColorSpace; } } var details = ColorSpaceDetailsParser.GetColorSpaceDetails(colorSpace, dictionary, pdfScanner, resourceStore, filterProvider); return(new XObjectImage( bounds, width, height, bitsPerComponent, colorSpace, isJpxDecode, isImageMask, intent, interpolate, decode, dictionary, xObject.Stream.Data, decodedBytes, details)); }