All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itextpdf.layout.element.Image Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2024 Apryse Group NV
    Authors: Apryse Software.

    This program is offered under a commercial and under the AGPL license.
    For commercial licensing, contact us at https://itextpdf.com/sales.  For AGPL licensing, see below.

    AGPL licensing:
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see .
 */
package com.itextpdf.layout.element;

import com.itextpdf.io.logs.IoLogMessageConstant;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.kernel.exceptions.PdfException;
import com.itextpdf.kernel.pdf.canvas.wmf.WmfImageData;
import com.itextpdf.kernel.pdf.tagging.StandardRoles;
import com.itextpdf.kernel.pdf.tagutils.DefaultAccessibilityProperties;
import com.itextpdf.kernel.pdf.tagutils.AccessibilityProperties;
import com.itextpdf.layout.exceptions.LayoutExceptionMessageConstant;
import com.itextpdf.layout.properties.ObjectFit;
import com.itextpdf.layout.tagging.IAccessibleElement;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.kernel.pdf.xobject.PdfImageXObject;
import com.itextpdf.kernel.pdf.xobject.PdfXObject;
import com.itextpdf.layout.properties.Property;
import com.itextpdf.layout.layout.LayoutPosition;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.ImageRenderer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A layout element that represents an image for inclusion in the document model.
 */
public class Image extends AbstractElement implements ILeafElement, IAccessibleElement {

    protected PdfXObject xObject;
    protected DefaultAccessibilityProperties tagProperties;

    /**
     * Creates an {@link Image} from an image XObject, the representation of an
     * image in PDF syntax.
     *
     * @param xObject an internal {@link PdfImageXObject}
     */
    public Image(PdfImageXObject xObject) {
        this.xObject = xObject;
    }

    /**
     * Creates an {@link Image} from a form XObject, the representation of a
     * form in PDF syntax.
     *
     * @param xObject an internal {@link PdfFormXObject}
     */
    public Image(PdfFormXObject xObject) {
        this.xObject = xObject;
    }

    /**
     * Creates an {@link Image} from an image XObject, the representation of an
     * image in PDF syntax, with a custom width.
     *
     * @param xObject an internal {@link PdfImageXObject}
     * @param width   a float value
     */
    public Image(PdfImageXObject xObject, float width) {
        this.xObject = xObject;
        setWidth(width);
    }

    /**
     * Creates an {@link Image} from an image XObject, the representation of an
     * image in PDF syntax, with a custom width and on a fixed position.
     *
     * @param xObject an internal {@link PdfImageXObject}
     * @param left    a float value representing the horizontal offset of the lower left corner of the image
     * @param bottom  a float value representing the vertical offset of the lower left corner of the image
     * @param width   a float value
     */
    public Image(PdfImageXObject xObject, float left, float bottom, float width) {
        this.xObject = xObject;
        setProperty(Property.LEFT, left);
        setProperty(Property.BOTTOM, bottom);
        setWidth(width);
        setProperty(Property.POSITION, LayoutPosition.FIXED);
    }

    /**
     * Creates an {@link Image} from an image XObject, the representation of an
     * image in PDF syntax, on a fixed position.
     *
     * @param xObject an internal {@link PdfImageXObject}
     * @param left    a float value representing the horizontal offset of the lower left corner of the image
     * @param bottom  a float value representing the vertical offset of the lower left corner of the image
     */
    public Image(PdfImageXObject xObject, float left, float bottom) {
        this.xObject = xObject;
        setProperty(Property.LEFT, left);
        setProperty(Property.BOTTOM, bottom);
        setProperty(Property.POSITION, LayoutPosition.FIXED);
    }

    /**
     * Creates an {@link Image} from a form XObject, the representation of a
     * form in PDF syntax.
     *
     * @param xObject an internal {@link PdfFormXObject}
     * @param left    a float value representing the horizontal offset of the lower left corner of the form
     * @param bottom  a float value representing the vertical offset of the lower left corner of the form
     */
    public Image(PdfFormXObject xObject, float left, float bottom) {
        this.xObject = xObject;
        setProperty(Property.LEFT, left);
        setProperty(Property.BOTTOM, bottom);
        setProperty(Property.POSITION, LayoutPosition.FIXED);
    }

