Question

I would like to have cell background using it's natural dimensions and if they don't fit cell - image should be cropped. One more thing that when I use pattern fill image is actually 90 degress rotated. So the main thing in this question is why pattern image is rotated after it adding I have googled for answer and read documentation, but can't find any explanation. Here is code:

Image img = Image.GetInstance("someImage.png");

var cell = new PdfPCell()
{
    BorderWidthTop = 0,
    BorderWidthBottom = 0,
    BorderWidthLeft = 0,
    BorderWidthRight = 0,
    Padding = 0,
    BackgroundColor = new BaseColor(244, 244, 244),
    BorderColor = new BaseColor(217, 217, 217),
    HorizontalAlignment = Element.ALIGN_CENTER
};
cell.CellEvent = new CellBackgroundEvent() {Image = img};
table.AddCell(cell)
;

And here is event handler class:

private class CellBackgroundEvent : IPdfPCellEvent
{
    public Image Image { get; set; }

    void IPdfPCellEvent.CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
    {
        PdfContentByte cb = canvases[PdfPTable.BACKGROUNDCANVAS];
        PdfPatternPainter patternPainter = cb.CreatePattern(position.Right - position.Left, position.Top - position.Bottom);
        patternPainter.AddImage(Image, position.Right - position.Left, 0, 0, position.Top - position.Bottom, 0, 0);
        cb.SaveState();
        cb.SetPatternFill(patternPainter);
        cb.Rectangle(position.Left, position.Bottom, position.Width, position.Height);
        cb.Fill();
        cb.RestoreState();
    }
}

After execution cell background image is rotated 90 degrees clockwise, why?

Image is: enter image description here

Actual result cell is:

enter image description here

C# iTextSharp lib version: 5.5.0.0

Was it helpful?

Solution

You're trying to achieve something very simple using very complex code. This is what happens when you code by Google instead of reading the documentation!

Please try this:

PdfContentByte cb = canvases[PdfPTable.BACKGROUNDCANVAS];
Image.ScaleToFit( position.Top - position.Bottom,position.Right - position.Left);
Image.SetAbsolutePosition(position.Bottom, position.Left);
cb.AddImage(image);

Now you are scaling the image to fit the cell and adding it at the coordinate of the lower-left corner of the cell.

Update 1:

After having established that you actually want to tile the image, I've written an example trying to reproduce the problem. As I didn't understand your code (*), I had to rewrite large parts of it.

Anyway, you'll find a working Java sample here. The resulting PDF looks like this The image isn't rotated, is it? It looks the exact same way as it looks in your question.

This is the relevant code:

public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
    try {
        PdfContentByte cb = canvases[PdfPTable.BACKGROUNDCANVAS];
        PdfPatternPainter patternPainter = cb.createPattern(image.getScaledWidth(), image.getScaledHeight());
        image.setAbsolutePosition(0, 0);
        patternPainter.addImage(image);
        cb.saveState();
        cb.setPatternFill(patternPainter);
        cb.rectangle(position.getLeft(), position.getBottom(), position.getWidth(), position.getHeight());
        cb.fill();
        cb.restoreState();
    } catch (DocumentException e) {
        throw new ExceptionConverter(e);
    }
}

(*) Note that you ignored the fact that a Rectangle can also give you its width and height. You preferred using the difficult version of the AddImage() method. You confused the dimensions of the cell with the dimensions of the image...

Update 2:

The Java example was ported to C# (using iTextSharp 5.5.0.0):

using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace ConsoleApplication1 {
    public class TiledImageBackground : IPdfPCellEvent {
        protected Image image;

        public TiledImageBackground(Image image) {
            this.image = image;
        }

        public void CellLayout(PdfPCell cell, Rectangle position,
            PdfContentByte[] canvases) {
            PdfContentByte cb = canvases[PdfPTable.BACKGROUNDCANVAS];
            PdfPatternPainter patternPainter = cb.CreatePattern(image.ScaledWidth, image.ScaledHeight);
            image.SetAbsolutePosition(0, 0);
            patternPainter.AddImage(image);
            cb.SaveState();
            cb.SetPatternFill(patternPainter);
            cb.Rectangle(position.Left, position.Bottom, position.Width, position.Height);
            cb.Fill();
            cb.RestoreState();
        }
    }


    public class TiledBackground {
        public const String DEST = "results/tables/tiled_pattern.pdf";
        public const String IMG1 = "resources/images/ALxRF.png";
        public const String IMG2 = "resources/images/bulb.gif";

        private static void Main(string[] args) {
            Directory.CreateDirectory(Directory.GetParent(DEST).FullName);
            new TiledBackground().CreatePdf(DEST);
        }

        public void CreatePdf(String dest) {
            Document document = new Document();
            PdfWriter.GetInstance(document, new FileStream(dest, FileMode.Create));
            document.Open();
            PdfPTable table = new PdfPTable(2);
            PdfPCell cell = new PdfPCell();
            Image image = Image.GetInstance(IMG1);
            cell.CellEvent = new TiledImageBackground(image);
            cell.FixedHeight = 770;
            table.AddCell(cell);
            cell = new PdfPCell();
            image = Image.GetInstance(IMG2);
            cell.CellEvent = new TiledImageBackground(image);
            cell.FixedHeight = 770;
            table.AddCell(cell);
            document.Add(table);
            document.Close();
        }
    }
}

The problem couldn't be reproduced with this code. In other words: there is no bug in iTextSharp, the functionality was ported correctly.

Please take a moment to try the sample code from this answer to make assure yourself that the error is in your code. If you still have a problem with a changed orientation, you need to take a look at what is different in your code.

Update 3:

After an additional comment, we've now established that the 90 degree rotation was intentional. The document was created using:

Document document = new Document(PageSize.A4.Rotate());

In this case, you create a document of which the width is smaller than the height (the MediaBox is defined as a rectangle in portrait), but you rotate that page (adding a Rotate entry equal to 90 to the page dictionary).

If you want the pattern to match the orientation of a page in landscape, you have two options:

  • either you rotate the pattern: img_pattern.setPatternMatrix(0, 1, -1, 0, 0, 0);
  • or you create a MediaBox in landscape: new Document(new Rectangle(842, 595));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top