1 | /* | |
2 | * $Id: PdfImage.java 4067 2009-09-19 12:56:50Z psoares33 $ | |
3 | * | |
4 | * Copyright 1999, 2000, 2001, 2002 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.pdf; | |
51 | ||
52 | import java.io.ByteArrayOutputStream; | |
53 | import java.io.IOException; | |
54 | import java.io.InputStream; | |
55 | import java.io.OutputStream; | |
56 | import com.lowagie.text.error_messages.MessageLocalization; | |
57 | ||
58 | import com.lowagie.text.Image; | |
59 | ||
60 | /** | |
61 | * <CODE>PdfImage</CODE> is a <CODE>PdfStream</CODE> containing an image-<CODE>Dictionary</CODE> and -stream. | |
62 | */ | |
63 | ||
64 | public class PdfImage extends PdfStream { | |
65 | | |
66 | static final int TRANSFERSIZE = 4096; | |
67 | // membervariables | |
68 | | |
69 | /** This is the <CODE>PdfName</CODE> of the image. */ | |
70 | protected PdfName name = null; | |
71 | | |
72 | // constructor | |
73 | | |
74 | /** | |
75 | * Constructs a <CODE>PdfImage</CODE>-object. | |
76 | * | |
77 | * @param image the <CODE>Image</CODE>-object | |
78 | * @param name the <CODE>PdfName</CODE> for this image | |
79 | * @throws BadPdfFormatException on error | |
80 | */ | |
81 | | |
82 | public PdfImage(Image image, String name, PdfIndirectReference maskRef) throws BadPdfFormatException { | |
83 | super(); | |
84 | this.name = new PdfName(name); | |
85 |
1
1. |
put(PdfName.TYPE, PdfName.XOBJECT); |
86 |
1
1. |
put(PdfName.SUBTYPE, PdfName.IMAGE); |
87 |
1
1. |
put(PdfName.WIDTH, new PdfNumber(image.getWidth())); |
88 |
1
1. |
put(PdfName.HEIGHT, new PdfNumber(image.getHeight())); |
89 |
1
1. |
if (image.getLayer() != null) |
90 |
1
1. |
put(PdfName.OC, image.getLayer().getRef()); |
91 |
4
1. 2. 3. 4. |
if (image.isMask() && (image.getBpc() == 1 || image.getBpc() > 0xff)) |
92 |
1
1. |
put(PdfName.IMAGEMASK, PdfBoolean.PDFTRUE); |
93 |
1
1. |
if (maskRef != null) { |
94 |
1
1. |
if (image.isSmask()) |
95 |
1
1. |
put(PdfName.SMASK, maskRef); |
96 | else | |
97 |
1
1. |
put(PdfName.MASK, maskRef); |
98 | } | |
99 |
2
1. 2. |
if (image.isMask() && image.isInverted()) |
100 |
1
1. |
put(PdfName.DECODE, new PdfLiteral("[1 0]")); |
101 |
1
1. |
if (image.isInterpolation()) |
102 |
1
1. |
put(PdfName.INTERPOLATE, PdfBoolean.PDFTRUE); |
103 | InputStream is = null; | |
104 | try { | |
105 | // Raw Image data | |
106 |
1
1. |
if (image.isImgRaw()) { |
107 | // will also have the CCITT parameters | |
108 | int colorspace = image.getColorspace(); | |
109 | int[] transparency = image.getTransparency(); | |
110 |
3
1. 2. 3. |
if (transparency != null && !image.isMask() && maskRef == null) { |
111 | String s = "["; | |
112 | for (int i : transparency) s += i + " "; | |
113 | s += "]"; | |
114 |
1
1. |
put(PdfName.MASK, new PdfLiteral(s)); |
115 | } | |
116 | bytes = image.getRawData(); | |
117 |
1
1. |
put(PdfName.LENGTH, new PdfNumber(bytes.length)); |
118 | int bpc = image.getBpc(); | |
119 |
2
1. 2. |
if (bpc > 0xff) { |
120 |
1
1. |
if (!image.isMask()) |
121 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICEGRAY); |
122 |
1
1. |
put(PdfName.BITSPERCOMPONENT, new PdfNumber(1)); |
123 |
1
1. |
put(PdfName.FILTER, PdfName.CCITTFAXDECODE); |
124 |
1
1. |
int k = bpc - Image.CCITTG3_1D; |
125 | PdfDictionary decodeparms = new PdfDictionary(); | |
126 |
1
1. |
if (k != 0) |
127 |
1
1. |
decodeparms.put(PdfName.K, new PdfNumber(k)); |
128 |
2
1. 2. |
if ((colorspace & Image.CCITT_BLACKIS1) != 0) |
129 |
1
1. |
decodeparms.put(PdfName.BLACKIS1, PdfBoolean.PDFTRUE); |
130 |
2
1. 2. |
if ((colorspace & Image.CCITT_ENCODEDBYTEALIGN) != 0) |
131 |
1
1. |
decodeparms.put(PdfName.ENCODEDBYTEALIGN, PdfBoolean.PDFTRUE); |
132 |
2
1. 2. |
if ((colorspace & Image.CCITT_ENDOFLINE) != 0) |
133 |
1
1. |
decodeparms.put(PdfName.ENDOFLINE, PdfBoolean.PDFTRUE); |
134 |
2
1. 2. |
if ((colorspace & Image.CCITT_ENDOFBLOCK) != 0) |
135 |
1
1. |
decodeparms.put(PdfName.ENDOFBLOCK, PdfBoolean.PDFFALSE); |
136 |
1
1. |
decodeparms.put(PdfName.COLUMNS, new PdfNumber(image.getWidth())); |
137 |
1
1. |
decodeparms.put(PdfName.ROWS, new PdfNumber(image.getHeight())); |
138 |
1
1. |
put(PdfName.DECODEPARMS, decodeparms); |
139 | } | |
140 | else { | |
141 | switch(colorspace) { | |
142 | case 1: | |
143 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICEGRAY); |
144 |
1
1. |
if (image.isInverted()) |
145 |
1
1. |
put(PdfName.DECODE, new PdfLiteral("[1 0]")); |
146 | break; | |
147 | case 3: | |
148 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICERGB); |
149 |
1
1. |
if (image.isInverted()) |
150 |
1
1. |
put(PdfName.DECODE, new PdfLiteral("[1 0 1 0 1 0]")); |
151 | break; | |
152 | case 4: | |
153 | default: | |
154 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICECMYK); |
155 |
1
1. |
if (image.isInverted()) |
156 |
1
1. |
put(PdfName.DECODE, new PdfLiteral("[1 0 1 0 1 0 1 0]")); |
157 | } | |
158 | PdfDictionary additional = image.getAdditional(); | |
159 |
1
1. |
if (additional != null) |
160 |
1
1. |
putAll(additional); |
161 |
4
1. 2. 3. 4. |
if (image.isMask() && (image.getBpc() == 1 || image.getBpc() > 8)) |
162 |
1
1. |
remove(PdfName.COLORSPACE); |
163 |
1
1. |
put(PdfName.BITSPERCOMPONENT, new PdfNumber(image.getBpc())); |
164 |
1
1. |
if (image.isDeflated()) |
165 |
1
1. |
put(PdfName.FILTER, PdfName.FLATEDECODE); |
166 | else { | |
167 |
1
1. |
flateCompress(image.getCompressionLevel()); |
168 | } | |
169 | } | |
170 | return; | |
171 | } | |
172 | // GIF, JPEG or PNG | |
173 | String errorID; | |
174 |
1
1. |
if (image.getRawData() == null){ |
175 | is = image.getUrl().openStream(); | |
176 | errorID = image.getUrl().toString(); | |
177 | } | |
178 | else{ | |
179 | is = new java.io.ByteArrayInputStream(image.getRawData()); | |
180 | errorID = "Byte array"; | |
181 | } | |
182 | switch(image.type()) { | |
183 | case Image.JPEG: | |
184 |
1
1. |
put(PdfName.FILTER, PdfName.DCTDECODE); |
185 | switch(image.getColorspace()) { | |
186 | case 1: | |
187 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICEGRAY); |
188 | break; | |
189 | case 3: | |
190 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICERGB); |
191 | break; | |
192 | default: | |
193 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICECMYK); |
194 |
1
1. |
if (image.isInverted()) { |
195 |
1
1. |
put(PdfName.DECODE, new PdfLiteral("[1 0 1 0 1 0 1 0]")); |
196 | } | |
197 | } | |
198 |
1
1. |
put(PdfName.BITSPERCOMPONENT, new PdfNumber(8)); |
199 |
1
1. |
if (image.getRawData() != null){ |
200 | bytes = image.getRawData(); | |
201 |
1
1. |
put(PdfName.LENGTH, new PdfNumber(bytes.length)); |
202 | return; | |
203 | } | |
204 | streamBytes = new ByteArrayOutputStream(); | |
205 |
1
1. |
transferBytes(is, streamBytes, -1); |
206 | break; | |
207 | case Image.JPEG2000: | |
208 |
1
1. |
put(PdfName.FILTER, PdfName.JPXDECODE); |
209 |
2
1. 2. |
if (image.getColorspace() > 0) { |
210 | switch(image.getColorspace()) { | |
211 | case 1: | |
212 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICEGRAY); |
213 | break; | |
214 | case 3: | |
215 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICERGB); |
216 | break; | |
217 | default: | |
218 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICECMYK); |
219 | } | |
220 |
1
1. |
put(PdfName.BITSPERCOMPONENT, new PdfNumber(image.getBpc())); |
221 | } | |
222 |
1
1. |
if (image.getRawData() != null){ |
223 | bytes = image.getRawData(); | |
224 |
1
1. |
put(PdfName.LENGTH, new PdfNumber(bytes.length)); |
225 | return; | |
226 | } | |
227 | streamBytes = new ByteArrayOutputStream(); | |
228 |
1
1. |
transferBytes(is, streamBytes, -1); |
229 | break; | |
230 | case Image.JBIG2: | |
231 |
1
1. |
put(PdfName.FILTER, PdfName.JBIG2DECODE); |
232 |
1
1. |
put(PdfName.COLORSPACE, PdfName.DEVICEGRAY); |
233 |
1
1. |
put(PdfName.BITSPERCOMPONENT, new PdfNumber(1)); |
234 |
1
1. |
if (image.getRawData() != null){ |
235 | bytes = image.getRawData(); | |
236 |
1
1. |
put(PdfName.LENGTH, new PdfNumber(bytes.length)); |
237 | return; | |
238 | } | |
239 | streamBytes = new ByteArrayOutputStream(); | |
240 |
1
1. |
transferBytes(is, streamBytes, -1); |
241 | break; | |
242 | default: | |
243 | throw new BadPdfFormatException(MessageLocalization.getComposedMessage("1.is.an.unknown.image.format", errorID)); | |
244 | } | |
245 |
1
1. |
put(PdfName.LENGTH, new PdfNumber(streamBytes.size())); |
246 | } | |
247 | catch(IOException ioe) { | |
248 | throw new BadPdfFormatException(ioe.getMessage()); | |
249 | } | |
250 | finally { | |
251 |
1
1. |
if (is != null) { |
252 | try{ | |
253 |
1
1. |
is.close(); |
254 | } | |
255 | catch (Exception ee) { | |
256 | // empty on purpose | |
257 | } | |
258 | } | |
259 | } | |
260 | } | |
261 | | |
262 | /** | |
263 | * Returns the <CODE>PdfName</CODE> of the image. | |
264 | * | |
265 | * @return the name | |
266 | */ | |
267 | | |
268 | public PdfName name() { | |
269 | return name; | |
270 | } | |
271 | | |
272 | static void transferBytes(InputStream in, OutputStream out, int len) throws IOException { | |
273 | byte[] buffer = new byte[TRANSFERSIZE]; | |
274 |
2
1. transferBytes : changed conditional boundary → NO_COVERAGE 2. transferBytes : negated conditional → NO_COVERAGE |
if (len < 0) |
275 | len = 0x7fff0000; | |
276 | int size; | |
277 |
1
1. transferBytes : negated conditional → NO_COVERAGE |
while (len != 0) { |
278 | size = in.read(buffer, 0, Math.min(len, TRANSFERSIZE)); | |
279 |
2
1. transferBytes : changed conditional boundary → NO_COVERAGE 2. transferBytes : negated conditional → NO_COVERAGE |
if (size < 0) |
280 | return; | |
281 |
1
1. transferBytes : removed call to java/io/OutputStream::write → NO_COVERAGE |
out.write(buffer, 0, size); |
282 |
1
1. transferBytes : Replaced integer subtraction with addition → NO_COVERAGE |
len -= size; |
283 | } | |
284 | } | |
285 | | |
286 | protected void importAll(PdfImage dup) { | |
287 | name = dup.name; | |
288 | compressed = dup.compressed; | |
289 | compressionLevel = dup.compressionLevel; | |
290 | streamBytes = dup.streamBytes; | |
291 | bytes = dup.bytes; | |
292 | hashMap = dup.hashMap; | |
293 | } | |
294 | } | |
Mutations | ||
85 |
1.1 |
|
86 |
1.1 |
|
87 |
1.1 |
|
88 |
1.1 |
|
89 |
1.1 |
|
90 |
1.1 |
|
91 |
1.1 2.2 3.3 4.4 |
|
92 |
1.1 |
|
93 |
1.1 |
|
94 |
1.1 |
|
95 |
1.1 |
|
97 |
1.1 |
|
99 |
1.1 2.2 |
|
100 |
1.1 |
|
101 |
1.1 |
|
102 |
1.1 |
|
106 |
1.1 |
|
110 |
1.1 2.2 3.3 |
|
114 |
1.1 |
|
117 |
1.1 |
|
119 |
1.1 2.2 |
|
120 |
1.1 |
|
121 |
1.1 |
|
122 |
1.1 |
|
123 |
1.1 |
|
124 |
1.1 |
|
126 |
1.1 |
|
127 |
1.1 |
|
128 |
1.1 2.2 |
|
129 |
1.1 |
|
130 |
1.1 2.2 |
|
131 |
1.1 |
|
132 |
1.1 2.2 |
|
133 |
1.1 |
|
134 |
1.1 2.2 |
|
135 |
1.1 |
|
136 |
1.1 |
|
137 |
1.1 |
|
138 |
1.1 |
|
143 |
1.1 |
|
144 |
1.1 |
|
145 |
1.1 |
|
148 |
1.1 |
|
149 |
1.1 |
|
150 |
1.1 |
|
154 |
1.1 |
|
155 |
1.1 |
|
156 |
1.1 |
|
159 |
1.1 |
|
160 |
1.1 |
|
161 |
1.1 2.2 3.3 4.4 |
|
162 |
1.1 |
|
163 |
1.1 |
|
164 |
1.1 |
|
165 |
1.1 |
|
167 |
1.1 |
|
174 |
1.1 |
|
184 |
1.1 |
|
187 |
1.1 |
|
190 |
1.1 |
|
193 |
1.1 |
|
194 |
1.1 |
|
195 |
1.1 |
|
198 |
1.1 |
|
199 |
1.1 |
|
201 |
1.1 |
|
205 |
1.1 |
|
208 |
1.1 |
|
209 |
1.1 2.2 |
|
212 |
1.1 |
|
215 |
1.1 |
|
218 |
1.1 |
|
220 |
1.1 |
|
222 |
1.1 |
|
224 |
1.1 |
|
228 |
1.1 |
|
231 |
1.1 |
|
232 |
1.1 |
|
233 |
1.1 |
|
234 |
1.1 |
|
236 |
1.1 |
|
240 |
1.1 |
|
245 |
1.1 |
|
251 |
1.1 |
|
253 |
1.1 |
|
274 |
1.1 2.2 |
|
277 |
1.1 |
|
279 |
1.1 2.2 |
|
281 |
1.1 |
|
282 |
1.1 |