    /**
     * Creates an {@link Image} from an image resource, read in from a file
     * with the iText I/O module.
     *
     * @param img an internal representation of the {@link com.itextpdf.io.image.ImageData image resource}
     */
    public Image(ImageData img) {
        this(new PdfImageXObject(checkImageType(img)));
        setProperty(Property.FLUSH_ON_DRAW, true);
    }

    /**
     * Creates an {@link Image} from an image resource, read in from a file
     * with the iText I/O module, on a fixed position.
     *
     * @param img    an internal representation of the {@link com.itextpdf.io.image.ImageData image resource}
     * @param left   a float value representing the horizontal offset of the lower left corner of the image
     * @param bottom a float value representing the vertical offset of the lower left corner of the image
     */
    public Image(ImageData img, float left, float bottom) {
        this(new PdfImageXObject(checkImageType(img)), left, bottom);
        setProperty(Property.FLUSH_ON_DRAW, true);
    }

    /**
     * Creates an {@link Image} from an image resource, read in from a file
     * with the iText I/O module, with a custom width and on a fixed position.
     *
     * @param img    an internal representation of the {@link com.itextpdf.io.image.ImageData image resource}
     * @param left   a float value representing the horizontal offset of the lower left corner of the image
     * @param bottom a float value representing the vertical offset of the lower left corner of the image
     * @param width  a float value
     */
    public Image(ImageData img, float left, float bottom, float width) {
        this(new PdfImageXObject(checkImageType(img)), left, bottom, width);
        setProperty(Property.FLUSH_ON_DRAW, true);
    }

    /**
     * Gets the XObject contained in this image object
     *
     * @return a {@link PdfXObject}
     */
    public PdfXObject getXObject() {
        return xObject;
    }

    /**
     * Sets the rotation radAngle.
     *
     * @param radAngle a value in radians
     * @return this element
     */
    public Image setRotationAngle(double radAngle) {
        setProperty(Property.ROTATION_ANGLE, radAngle);
        return this;
    }

    /**
     * Gets the current left margin width of the element.
     *
     * @return the left margin width, as a {@link UnitValue} object
     */
    public UnitValue getMarginLeft() {
        return this.getProperty(Property.MARGIN_LEFT);
    }

    /**
     * Sets the left margin width of the element.
     *
     * @param value the new left margin width
     * @return this element
     */
    public Image setMarginLeft(float value) {
        UnitValue marginUV = UnitValue.createPointValue(value);
        setProperty(Property.MARGIN_LEFT, marginUV);
        return this;
    }

    /**
     * Gets the current right margin width of the image.
     *
     * @return the right margin width, as a {@link UnitValue} object
     */
    public UnitValue getMarginRight() {
        return this.getProperty(Property.MARGIN_RIGHT);
    }

    /**
     * Sets the right margin width of the image.
     *
     * @param value the new right margin width
     * @return this image
     */
    public Image setMarginRight(float value) {
        UnitValue marginUV = UnitValue.createPointValue(value);
        setProperty(Property.MARGIN_RIGHT, marginUV);
        return this;
    }

    /**
     * Gets the current top margin width of the image.
     *
     * @return the top margin width, as a {@link UnitValue} object
     */
    public UnitValue getMarginTop() {
        return this.getProperty(Property.MARGIN_TOP);
    }

    /**
     * Sets the top margin width of the image.
     *
     * @param value the new top margin width
     * @return this image
     */
    public Image setMarginTop(float value) {
        UnitValue marginUV = UnitValue.createPointValue(value);
        setProperty(Property.MARGIN_TOP, marginUV);
        return this;
    }

