/*
* $Id: Image.java,v 1.115 2006/02/16 16:17:59 psoares33 Exp $
* $Name: $
*
* Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or any later version.
*
* This library 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 Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
package com.lowagie.text;
import java.awt.Graphics2D;
import java.awt.color.ICC_Profile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Set;
import com.lowagie.text.pdf.PRIndirectReference;
import com.lowagie.text.pdf.PRTokeniser;
import com.lowagie.text.pdf.PdfArray;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfIndirectReference;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfNumber;
import com.lowagie.text.pdf.PdfOCG;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;
import com.lowagie.text.pdf.RandomAccessFileOrArray;
import com.lowagie.text.pdf.codec.BmpImage;
import com.lowagie.text.pdf.codec.CCITTG4Encoder;
import com.lowagie.text.pdf.codec.GifImage;
import com.lowagie.text.pdf.codec.PngImage;
import com.lowagie.text.pdf.codec.TiffImage;
/**
* An Image
is the representation of a graphic element (JPEG, PNG
* or GIF) that has to be inserted into the document
*
* @see Element
* @see Rectangle
*/
public abstract class Image extends Rectangle implements Element,
MarkupAttributes {
// static membervariables
/** this is a kind of image alignment. */
public static final int DEFAULT = 0;
/** this is a kind of image alignment. */
public static final int RIGHT = 2;
/** this is a kind of image alignment. */
public static final int LEFT = 0;
/** this is a kind of image alignment. */
public static final int MIDDLE = 1;
/** this is a kind of image alignment. */
public static final int TEXTWRAP = 4;
/** this is a kind of image alignment. */
public static final int UNDERLYING = 8;
/** This represents a coordinate in the transformation matrix. */
public static final int AX = 0;
/** This represents a coordinate in the transformation matrix. */
public static final int AY = 1;
/** This represents a coordinate in the transformation matrix. */
public static final int BX = 2;
/** This represents a coordinate in the transformation matrix. */
public static final int BY = 3;
/** This represents a coordinate in the transformation matrix. */
public static final int CX = 4;
/** This represents a coordinate in the transformation matrix. */
public static final int CY = 5;
/** This represents a coordinate in the transformation matrix. */
public static final int DX = 6;
/** This represents a coordinate in the transformation matrix. */
public static final int DY = 7;
/** type of image */
public static final int ORIGINAL_NONE = 0;
/** type of image */
public static final int ORIGINAL_JPEG = 1;
/** type of image */
public static final int ORIGINAL_PNG = 2;
/** type of image */
public static final int ORIGINAL_GIF = 3;
/** type of image */
public static final int ORIGINAL_BMP = 4;
/** type of image */
public static final int ORIGINAL_TIFF = 5;
/** type of image */
public static final int ORIGINAL_WMF = 6;
/** type of image */
public static final int ORIGINAL_PS = 7;
/** Image color inversion */
protected boolean invert = false;
/** The imagetype. */
protected int type;
/** The URL of the image. */
protected URL url;
/** The raw data of the image. */
protected byte rawData[];
/** The template to be treated as an image. */
protected PdfTemplate template[] = new PdfTemplate[1];
/** The alignment of the Image. */
protected int alignment;
/** Text that can be shown instead of the image. */
protected String alt;
/** This is the absolute X-position of the image. */
protected float absoluteX = Float.NaN;
/** This is the absolute Y-position of the image. */
protected float absoluteY = Float.NaN;
/** This is the width of the image without rotation. */
protected float plainWidth;
/** This is the width of the image without rotation. */
protected float plainHeight;
/** This is the scaled width of the image taking rotation into account. */
protected float scaledWidth;
/** This is the original height of the image taking rotation into account. */
protected float scaledHeight;
/** This is the rotation of the image. */
protected float rotation;
/** this is the colorspace of a jpeg-image. */
protected int colorspace = -1;
/**
* this is the bits per component of the raw image. It also flags a CCITT
* image.
*/
protected int bpc = 1;
/** this is the transparency information of the raw image */
protected int transparency[];
// for the moment these variables are only used for Images in class Table
// code contributed by Pelikan Stephan
/** the indentation to the left. */
protected float indentationLeft = 0;
/** the indentation to the right. */
protected float indentationRight = 0;
// serial stamping
protected Long mySerialId = getSerialId();
static long serialId = 0;
/** Holds value of property dpiX. */
protected int dpiX = 0;
/** Holds value of property dpiY. */
protected int dpiY = 0;
protected boolean mask = false;
protected Image imageMask;
/** Holds value of property interpolation. */
protected boolean interpolation;
/** if the annotation is not null the image will be clickable. */
protected Annotation annotation = null;
/** Contains extra markupAttributes */
protected Properties markupAttributes;
/** ICC Profile attached */
protected ICC_Profile profile = null;
/** Holds value of property deflated. */
protected boolean deflated = false;
private PdfDictionary additional = null;
/** Holds value of property smask. */
private boolean smask;
/** Holds value of property XYRatio. */
private float XYRatio = 0;
/** Holds value of property originalType. */
protected int originalType = ORIGINAL_NONE;
/** Holds value of property originalData. */
protected byte[] originalData;
/** The spacing before the image. */
protected float spacingBefore;
/** The spacing after the image. */
protected float spacingAfter;
/**
* Holds value of property widthPercentage.
*/
private float widthPercentage = 100;
protected PdfOCG layer;
/**
* Holds value of property initialRotation.
*/
private float initialRotation;
// constructors
/**
* Constructs an Image
-object, using an url .
*
* @param url
* the URL
where the image can be found.
*/
public Image(URL url) {
super(0, 0);
this.url = url;
this.alignment = DEFAULT;
rotation = 0;
}
/**
* Constructs an Image
-object, using an url .
*
* @param image
* another Image object.
*/
protected Image(Image image) {
super(image);
this.type = image.type;
this.url = image.url;
this.alignment = image.alignment;
this.alt = image.alt;
this.absoluteX = image.absoluteX;
this.absoluteY = image.absoluteY;
this.plainWidth = image.plainWidth;
this.plainHeight = image.plainHeight;
this.scaledWidth = image.scaledWidth;
this.scaledHeight = image.scaledHeight;
this.rotation = image.rotation;
this.colorspace = image.colorspace;
this.rawData = image.rawData;
this.template = image.template;
this.bpc = image.bpc;
this.transparency = image.transparency;
this.mySerialId = image.mySerialId;
this.invert = image.invert;
this.dpiX = image.dpiX;
this.dpiY = image.dpiY;
this.mask = image.mask;
this.imageMask = image.imageMask;
this.interpolation = image.interpolation;
this.annotation = image.annotation;
this.markupAttributes = image.markupAttributes;
this.profile = image.profile;
this.deflated = image.deflated;
this.additional = image.additional;
this.smask = image.smask;
this.XYRatio = image.XYRatio;
this.originalData = image.originalData;
this.originalType = image.originalType;
this.spacingAfter = image.spacingAfter;
this.spacingBefore = image.spacingBefore;
this.widthPercentage = image.widthPercentage;
this.layer = image.layer;
this.initialRotation = image.initialRotation;
this.directReference = image.directReference;
}
/**
* gets an instance of an Image
*
* @param image
* an Image object
* @return a new Image object
*/
public static Image getInstance(Image image) {
if (image == null)
return null;
try {
Class cs = image.getClass();
Constructor constructor = cs
.getDeclaredConstructor(new Class[] { Image.class });
return (Image) constructor.newInstance(new Object[] { image });
} catch (Exception e) {
throw new ExceptionConverter(e);
}
}
/**
* Gets an instance of an Image.
*
* @param url
* an URL
* @return an Image
* @throws BadElementException
* @throws MalformedURLException
* @throws IOException
*/
public static Image getInstance(URL url) throws BadElementException,
MalformedURLException, IOException {
InputStream is = null;
try {
is = url.openStream();
int c1 = is.read();
int c2 = is.read();
int c3 = is.read();
int c4 = is.read();
is.close();
is = null;
if (c1 == 'G' && c2 == 'I' && c3 == 'F') {
GifImage gif = new GifImage(url);
Image img = gif.getImage(1);
return img;
}
if (c1 == 0xFF && c2 == 0xD8) {
return new Jpeg(url);
}
if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1]
&& c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
return PngImage.getImage(url);
}
if (c1 == '%' && c2 == '!' && c3 == 'P' && c4 == 'S') {
return new ImgPostscript(url);
}
if (c1 == 0xD7 && c2 == 0xCD) {
return new ImgWMF(url);
}
if (c1 == 'B' && c2 == 'M') {
return BmpImage.getImage(url);
}
if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) {
RandomAccessFileOrArray ra = null;
try {
if (url.getProtocol().equals("file")) {
String file = url.getFile();
file = unEscapeURL(file);
ra = new RandomAccessFileOrArray(file);
} else
ra = new RandomAccessFileOrArray(url);
Image img = TiffImage.getTiffImage(ra, 1);
img.url = url;
return img;
} finally {
if (ra != null)
ra.close();
}
}
throw new IOException(url.toString()
+ " is not a recognized imageformat.");
} finally {
if (is != null) {
is.close();
}
}
}
/**
* gets an instance of an Image
*
* @param imgb
* raw image date
* @return an Image object
* @throws BadElementException
* @throws MalformedURLException
* @throws IOException
*/
public static Image getInstance(byte imgb[]) throws BadElementException,
MalformedURLException, IOException {
InputStream is = null;
try {
is = new java.io.ByteArrayInputStream(imgb);
int c1 = is.read();
int c2 = is.read();
int c3 = is.read();
int c4 = is.read();
is.close();
is = null;
if (c1 == 'G' && c2 == 'I' && c3 == 'F') {
GifImage gif = new GifImage(imgb);
return gif.getImage(1);
}
if (c1 == 0xFF && c2 == 0xD8) {
return new Jpeg(imgb);
}
if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1]
&& c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
return PngImage.getImage(imgb);
}
if (c1 == '%' && c2 == '!' && c3 == 'P' && c4 == 'S') {
return new ImgPostscript(imgb);
}
if (c1 == 0xD7 && c2 == 0xCD) {
return new ImgWMF(imgb);
}
if (c1 == 'B' && c2 == 'M') {
return BmpImage.getImage(imgb);
}
if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) {
RandomAccessFileOrArray ra = null;
try {
ra = new RandomAccessFileOrArray(imgb);
Image img = TiffImage.getTiffImage(ra, 1);
if (img.getOriginalData() == null)
img.setOriginalData(imgb);
return img;
} finally {
if (ra != null)
ra.close();
}
}
throw new IOException(
"The byte array is not a recognized imageformat.");
} finally {
if (is != null) {
is.close();
}
}
}
/**
* Gets an instance of an Image from a java.awt.Image.
*
* @param image
* the java.awt.Image
to convert
* @param color
* if different from null
the transparency pixels
* are replaced by this color
* @param forceBW
* if true
the image is treated as black and white
* @return an object of type ImgRaw
* @throws BadElementException
* on error
* @throws IOException
* on error
*/
public static Image getInstance(java.awt.Image image, java.awt.Color color,
boolean forceBW) throws BadElementException, IOException {
java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber(image,
0, 0, -1, -1, true);
try {
pg.grabPixels();
} catch (InterruptedException e) {
throw new IOException(
"java.awt.Image Interrupted waiting for pixels!");
}
if ((pg.getStatus() & java.awt.image.ImageObserver.ABORT) != 0) {
throw new IOException("java.awt.Image fetch aborted or errored");
}
int w = pg.getWidth();
int h = pg.getHeight();
int[] pixels = (int[]) pg.getPixels();
if (forceBW) {
int byteWidth = (w / 8) + ((w & 7) != 0 ? 1 : 0);
byte[] pixelsByte = new byte[byteWidth * h];
int index = 0;
int size = h * w;
int transColor = 1;
if (color != null) {
transColor = (color.getRed() + color.getGreen()
+ color.getBlue() < 384) ? 0 : 1;
}
int transparency[] = null;
int cbyte = 0x80;
int wMarker = 0;
int currByte = 0;
if (color != null) {
for (int j = 0; j < size; j++) {
int alpha = (pixels[j] >> 24) & 0xff;
if (alpha < 250) {
if (transColor == 1)
currByte |= cbyte;
} else {
if ((pixels[j] & 0x888) != 0)
currByte |= cbyte;
}
cbyte >>= 1;
if (cbyte == 0 || wMarker + 1 >= w) {
pixelsByte[index++] = (byte) currByte;
cbyte = 0x80;
currByte = 0;
}
++wMarker;
if (wMarker >= w)
wMarker = 0;
}
} else {
for (int j = 0; j < size; j++) {
if (transparency == null) {
int alpha = (pixels[j] >> 24) & 0xff;
if (alpha == 0) {
transparency = new int[2];
transparency[0] = transparency[1] = ((pixels[j] & 0x888) != 0) ? 1
: 0;
}
}
if ((pixels[j] & 0x888) != 0)
currByte |= cbyte;
cbyte >>= 1;
if (cbyte == 0 || wMarker + 1 >= w) {
pixelsByte[index++] = (byte) currByte;
cbyte = 0x80;
currByte = 0;
}
++wMarker;
if (wMarker >= w)
wMarker = 0;
}
}
return Image.getInstance(w, h, 1, 1, pixelsByte, transparency);
} else {
byte[] pixelsByte = new byte[w * h * 3];
byte[] smask = null;
int index = 0;
int size = h * w;
int red = 255;
int green = 255;
int blue = 255;
if (color != null) {
red = color.getRed();
green = color.getGreen();
blue = color.getBlue();
}
int transparency[] = null;
if (color != null) {
for (int j = 0; j < size; j++) {
int alpha = (pixels[j] >> 24) & 0xff;
if (alpha < 250) {
pixelsByte[index++] = (byte) red;
pixelsByte[index++] = (byte) green;
pixelsByte[index++] = (byte) blue;
} else {
pixelsByte[index++] = (byte) ((pixels[j] >> 16) & 0xff);
pixelsByte[index++] = (byte) ((pixels[j] >> 8) & 0xff);
pixelsByte[index++] = (byte) ((pixels[j]) & 0xff);
}
}
} else {
int transparentPixel = 0;
smask = new byte[w * h];
boolean shades = false;
for (int j = 0; j < size; j++) {
byte alpha = smask[j] = (byte) ((pixels[j] >> 24) & 0xff);
/* bugfix by Chris Nokleberg */
if (!shades) {
if (alpha != 0 && alpha != -1) {
shades = true;
} else if (transparency == null) {
if (alpha == 0) {
transparentPixel = pixels[j] & 0xffffff;
transparency = new int[6];
transparency[0] = transparency[1] = (transparentPixel >> 16) & 0xff;
transparency[2] = transparency[3] = (transparentPixel >> 8) & 0xff;
transparency[4] = transparency[5] = transparentPixel & 0xff;
}
} else if ((pixels[j] & 0xffffff) != transparentPixel) {
shades = true;
}
}
pixelsByte[index++] = (byte) ((pixels[j] >> 16) & 0xff);
pixelsByte[index++] = (byte) ((pixels[j] >> 8) & 0xff);
pixelsByte[index++] = (byte) ((pixels[j]) & 0xff);
}
if (shades)
transparency = null;
else
smask = null;
}
Image img = Image.getInstance(w, h, 3, 8, pixelsByte, transparency);
if (smask != null) {
Image sm = Image.getInstance(w, h, 1, 8, smask);
try {
sm.makeMask();
img.setImageMask(sm);
} catch (DocumentException de) {
throw new ExceptionConverter(de);
}
}
return img;
}
}
/**
* Gets an instance of an Image from a java.awt.Image.
*
* @param image
* the java.awt.Image
to convert
* @param color
* if different from null
the transparency pixels
* are replaced by this color
* @return an object of type ImgRaw
* @throws BadElementException
* on error
* @throws IOException
* on error
*/
public static Image getInstance(java.awt.Image image, java.awt.Color color)
throws BadElementException, IOException {
return Image.getInstance(image, color, false);
}
/**
* Gets an instance of a Image from a java.awt.Image.
* The image is added as a JPEG with a userdefined quality.
*
* @param writer
* the PdfWriter
object to which the image will be added
* @param awtImage
* the java.awt.Image
to convert
* @param quality
* a float value between 0 and 1
* @return an object of type PdfTemplate
* @throws BadElementException
* on error
* @throws IOException
*/
public static Image getInstance(PdfWriter writer, java.awt.Image awtImage, float quality) throws BadElementException, IOException {
return getInstance(new PdfContentByte(writer), awtImage, quality);
}
/**
* Gets an instance of a Image from a java.awt.Image.
* The image is added as a JPEG with a userdefined quality.
*
* @param cb
* the PdfContentByte
object to which the image will be added
* @param awtImage
* the java.awt.Image
to convert
* @param quality
* a float value between 0 and 1
* @return an object of type PdfTemplate
* @throws BadElementException
* on error
* @throws IOException
*/
public static Image getInstance(PdfContentByte cb, java.awt.Image awtImage, float quality) throws BadElementException, IOException {
java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber(awtImage,
0, 0, -1, -1, true);
try {
pg.grabPixels();
} catch (InterruptedException e) {
throw new IOException(
"java.awt.Image Interrupted waiting for pixels!");
}
if ((pg.getStatus() & java.awt.image.ImageObserver.ABORT) != 0) {
throw new IOException("java.awt.Image fetch aborted or errored");
}
int w = pg.getWidth();
int h = pg.getHeight();
PdfTemplate tp = cb.createTemplate(w, h);
Graphics2D g2d = tp.createGraphics(w, h, true, quality);
g2d.drawImage(awtImage, 0, 0, null);
g2d.dispose();
return getInstance(tp);
}
/**
* Gets an instance of an Image.
*
* @param filename
* a filename
* @return an object of type Gif
,Jpeg
or
* Png
* @throws BadElementException
* @throws MalformedURLException
* @throws IOException
*/
public static Image getInstance(String filename)
throws BadElementException, MalformedURLException, IOException {
return getInstance(toURL(filename));
}
/**
* Gets an instance of an Image in raw mode.
*
* @param width
* the width of the image in pixels
* @param height
* the height of the image in pixels
* @param components
* 1,3 or 4 for GrayScale, RGB and CMYK
* @param data
* the image data
* @param bpc
* bits per component
* @return an object of type ImgRaw
* @throws BadElementException
* on error
*/
public static Image getInstance(int width, int height, int components,
int bpc, byte data[]) throws BadElementException {
return Image.getInstance(width, height, components, bpc, data, null);
}
/**
* Reuses an existing image.
* @param ref the reference to the image dictionary
* @throws BadElementException on error
* @return the image
*/
public static Image getInstance(PRIndirectReference ref) throws BadElementException {
PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObjectRelease(ref);
int width = ((PdfNumber)PdfReader.getPdfObjectRelease(dic.get(PdfName.WIDTH))).intValue();
int height = ((PdfNumber)PdfReader.getPdfObjectRelease(dic.get(PdfName.HEIGHT))).intValue();
Image imask = null;
PdfObject obj = dic.get(PdfName.SMASK);
if (obj != null && obj.isIndirect()) {
imask = getInstance((PRIndirectReference)obj);
}
else {
obj = dic.get(PdfName.MASK);
if (obj != null && obj.isIndirect()) {
PdfObject obj2 = PdfReader.getPdfObjectRelease(obj);
if (obj2 instanceof PdfDictionary)
imask = getInstance((PRIndirectReference)obj);
}
}
Image img = new ImgRaw(width, height, 1, 1, null);
img.imageMask = imask;
img.directReference = ref;
return img;
}
/**
* gets an instance of an Image
*
* @param template
* a PdfTemplate that has to be wrapped in an Image object
* @return an Image object
* @throws BadElementException
*/
public static Image getInstance(PdfTemplate template)
throws BadElementException {
return new ImgTemplate(template);
}
/**
* Creates an Image with CCITT G3 or G4 compression. It assumes that the
* data bytes are already compressed.
*
* @param width
* the exact width of the image
* @param height
* the exact height of the image
* @param reverseBits
* reverses the bits in data
. Bit 0 is swapped
* with bit 7 and so on
* @param typeCCITT
* the type of compression in data
. It can be
* CCITTG4, CCITTG31D, CCITTG32D
* @param parameters
* parameters associated with this stream. Possible values are
* CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and
* CCITT_ENDOFBLOCK or a combination of them
* @param data
* the image data
* @return an Image object
* @throws BadElementException
* on error
*/
public static Image getInstance(int width, int height, boolean reverseBits,
int typeCCITT, int parameters, byte[] data)
throws BadElementException {
return Image.getInstance(width, height, reverseBits, typeCCITT,
parameters, data, null);
}
/**
* Creates an Image with CCITT G3 or G4 compression. It assumes that the
* data bytes are already compressed.
*
* @param width
* the exact width of the image
* @param height
* the exact height of the image
* @param reverseBits
* reverses the bits in data
. Bit 0 is swapped
* with bit 7 and so on
* @param typeCCITT
* the type of compression in data
. It can be
* CCITTG4, CCITTG31D, CCITTG32D
* @param parameters
* parameters associated with this stream. Possible values are
* CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and
* CCITT_ENDOFBLOCK or a combination of them
* @param data
* the image data
* @param transparency
* transparency information in the Mask format of the image
* dictionary
* @return an Image object
* @throws BadElementException
* on error
*/
public static Image getInstance(int width, int height, boolean reverseBits,
int typeCCITT, int parameters, byte[] data, int transparency[])
throws BadElementException {
if (transparency != null && transparency.length != 2)
throw new BadElementException(
"Transparency length must be equal to 2 with CCITT images");
Image img = new ImgCCITT(width, height, reverseBits, typeCCITT,
parameters, data);
img.transparency = transparency;
return img;
}
/**
* Gets an instance of an Image in raw mode.
*
* @param width
* the width of the image in pixels
* @param height
* the height of the image in pixels
* @param components
* 1,3 or 4 for GrayScale, RGB and CMYK
* @param data
* the image data
* @param bpc
* bits per component
* @param transparency
* transparency information in the Mask format of the image
* dictionary
* @return an object of type ImgRaw
* @throws BadElementException
* on error
*/
public static Image getInstance(int width, int height, int components,
int bpc, byte data[], int transparency[])
throws BadElementException {
if (transparency != null && transparency.length != components * 2)
throw new BadElementException(
"Transparency length must be equal to (componentes * 2)");
if (components == 1 && bpc == 1) {
byte g4[] = CCITTG4Encoder.compress(data, width, height);
return Image.getInstance(width, height, false, Image.CCITTG4,
Image.CCITT_BLACKIS1, g4, transparency);
}
Image img = new ImgRaw(width, height, components, bpc, data);
img.transparency = transparency;
return img;
}
/**
* Returns an Image
that has been constructed taking in
* account the value of some attributes .
*
* @param attributes
* Some attributes
* @return an Image
* @throws BadElementException
* @throws MalformedURLException
* @throws IOException
*/
public static Image getInstance(Properties attributes)
throws BadElementException, MalformedURLException, IOException {
String value = (String) attributes.remove(ElementTags.URL);
if (value == null)
throw new MalformedURLException("The URL of the image is missing.");
Image image = Image.getInstance(value);
int align = 0;
if ((value = (String) attributes.remove(ElementTags.ALIGN)) != null) {
if (ElementTags.ALIGN_LEFT.equalsIgnoreCase(value))
align |= Image.LEFT;
else if (ElementTags.ALIGN_RIGHT.equalsIgnoreCase(value))
align |= Image.RIGHT;
else if (ElementTags.ALIGN_MIDDLE.equalsIgnoreCase(value))
align |= Image.MIDDLE;
}
if ((value = (String) attributes.remove(ElementTags.UNDERLYING)) != null) {
if (new Boolean(value).booleanValue())
align |= Image.UNDERLYING;
}
if ((value = (String) attributes.remove(ElementTags.TEXTWRAP)) != null) {
if (new Boolean(value).booleanValue())
align |= Image.TEXTWRAP;
}
image.setAlignment(align);
if ((value = (String) attributes.remove(ElementTags.ALT)) != null) {
image.setAlt(value);
}
String x;
String y;
if (((x = (String) attributes.remove(ElementTags.ABSOLUTEX)) != null)
&& ((y = (String) attributes.remove(ElementTags.ABSOLUTEY)) != null)) {
image.setAbsolutePosition(Float.valueOf(x + "f").floatValue(),
Float.valueOf(y + "f").floatValue());
}
if ((value = (String) attributes.remove(ElementTags.PLAINWIDTH)) != null) {
image.scaleAbsoluteWidth(Float.valueOf(value + "f").floatValue());
}
if ((value = (String) attributes.remove(ElementTags.PLAINHEIGHT)) != null) {
image.scaleAbsoluteHeight(Float.valueOf(value + "f").floatValue());
}
if ((value = (String) attributes.remove(ElementTags.ROTATION)) != null) {
image.setRotation(Float.valueOf(value + "f").floatValue());
}
if (attributes.size() > 0)
image.setMarkupAttributes(attributes);
return image;
}
// methods to set information
/**
* Sets the alignment for the image.
*
* @param alignment
* the alignment
*/
public void setAlignment(int alignment) {
this.alignment = alignment;
}
/**
* Sets the alternative information for the image.
*
* @param alt
* the alternative information
*/
public void setAlt(String alt) {
this.alt = alt;
}
/**
* Sets the absolute position of the Image
.
*
* @param absoluteX
* @param absoluteY
*/
public void setAbsolutePosition(float absoluteX, float absoluteY) {
this.absoluteX = absoluteX;
this.absoluteY = absoluteY;
}
/**
* Scale the image to an absolute width and an absolute height.
*
* @param newWidth
* the new width
* @param newHeight
* the new height
*/
public void scaleAbsolute(float newWidth, float newHeight) {
plainWidth = newWidth;
plainHeight = newHeight;
float[] matrix = matrix();
scaledWidth = matrix[DX] - matrix[CX];
scaledHeight = matrix[DY] - matrix[CY];
}
/**
* Scale the image to an absolute width.
*
* @param newWidth
* the new width
*/
public void scaleAbsoluteWidth(float newWidth) {
plainWidth = newWidth;
float[] matrix = matrix();
scaledWidth = matrix[DX] - matrix[CX];
scaledHeight = matrix[DY] - matrix[CY];
}
/**
* Scale the image to an absolute height.
*
* @param newHeight
* the new height
*/
public void scaleAbsoluteHeight(float newHeight) {
plainHeight = newHeight;
float[] matrix = matrix();
scaledWidth = matrix[DX] - matrix[CX];
scaledHeight = matrix[DY] - matrix[CY];
}
/**
* Scale the image to a certain percentage.
*
* @param percent
* the scaling percentage
*/
public void scalePercent(float percent) {
scalePercent(percent, percent);
}
/**
* Scale the width and height of an image to a certain percentage.
*
* @param percentX
* the scaling percentage of the width
* @param percentY
* the scaling percentage of the height
*/
public void scalePercent(float percentX, float percentY) {
plainWidth = (width() * percentX) / 100f;
plainHeight = (height() * percentY) / 100f;
float[] matrix = matrix();
scaledWidth = matrix[DX] - matrix[CX];
scaledHeight = matrix[DY] - matrix[CY];
}
/**
* Scales the image so that it fits a certain width and height.
*
* @param fitWidth
* the width to fit
* @param fitHeight
* the height to fit
*/
public void scaleToFit(float fitWidth, float fitHeight) {
scalePercent(100);
float percentX = (fitWidth * 100) / scaledWidth();
float percentY = (fitHeight * 100) / scaledHeight();
scalePercent(percentX < percentY ? percentX : percentY);
}
/**
* Gets the current image rotation in radians.
* @return the current image rotation in radians
*/
public float getImageRotation() {
float rot = (float) ((rotation - initialRotation) % (2.0 * Math.PI));
if (rot < 0) {
rot += 2.0 * Math.PI; //__IDS__
}
return rot;
}
/**
* Sets the rotation of the image in radians.
*
* @param r
* rotation in radians
*/
public void setRotation(float r) {
double d = Math.PI; //__IDS__
rotation = (float) ((r + initialRotation) % (2.0 * d)); //__IDS__
if (rotation < 0) {
rotation += 2.0 * d; //__IDS__
}
float[] matrix = matrix();
scaledWidth = matrix[DX] - matrix[CX];
scaledHeight = matrix[DY] - matrix[CY];
}
/**
* Sets the rotation of the image in degrees.
*
* @param deg
* rotation in degrees
*/
public void setRotationDegrees(float deg) {
double d = Math.PI; //__IDS__
setRotation(deg / 180 * (float) d); //__IDS__
}
/**
* Sets the annotation of this Image.
*
* @param annotation
* the annotation
*/
public void setAnnotation(Annotation annotation) {
this.annotation = annotation;
}
/**
* Gets the annotation.
*
* @return the annotation that is linked to this image
*/
public Annotation annotation() {
return annotation;
}
// methods to retrieve information
/**
* Gets the bpc for the image.
*
* Remark: this only makes sense for Images of the type RawImage
*
.
*
* @return a bpc value
*/
public int bpc() {
return bpc;
}
/**
* Gets the raw data for the image.
*
* Remark: this only makes sense for Images of the type RawImage
*
.
*
* @return the raw data
*/
public byte[] rawData() {
return rawData;
}
/**
* Gets the template to be used as an image.
*
* Remark: this only makes sense for Images of the type ImgTemplate
*
.
*
* @return the template
*/
public PdfTemplate templateData() {
return template[0];
}
/**
* Sets data from a PdfTemplate
*
* @param template
* the template with the content
*/
public void setTemplateData(PdfTemplate template) {
this.template[0] = template;
}
/**
* Checks if the Images
has to be added at an absolute
* position.
*
* @return a boolean
*/
public boolean hasAbsolutePosition() {
return !Float.isNaN(absoluteY);
}
/**
* Checks if the Images
has to be added at an absolute X
* position.
*
* @return a boolean
*/
public boolean hasAbsoluteX() {
return !Float.isNaN(absoluteX);
}
/**
* Returns the absolute X position.
*
* @return a position
*/
public float absoluteX() {
return absoluteX;
}
/**
* Returns the absolute Y position.
*
* @return a position
*/
public float absoluteY() {
return absoluteY;
}
/**
* Returns the type.
*
* @return a type
*/
public int type() {
return type;
}
/**
* Returns true
if the image is a Jpeg
* -object.
*
* @return a boolean
*/
public boolean isJpeg() {
return type == JPEG;
}
/**
* Returns true
if the image is a ImgRaw
* -object.
*
* @return a boolean
*/
public boolean isImgRaw() {
return type == IMGRAW;
}
/**
* Returns true
if the image is an ImgTemplate
* -object.
*
* @return a boolean
*/
public boolean isImgTemplate() {
return type == IMGTEMPLATE;
}
/**
* Gets the String
-representation of the reference to the
* image.
*
* @return a String
*/
public URL url() {
return url;
}
/**
* Gets the alignment for the image.
*
* @return a value
*/
public int alignment() {
return alignment;
}
/**
* Gets the alternative text for the image.
*
* @return a String
*/
public String alt() {
return alt;
}
/**
* Gets the scaled width of the image.
*
* @return a value
*/
public float scaledWidth() {
return scaledWidth;
}
/**
* Gets the scaled height of the image.
*
* @return a value
*/
public float scaledHeight() {
return scaledHeight;
}
/**
* Gets the colorspace for the image.
*
* Remark: this only makes sense for Images of the type Jpeg
.
*
* @return a colorspace value
*/
public int colorspace() {
return colorspace;
}
/**
* Returns the transformation matrix of the image.
*
* @return an array [AX, AY, BX, BY, CX, CY, DX, DY]
*/
public float[] matrix() {
float[] matrix = new float[8];
float cosX = (float) Math.cos(rotation);
float sinX = (float) Math.sin(rotation);
matrix[AX] = plainWidth * cosX;
matrix[AY] = plainWidth * sinX;
matrix[BX] = (-plainHeight) * sinX;
matrix[BY] = plainHeight * cosX;
if (rotation < Math.PI / 2f) {
matrix[CX] = matrix[BX];
matrix[CY] = 0;
matrix[DX] = matrix[AX];
matrix[DY] = matrix[AY] + matrix[BY];
} else if (rotation < Math.PI) {
matrix[CX] = matrix[AX] + matrix[BX];
matrix[CY] = matrix[BY];
matrix[DX] = 0;
matrix[DY] = matrix[AY];
} else if (rotation < Math.PI * 1.5f) {
matrix[CX] = matrix[AX];
matrix[CY] = matrix[AY] + matrix[BY];
matrix[DX] = matrix[BX];
matrix[DY] = 0;
} else {
matrix[CX] = 0;
matrix[CY] = matrix[AY];
matrix[DX] = matrix[AX] + matrix[BX];
matrix[DY] = matrix[BY];
}
return matrix;
}
/**
* This method is an alternative for the InputStream.skip()
* -method that doesn't seem to work properly for big values of size
*
.
*
* @param is
* the InputStream
* @param size
* the number of bytes to skip
* @throws IOException
*/
static public void skip(InputStream is, int size) throws IOException {
long n;
while (size > 0) {
n = is.skip(size);
if (n <= 0)
break;
size -= n;
}
}
private static String excUri = " <>#%\"{}[]|\\\u005E\u0060";
private static String[] excUriEsc = {"%20", "%3C", "%3E", "%23", "%25", "%22", "%7B", "%7D", "%5B", "%5D", "%7C", "%5C", "%5E", "%60"};
/**
* Holds value of property directReference.
*/
private PdfIndirectReference directReference;
/**
* This method makes a valid URL from a given filename.
*
* This method makes the conversion of this library from the JAVA 2 platform
* to a JDK1.1.x-version easier.
*
* @param filename
* a given filename
* @return a valid URL
* @throws MalformedURLException
*/
public static URL toURL(String filename) throws MalformedURLException {
if (filename.startsWith("file:/") || filename.startsWith("http://")
|| filename.startsWith("https://")
|| filename.startsWith("jar:")) {
return new URL(filename);
}
File f = new File(filename);
String path = f.getAbsolutePath();
if (File.separatorChar != '/') {
path = path.replace(File.separatorChar, '/');
}
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.endsWith("/") && f.isDirectory()) {
path = path + "/";
}
char[] t = path.toCharArray();
StringBuffer sb = new StringBuffer();
for (int k = 0; k < t.length; ++k) {
char c = t[k];
int a = excUri.indexOf(c);
if (a >= 0)
sb.append(excUriEsc[a]);
else
sb.append(c);
}
return new URL("file", "", sb.toString());
}
/**
* Unescapes an URL. All the "%xx" are replaced by the 'xx' hex char value.
* @param src the url to unescape
* @return the eunescaped value
*/
public static String unEscapeURL(String src) {
StringBuffer bf = new StringBuffer();
char[] s = src.toCharArray();
for (int k = 0; k < s.length; ++k) {
char c = s[k];
if (c == '%') {
if (k + 2 >= s.length) {
bf.append(c);
continue;
}
int a0 = PRTokeniser.getHex((int)s[k + 1]);
int a1 = PRTokeniser.getHex((int)s[k + 2]);
if (a0 < 0 || a1 < 0) {
bf.append(c);
continue;
}
bf.append((char)(a0 * 16 + a1));
k += 2;
}
else
bf.append(c);
}
return bf.toString();
}
/**
* Returns the transparency.
*
* @return the transparency values
*/
public int[] getTransparency() {
return transparency;
}
/**
* Sets the transparency values
*
* @param transparency
* the transparency values
*/
public void setTransparency(int transparency[]) {
this.transparency = transparency;
}
/**
* Checks if a given tag corresponds with this object.
*
* @param tag
* the given tag
* @return true if the tag corresponds
*/
public static boolean isTag(String tag) {
return ElementTags.IMAGE.equals(tag);
}
/**
* Gets the plain width of the image.
*
* @return a value
*/
public float plainWidth() {
return plainWidth;
}
/**
* Gets the plain height of the image.
*
* @return a value
*/
public float plainHeight() {
return plainHeight;
}
static protected synchronized Long getSerialId() {
++serialId;
return new Long(serialId);
}
/**
* Returns a serial id for the Image (reuse the same image more than once)
*
* @return a serialId
*/
public Long getMySerialId() {
return mySerialId;
}
/**
* Gets the dots-per-inch in the X direction. Returns 0 if not available.
*
* @return the dots-per-inch in the X direction
*/
public int getDpiX() {
return dpiX;
}
/**
* Gets the dots-per-inch in the Y direction. Returns 0 if not available.
*
* @return the dots-per-inch in the Y direction
*/
public int getDpiY() {
return dpiY;
}
/**
* Sets the dots per inch value
*
* @param dpiX
* dpi for x coordinates
* @param dpiY
* dpi for y coordinates
*/
public void setDpi(int dpiX, int dpiY) {
this.dpiX = dpiX;
this.dpiY = dpiY;
}
/**
* Returns true
if this Image
has the
* requisites to be a mask.
*
* @return true
if this Image
can be a mask
*/
public boolean isMaskCandidate() {
if (type == IMGRAW) {
if (bpc > 0xff)
return true;
}
return colorspace == 1;
}
/**
* Make this Image
a mask.
*
* @throws DocumentException
* if this Image
can not be a mask
*/
public void makeMask() throws DocumentException {
if (!isMaskCandidate())
throw new DocumentException("This image can not be an image mask.");
mask = true;
}
/**
* Sets the explicit masking.
*
* @param mask
* the mask to be applied
* @throws DocumentException
* on error
*/
public void setImageMask(Image mask) throws DocumentException {
if (this.mask)
throw new DocumentException(
"An image mask cannot contain another image mask.");
if (!mask.mask)
throw new DocumentException(
"The image mask is not a mask. Did you do makeMask()?");
imageMask = mask;
smask = (mask.bpc > 1 && mask.bpc <= 8);
}
/**
* Gets the explicit masking.
*
* @return the explicit masking
*/
public Image getImageMask() {
return imageMask;
}
/**
* Returns true
if this Image
is a mask.
*
* @return true
if this Image
is a mask
*/
public boolean isMask() {
return mask;
}
/**
* Inverts the meaning of the bits of a mask.
*
* @param invert
* true
to invert the meaning of the bits of a
* mask
*/
public void setInvertMask(boolean invert) {
this.invert = invert;
}
/**
* Returns true
if the bits are to be inverted in the mask.
*
* @return true
if the bits are to be inverted in the mask
*/
public boolean isInvertMask() {
return invert;
}
/**
* Getter for the inverted value
*
* @return true if the image is inverted
*/
public boolean isInverted() {
return invert;
}
/**
* Sets inverted true or false
*
* @param invert
* true or false
*/
public void setInverted(boolean invert) {
this.invert = invert;
}
/**
* Getter for property interpolation.
*
* @return Value of property interpolation.
*/
public boolean isInterpolation() {
return interpolation;
}
/**
* Sets the image interpolation. Image interpolation attempts to produce a
* smooth transition between adjacent sample values.
*
* @param interpolation
* New value of property interpolation.
*/
public void setInterpolation(boolean interpolation) {
this.interpolation = interpolation;
}
/**
* @see com.lowagie.text.MarkupAttributes#setMarkupAttribute(java.lang.String,
* java.lang.String)
*/
public void setMarkupAttribute(String name, String value) {
if (markupAttributes == null) markupAttributes = new Properties();
markupAttributes.put(name, value);
}
/**
* @see com.lowagie.text.MarkupAttributes#setMarkupAttributes(java.util.Properties)
*/
public void setMarkupAttributes(Properties markupAttributes) {
this.markupAttributes = markupAttributes;
}
/**
* @see com.lowagie.text.MarkupAttributes#getMarkupAttribute(java.lang.String)
*/
public String getMarkupAttribute(String name) {
return (markupAttributes == null) ? null : String
.valueOf(markupAttributes.get(name));
}
/**
* @see com.lowagie.text.MarkupAttributes#getMarkupAttributeNames()
*/
public Set getMarkupAttributeNames() {
return Chunk.getKeySet(markupAttributes);
}
/**
* @see com.lowagie.text.MarkupAttributes#getMarkupAttributes()
*/
public Properties getMarkupAttributes() {
return markupAttributes;
}
/**
* Tags this image with an ICC profile.
*
* @param profile
* the profile
*/
public void tagICC(ICC_Profile profile) {
this.profile = profile;
}
/**
* Checks is the image has an ICC profile.
*
* @return the ICC profile or null
*/
public boolean hasICCProfile() {
return (this.profile != null);
}
/**
* Gets the images ICC profile.
*
* @return the ICC profile
*/
public ICC_Profile getICCProfile() {
return profile;
}
/**
* Getter for property deflated.
*
* @return Value of property deflated.
*
*/
public boolean isDeflated() {
return this.deflated;
}
/**
* Setter for property deflated.
*
* @param deflated
* New value of property deflated.
*
*/
public void setDeflated(boolean deflated) {
this.deflated = deflated;
}
/**
* Getter for property indexed.
*
* @return Value of property indexed.
*
*/
public PdfDictionary getAdditional() {
return this.additional;
}
/**
* Sets the /Colorspace key.
*
* @param additional
* New value of property indexed.
*/
public void setAdditional(PdfDictionary additional) {
this.additional = additional;
}
/**
* Getter for property smask.
*
* @return Value of property smask.
*
*/
public boolean isSmask() {
return this.smask;
}
/**
* Setter for property smask.
*
* @param smask
* New value of property smask.
*
*/
public void setSmask(boolean smask) {
this.smask = smask;
}
/**
* Gets the X/Y pixel dimensionless aspect ratio.
*
* @return the X/Y pixel dimensionless aspect ratio
*/
public float getXYRatio() {
return this.XYRatio;
}
/**
* Sets the X/Y pixel dimensionless aspect ratio.
*
* @param XYRatio
* the X/Y pixel dimensionless aspect ratio
*/
public void setXYRatio(float XYRatio) {
this.XYRatio = XYRatio;
}
/**
* Gets the left indentation.
*
* @return the left indentation
*/
public float indentationLeft() {
return indentationLeft;
}
/**
* Gets the right indentation.
*
* @return the right indentation
*/
public float indentationRight() {
return indentationRight;
}
/**
* Sets the left indentation.
*
* @param f
*/
public void setIndentationLeft(float f) {
indentationLeft = f;
}
/**
* Sets the right indentation.
*
* @param f
*/
public void setIndentationRight(float f) {
indentationRight = f;
}
/**
* Getter for property originalType.
*
* @return Value of property originalType.
*
*/
public int getOriginalType() {
return this.originalType;
}
/**
* Setter for property originalType.
*
* @param originalType
* New value of property originalType.
*
*/
public void setOriginalType(int originalType) {
this.originalType = originalType;
}
/**
* Getter for property originalData.
*
* @return Value of property originalData.
*
*/
public byte[] getOriginalData() {
return this.originalData;
}
/**
* Setter for property originalData.
*
* @param originalData
* New value of property originalData.
*
*/
public void setOriginalData(byte[] originalData) {
this.originalData = originalData;
}
/**
* Sets the url of the image
*
* @param url
* the url of the image
*/
public void setUrl(URL url) {
this.url = url;
}
/**
* Sets the spacing before this image.
*
* @param spacing
* the new spacing
*/
public void setSpacingBefore(float spacing) {
this.spacingBefore = spacing;
}
/**
* Sets the spacing after this image.
*
* @param spacing
* the new spacing
*/
public void setSpacingAfter(float spacing) {
this.spacingAfter = spacing;
}
/**
* Gets the spacing before this image.
*
* @return the spacing
*/
public float spacingBefore() {
return spacingBefore;
}
/**
* Gets the spacing before this image.
*
* @return the spacing
*/
public float spacingAfter() {
return spacingAfter;
}
/**
* Getter for property widthPercentage.
*
* @return Value of property widthPercentage.
*/
public float getWidthPercentage() {
return this.widthPercentage;
}
/**
* Setter for property widthPercentage.
*
* @param widthPercentage
* New value of property widthPercentage.
*/
public void setWidthPercentage(float widthPercentage) {
this.widthPercentage = widthPercentage;
}
/**
* Gets the layer this image belongs to.
*
* @return the layer this image belongs to or null
for no
* layer defined
*/
public PdfOCG getLayer() {
return layer;
}
/**
* Sets the layer this image belongs to.
*
* @param layer
* the layer this image belongs to
*/
public void setLayer(PdfOCG layer) {
this.layer = layer;
}
private PdfObject simplifyColorspace(PdfObject obj) {
if (obj == null || !obj.isArray())
return obj;
PdfObject first = (PdfObject)(((PdfArray)obj).getArrayList().get(0));
if (PdfName.CALGRAY.equals(first))
return PdfName.DEVICEGRAY;
else if (PdfName.CALRGB.equals(first))
return PdfName.DEVICERGB;
else
return obj;
}
/**
* Replaces CalRGB and CalGray colorspaces with DeviceRGB and DeviceGray.
*/
public void simplifyColorspace() {
if (additional == null)
return;
PdfObject value = additional.get(PdfName.COLORSPACE);
if (value == null || !value.isArray())
return;
PdfObject cs = simplifyColorspace(value);
if (cs.isName())
value = cs;
else {
PdfObject first = (PdfObject)(((PdfArray)value).getArrayList().get(0));
if (PdfName.INDEXED.equals(first)) {
ArrayList array = ((PdfArray)value).getArrayList();
if (array.size() >= 2 && ((PdfObject)array.get(1)).isArray()) {
array.set(1, simplifyColorspace((PdfObject)array.get(1)));
}
}
}
additional.put(PdfName.COLORSPACE, value);
}
/**
* Getter for property initialRotation.
* @return Value of property initialRotation.
*/
public float getInitialRotation() {
return this.initialRotation;
}
/**
* Some image formats, like TIFF may present the images rotated that have
* to be compensated.
* @param initialRotation New value of property initialRotation.
*/
public void setInitialRotation(float initialRotation) {
float old_rot = rotation - this.initialRotation;
this.initialRotation = initialRotation;
setRotation(old_rot);
}
/**
* Getter for property directReference.
* @return Value of property directReference.
*/
public PdfIndirectReference getDirectReference() {
return this.directReference;
}
/**
* Setter for property directReference.
* @param directReference New value of property directReference.
*/
public void setDirectReference(PdfIndirectReference directReference) {
this.directReference = directReference;
}
}