Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » [javadoc | source]
    1   /*
    2    * $Id: Image.java 3537 2008-07-08 08:53:00Z blowagie $
    3    *
    4    * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
    5    *
    6    * The contents of this file are subject to the Mozilla Public License Version 1.1
    7    * (the "License"); you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    9    *
   10    * Software distributed under the License is distributed on an "AS IS" basis,
   11    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   12    * for the specific language governing rights and limitations under the License.
   13    *
   14    * The Original Code is 'iText, a free JAVA-PDF library'.
   15    *
   16    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   17    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   18    * All Rights Reserved.
   19    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   20    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   21    *
   22    * Contributor(s): all the names of the contributors are added in the source code
   23    * where applicable.
   24    *
   25    * Alternatively, the contents of this file may be used under the terms of the
   26    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   27    * provisions of LGPL are applicable instead of those above.  If you wish to
   28    * allow use of your version of this file only under the terms of the LGPL
   29    * License and not to allow others to use your version of this file under
   30    * the MPL, indicate your decision by deleting the provisions above and
   31    * replace them with the notice and other provisions required by the LGPL.
   32    * If you do not delete the provisions above, a recipient may use your version
   33    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   34    *
   35    * This library is free software; you can redistribute it and/or modify it
   36    * under the terms of the MPL as stated above or under the terms of the GNU
   37    * Library General Public License as published by the Free Software Foundation;
   38    * either version 2 of the License, or any later version.
   39    *
   40    * This library is distributed in the hope that it will be useful, but WITHOUT
   41    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   42    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   43    * details.
   44    *
   45    * If you didn't download this code from the following link, you should check if
   46    * you aren't using an obsolete version:
   47    * http://www.lowagie.com/iText/
   48    */
   49   
   50   package com.lowagie.text;
   51   
   52   import java.awt.Graphics2D;
   53   import java.awt.color.ICC_Profile;
   54   import java.awt.image.BufferedImage;
   55   import java.io.IOException;
   56   import java.io.InputStream;
   57   import java.lang.reflect.Constructor;
   58   import java.net.MalformedURLException;
   59   import java.net.URL;
   60   import java.util.ArrayList;
   61   
   62   import com.lowagie.text.pdf.PRIndirectReference;
   63   import com.lowagie.text.pdf.PdfArray;
   64   import com.lowagie.text.pdf.PdfContentByte;
   65   import com.lowagie.text.pdf.PdfDictionary;
   66   import com.lowagie.text.pdf.PdfIndirectReference;
   67   import com.lowagie.text.pdf.PdfName;
   68   import com.lowagie.text.pdf.PdfNumber;
   69   import com.lowagie.text.pdf.PdfOCG;
   70   import com.lowagie.text.pdf.PdfObject;
   71   import com.lowagie.text.pdf.PdfReader;
   72   import com.lowagie.text.pdf.PdfStream;
   73   import com.lowagie.text.pdf.PdfTemplate;
   74   import com.lowagie.text.pdf.PdfWriter;
   75   import com.lowagie.text.pdf.RandomAccessFileOrArray;
   76   import com.lowagie.text.pdf.codec.BmpImage;
   77   import com.lowagie.text.pdf.codec.CCITTG4Encoder;
   78   import com.lowagie.text.pdf.codec.GifImage;
   79   import com.lowagie.text.pdf.codec.PngImage;
   80   import com.lowagie.text.pdf.codec.TiffImage;
   81   
   82   /**
   83    * An <CODE>Image</CODE> is the representation of a graphic element (JPEG, PNG
   84    * or GIF) that has to be inserted into the document
   85    * 
   86    * @see Element
   87    * @see Rectangle
   88    */
   89   
   90   public abstract class Image extends Rectangle {
   91   
   92   	// static final membervariables
   93   
   94   	/** this is a kind of image alignment. */
   95   	public static final int DEFAULT = 0;
   96   
   97   	/** this is a kind of image alignment. */
   98   	public static final int RIGHT = 2;
   99   
  100   	/** this is a kind of image alignment. */
  101   	public static final int LEFT = 0;
  102   
  103   	/** this is a kind of image alignment. */
  104   	public static final int MIDDLE = 1;
  105   
  106   	/** this is a kind of image alignment. */
  107   	public static final int TEXTWRAP = 4;
  108   
  109   	/** this is a kind of image alignment. */
  110   	public static final int UNDERLYING = 8;
  111   
  112   	/** This represents a coordinate in the transformation matrix. */
  113   	public static final int AX = 0;
  114   
  115   	/** This represents a coordinate in the transformation matrix. */
  116   	public static final int AY = 1;
  117   
  118   	/** This represents a coordinate in the transformation matrix. */
  119   	public static final int BX = 2;
  120   
  121   	/** This represents a coordinate in the transformation matrix. */
  122   	public static final int BY = 3;
  123   
  124   	/** This represents a coordinate in the transformation matrix. */
  125   	public static final int CX = 4;
  126   
  127   	/** This represents a coordinate in the transformation matrix. */
  128   	public static final int CY = 5;
  129   
  130   	/** This represents a coordinate in the transformation matrix. */
  131   	public static final int DX = 6;
  132   
  133   	/** This represents a coordinate in the transformation matrix. */
  134   	public static final int DY = 7;
  135   
  136   	/** type of image */
  137   	public static final int ORIGINAL_NONE = 0;
  138   
  139   	/** type of image */
  140   	public static final int ORIGINAL_JPEG = 1;
  141   
  142   	/** type of image */
  143   	public static final int ORIGINAL_PNG = 2;
  144   
  145   	/** type of image */
  146   	public static final int ORIGINAL_GIF = 3;
  147   
  148   	/** type of image */
  149   	public static final int ORIGINAL_BMP = 4;
  150   
  151   	/** type of image */
  152   	public static final int ORIGINAL_TIFF = 5;
  153   
  154   	/** type of image */
  155   	public static final int ORIGINAL_WMF = 6;
  156   
  157   	/** type of image */
  158       public static final int ORIGINAL_PS = 7;
  159   
  160   	/** type of image */
  161   	public static final int ORIGINAL_JPEG2000 = 8;
  162   
  163       // member variables
  164   
  165   	/** The image type. */
  166   	protected int type;
  167   
  168   	/** The URL of the image. */
  169   	protected URL url;
  170   
  171   	/** The raw data of the image. */
  172   	protected byte rawData[];
  173   
  174   	/** The bits per component of the raw image. It also flags a CCITT image. */
  175   	protected int bpc = 1;
  176   	
  177   	/** The template to be treated as an image. */
  178   	protected PdfTemplate template[] = new PdfTemplate[1];
  179   
  180   	/** The alignment of the Image. */
  181   	protected int alignment;
  182   
  183   	/** Text that can be shown instead of the image. */
  184   	protected String alt;
  185   
  186   	/** This is the absolute X-position of the image. */
  187   	protected float absoluteX = Float.NaN;
  188   
  189   	/** This is the absolute Y-position of the image. */
  190   	protected float absoluteY = Float.NaN;
  191   
  192   	/** This is the width of the image without rotation. */
  193   	protected float plainWidth;
  194   
  195   	/** This is the width of the image without rotation. */
  196   	protected float plainHeight;
  197   
  198   	/** This is the scaled width of the image taking rotation into account. */
  199   	protected float scaledWidth;
  200   
  201   	/** This is the original height of the image taking rotation into account. */
  202   	protected float scaledHeight;
  203   	
  204       /**
  205        * The compression level of the content streams.
  206        * @since	2.1.3
  207        */
  208       protected int compressionLevel = PdfStream.DEFAULT_COMPRESSION;
  209   
  210   	/** an iText attributed unique id for this image. */
  211   	protected Long mySerialId = getSerialId();
  212   
  213   	// image from file or URL
  214   	
  215   	/**
  216   	 * Constructs an <CODE>Image</CODE> -object, using an <VAR>url </VAR>.
  217   	 * 
  218   	 * @param url
  219   	 *            the <CODE>URL</CODE> where the image can be found.
  220   	 */
  221   	public Image(URL url) {
  222   		super(0, 0);
  223   		this.url = url;
  224   		this.alignment = DEFAULT;
  225   		rotationRadians = 0;
  226   	}
  227   
  228   	/**
  229   	 * Gets an instance of an Image.
  230   	 * 
  231   	 * @param url
  232   	 *            an URL
  233   	 * @return an Image
  234   	 * @throws BadElementException
  235   	 * @throws MalformedURLException
  236   	 * @throws IOException
  237   	 */
  238   	public static Image getInstance(URL url) throws BadElementException,
  239   			MalformedURLException, IOException {
  240   		InputStream is = null;
  241   		try {
  242   			is = url.openStream();
  243   			int c1 = is.read();
  244   			int c2 = is.read();
  245   			int c3 = is.read();
  246   			int c4 = is.read();
  247   			is.close();
  248   
  249   			is = null;
  250   			if (c1 == 'G' && c2 == 'I' && c3 == 'F') {
  251   				GifImage gif = new GifImage(url);
  252   				Image img = gif.getImage(1);
  253   				return img;
  254   			}
  255   			if (c1 == 0xFF && c2 == 0xD8) {
  256   				return new Jpeg(url);
  257   			}
  258   			if (c1 == 0x00 && c2 == 0x00 && c3 == 0x00 && c4 == 0x0c) {
  259   				return new Jpeg2000(url);
  260   			}
  261   			if (c1 == 0xff && c2 == 0x4f && c3 == 0xff && c4 == 0x51) {
  262   				return new Jpeg2000(url);
  263   			}
  264   			if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1]
  265   					&& c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
  266   				return PngImage.getImage(url);
  267   			}
  268   			if (c1 == 0xD7 && c2 == 0xCD) {
  269   				return new ImgWMF(url);
  270   			}
  271   			if (c1 == 'B' && c2 == 'M') {
  272   				return  BmpImage.getImage(url);
  273   			}
  274   			if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
  275   					|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) {
  276   				RandomAccessFileOrArray ra = null;
  277   				try {
  278   					if (url.getProtocol().equals("file")) {
  279   						String file = url.getFile();
  280                           file = Utilities.unEscapeURL(file);
  281   						ra = new RandomAccessFileOrArray(file);
  282   					} else
  283   						ra = new RandomAccessFileOrArray(url);
  284   					Image img = TiffImage.getTiffImage(ra, 1);
  285   					img.url = url;
  286   					return img;
  287   				} finally {
  288   					if (ra != null)
  289   						ra.close();
  290   				}
  291   
  292   			}
  293   			throw new IOException(url.toString()
  294   					+ " is not a recognized imageformat.");
  295   		} finally {
  296   			if (is != null) {
  297   				is.close();
  298   			}
  299   		}
  300   	}
  301   
  302   	/**
  303   	 * Gets an instance of an Image.
  304   	 * 
  305   	 * @param filename
  306   	 *            a filename
  307   	 * @return an object of type <CODE>Gif</CODE>,<CODE>Jpeg</CODE> or
  308   	 *         <CODE>Png</CODE>
  309   	 * @throws BadElementException
  310   	 * @throws MalformedURLException
  311   	 * @throws IOException
  312   	 */
  313   	public static Image getInstance(String filename)
  314   			throws BadElementException, MalformedURLException, IOException {
  315   		return getInstance(Utilities.toURL(filename));
  316   	}
  317       
  318   	/**
  319   	 * gets an instance of an Image
  320   	 * 
  321   	 * @param imgb
  322   	 *            raw image date
  323   	 * @return an Image object
  324   	 * @throws BadElementException
  325   	 * @throws MalformedURLException
  326   	 * @throws IOException
  327   	 */
  328   	public static Image getInstance(byte imgb[]) throws BadElementException,
  329   			MalformedURLException, IOException {
  330   		InputStream is = null;
  331   		try {
  332   			is = new java.io.ByteArrayInputStream(imgb);
  333   			int c1 = is.read();
  334   			int c2 = is.read();
  335   			int c3 = is.read();
  336   			int c4 = is.read();
  337   			is.close();
  338   
  339   			is = null;
  340   			if (c1 == 'G' && c2 == 'I' && c3 == 'F') {
  341   				GifImage gif = new GifImage(imgb);
  342   				return gif.getImage(1);
  343   			}
  344   			if (c1 == 0xFF && c2 == 0xD8) {
  345   				return new Jpeg(imgb);
  346   			}
  347   			if (c1 == 0x00 && c2 == 0x00 && c3 == 0x00 && c4 == 0x0c) {
  348   				return new Jpeg2000(imgb);
  349   			}
  350   			if (c1 == 0xff && c2 == 0x4f && c3 == 0xff && c4 == 0x51) {
  351   				return new Jpeg2000(imgb);
  352   			}
  353   			if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1]
  354   					&& c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
  355   				return PngImage.getImage(imgb);
  356   			}
  357   			if (c1 == 0xD7 && c2 == 0xCD) {
  358   				return new ImgWMF(imgb);
  359   			}
  360   			if (c1 == 'B' && c2 == 'M') {
  361   				return BmpImage.getImage(imgb);
  362   			}
  363   			if ((c1 == 'M' && c2 == 'M' && c3 == 0 && c4 == 42)
  364   					|| (c1 == 'I' && c2 == 'I' && c3 == 42 && c4 == 0)) {
  365   				RandomAccessFileOrArray ra = null;
  366   				try {
  367   					ra = new RandomAccessFileOrArray(imgb);
  368   					Image img = TiffImage.getTiffImage(ra, 1);
  369                       if (img.getOriginalData() == null)
  370                           img.setOriginalData(imgb);
  371   					return img;
  372   				} finally {
  373   					if (ra != null)
  374   						ra.close();
  375   				}
  376   
  377   			}
  378   			throw new IOException(
  379   					"The byte array is not a recognized imageformat.");
  380   		} finally {
  381   			if (is != null) {
  382   				is.close();
  383   			}
  384   		}
  385   	}
  386   
  387   	/**
  388   	 * Gets an instance of an Image in raw mode.
  389   	 * 
  390   	 * @param width
  391   	 *            the width of the image in pixels
  392   	 * @param height
  393   	 *            the height of the image in pixels
  394   	 * @param components
  395   	 *            1,3 or 4 for GrayScale, RGB and CMYK
  396   	 * @param data
  397   	 *            the image data
  398   	 * @param bpc
  399   	 *            bits per component
  400   	 * @return an object of type <CODE>ImgRaw</CODE>
  401   	 * @throws BadElementException
  402   	 *             on error
  403   	 */
  404   	public static Image getInstance(int width, int height, int components,
  405   			int bpc, byte data[]) throws BadElementException {
  406   		return Image.getInstance(width, height, components, bpc, data, null);
  407   	}
  408   
  409   	/**
  410   	 * Creates an Image with CCITT G3 or G4 compression. It assumes that the
  411   	 * data bytes are already compressed.
  412   	 * 
  413   	 * @param width
  414   	 *            the exact width of the image
  415   	 * @param height
  416   	 *            the exact height of the image
  417   	 * @param reverseBits
  418   	 *            reverses the bits in <code>data</code>. Bit 0 is swapped
  419   	 *            with bit 7 and so on
  420   	 * @param typeCCITT
  421   	 *            the type of compression in <code>data</code>. It can be
  422   	 *            CCITTG4, CCITTG31D, CCITTG32D
  423   	 * @param parameters
  424   	 *            parameters associated with this stream. Possible values are
  425   	 *            CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and
  426   	 *            CCITT_ENDOFBLOCK or a combination of them
  427   	 * @param data
  428   	 *            the image data
  429   	 * @return an Image object
  430   	 * @throws BadElementException
  431   	 *             on error
  432   	 */
  433   	public static Image getInstance(int width, int height, boolean reverseBits,
  434   			int typeCCITT, int parameters, byte[] data)
  435   			throws BadElementException {
  436   		return Image.getInstance(width, height, reverseBits, typeCCITT,
  437   				parameters, data, null);
  438   	}
  439   
  440   	/**
  441   	 * Creates an Image with CCITT G3 or G4 compression. It assumes that the
  442   	 * data bytes are already compressed.
  443   	 * 
  444   	 * @param width
  445   	 *            the exact width of the image
  446   	 * @param height
  447   	 *            the exact height of the image
  448   	 * @param reverseBits
  449   	 *            reverses the bits in <code>data</code>. Bit 0 is swapped
  450   	 *            with bit 7 and so on
  451   	 * @param typeCCITT
  452   	 *            the type of compression in <code>data</code>. It can be
  453   	 *            CCITTG4, CCITTG31D, CCITTG32D
  454   	 * @param parameters
  455   	 *            parameters associated with this stream. Possible values are
  456   	 *            CCITT_BLACKIS1, CCITT_ENCODEDBYTEALIGN, CCITT_ENDOFLINE and
  457   	 *            CCITT_ENDOFBLOCK or a combination of them
  458   	 * @param data
  459   	 *            the image data
  460   	 * @param transparency
  461   	 *            transparency information in the Mask format of the image
  462   	 *            dictionary
  463   	 * @return an Image object
  464   	 * @throws BadElementException
  465   	 *             on error
  466   	 */
  467   	public static Image getInstance(int width, int height, boolean reverseBits,
  468   			int typeCCITT, int parameters, byte[] data, int transparency[])
  469   			throws BadElementException {
  470   		if (transparency != null && transparency.length != 2)
  471   			throw new BadElementException(
  472   					"Transparency length must be equal to 2 with CCITT images");
  473   		Image img = new ImgCCITT(width, height, reverseBits, typeCCITT,
  474   				parameters, data);
  475   		img.transparency = transparency;
  476   		return img;
  477   	}
  478   
  479   	/**
  480   	 * Gets an instance of an Image in raw mode.
  481   	 * 
  482   	 * @param width
  483   	 *            the width of the image in pixels
  484   	 * @param height
  485   	 *            the height of the image in pixels
  486   	 * @param components
  487   	 *            1,3 or 4 for GrayScale, RGB and CMYK
  488   	 * @param data
  489   	 *            the image data
  490   	 * @param bpc
  491   	 *            bits per component
  492   	 * @param transparency
  493   	 *            transparency information in the Mask format of the image
  494   	 *            dictionary
  495   	 * @return an object of type <CODE>ImgRaw</CODE>
  496   	 * @throws BadElementException
  497   	 *             on error
  498   	 */
  499   	public static Image getInstance(int width, int height, int components,
  500   			int bpc, byte data[], int transparency[])
  501   			throws BadElementException {
  502   		if (transparency != null && transparency.length != components * 2)
  503   			throw new BadElementException(
  504   					"Transparency length must be equal to (componentes * 2)");
  505   		if (components == 1 && bpc == 1) {
  506   			byte g4[] = CCITTG4Encoder.compress(data, width, height);
  507   			return Image.getInstance(width, height, false, Image.CCITTG4,
  508   					Image.CCITT_BLACKIS1, g4, transparency);
  509   		}
  510   		Image img = new ImgRaw(width, height, components, bpc, data);
  511   		img.transparency = transparency;
  512   		return img;
  513   	}
  514   
  515   	// images from a PdfTemplate
  516   	
  517   	/**
  518   	 * gets an instance of an Image
  519   	 * 
  520   	 * @param template
  521   	 *            a PdfTemplate that has to be wrapped in an Image object
  522   	 * @return an Image object
  523   	 * @throws BadElementException
  524   	 */
  525   	public static Image getInstance(PdfTemplate template)
  526   			throws BadElementException {
  527   		return new ImgTemplate(template);
  528   	}
  529       
  530       // images from a java.awt.Image
  531       
  532   	/**
  533   	 * Gets an instance of an Image from a java.awt.Image.
  534   	 * 
  535   	 * @param image
  536   	 *            the <CODE>java.awt.Image</CODE> to convert
  537   	 * @param color
  538   	 *            if different from <CODE>null</CODE> the transparency pixels
  539   	 *            are replaced by this color
  540   	 * @param forceBW
  541   	 *            if <CODE>true</CODE> the image is treated as black and white
  542   	 * @return an object of type <CODE>ImgRaw</CODE>
  543   	 * @throws BadElementException
  544   	 *             on error
  545   	 * @throws IOException
  546   	 *             on error
  547   	 */
  548   	public static Image getInstance(java.awt.Image image, java.awt.Color color,
  549   			boolean forceBW) throws BadElementException, IOException {
  550   		
  551   		if(image instanceof BufferedImage){
  552   			BufferedImage bi = (BufferedImage) image;
  553   			if(bi.getType()==BufferedImage.TYPE_BYTE_BINARY) {
  554   				forceBW=true;
  555   			}
  556   		}
  557   		
  558   		java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber(image,
  559   				0, 0, -1, -1, true);
  560   		try {
  561   			pg.grabPixels();
  562   		} catch (InterruptedException e) {
  563   			throw new IOException(
  564   					"java.awt.Image Interrupted waiting for pixels!");
  565   		}
  566   		if ((pg.getStatus() & java.awt.image.ImageObserver.ABORT) != 0) {
  567   			throw new IOException("java.awt.Image fetch aborted or errored");
  568   		}
  569   		int w = pg.getWidth();
  570   		int h = pg.getHeight();
  571   		int[] pixels = (int[]) pg.getPixels();
  572   		if (forceBW) {
  573   			int byteWidth = (w / 8) + ((w & 7) != 0 ? 1 : 0);
  574   			byte[] pixelsByte = new byte[byteWidth * h];
  575   
  576   			int index = 0;
  577   			int size = h * w;
  578   			int transColor = 1;
  579   			if (color != null) {
  580   				transColor = (color.getRed() + color.getGreen()
  581   						+ color.getBlue() < 384) ? 0 : 1;
  582   			}
  583   			int transparency[] = null;
  584   			int cbyte = 0x80;
  585   			int wMarker = 0;
  586   			int currByte = 0;
  587   			if (color != null) {
  588   				for (int j = 0; j < size; j++) {
  589   					int alpha = (pixels[j] >> 24) & 0xff;
  590   					if (alpha < 250) {
  591   						if (transColor == 1)
  592   							currByte |= cbyte;
  593   					} else {
  594   						if ((pixels[j] & 0x888) != 0)
  595   							currByte |= cbyte;
  596   					}
  597   					cbyte >>= 1;
  598   					if (cbyte == 0 || wMarker + 1 >= w) {
  599   						pixelsByte[index++] = (byte) currByte;
  600   						cbyte = 0x80;
  601   						currByte = 0;
  602   					}
  603   					++wMarker;
  604   					if (wMarker >= w)
  605   						wMarker = 0;
  606   				}
  607   			} else {
  608   				for (int j = 0; j < size; j++) {
  609   					if (transparency == null) {
  610   						int alpha = (pixels[j] >> 24) & 0xff;
  611   						if (alpha == 0) {
  612   							transparency = new int[2];
  613   							transparency[0] = transparency[1] = ((pixels[j] & 0x888) != 0) ? 1
  614   									: 0;
  615   						}
  616   					}
  617   					if ((pixels[j] & 0x888) != 0)
  618   						currByte |= cbyte;
  619   					cbyte >>= 1;
  620   					if (cbyte == 0 || wMarker + 1 >= w) {
  621   						pixelsByte[index++] = (byte) currByte;
  622   						cbyte = 0x80;
  623   						currByte = 0;
  624   					}
  625   					++wMarker;
  626   					if (wMarker >= w)
  627   						wMarker = 0;
  628   				}
  629   			}
  630   			return Image.getInstance(w, h, 1, 1, pixelsByte, transparency);
  631   		} else {
  632   			byte[] pixelsByte = new byte[w * h * 3];
  633   			byte[] smask = null;
  634   
  635   			int index = 0;
  636   			int size = h * w;
  637   			int red = 255;
  638   			int green = 255;
  639   			int blue = 255;
  640   			if (color != null) {
  641   				red = color.getRed();
  642   				green = color.getGreen();
  643   				blue = color.getBlue();
  644   			}
  645   			int transparency[] = null;
  646   			if (color != null) {
  647   				for (int j = 0; j < size; j++) {
  648   					int alpha = (pixels[j] >> 24) & 0xff;
  649   					if (alpha < 250) {
  650   						pixelsByte[index++] = (byte) red;
  651   						pixelsByte[index++] = (byte) green;
  652   						pixelsByte[index++] = (byte) blue;
  653   					} else {
  654   						pixelsByte[index++] = (byte) ((pixels[j] >> 16) & 0xff);
  655   						pixelsByte[index++] = (byte) ((pixels[j] >> 8) & 0xff);
  656   						pixelsByte[index++] = (byte) ((pixels[j]) & 0xff);
  657   					}
  658   				}
  659   			} else {
  660   				int transparentPixel = 0;
  661   				smask = new byte[w * h];
  662   				boolean shades = false;
  663   				for (int j = 0; j < size; j++) {
  664   					byte alpha = smask[j] = (byte) ((pixels[j] >> 24) & 0xff);
  665   					/* bugfix by Chris Nokleberg */
  666   					if (!shades) {
  667   						if (alpha != 0 && alpha != -1) {
  668   							shades = true;
  669   						} else if (transparency == null) {
  670   							if (alpha == 0) {
  671   								transparentPixel = pixels[j] & 0xffffff;
  672   								transparency = new int[6];
  673   								transparency[0] = transparency[1] = (transparentPixel >> 16) & 0xff;
  674   								transparency[2] = transparency[3] = (transparentPixel >> 8) & 0xff;
  675   								transparency[4] = transparency[5] = transparentPixel & 0xff;
  676   							}
  677   						} else if ((pixels[j] & 0xffffff) != transparentPixel) {
  678   							shades = true;
  679   						}
  680   					}
  681   					pixelsByte[index++] = (byte) ((pixels[j] >> 16) & 0xff);
  682   					pixelsByte[index++] = (byte) ((pixels[j] >> 8) & 0xff);
  683   					pixelsByte[index++] = (byte) ((pixels[j]) & 0xff);
  684   				}
  685   				if (shades)
  686   					transparency = null;
  687   				else
  688   					smask = null;
  689   			}
  690   			Image img = Image.getInstance(w, h, 3, 8, pixelsByte, transparency);
  691   			if (smask != null) {
  692   				Image sm = Image.getInstance(w, h, 1, 8, smask);
  693   				try {
  694   					sm.makeMask();
  695   					img.setImageMask(sm);
  696   				} catch (DocumentException de) {
  697   					throw new ExceptionConverter(de);
  698   				}
  699   			}
  700   			return img;
  701   		}
  702   	}
  703   
  704   	/**
  705   	 * Gets an instance of an Image from a java.awt.Image.
  706   	 * 
  707   	 * @param image
  708   	 *            the <CODE>java.awt.Image</CODE> to convert
  709   	 * @param color
  710   	 *            if different from <CODE>null</CODE> the transparency pixels
  711   	 *            are replaced by this color
  712   	 * @return an object of type <CODE>ImgRaw</CODE>
  713   	 * @throws BadElementException
  714   	 *             on error
  715   	 * @throws IOException
  716   	 *             on error
  717   	 */
  718   	public static Image getInstance(java.awt.Image image, java.awt.Color color)
  719   			throws BadElementException, IOException {
  720   		return Image.getInstance(image, color, false);
  721   	}
  722   	
  723   	/**
  724   	 * Gets an instance of a Image from a java.awt.Image.
  725   	 * The image is added as a JPEG with a user defined quality.
  726   	 * 
  727   	 * @param writer
  728   	 *            the <CODE>PdfWriter</CODE> object to which the image will be added
  729   	 * @param awtImage
  730   	 *            the <CODE>java.awt.Image</CODE> to convert
  731   	 * @param quality
  732   	 *            a float value between 0 and 1
  733   	 * @return an object of type <CODE>PdfTemplate</CODE>
  734   	 * @throws BadElementException
  735   	 *             on error
  736   	 * @throws IOException
  737   	 */
  738   	public static Image getInstance(PdfWriter writer, java.awt.Image awtImage, float quality) throws BadElementException, IOException {
  739   		return getInstance(new PdfContentByte(writer), awtImage, quality);
  740   	}
  741   	
  742       /**
  743        * Gets an instance of a Image from a java.awt.Image.
  744        * The image is added as a JPEG with a user defined quality.
  745        *
  746        * @param cb
  747        *            the <CODE>PdfContentByte</CODE> object to which the image will be added
  748        * @param awtImage
  749        *            the <CODE>java.awt.Image</CODE> to convert
  750        * @param quality
  751        *            a float value between 0 and 1
  752        * @return an object of type <CODE>PdfTemplate</CODE>
  753        * @throws BadElementException
  754        *             on error
  755        * @throws IOException
  756        */
  757       public static Image getInstance(PdfContentByte cb, java.awt.Image awtImage, float quality) throws BadElementException, IOException {
  758           java.awt.image.PixelGrabber pg = new java.awt.image.PixelGrabber(awtImage,
  759                   0, 0, -1, -1, true);
  760           try {
  761               pg.grabPixels();
  762           } catch (InterruptedException e) {
  763               throw new IOException(
  764                       "java.awt.Image Interrupted waiting for pixels!");
  765           }
  766           if ((pg.getStatus() & java.awt.image.ImageObserver.ABORT) != 0) {
  767               throw new IOException("java.awt.Image fetch aborted or errored");
  768           }
  769           int w = pg.getWidth();
  770           int h = pg.getHeight();
  771           PdfTemplate tp = cb.createTemplate(w, h);
  772           Graphics2D g2d = tp.createGraphics(w, h, true, quality);
  773           g2d.drawImage(awtImage, 0, 0, null);
  774           g2d.dispose();
  775           return getInstance(tp);
  776       }
  777   
  778       // image from indirect reference
  779       
  780       /**
  781        * Holds value of property directReference.
  782        * An image is embedded into a PDF as an Image XObject.
  783        * This object is referenced by a PdfIndirectReference object.
  784        */
  785       private PdfIndirectReference directReference;
  786       
  787       /**
  788        * Getter for property directReference.
  789        * @return Value of property directReference.
  790        */
  791       public PdfIndirectReference getDirectReference() {
  792           return this.directReference;
  793       }
  794       
  795       /**
  796        * Setter for property directReference.
  797        * @param directReference New value of property directReference.
  798        */
  799       public void setDirectReference(PdfIndirectReference directReference) {
  800           this.directReference = directReference;
  801       }
  802       
  803       /**
  804        * Reuses an existing image.
  805        * @param ref the reference to the image dictionary
  806        * @throws BadElementException on error
  807        * @return the image
  808        */    
  809       public static Image getInstance(PRIndirectReference ref) throws BadElementException {
  810           PdfDictionary dic = (PdfDictionary)PdfReader.getPdfObjectRelease(ref);
  811           int width = ((PdfNumber)PdfReader.getPdfObjectRelease(dic.get(PdfName.WIDTH))).intValue();
  812           int height = ((PdfNumber)PdfReader.getPdfObjectRelease(dic.get(PdfName.HEIGHT))).intValue();
  813           Image imask = null;
  814           PdfObject obj = dic.get(PdfName.SMASK);
  815           if (obj != null && obj.isIndirect()) {
  816               imask = getInstance((PRIndirectReference)obj);
  817           }
  818           else {
  819               obj = dic.get(PdfName.MASK);
  820               if (obj != null && obj.isIndirect()) {
  821                   PdfObject obj2 = PdfReader.getPdfObjectRelease(obj);
  822                   if (obj2 instanceof PdfDictionary)
  823                       imask = getInstance((PRIndirectReference)obj);
  824               }
  825           }
  826           Image img = new ImgRaw(width, height, 1, 1, null);
  827           img.imageMask = imask;
  828           img.directReference = ref;
  829           return img;
  830       }
  831   
  832       // copy constructor
  833       
  834   	/**
  835   	 * Constructs an <CODE>Image</CODE> -object, using an <VAR>url </VAR>.
  836   	 * 
  837   	 * @param image
  838   	 *            another Image object.
  839   	 */
  840   	protected Image(Image image) {
  841   		super(image);
  842   		this.type = image.type;
  843   		this.url = image.url;
  844   		this.rawData = image.rawData;
  845   		this.bpc = image.bpc;
  846   		this.template = image.template;
  847   		this.alignment = image.alignment;
  848   		this.alt = image.alt;
  849   		this.absoluteX = image.absoluteX;
  850   		this.absoluteY = image.absoluteY;
  851   		this.plainWidth = image.plainWidth;
  852   		this.plainHeight = image.plainHeight;
  853   		this.scaledWidth = image.scaledWidth;
  854   		this.scaledHeight = image.scaledHeight;
  855   		this.mySerialId = image.mySerialId;
  856   
  857           this.directReference = image.directReference;
  858           
  859   		this.rotationRadians = image.rotationRadians;
  860           this.initialRotation = image.initialRotation;
  861           this.indentationLeft = image.indentationLeft;
  862           this.indentationRight = image.indentationRight;
  863   		this.spacingBefore = image.spacingBefore;
  864   		this.spacingAfter = image.spacingAfter;
  865   
  866   		this.widthPercentage = image.widthPercentage;
  867   		this.annotation = image.annotation;
  868   		this.layer = image.layer;
  869   		this.interpolation = image.interpolation;
  870   		this.originalType = image.originalType;
  871   		this.originalData = image.originalData;
  872   		this.deflated = image.deflated;
  873   		this.dpiX = image.dpiX;
  874   		this.dpiY = image.dpiY;
  875   		this.XYRatio = image.XYRatio;
  876   		
  877   		this.colorspace = image.colorspace;
  878   		this.invert = image.invert;
  879   		this.profile = image.profile;
  880   		this.additional = image.additional;
  881   		this.mask = image.mask;
  882   		this.imageMask = image.imageMask;
  883   		this.smask = image.smask;
  884   		this.transparency = image.transparency;
  885   	}
  886   
  887   	/**
  888   	 * gets an instance of an Image
  889   	 * 
  890   	 * @param image
  891   	 *            an Image object
  892   	 * @return a new Image object
  893   	 */
  894   	public static Image getInstance(Image image) {
  895   		if (image == null)
  896   			return null;
  897   		try {
  898   			Class cs = image.getClass();
  899   			Constructor constructor = cs
  900   					.getDeclaredConstructor(new Class[] { Image.class });
  901   			return (Image) constructor.newInstance(new Object[] { image });
  902   		} catch (Exception e) {
  903   			throw new ExceptionConverter(e);
  904   		}
  905   	}
  906   
  907   	// implementation of the Element interface
  908   	
  909   	/**
  910   	 * Returns the type.
  911   	 * 
  912   	 * @return a type
  913   	 */
  914   
  915   	public int type() {
  916   		return type;
  917   	}
  918   
  919   	/**
  920   	 * @see com.lowagie.text.Element#isNestable()
  921   	 * @since	iText 2.0.8
  922   	 */
  923   	public boolean isNestable() {
  924   		return true;
  925   	}
  926   
  927   	// checking the type of Image
  928   
  929   	/**
  930   	 * Returns <CODE>true</CODE> if the image is a <CODE>Jpeg</CODE>
  931   	 * -object.
  932   	 * 
  933   	 * @return a <CODE>boolean</CODE>
  934   	 */
  935   
  936   	public boolean isJpeg() {
  937   		return type == JPEG;
  938   	}
  939   
  940   	/**
  941   	 * Returns <CODE>true</CODE> if the image is a <CODE>ImgRaw</CODE>
  942   	 * -object.
  943   	 * 
  944   	 * @return a <CODE>boolean</CODE>
  945   	 */
  946   
  947   	public boolean isImgRaw() {
  948   		return type == IMGRAW;
  949   	}
  950   
  951   	/**
  952   	 * Returns <CODE>true</CODE> if the image is an <CODE>ImgTemplate</CODE>
  953   	 * -object.
  954   	 * 
  955   	 * @return a <CODE>boolean</CODE>
  956   	 */
  957   
  958   	public boolean isImgTemplate() {
  959   		return type == IMGTEMPLATE;
  960   	}
  961   	
  962   	// getters and setters
  963   
  964   	/**
  965   	 * Gets the <CODE>String</CODE> -representation of the reference to the
  966   	 * image.
  967   	 * 
  968   	 * @return a <CODE>String</CODE>
  969   	 */
  970   
  971   	public URL getUrl() {
  972   		return url;
  973   	}
  974   
  975   	/**
  976   	 * Sets the url of the image
  977   	 * 
  978   	 * @param url
  979   	 *            the url of the image
  980   	 */
  981   	public void setUrl(URL url) {
  982   		this.url = url;
  983   	}
  984   
  985   	/**
  986   	 * Gets the raw data for the image.
  987   	 * <P>
  988   	 * Remark: this only makes sense for Images of the type <CODE>RawImage
  989   	 * </CODE>.
  990   	 * 
  991   	 * @return the raw data
  992   	 */
  993   	public byte[] getRawData() {
  994   		return rawData;
  995   	}
  996   
  997   	/**
  998   	 * Gets the bpc for the image.
  999   	 * <P>
 1000   	 * Remark: this only makes sense for Images of the type <CODE>RawImage
 1001   	 * </CODE>.
 1002   	 * 
 1003   	 * @return a bpc value
 1004   	 */
 1005   	public int getBpc() {
 1006   		return bpc;
 1007   	}
 1008   
 1009   	/**
 1010   	 * Gets the template to be used as an image.
 1011   	 * <P>
 1012   	 * Remark: this only makes sense for Images of the type <CODE>ImgTemplate
 1013   	 * </CODE>.
 1014   	 * 
 1015   	 * @return the template
 1016   	 */
 1017   	public PdfTemplate getTemplateData() {
 1018   		return template[0];
 1019   	}
 1020   
 1021   	/**
 1022   	 * Sets data from a PdfTemplate
 1023   	 * 
 1024   	 * @param template
 1025   	 *            the template with the content
 1026   	 */
 1027   	public void setTemplateData(PdfTemplate template) {
 1028   		this.template[0] = template;
 1029   	}
 1030   
 1031   	/**
 1032   	 * Gets the alignment for the image.
 1033   	 * 
 1034   	 * @return a value
 1035   	 */
 1036   	public int getAlignment() {
 1037   		return alignment;
 1038   	}
 1039   
 1040   	/**
 1041   	 * Sets the alignment for the image.
 1042   	 * 
 1043   	 * @param alignment
 1044   	 *            the alignment
 1045   	 */
 1046   
 1047   	public void setAlignment(int alignment) {
 1048   		this.alignment = alignment;
 1049   	}
 1050   
 1051   	/**
 1052   	 * Gets the alternative text for the image.
 1053   	 * 
 1054   	 * @return a <CODE>String</CODE>
 1055   	 */
 1056   
 1057   	public String getAlt() {
 1058   		return alt;
 1059   	}
 1060   
 1061   	/**
 1062   	 * Sets the alternative information for the image.
 1063   	 * 
 1064   	 * @param alt
 1065   	 *            the alternative information
 1066   	 */
 1067   
 1068   	public void setAlt(String alt) {
 1069   		this.alt = alt;
 1070   	}
 1071   
 1072   	/**
 1073   	 * Sets the absolute position of the <CODE>Image</CODE>.
 1074   	 * 
 1075   	 * @param absoluteX
 1076   	 * @param absoluteY
 1077   	 */
 1078   
 1079   	public void setAbsolutePosition(float absoluteX, float absoluteY) {
 1080   		this.absoluteX = absoluteX;
 1081   		this.absoluteY = absoluteY;
 1082   	}
 1083   
 1084   	/**
 1085   	 * Checks if the <CODE>Images</CODE> has to be added at an absolute X
 1086   	 * position.
 1087   	 * 
 1088   	 * @return a boolean
 1089   	 */
 1090   	public boolean hasAbsoluteX() {
 1091   		return !Float.isNaN(absoluteX);
 1092   	}
 1093   
 1094   	/**
 1095   	 * Returns the absolute X position.
 1096   	 * 
 1097   	 * @return a position
 1098   	 */
 1099   	public float getAbsoluteX() {
 1100   		return absoluteX;
 1101   	}
 1102   
 1103   	/**
 1104   	 * Checks if the <CODE>Images</CODE> has to be added at an absolute
 1105   	 * position.
 1106   	 * 
 1107   	 * @return a boolean
 1108   	 */
 1109   	public boolean hasAbsoluteY() {
 1110   		return !Float.isNaN(absoluteY);
 1111   	}
 1112   
 1113   	/**
 1114   	 * Returns the absolute Y position.
 1115   	 * 
 1116   	 * @return a position
 1117   	 */
 1118   	public float getAbsoluteY() {
 1119   		return absoluteY;
 1120   	}
 1121   
 1122   	// width and height
 1123   
 1124   	/**
 1125   	 * Gets the scaled width of the image.
 1126   	 * 
 1127   	 * @return a value
 1128   	 */
 1129   	public float getScaledWidth() {
 1130   		return scaledWidth;
 1131   	}
 1132   
 1133   	/**
 1134   	 * Gets the scaled height of the image.
 1135   	 * 
 1136   	 * @return a value
 1137   	 */
 1138   	public float getScaledHeight() {
 1139   		return scaledHeight;
 1140   	}
 1141   
 1142   	/**
 1143   	 * Gets the plain width of the image.
 1144   	 * 
 1145   	 * @return a value
 1146   	 */
 1147   	public float getPlainWidth() {
 1148   		return plainWidth;
 1149   	}
 1150   
 1151   	/**
 1152   	 * Gets the plain height of the image.
 1153   	 * 
 1154   	 * @return a value
 1155   	 */
 1156   	public float getPlainHeight() {
 1157   		return plainHeight;
 1158   	}
 1159   	
 1160   	/**
 1161   	 * Scale the image to an absolute width and an absolute height.
 1162   	 * 
 1163   	 * @param newWidth
 1164   	 *            the new width
 1165   	 * @param newHeight
 1166   	 *            the new height
 1167   	 */
 1168   	public void scaleAbsolute(float newWidth, float newHeight) {
 1169   		plainWidth = newWidth;
 1170   		plainHeight = newHeight;
 1171   		float[] matrix = matrix();
 1172   		scaledWidth = matrix[DX] - matrix[CX];
 1173   		scaledHeight = matrix[DY] - matrix[CY];
 1174   		setWidthPercentage(0);
 1175   	}
 1176   
 1177   	/**
 1178   	 * Scale the image to an absolute width.
 1179   	 * 
 1180   	 * @param newWidth
 1181   	 *            the new width
 1182   	 */
 1183   	public void scaleAbsoluteWidth(float newWidth) {
 1184   		plainWidth = newWidth;
 1185   		float[] matrix = matrix();
 1186   		scaledWidth = matrix[DX] - matrix[CX];
 1187   		scaledHeight = matrix[DY] - matrix[CY];
 1188   		setWidthPercentage(0);
 1189   	}
 1190   
 1191   	/**
 1192   	 * Scale the image to an absolute height.
 1193   	 * 
 1194   	 * @param newHeight
 1195   	 *            the new height
 1196   	 */
 1197   	public void scaleAbsoluteHeight(float newHeight) {
 1198   		plainHeight = newHeight;
 1199   		float[] matrix = matrix();
 1200   		scaledWidth = matrix[DX] - matrix[CX];
 1201   		scaledHeight = matrix[DY] - matrix[CY];
 1202   		setWidthPercentage(0);
 1203   	}
 1204   
 1205   	/**
 1206   	 * Scale the image to a certain percentage.
 1207   	 * 
 1208   	 * @param percent
 1209   	 *            the scaling percentage
 1210   	 */
 1211   	public void scalePercent(float percent) {
 1212   		scalePercent(percent, percent);
 1213   	}
 1214   
 1215   	/**
 1216   	 * Scale the width and height of an image to a certain percentage.
 1217   	 * 
 1218   	 * @param percentX
 1219   	 *            the scaling percentage of the width
 1220   	 * @param percentY
 1221   	 *            the scaling percentage of the height
 1222   	 */
 1223   	public void scalePercent(float percentX, float percentY) {
 1224   		plainWidth = (getWidth() * percentX) / 100f;
 1225   		plainHeight = (getHeight() * percentY) / 100f;
 1226   		float[] matrix = matrix();
 1227   		scaledWidth = matrix[DX] - matrix[CX];
 1228   		scaledHeight = matrix[DY] - matrix[CY];
 1229   		setWidthPercentage(0);
 1230   	}
 1231   
 1232   	/**
 1233   	 * Scales the image so that it fits a certain width and height.
 1234   	 * 
 1235   	 * @param fitWidth
 1236   	 *            the width to fit
 1237   	 * @param fitHeight
 1238   	 *            the height to fit
 1239   	 */
 1240   	public void scaleToFit(float fitWidth, float fitHeight) {
 1241           scalePercent(100);
 1242   		float percentX = (fitWidth * 100) / getScaledWidth();
 1243   		float percentY = (fitHeight * 100) / getScaledHeight();
 1244   		scalePercent(percentX < percentY ? percentX : percentY);
 1245   		setWidthPercentage(0);
 1246   	}
 1247   
 1248   	/**
 1249   	 * Returns the transformation matrix of the image.
 1250   	 * 
 1251   	 * @return an array [AX, AY, BX, BY, CX, CY, DX, DY]
 1252   	 */
 1253   	public float[] matrix() {
 1254   		float[] matrix = new float[8];
 1255   		float cosX = (float) Math.cos(rotationRadians);
 1256   		float sinX = (float) Math.sin(rotationRadians);
 1257   		matrix[AX] = plainWidth * cosX;
 1258   		matrix[AY] = plainWidth * sinX;
 1259   		matrix[BX] = (-plainHeight) * sinX;
 1260   		matrix[BY] = plainHeight * cosX;
 1261   		if (rotationRadians < Math.PI / 2f) {
 1262   			matrix[CX] = matrix[BX];
 1263   			matrix[CY] = 0;
 1264   			matrix[DX] = matrix[AX];
 1265   			matrix[DY] = matrix[AY] + matrix[BY];
 1266   		} else if (rotationRadians < Math.PI) {
 1267   			matrix[CX] = matrix[AX] + matrix[BX];
 1268   			matrix[CY] = matrix[BY];
 1269   			matrix[DX] = 0;
 1270   			matrix[DY] = matrix[AY];
 1271   		} else if (rotationRadians < Math.PI * 1.5f) {
 1272   			matrix[CX] = matrix[AX];
 1273   			matrix[CY] = matrix[AY] + matrix[BY];
 1274   			matrix[DX] = matrix[BX];
 1275   			matrix[DY] = 0;
 1276   		} else {
 1277   			matrix[CX] = 0;
 1278   			matrix[CY] = matrix[AY];
 1279   			matrix[DX] = matrix[AX] + matrix[BX];
 1280   			matrix[DY] = matrix[BY];
 1281   		}
 1282   		return matrix;
 1283   	}
 1284   
 1285   	// serial stamping
 1286   
 1287   	/** a static that is used for attributing a unique id to each image. */
 1288   	static long serialId = 0;
 1289   	
 1290   	/** Creates a new serial id. */
 1291   	static protected synchronized Long getSerialId() {
 1292   		++serialId;
 1293   		return new Long(serialId);
 1294   	}
 1295   
 1296   	/**
 1297   	 * Returns a serial id for the Image (reuse the same image more than once)
 1298   	 * 
 1299   	 * @return a serialId
 1300   	 */
 1301   	public Long getMySerialId() {
 1302   		return mySerialId;
 1303   	}
 1304   
 1305       // rotation, note that the superclass also has a rotation value.
 1306   
 1307   	/** This is the rotation of the image in radians. */
 1308   	protected float rotationRadians;
 1309       
 1310       /** Holds value of property initialRotation. */
 1311       private float initialRotation;
 1312   
 1313       /**
 1314        * Gets the current image rotation in radians.
 1315        * @return the current image rotation in radians
 1316        */
 1317       public float getImageRotation() {
 1318   		double d = 2.0 * Math.PI;
 1319   		float rot = (float) ((rotationRadians - initialRotation) % d);
 1320   		if (rot < 0) {
 1321   			rot += d;
 1322   		}
 1323           return rot;
 1324       }
 1325       
 1326   	/**
 1327   	 * Sets the rotation of the image in radians.
 1328   	 * 
 1329   	 * @param r
 1330   	 *            rotation in radians
 1331   	 */
 1332   	public void setRotation(float r) {
 1333   		double d = 2.0 * Math.PI;
 1334   		rotationRadians = (float) ((r + initialRotation) % d);
 1335   		if (rotationRadians < 0) {
 1336   			rotationRadians += d;
 1337   		}
 1338   		float[] matrix = matrix();
 1339   		scaledWidth = matrix[DX] - matrix[CX];
 1340   		scaledHeight = matrix[DY] - matrix[CY];
 1341   	}
 1342   
 1343   	/**
 1344   	 * Sets the rotation of the image in degrees.
 1345   	 * 
 1346   	 * @param deg
 1347   	 *            rotation in degrees
 1348   	 */
 1349   	public void setRotationDegrees(float deg) {
 1350   		double d = Math.PI;
 1351   		setRotation(deg / 180 * (float) d);
 1352   	}
 1353       
 1354       /**
 1355        * Getter for property initialRotation.
 1356        * @return Value of property initialRotation.
 1357        */
 1358       public float getInitialRotation() {
 1359           return this.initialRotation;
 1360       }
 1361       
 1362       /**
 1363        * Some image formats, like TIFF may present the images rotated that have
 1364        * to be compensated.
 1365        * @param initialRotation New value of property initialRotation.
 1366        */
 1367       public void setInitialRotation(float initialRotation) {
 1368           float old_rot = rotationRadians - this.initialRotation;
 1369           this.initialRotation = initialRotation;
 1370           setRotation(old_rot);
 1371       }
 1372       
 1373       // indentations
 1374   
 1375   	/** the indentation to the left. */
 1376   	protected float indentationLeft = 0;
 1377   
 1378   	/** the indentation to the right. */
 1379   	protected float indentationRight = 0;
 1380   
 1381   	/** The spacing before the image. */
 1382   	protected float spacingBefore;
 1383   
 1384   	/** The spacing after the image. */
 1385   	protected float spacingAfter;
 1386   
 1387   	/**
 1388   	 * Gets the left indentation.
 1389   	 * 
 1390   	 * @return the left indentation
 1391   	 */
 1392   	public float getIndentationLeft() {
 1393   		return indentationLeft;
 1394   	}
 1395   
 1396   	/**
 1397   	 * Sets the left indentation.
 1398   	 * 
 1399   	 * @param f
 1400   	 */
 1401   	public void setIndentationLeft(float f) {
 1402   		indentationLeft = f;
 1403   	}
 1404   
 1405   	/**
 1406   	 * Gets the right indentation.
 1407   	 * 
 1408   	 * @return the right indentation
 1409   	 */
 1410   	public float getIndentationRight() {
 1411   		return indentationRight;
 1412   	}
 1413   
 1414   	/**
 1415   	 * Sets the right indentation.
 1416   	 * 
 1417   	 * @param f
 1418   	 */
 1419   	public void setIndentationRight(float f) {
 1420   		indentationRight = f;
 1421   	}
 1422   
 1423   	/**
 1424   	 * Gets the spacing before this image.
 1425   	 * 
 1426   	 * @return the spacing
 1427   	 */
 1428   	public float getSpacingBefore() {
 1429   		return spacingBefore;
 1430   	}
 1431   
 1432   	/**
 1433   	 * Sets the spacing before this image.
 1434   	 * 
 1435   	 * @param spacing
 1436   	 *            the new spacing
 1437   	 */
 1438   
 1439   	public void setSpacingBefore(float spacing) {
 1440   		this.spacingBefore = spacing;
 1441   	}
 1442   
 1443   	/**
 1444   	 * Gets the spacing before this image.
 1445   	 * 
 1446   	 * @return the spacing
 1447   	 */
 1448   	public float getSpacingAfter() {
 1449   		return spacingAfter;
 1450   	}
 1451   
 1452   	/**
 1453   	 * Sets the spacing after this image.
 1454   	 * 
 1455   	 * @param spacing
 1456   	 *            the new spacing
 1457   	 */
 1458   
 1459   	public void setSpacingAfter(float spacing) {
 1460   		this.spacingAfter = spacing;
 1461   	}
 1462   
 1463       // widthpercentage (for the moment only used in ColumnText)
 1464   
 1465   	/**
 1466   	 * Holds value of property widthPercentage.
 1467   	 */
 1468   	private float widthPercentage = 100;
 1469   	
 1470   	/**
 1471   	 * Getter for property widthPercentage.
 1472   	 * 
 1473   	 * @return Value of property widthPercentage.
 1474   	 */
 1475   	public float getWidthPercentage() {
 1476   		return this.widthPercentage;
 1477   	}
 1478   
 1479   	/**
 1480   	 * Setter for property widthPercentage.
 1481   	 * 
 1482   	 * @param widthPercentage
 1483   	 *            New value of property widthPercentage.
 1484   	 */
 1485   	public void setWidthPercentage(float widthPercentage) {
 1486   		this.widthPercentage = widthPercentage;
 1487   	}
 1488   
 1489       // annotation
 1490   
 1491   	/** if the annotation is not null the image will be clickable. */
 1492   	protected Annotation annotation = null;
 1493   	
 1494   	/**
 1495   	 * Sets the annotation of this Image.
 1496   	 * 
 1497   	 * @param annotation
 1498   	 *            the annotation
 1499   	 */
 1500   	public void setAnnotation(Annotation annotation) {
 1501   		this.annotation = annotation;
 1502   	}
 1503   
 1504   	/**
 1505   	 * Gets the annotation.
 1506   	 * 
 1507   	 * @return the annotation that is linked to this image
 1508   	 */
 1509   	public Annotation getAnnotation() {
 1510   		return annotation;
 1511   	}
 1512   
 1513       // Optional Content
 1514   
 1515       /** Optional Content layer to which we want this Image to belong. */
 1516   	protected PdfOCG layer;
 1517   	
 1518   	/**
 1519   	 * Gets the layer this image belongs to.
 1520   	 * 
 1521   	 * @return the layer this image belongs to or <code>null</code> for no
 1522   	 *         layer defined
 1523   	 */
 1524   	public PdfOCG getLayer() {
 1525   		return layer;
 1526   	}
 1527   
 1528   	/**
 1529   	 * Sets the layer this image belongs to.
 1530   	 * 
 1531   	 * @param layer
 1532   	 *            the layer this image belongs to
 1533   	 */
 1534   	public void setLayer(PdfOCG layer) {
 1535   		this.layer = layer;
 1536   	}
 1537   
 1538   	// interpolation
 1539   
 1540   	/** Holds value of property interpolation. */
 1541   	protected boolean interpolation;
 1542   
 1543   	/**
 1544   	 * Getter for property interpolation.
 1545   	 * 
 1546   	 * @return Value of property interpolation.
 1547   	 */
 1548   	public boolean isInterpolation() {
 1549   		return interpolation;
 1550   	}
 1551   
 1552   	/**
 1553   	 * Sets the image interpolation. Image interpolation attempts to produce a
 1554   	 * smooth transition between adjacent sample values.
 1555   	 * 
 1556   	 * @param interpolation
 1557   	 *            New value of property interpolation.
 1558   	 */
 1559   	public void setInterpolation(boolean interpolation) {
 1560   		this.interpolation = interpolation;
 1561   	}
 1562   	
 1563   	// original type and data
 1564   
 1565   	/** Holds value of property originalType. */
 1566   	protected int originalType = ORIGINAL_NONE;
 1567   
 1568   	/** Holds value of property originalData. */
 1569   	protected byte[] originalData;
 1570   	
 1571   	/**
 1572   	 * Getter for property originalType.
 1573   	 * 
 1574   	 * @return Value of property originalType.
 1575   	 *  
 1576   	 */
 1577   	public int getOriginalType() {
 1578   		return this.originalType;
 1579   	}
 1580   
 1581   	/**
 1582   	 * Setter for property originalType.
 1583   	 * 
 1584   	 * @param originalType
 1585   	 *            New value of property originalType.
 1586   	 *  
 1587   	 */
 1588   	public void setOriginalType(int originalType) {
 1589   		this.originalType = originalType;
 1590   	}
 1591   
 1592   	/**
 1593   	 * Getter for property originalData.
 1594   	 * 
 1595   	 * @return Value of property originalData.
 1596   	 *  
 1597   	 */
 1598   	public byte[] getOriginalData() {
 1599   		return this.originalData;
 1600   	}
 1601   
 1602   	/**
 1603   	 * Setter for property originalData.
 1604   	 * 
 1605   	 * @param originalData
 1606   	 *            New value of property originalData.
 1607   	 *  
 1608   	 */
 1609   	public void setOriginalData(byte[] originalData) {
 1610   		this.originalData = originalData;
 1611   	}
 1612   
 1613   	// the following values are only set for specific types of images.
 1614   	
 1615   	/** Holds value of property deflated. */
 1616   	protected boolean deflated = false;
 1617   
 1618   	/**
 1619   	 * Getter for property deflated.
 1620   	 * 
 1621   	 * @return Value of property deflated.
 1622   	 *  
 1623   	 */
 1624   	public boolean isDeflated() {
 1625   		return this.deflated;
 1626   	}
 1627   
 1628   	/**
 1629   	 * Setter for property deflated.
 1630   	 * 
 1631   	 * @param deflated
 1632   	 *            New value of property deflated.
 1633   	 */
 1634   	public void setDeflated(boolean deflated) {
 1635   		this.deflated = deflated;
 1636   	}
 1637   	
 1638   	// DPI info
 1639   	
 1640   	/** Holds value of property dpiX. */
 1641   	protected int dpiX = 0;
 1642   
 1643   	/** Holds value of property dpiY. */
 1644   	protected int dpiY = 0;
 1645   
 1646   	/**
 1647   	 * Gets the dots-per-inch in the X direction. Returns 0 if not available.
 1648   	 * 
 1649   	 * @return the dots-per-inch in the X direction
 1650   	 */
 1651   	public int getDpiX() {
 1652   		return dpiX;
 1653   	}
 1654   
 1655   	/**
 1656   	 * Gets the dots-per-inch in the Y direction. Returns 0 if not available.
 1657   	 * 
 1658   	 * @return the dots-per-inch in the Y direction
 1659   	 */
 1660   	public int getDpiY() {
 1661   		return dpiY;
 1662   	}
 1663   
 1664   	/**
 1665   	 * Sets the dots per inch value
 1666   	 * 
 1667   	 * @param dpiX
 1668   	 *            dpi for x coordinates
 1669   	 * @param dpiY
 1670   	 *            dpi for y coordinates
 1671   	 */
 1672   	public void setDpi(int dpiX, int dpiY) {
 1673   		this.dpiX = dpiX;
 1674   		this.dpiY = dpiY;
 1675   	}
 1676   	
 1677   	// XY Ratio
 1678   	
 1679   	/** Holds value of property XYRatio. */
 1680   	private float XYRatio = 0;
 1681   
 1682   	/**
 1683   	 * Gets the X/Y pixel dimensionless aspect ratio.
 1684   	 * 
 1685   	 * @return the X/Y pixel dimensionless aspect ratio
 1686   	 */
 1687   	public float getXYRatio() {
 1688   		return this.XYRatio;
 1689   	}
 1690   
 1691   	/**
 1692   	 * Sets the X/Y pixel dimensionless aspect ratio.
 1693   	 * 
 1694   	 * @param XYRatio
 1695   	 *            the X/Y pixel dimensionless aspect ratio
 1696   	 */
 1697   	public void setXYRatio(float XYRatio) {
 1698   		this.XYRatio = XYRatio;
 1699   	}
 1700   	
 1701   	// color, colorspaces and transparency
 1702   
 1703   	/** this is the colorspace of a jpeg-image. */
 1704   	protected int colorspace = -1;
 1705   
 1706   	/**
 1707   	 * Gets the colorspace for the image.
 1708   	 * <P>
 1709   	 * Remark: this only makes sense for Images of the type <CODE>Jpeg</CODE>.
 1710   	 * 
 1711   	 * @return a colorspace value
 1712   	 */
 1713   	public int getColorspace() {
 1714   		return colorspace;
 1715   	}
 1716       
 1717   	/** Image color inversion */
 1718   	protected boolean invert = false;
 1719   
 1720   	/**
 1721   	 * Getter for the inverted value
 1722   	 * 
 1723   	 * @return true if the image is inverted
 1724   	 */
 1725   	public boolean isInverted() {
 1726   		return invert;
 1727   	}
 1728   
 1729   	/**
 1730   	 * Sets inverted true or false
 1731   	 * 
 1732   	 * @param invert
 1733   	 *            true or false
 1734   	 */
 1735   	public void setInverted(boolean invert) {
 1736   		this.invert = invert;
 1737   	}
 1738   
 1739   	/** ICC Profile attached */
 1740   	protected ICC_Profile profile = null;
 1741   
 1742   	/**
 1743   	 * Tags this image with an ICC profile.
 1744   	 * 
 1745   	 * @param profile
 1746   	 *            the profile
 1747   	 */
 1748   	public void tagICC(ICC_Profile profile) {
 1749   		this.profile = profile;
 1750   	}
 1751   
 1752   	/**
 1753   	 * Checks is the image has an ICC profile.
 1754   	 * 
 1755   	 * @return the ICC profile or <CODE>null</CODE>
 1756   	 */
 1757   	public boolean hasICCProfile() {
 1758   		return (this.profile != null);
 1759   	}
 1760   
 1761   	/**
 1762   	 * Gets the images ICC profile.
 1763   	 * 
 1764   	 * @return the ICC profile
 1765   	 */
 1766   	public ICC_Profile getICCProfile() {
 1767   		return profile;
 1768   	}
 1769   
 1770   	/** a dictionary with additional information */
 1771   	private PdfDictionary additional = null;
 1772   	
 1773   	/**
 1774   	 * Getter for the dictionary with additional information.
 1775   	 * 
 1776   	 * @return a PdfDictionary with additional information.
 1777   	 */
 1778   	public PdfDictionary getAdditional() {
 1779   		return this.additional;
 1780   	}
 1781   
 1782   	/**
 1783   	 * Sets the /Colorspace key.
 1784   	 * 
 1785   	 * @param additional
 1786   	 *            a PdfDictionary with additional information.
 1787   	 */
 1788   	public void setAdditional(PdfDictionary additional) {
 1789   		this.additional = additional;
 1790   	}
 1791   
 1792       /**
 1793        * Replaces CalRGB and CalGray colorspaces with DeviceRGB and DeviceGray.
 1794        */    
 1795       public void simplifyColorspace() {
 1796           if (additional == null)
 1797               return;
 1798           PdfObject value = additional.get(PdfName.COLORSPACE);
 1799           if (value == null || !value.isArray())
 1800               return;
 1801           PdfObject cs = simplifyColorspace(value);
 1802           if (cs.isName())
 1803               value = cs;
 1804           else {
 1805               PdfObject first = (PdfObject)(((PdfArray)value).getArrayList().get(0));
 1806               if (PdfName.INDEXED.equals(first)) {
 1807                   ArrayList array = ((PdfArray)value).getArrayList();
 1808                   if (array.size() >= 2 && ((PdfObject)array.get(1)).isArray()) {
 1809                        array.set(1, simplifyColorspace((PdfObject)array.get(1)));
 1810                   }
 1811               }
 1812           }
 1813           additional.put(PdfName.COLORSPACE, value);
 1814       }
 1815   	
 1816   	/**
 1817   	 * Gets a PDF Name from an array or returns the object that was passed.
 1818   	 */
 1819       private PdfObject simplifyColorspace(PdfObject obj) {
 1820           if (obj == null || !obj.isArray())
 1821               return obj;
 1822           PdfObject first = (PdfObject)(((PdfArray)obj).getArrayList().get(0));
 1823           if (PdfName.CALGRAY.equals(first))
 1824               return PdfName.DEVICEGRAY;
 1825           else if (PdfName.CALRGB.equals(first))
 1826               return PdfName.DEVICERGB;
 1827           else
 1828               return obj;
 1829       }
 1830   
 1831   	/** Is this image a mask? */
 1832   	protected boolean mask = false;
 1833   	
 1834   	/** The image that serves as a mask for this image. */
 1835   	protected Image imageMask;
 1836   
 1837   	/** Holds value of property smask. */
 1838   	private boolean smask;
 1839   
 1840   	/**
 1841   	 * Returns <CODE>true</CODE> if this <CODE>Image</CODE> is a mask.
 1842   	 * 
 1843   	 * @return <CODE>true</CODE> if this <CODE>Image</CODE> is a mask
 1844   	 */
 1845   	public boolean isMask() {
 1846   		return mask;
 1847   	}
 1848   
 1849   	/**
 1850   	 * Make this <CODE>Image</CODE> a mask.
 1851   	 * 
 1852   	 * @throws DocumentException
 1853   	 *             if this <CODE>Image</CODE> can not be a mask
 1854   	 */
 1855   	public void makeMask() throws DocumentException {
 1856   		if (!isMaskCandidate())
 1857   			throw new DocumentException("This image can not be an image mask.");
 1858   		mask = true;
 1859   	}
 1860   
 1861   	/**
 1862   	 * Returns <CODE>true</CODE> if this <CODE>Image</CODE> has the
 1863   	 * requisites to be a mask.
 1864   	 * 
 1865   	 * @return <CODE>true</CODE> if this <CODE>Image</CODE> can be a mask
 1866   	 */
 1867   	public boolean isMaskCandidate() {
 1868   		if (type == IMGRAW) {
 1869   			if (bpc > 0xff)
 1870   				return true;
 1871   		}
 1872   		return colorspace == 1;
 1873   	}
 1874   
 1875   	/**
 1876   	 * Gets the explicit masking.
 1877   	 * 
 1878   	 * @return the explicit masking
 1879   	 */
 1880   	public Image getImageMask() {
 1881   		return imageMask;
 1882   	}
 1883   
 1884   	/**
 1885   	 * Sets the explicit masking.
 1886   	 * 
 1887   	 * @param mask
 1888   	 *            the mask to be applied
 1889   	 * @throws DocumentException
 1890   	 *             on error
 1891   	 */
 1892   	public void setImageMask(Image mask) throws DocumentException {
 1893   		if (this.mask)
 1894   			throw new DocumentException(
 1895   					"An image mask cannot contain another image mask.");
 1896   		if (!mask.mask)
 1897   			throw new DocumentException(
 1898   					"The image mask is not a mask. Did you do makeMask()?");
 1899   		imageMask = mask;
 1900   		smask = (mask.bpc > 1 && mask.bpc <= 8);
 1901   	}
 1902   
 1903   	/**
 1904   	 * Getter for property smask.
 1905   	 * 
 1906   	 * @return Value of property smask.
 1907   	 *  
 1908   	 */
 1909   	public boolean isSmask() {
 1910   		return this.smask;
 1911   	}
 1912   
 1913   	/**
 1914   	 * Setter for property smask.
 1915   	 * 
 1916   	 * @param smask
 1917   	 *            New value of property smask.
 1918   	 */
 1919   	public void setSmask(boolean smask) {
 1920   		this.smask = smask;
 1921   	}
 1922   
 1923   	/** this is the transparency information of the raw image */
 1924   	protected int transparency[];
 1925   
 1926   	/**
 1927   	 * Returns the transparency.
 1928   	 * 
 1929   	 * @return the transparency values
 1930   	 */
 1931   
 1932   	public int[] getTransparency() {
 1933   		return transparency;
 1934   	}
 1935   
 1936   	/**
 1937   	 * Sets the transparency values
 1938   	 * 
 1939   	 * @param transparency
 1940   	 *            the transparency values
 1941   	 */
 1942   	public void setTransparency(int transparency[]) {
 1943   		this.transparency = transparency;
 1944   	}
 1945   
 1946   
 1947   	/**
 1948   	 * Returns the compression level used for images written as a compressed stream.
 1949   	 * @return the compression level (0 = best speed, 9 = best compression, -1 is default)
 1950        * @since	2.1.3
 1951   	 */
 1952   	public int getCompressionLevel() {
 1953   		return compressionLevel;
 1954   	}
 1955   
 1956   	/**
 1957   	 * Sets the compression level to be used if the image is written as a compressed stream.
 1958   	 * @param compressionLevel a value between 0 (best speed) and 9 (best compression)
 1959        * @since	2.1.3
 1960   	 */
 1961   	public void setCompressionLevel(int compressionLevel) {
 1962   		if (compressionLevel < PdfStream.NO_COMPRESSION || compressionLevel > PdfStream.BEST_COMPRESSION)
 1963   			this.compressionLevel = PdfStream.DEFAULT_COMPRESSION;
 1964   		else
 1965   			this.compressionLevel = compressionLevel;
 1966   	}
 1967   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » [javadoc | source]