    /**
     * Gets the current bottom margin width of the image.
     *
     * @return the bottom margin width, as a {@link UnitValue} object
     */
    public UnitValue getMarginBottom() {
        return this.getProperty(Property.MARGIN_BOTTOM);
    }

    /**
     * Sets the bottom margin width of the image.
     *
     * @param value the new bottom margin width
     * @return this image
     */
    public Image setMarginBottom(float value) {
        UnitValue marginUV = UnitValue.createPointValue(value);
        setProperty(Property.MARGIN_BOTTOM, marginUV);
        return this;
    }

    /**
     * Sets the margins around the image to a series of new widths.
     *
     * @param marginTop    the new margin top width
     * @param marginRight  the new margin right width
     * @param marginBottom the new margin bottom width
     * @param marginLeft   the new margin left width
     * @return this image
     */
    public Image setMargins(float marginTop, float marginRight, float marginBottom, float marginLeft) {
        return setMarginTop(marginTop).setMarginRight(marginRight).setMarginBottom(marginBottom).setMarginLeft(marginLeft);
    }

    /**
     * Gets the current left padding width of the image.
     *
     * @return the left padding width, as a {@link UnitValue} object
     */
    public UnitValue getPaddingLeft() {
        return this.getProperty(Property.PADDING_LEFT);
    }

    /**
     * Sets the left padding width of the image.
     *
     * @param value the new left padding width
     * @return this image
     */
    public Image setPaddingLeft(float value) {
        UnitValue paddingUV = UnitValue.createPointValue(value);
        setProperty(Property.PADDING_LEFT, paddingUV);
        return (Image) (Object) this;
    }

    /**
     * Gets the current right padding width of the image.
     *
     * @return the right padding width, as a {@link UnitValue} object
     */
    public UnitValue getPaddingRight() {
        return this.getProperty(Property.PADDING_RIGHT);
    }

    /**
     * Sets the right padding width of the image.
     *
     * @param value the new right padding width
     * @return this image
     */
    public Image setPaddingRight(float value) {
        UnitValue paddingUV = UnitValue.createPointValue(value);
        setProperty(Property.PADDING_RIGHT, paddingUV);
        return (Image) (Object) this;
    }

    /**
     * Gets the current top padding width of the image.
     *
     * @return the top padding width, as a {@link UnitValue} object
     */
    public UnitValue getPaddingTop() {
        return this.getProperty(Property.PADDING_TOP);
    }

    /**
     * Sets the top padding width of the image.
     *
     * @param value the new top padding width
     * @return this image
     */
    public Image setPaddingTop(float value) {
        UnitValue paddingUV = UnitValue.createPointValue(value);
        setProperty(Property.PADDING_TOP, paddingUV);
        return (Image) (Object) this;
    }

    /**
     * Gets the current bottom padding width of the image.
     *
     * @return the bottom padding width, as a {@link UnitValue} object
     */
    public UnitValue getPaddingBottom() {
        return this.getProperty(Property.PADDING_BOTTOM);
    }

    /**
     * Sets the bottom padding width of the image.
     *
     * @param value the new bottom padding width
     * @return this image
     */
    public Image setPaddingBottom(float value) {
        UnitValue paddingUV = UnitValue.createPointValue(value);
        setProperty(Property.PADDING_BOTTOM, paddingUV);
        return (Image) (Object) this;
    }

    /**
     * Sets all paddings around the image to the same width.
     *
     * @param commonPadding the new padding width
     * @return this image
     */
    public Image setPadding(float commonPadding) {
        return setPaddings(commonPadding, commonPadding, commonPadding, commonPadding);
    }

    /**
     * Sets the paddings around the image to a series of new widths.
     *
     * @param paddingTop    the new padding top width
     * @param paddingRight  the new padding right width
     * @param paddingBottom the new padding bottom width
     * @param paddingLeft   the new padding left width
     * @return this image
     */
    public Image setPaddings(float paddingTop, float paddingRight, float paddingBottom, float paddingLeft) {
        setPaddingTop(paddingTop);
        setPaddingRight(paddingRight);
        setPaddingBottom(paddingBottom);
        setPaddingLeft(paddingLeft);
        return this;
    }


