Search code examples
c#itextembedded-resource

ITextSharp: How to get an image embedded resource


I'm parsing an HTML with some images inside this.

This images are stored as embedded resource, not in the filesystem.

as I know, i need to set a custom image provider in HtmlPipelineContext, and this provider need to retrieve the image path or the itextsharp image.

The question is, somebody know which method of Abstract Image Provider i need to implement? and how?

this is my code:

            var list = new List<string> { text };
            byte[] renderedBuffer;
            using (var outputMemoryStream = new MemoryStream())
            {
                using (
                    var pdfDocument = new Document(PageSize.A4, 30, 30, 30, 30))
                {
                    var pdfWriter = PdfWriter.GetInstance(pdfDocument, outputMemoryStream);
                    pdfWriter.CloseStream = false;
                    pdfDocument.Open();
                    HtmlPipelineContext htmlContext = new HtmlPipelineContext(new CssAppliersImpl());
                    htmlContext.SetImageProvider(new MyImageProvider());
                    htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
                    ICSSResolver cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true);
                    CssResolverPipeline pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(pdfDocument, pdfWriter)));
                    XMLWorker worker = new XMLWorker(pipeline, true);
                    XMLParser p = new XMLParser(worker);
                    foreach (var htmlText in list)
                    {
                        using (var htmlViewReader = new StringReader(htmlText))
                        {
                            p.Parse(htmlViewReader);
                        }
                    }
                }

                renderedBuffer = new byte[outputMemoryStream.Position];
                outputMemoryStream.Position = 0;
                outputMemoryStream.Read(renderedBuffer, 0, renderedBuffer.Length);
            }

Thanks in advance.


Solution

  • Using a custom Image Provider it doesn't seem to be supported. The only thing it really supports is changing root paths.

    However, here's one solution to the problem:

    Create a new html tag, called <resimg src="{resource name}"/>, and write a custom tag processor for it.

    Here's the implementation:

    /// <summary>
    /// Our custom HTML Tag to add an IElement.
    /// </summary>
    public class ResourceImageHtmlTagProcessor : AbstractTagProcessor
    {
        public override IList<IElement> End(IWorkerContext ctx, Tag tag, IList<IElement> currentContent)
        {
            var src = tag.Attributes["src"];
            var bitmap = (Bitmap)Resources.ResourceManager.GetObject(src);
    
            if (bitmap == null)
                throw new RuntimeWorkerException("No resource with the name: " + src);
    
            var converter = new ImageConverter();
            var image = Image.GetInstance((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
            HtmlPipelineContext htmlPipelineContext = this.GetHtmlPipelineContext(ctx);
            return new List<IElement>(1)
                {
                    this.GetCssAppliers().Apply(
                        new Chunk((Image)this.GetCssAppliers().Apply(image, tag, htmlPipelineContext), 0f, 0f, true),
                        tag,
                        htmlPipelineContext)
                };
        }
    }
    

    To configure your new processor replace the line where you specify the TagFactory with the following:

    var tagProcessorFactory = Tags.GetHtmlTagProcessorFactory();
    tagProcessorFactory.AddProcessor(new ResourceImageHtmlTagProcessor(), new[] { "resimg" });
    htmlContext.SetTagFactory(tagProcessorFactory);