001: package com.etymon.pjx.util;
002:
003: import java.io.*;
004: import java.nio.*;
005: import java.nio.channels.*;
006: import java.util.*;
007: import com.etymon.pjx.*;
008:
009: /**
010: Provides a very rudimentary function for adding JPEG images to a
011: PDF document. This works with most JPEG images.
012: @author Nassib Nassar
013: @deprecated This class will be removed when a more comprehensive
014: image class is completed.
015: */
016: public class AddImageSimple {
017:
018: protected static final PdfName PDFNAME_CONTENTS = new PdfName(
019: "Contents");
020: protected static final PdfName PDFNAME_RESOURCES = new PdfName(
021: "Resources");
022: protected static final PdfName PDFNAME_PROCSET = new PdfName(
023: "ProcSet");
024: protected static final PdfName PDFNAME_IMAGEC = new PdfName(
025: "ImageC");
026: protected static final PdfName PDFNAME_PARENT = new PdfName(
027: "Parent");
028: protected static final PdfName PDFNAME_NAME = new PdfName("Name");
029: protected static final PdfName PDFNAME_TYPE = new PdfName("Type");
030: protected static final PdfName PDFNAME_XOBJECT = new PdfName(
031: "XObject");
032: protected static final PdfName PDFNAME_SUBTYPE = new PdfName(
033: "Subtype");
034: protected static final PdfName PDFNAME_IMAGE = new PdfName("Image");
035: protected static final PdfName PDFNAME_FILTER = new PdfName(
036: "Filter");
037: protected static final PdfName PDFNAME_DCTDECODE = new PdfName(
038: "DCTDecode");
039: protected static final PdfName PDFNAME_WIDTH = new PdfName("Width");
040: protected static final PdfName PDFNAME_HEIGHT = new PdfName(
041: "Height");
042: protected static final PdfName PDFNAME_BITSPERCOMPONENT = new PdfName(
043: "BitsPerComponent");
044: protected static final PdfName PDFNAME_COLORSPACE = new PdfName(
045: "ColorSpace");
046: protected static final PdfName PDFNAME_DEVICERGB = new PdfName(
047: "DeviceRGB");
048: protected static final PdfInteger PDFINTEGER_8 = new PdfInteger(8);
049:
050: /**
051: The manager associated with this document.
052: */
053: protected PdfManager _m;
054:
055: /**
056: Constructs an <code>AddImageSimple</code> instance based on
057: a specified <code>PdfManager</code>.
058: */
059: public AddImageSimple(PdfManager manager) {
060:
061: _m = manager;
062:
063: }
064:
065: /**
066: Adds a specified JPEG image (contained in a file) to a page
067: in the PDF document. This method requires the calling
068: method to specify the original size of the image.
069: @param imageFile the file containing the JPEG image.
070: @param imageWidth the original width of the image.
071: @param imageHeight the original height of the image.
072: @param imageName a name object to associate with the image,
073: for identification purposes.
074: @param page an indirect reference to the page dictionary
075: object that the image will be added to.
076: @param positionX the X location to position the image at.
077: @param positionY the Y location to position the image at.
078: @param scaleX a scaling factor in the X dimension.
079: @param scaleY a scaling factor in the Y dimension.
080: @param background if <code>true</code>, the image will be
081: layered behind the existing page contents rather than on
082: top of it. This can be used to create simple watermarks.
083: @throws PdfFormatException
084: */
085: public void addImage(File imageFile, int imageWidth,
086: int imageHeight, PdfName imageName, PdfReference page,
087: float positionX, float positionY, float scaleX,
088: float scaleY, boolean background) throws IOException,
089: PdfFormatException {
090: synchronized (this ) {
091: synchronized (_m) {
092:
093: FileInputStream fis = new FileInputStream(imageFile);
094: FileChannel fc = fis.getChannel();
095: ByteBuffer bb = ByteBuffer.allocateDirect((int) fc
096: .size());
097: fc.read(bb);
098: fc.close();
099: fis.close();
100: bb.position(0);
101:
102: addImage(bb, imageWidth, imageHeight, imageName, page,
103: positionX, positionY, scaleX, scaleY,
104: background);
105:
106: }
107: }
108: }
109:
110: /**
111: Adds a specified JPEG image (contained in a buffer) to a
112: page in the PDF document. This method requires the calling
113: method to specify the original size of the image.
114: @param image the buffer containing the JPEG image. This
115: method reads from the current position until there are no
116: more bytes remaining.
117: @param imageWidth the original width of the image.
118: @param imageHeight the original height of the image.
119: @param imageName a name object to associate with the image,
120: for identification purposes.
121: @param page an indirect reference to the page dictionary
122: object that the image will be added to.
123: @param positionX the X location to position the image at.
124: @param positionY the Y location to position the image at.
125: @param scaleX a scaling factor in the X dimension.
126: @param scaleY a scaling factor in the Y dimension.
127: @param background if <code>true</code>, the image will be
128: layered behind the existing page contents rather than on
129: top of it. This can be used to create simple watermarks.
130: @throws PdfFormatException
131: */
132: public void addImage(ByteBuffer image, int imageWidth,
133: int imageHeight, PdfName imageName, PdfReference page,
134: float positionX, float positionY, float scaleX,
135: float scaleY, boolean background) throws IOException,
136: PdfFormatException {
137: synchronized (this ) {
138: synchronized (_m) {
139:
140: PdfPageTree pageTree = new PdfPageTree(_m);
141:
142: // get the page dictionary
143: Object obj = _m.getObjectIndirect(page);
144: if (!(obj instanceof PdfDictionary)) {
145: throw new PdfFormatException(
146: "Page object is not a dictionary.");
147: }
148: PdfDictionary pageExplicit = pageTree
149: .inheritAttributes((PdfDictionary) obj);
150: Map pageMap = new HashMap(pageExplicit.getMap());
151:
152: // create the image XObject
153: Map imageMap = new HashMap(9);
154: imageMap.put(PDFNAME_NAME, imageName);
155: imageMap.put(PDFNAME_TYPE, PDFNAME_XOBJECT);
156: imageMap.put(PDFNAME_SUBTYPE, PDFNAME_IMAGE);
157: imageMap.put(PDFNAME_FILTER, PDFNAME_DCTDECODE);
158: imageMap.put(PDFNAME_WIDTH, new PdfInteger(imageWidth));
159: imageMap.put(PDFNAME_HEIGHT,
160: new PdfInteger(imageHeight));
161: imageMap.put(PDFNAME_BITSPERCOMPONENT, PDFINTEGER_8);
162: imageMap.put(PDFNAME_COLORSPACE, PDFNAME_DEVICERGB);
163: PdfStream imageStream = new PdfStream(
164: new PdfDictionary(imageMap), image);
165:
166: // add the image XObject to the
167: // document
168: int imageId = _m.addObject(imageStream);
169:
170: // create a tiny contents stream with
171: // only "q" to save the state. this
172: // will go before all streams on the
173: // page, to ensure that we can get a
174: // clean coordinate matrix
175: String tinyString = "q\n";
176: byte[] tinyBytes = tinyString.getBytes();
177: ByteBuffer tinyBuffer = ByteBuffer.wrap(tinyBytes);
178: PdfStream tinyStream = new PdfStream(new PdfDictionary(
179: new HashMap()), tinyBuffer);
180:
181: // create the image contents stream
182: float sX = scaleX * imageWidth;
183: float sY = scaleY * imageHeight;
184: String contentsString = "Q q " + sX + " 0 0 " + sY
185: + ' ' + positionX + ' ' + positionY + " cm "
186: + imageName + " Do Q\n";
187: byte[] contentsBytes = contentsString.getBytes();
188: ByteBuffer contentsBuffer = ByteBuffer
189: .wrap(contentsBytes);
190: PdfStream contentsStream = new PdfStream(
191: new PdfDictionary(new HashMap()),
192: contentsBuffer);
193:
194: // add the contents streams to the
195: // document
196: int tinyId = _m.addObject(tinyStream);
197: int contentsId = _m.addObject(contentsStream);
198:
199: // add references to the contents
200: // streams to the page dictionary
201: obj = pageMap.get(PDFNAME_CONTENTS);
202: List contentList;
203: if (obj instanceof PdfArray) {
204: contentList = new ArrayList(((PdfArray) obj)
205: .getList());
206: } else if (obj instanceof PdfReference) {
207: contentList = new ArrayList();
208: contentList.add(obj);
209: } else {
210: throw new PdfFormatException(
211: "Page content stream is not an array or indirect reference.");
212: }
213: contentList.add(0, new PdfReference(tinyId, 0));
214: if (background) {
215: contentList.add(1, new PdfReference(contentsId, 0));
216: } else {
217: contentList.add(new PdfReference(contentsId, 0));
218: }
219: pageMap
220: .put(PDFNAME_CONTENTS,
221: new PdfArray(contentList));
222:
223: // get the resources dictionary
224: obj = pageMap.get(PDFNAME_RESOURCES);
225: if (obj == null) {
226: throw new PdfFormatException(
227: "Resources dictionary is missing from page.");
228: }
229: if (!(obj instanceof PdfObject)) {
230: throw new PdfFormatException(
231: "Resources dictionary is not a PDF object.");
232: }
233: obj = _m.getObjectIndirect((PdfObject) obj);
234: if (!(obj instanceof PdfDictionary)) {
235: throw new PdfFormatException(
236: "Resources object is not a dictionary.");
237: }
238: Map resourcesMap = new HashMap(((PdfDictionary) obj)
239: .getMap());
240:
241: // get the procedure set and add ImageC
242: obj = resourcesMap.get(PDFNAME_PROCSET);
243: Set procsetSet;
244: if (obj == null) {
245: procsetSet = new HashSet(1);
246: } else {
247: if (!(obj instanceof PdfObject)) {
248: throw new PdfFormatException(
249: "Procedure set is not a PDF object.");
250: }
251: obj = _m.getObjectIndirect((PdfObject) obj);
252: if (!(obj instanceof PdfArray)) {
253: throw new PdfFormatException(
254: "Procedure set is not an array.");
255: }
256: procsetSet = new HashSet(((PdfArray) obj).getList());
257: }
258: procsetSet.add(PDFNAME_IMAGEC);
259: resourcesMap.put(PDFNAME_PROCSET, new PdfArray(
260: new ArrayList(procsetSet)));
261:
262: // get the XObject dictionary, or
263: // create one
264: Map xobjectMap;
265: obj = resourcesMap.get(PDFNAME_XOBJECT);
266: if (obj == null) {
267: xobjectMap = new HashMap();
268: } else {
269: if (!(obj instanceof PdfObject)) {
270: throw new PdfFormatException(
271: "XObject is not a PDF object.");
272: }
273: obj = _m.getObjectIndirect((PdfObject) obj);
274: if (!(obj instanceof PdfDictionary)) {
275: throw new PdfFormatException(
276: "XObject is not a dictionary.");
277: }
278: xobjectMap = new HashMap(((PdfDictionary) obj)
279: .getMap());
280: }
281: xobjectMap.put(imageName, new PdfReference(imageId, 0));
282: resourcesMap.put(PDFNAME_XOBJECT, new PdfDictionary(
283: xobjectMap));
284:
285: // set the new resources dictionary
286: pageMap.put(PDFNAME_RESOURCES, new PdfDictionary(
287: resourcesMap));
288:
289: // update page dictionary
290: _m.setObject(new PdfDictionary(pageMap), page
291: .getObjectNumber());
292:
293: }
294: }
295: }
296:
297: }
|