    /**
     * Scale the image relative to its default size.
     *
     * @param horizontalScaling the horizontal scaling coefficient. default value 1 = 100%
     * @param verticalScaling   the vertical scaling coefficient. default value 1 = 100%
     * @return this element
     */
    public Image scale(float horizontalScaling, float verticalScaling) {
        setProperty(Property.HORIZONTAL_SCALING, horizontalScaling);
        setProperty(Property.VERTICAL_SCALING, verticalScaling);
        return this;
    }

    /**
     * Scale the image to an absolute size. This method will preserve the
     * width-height ratio of the image.
     *
     * @param fitWidth  the new maximum width of the image
     * @param fitHeight the new maximum height of the image
     * @return this element
     */
    public Image scaleToFit(float fitWidth, float fitHeight) {
        float horizontalScaling = fitWidth / xObject.getWidth();
        float verticalScaling = fitHeight / xObject.getHeight();
        return scale(Math.min(horizontalScaling, verticalScaling), Math.min(horizontalScaling, verticalScaling));
    }

    /**
     * Scale the image to an absolute size. This method will not
     * preserve the width-height ratio of the image.
     *
     * @param fitWidth  the new absolute width of the image
     * @param fitHeight the new absolute height of the image
     * @return this element
     */
    public Image scaleAbsolute(float fitWidth, float fitHeight) {
        float horizontalScaling = fitWidth / xObject.getWidth();
        float verticalScaling = fitHeight / xObject.getHeight();
        return scale(horizontalScaling, verticalScaling);
    }

    /**
     * Sets the autoscale property for both width and height.
     *
     * @param autoScale whether or not to let the image resize automatically
     * @return this image
     */
    public Image setAutoScale(boolean autoScale) {
        if (hasProperty(Property.AUTO_SCALE_WIDTH) && hasProperty(Property.AUTO_SCALE_HEIGHT) && autoScale &&
                ((boolean) this.getProperty(Property.AUTO_SCALE_WIDTH) ||
                        (boolean) this.getProperty(Property.AUTO_SCALE_HEIGHT))) {
            Logger logger = LoggerFactory.getLogger(Image.class);
            logger.warn(IoLogMessageConstant.IMAGE_HAS_AMBIGUOUS_SCALE);
        }
        setProperty(Property.AUTO_SCALE, autoScale);
        return this;
    }

    //TODO(DEVSIX-1659):Remove bugged mention
    /**
     * Sets the autoscale property for the height of the image.
     * Is currently bugged and will not work as expected.
     * @param autoScale whether or not to let the image height resize automatically
     * @return this image
     */
    public Image setAutoScaleHeight(boolean autoScale) {
        if (hasProperty(Property.AUTO_SCALE_WIDTH) && autoScale && (boolean) this.getProperty(Property.AUTO_SCALE_WIDTH)) {
            setProperty(Property.AUTO_SCALE_WIDTH, false);
            setProperty(Property.AUTO_SCALE_HEIGHT, false);
            setProperty(Property.AUTO_SCALE, true);
        } else {
            setProperty(Property.AUTO_SCALE_WIDTH, autoScale);
        }
        return this;
    }

    /**
     * Sets the autoscale property for the width of the image.
     *
     * @param autoScale whether or not to let the image width resize automatically
     * @return this image
     */
    public Image setAutoScaleWidth(boolean autoScale) {
        if (hasProperty(Property.AUTO_SCALE_HEIGHT) && autoScale && (boolean) this.getProperty(Property.AUTO_SCALE_HEIGHT)) {
            setProperty(Property.AUTO_SCALE_WIDTH, false);
            setProperty(Property.AUTO_SCALE_HEIGHT, false);
            setProperty(Property.AUTO_SCALE, true);
        } else {
            setProperty(Property.AUTO_SCALE_WIDTH, autoScale);
        }
        return this;
    }

    /**
     * Sets values for a absolute repositioning of the Element. Also has as a
     * side effect that the Element's {@link Property#POSITION} is changed to
     * {@link LayoutPosition#FIXED fixed}.
     *
     * @param left   horizontal position on the page
     * @param bottom vertical position on the page
     * @return this image.
     */
    public Image setFixedPosition(float left, float bottom) {
        setFixedPosition(left, bottom, getWidth());
        return this;
    }

    /**
     * Sets values for a absolute repositioning of the Element, on a specific
     * page. Also has as a side effect that the Element's {@link
     * Property#POSITION} is changed to {@link LayoutPosition#FIXED fixed}.
     *
     * @param pageNumber the page where the element must be positioned
     * @param left       horizontal position on the page
     * @param bottom     vertical position on the page
     * @return this Element.
     */
    public Image setFixedPosition(int pageNumber, float left, float bottom) {
        setFixedPosition(pageNumber, left, bottom, getWidth());
        return this;
    }

    /**
     * Gets width of the image. It returns width of image or form XObject,
     * not the width set by one of the #setWidth methods
     *
     * @return the original width of the image
     */
    public float getImageWidth() {
        return xObject.getWidth();
    }

    /**
     * Gets height of the image. It returns height of image or form XObject,
     * not the height set by one of the #setHeight methods
     *
     * @return the original height of the image
     */
    public float getImageHeight() {
        return xObject.getHeight();
    }

    /**
     * Sets the height property of the image, measured in points.
     *
     * @param height a value measured in points.
     * @return this image.
     */
    public Image setHeight(float height) {
        UnitValue heightAsUV = UnitValue.createPointValue(height);
        setProperty(Property.HEIGHT, heightAsUV);
        return (Image) (Object) this;
    }

    /**
     * Sets the height property of the image with a {@link UnitValue}.
     *
     * @param height a value measured in points.
     * @return this image.
     */
    public Image setHeight(UnitValue height) {
        setProperty(Property.HEIGHT, height);
        return (Image) (Object) this;
    }

    /**
     * Sets the max-height property of the image, measured in points.
     *
     * @param maxHeight a value measured in points.
     * @return this image.
     */
    public Image setMaxHeight(float maxHeight) {
        UnitValue maxHeightAsUv = UnitValue.createPointValue(maxHeight);
        setProperty(Property.MAX_HEIGHT, maxHeightAsUv);
        return (Image) (Object) this;
    }

    /**
     * Sets the max-height property of the image with a {@link UnitValue}.
     *
     * @param maxHeight a value measured in points.
     * @return this image.
     */
    public Image setMaxHeight(UnitValue maxHeight) {
        setProperty(Property.MAX_HEIGHT, maxHeight);
        return (Image) (Object) this;
    }

    /**
     * Sets the min-height property of the image, measured in points.
     *
     * @param minHeight a value measured in points.
     * @return this image.
     */
    public Image setMinHeight(float minHeight) {
        UnitValue minHeightAsUv = UnitValue.createPointValue(minHeight);
        setProperty(Property.MIN_HEIGHT, minHeightAsUv);
        return (Image) (Object) this;
    }

    /**
     * Sets the min-height property of the image with a {@link UnitValue}.
     *
     * @param minHeight a value measured in points.
     * @return this image.
     */
    public Image setMinHeight(UnitValue minHeight) {
        setProperty(Property.MIN_HEIGHT, minHeight);
        return (Image) (Object) this;
    }

    /**
     * Sets the max-width property of the image, measured in points.
     *
     * @param maxWidth a value measured in points.
     * @return this image.
     */
    public Image setMaxWidth(float maxWidth) {
        UnitValue minHeightAsUv = UnitValue.createPointValue(maxWidth);
        setProperty(Property.MAX_WIDTH, minHeightAsUv);
        return (Image) (Object) this;
    }

    /**
     * Sets the max-width property of the image with a {@link UnitValue}.
     *
     * @param maxWidth a value measured in points.
     * @return this image.
     */
    public Image setMaxWidth(UnitValue maxWidth) {
        setProperty(Property.MAX_WIDTH, maxWidth);
        return (Image) (Object) this;
    }

    /**
     * Sets the min-width property of the image, measured in points.
     *
     * @param minWidth a value measured in points.
     * @return this image.
     */
    public Image setMinWidth(float minWidth) {
        UnitValue minHeightAsUv = UnitValue.createPointValue(minWidth);
        setProperty(Property.MIN_WIDTH, minHeightAsUv);
        return (Image) (Object) this;
    }

    /**
     * Sets the min-width property of the image with a {@link UnitValue}.
     *
     * @param minWidth a value measured in points.
     * @return this image.
     */
    public Image setMinWidth(UnitValue minWidth) {
        setProperty(Property.MIN_WIDTH, minWidth);
        return (Image) (Object) this;
    }

    /**
     * Sets the width property of the image, measured in points.
     *
     * @param width a value measured in points.
     * @return this image.
     */
    public Image setWidth(float width) {
        setProperty(Property.WIDTH, UnitValue.createPointValue(width));
        return (Image) (Object) this;
    }

    /**
     * Sets the width property of the image with a {@link UnitValue}.
     *
     * @param width a {@link UnitValue} object
     * @return this image.
     */
    public Image setWidth(UnitValue width) {
        setProperty(Property.WIDTH, width);
        return (Image) (Object) this;
    }

    /**
     * Gets the width property of the image.
     *
     * @return the width of the element, with a value and a measurement unit.
     * @see UnitValue
     */
    public UnitValue getWidth() {
        return (UnitValue) this.getProperty(Property.WIDTH);
    }


    /**
     * Gets scaled width of the image.
     *
     * @return the current scaled width
     */
    public float getImageScaledWidth() {
        return null == this.getProperty(Property.HORIZONTAL_SCALING) ?
                xObject.getWidth() :
                xObject.getWidth() * (float) this.getProperty(Property.HORIZONTAL_SCALING);
    }

    /**
     * Gets scaled height of the image.
     *
     * @return the current scaled height
     */
    public float getImageScaledHeight() {
        return null == this.getProperty(Property.VERTICAL_SCALING) ?
                xObject.getHeight() :
                xObject.getHeight() * (float) this.getProperty(Property.VERTICAL_SCALING);
    }

    /**
     * Sets an object-fit mode for the image.
     *
     * @param objectFit is the {@link ObjectFit} mode
     * @return this image
     */
    public Image setObjectFit(ObjectFit objectFit) {
        setProperty(Property.OBJECT_FIT, objectFit);
        return this;
    }

    /**
     * Retrieves the {@link ObjectFit} mode for the image.
     *
     * @return an object-fit mode for the image if it was set
     *          and default value {@link ObjectFit#FILL} otherwise
     */
    public ObjectFit getObjectFit() {
        if (hasProperty(Property.OBJECT_FIT)) {
            return (ObjectFit) this.getProperty(Property.OBJECT_FIT);
        } else {
            return ObjectFit.FILL;
        }
    }

    @Override
    public AccessibilityProperties getAccessibilityProperties() {
        if (tagProperties == null) {
            tagProperties = new DefaultAccessibilityProperties(StandardRoles.FIGURE);
        }
        return tagProperties;
    }

    /**
     * Give this element a neutral role. See also {@link AccessibilityProperties#setRole(String)}.
     *
     * @return this Element
     */
    public Image setNeutralRole() {
        this.getAccessibilityProperties().setRole(null);
        return this;
    }

    @Override
    protected IRenderer makeNewRenderer() {
        return new ImageRenderer(this);
    }

    private static ImageData checkImageType(ImageData image) {
        if (image instanceof WmfImageData) {
            throw new PdfException(LayoutExceptionMessageConstant.CANNOT_CREATE_LAYOUT_IMAGE_BY_WMF_IMAGE);
        }
        return image;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy