15
15
* limitations under the License.
18
/* $Id: PSImageUtils.java 1353184 2012-06-23 19:18:01Z gadams $ */
18
/* $Id: PSImageUtils.java 1557632 2014-01-12 23:59:42Z lbernardo $ */
20
20
package org.apache.xmlgraphics.ps;
22
import java.awt.Color;
22
23
import java.awt.Dimension;
23
24
import java.awt.color.ColorSpace;
24
25
import java.awt.geom.Dimension2D;
25
26
import java.awt.geom.Rectangle2D;
26
27
import java.awt.image.ColorModel;
27
28
import java.awt.image.DataBuffer;
29
import java.awt.image.DataBufferByte;
28
30
import java.awt.image.IndexColorModel;
29
31
import java.awt.image.Raster;
30
32
import java.awt.image.RenderedImage;
31
33
import java.io.IOException;
32
34
import java.io.InputStream;
33
35
import java.io.OutputStream;
36
import java.util.Arrays;
35
38
import org.apache.commons.io.IOUtils;
141
144
gen.restoreGraphicsState();
147
public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription,
148
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen) throws IOException {
149
writeImage(encoder, imgDim, imgDescription, targetRect, colorModel, gen, null);
145
153
* Writes a bitmap image to the PostScript stream.
146
154
* @param encoder the image encoder
152
160
* @throws IOException In case of an I/O exception
154
162
public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription,
155
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen)
163
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen, RenderedImage ri)
156
164
throws IOException {
158
166
gen.saveGraphicsState();
178
186
imageDict.put("/DataSource", "Data");
180
188
populateImageDictionary(imgDim, colorModel, imageDict);
191
DataBuffer buffer = ri.getData().getDataBuffer();
192
if (!(buffer instanceof DataBufferByte)) {
193
imageDict.put("/BitsPerComponent", 8);
196
writeImageCommand(imageDict, colorModel, gen);
199
* the following two lines could be enabled if something still goes wrong
200
* gen.write("Data closefile");
201
* gen.write("RawData flushfile");
203
gen.writeln("} stopped {handleerror} if");
204
gen.writeln(" RawData flushfile");
205
gen.writeln("} exec");
207
compressAndWriteBitmap(encoder, gen);
210
gen.commentln("%AXGEndBitmap");
211
gen.restoreGraphicsState();
215
* Writes a bitmap image to the PostScript stream.
216
* @param encoder the image encoder
217
* @param imgDim the dimensions of the image
218
* @param imgDescription the name of the image
219
* @param targetRect the target rectangle to place the image in
220
* @param colorModel the color model of the image
221
* @param gen the PostScript generator
222
* @throws IOException In case of an I/O exception
224
public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription,
225
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen, RenderedImage ri,
229
gen.saveGraphicsState();
230
translateAndScale(gen, null, targetRect);
231
gen.commentln("%AXGBeginBitmap: " + imgDescription);
234
String implicitFilter = encoder.getImplicitFilter();
235
if (implicitFilter != null) {
236
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
237
gen.writeln("/Data RawData " + implicitFilter + " filter def");
239
if (gen.getPSLevel() >= 3) {
240
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
241
gen.writeln("/Data RawData /FlateDecode filter def");
243
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
244
gen.writeln("/Data RawData /RunLengthDecode filter def");
248
PSDictionary imageDict = new PSDictionary();
249
imageDict.put("/DataSource", "Data");
251
populateImageDictionary(imgDim, colorModel, imageDict, maskColor);
254
DataBuffer buffer = ri.getData().getDataBuffer();
255
if (!(buffer instanceof DataBufferByte)) {
256
imageDict.put("/BitsPerComponent", 8);
181
259
writeImageCommand(imageDict, colorModel, gen);
199
277
private static ColorModel populateImageDictionary(Dimension imgDim, ColorModel colorModel,
200
278
PSDictionary imageDict) {
279
imageDict.put("/ImageType", "1");
280
colorModel = writeImageDictionary(imgDim, imageDict, colorModel);
284
private static ColorModel populateImageDictionary(Dimension imgDim, ColorModel colorModel,
285
PSDictionary imageDict, Color maskColor) {
286
imageDict.put("/ImageType", "4");
288
colorModel = writeImageDictionary(imgDim, imageDict, colorModel);
289
imageDict.put("/MaskColor", String.format("[ %d %d %d ]", maskColor.getRed(),
290
maskColor.getGreen(), maskColor.getBlue()));
294
private static ColorModel writeImageDictionary(Dimension imgDim, PSDictionary imageDict,
295
ColorModel colorModel) {
201
296
String w = Integer.toString(imgDim.width);
202
297
String h = Integer.toString(imgDim.height);
203
imageDict.put("/ImageType", "1");
204
298
imageDict.put("/Width", w);
205
299
imageDict.put("/Height", h);
255
349
if ((cm instanceof IndexColorModel)) {
256
350
ColorSpace cs = cm.getColorSpace();
257
351
IndexColorModel im = (IndexColorModel)cm;
258
gen.write("[/Indexed " + getColorSpaceName(cs));
352
boolean isDeviceGray;
259
353
int c = im.getMapSize();
354
int[] palette = new int[c];
356
byte[] reds = new byte[c];
357
byte[] greens = new byte[c];
358
byte[] blues = new byte[c];
360
im.getGreens(greens);
260
362
int hival = c - 1;
261
363
if (hival > 4095) {
262
364
throw new UnsupportedOperationException("hival must not go beyond 4095");
366
isDeviceGray = Arrays.equals(reds, blues) && Arrays.equals(blues, greens);
368
gen.write("[/Indexed " + "/DeviceGray");
370
gen.write("[/Indexed " + getColorSpaceName(cs));
264
372
gen.writeln(" " + Integer.toString(hival));
266
int[] palette = new int[c];
268
for (int i = 0; i < c; i++) {
375
gen.write(toHexString(blues));
377
for (int i = 0; i < c; i++) {
386
gen.write(rgb2Hex(palette[i]));
277
gen.write(rgb2Hex(palette[i]));
279
389
gen.writeln(">");
280
390
gen.writeln("] setcolorspace");
396
static String toHexString(byte[] color) {
397
char[] hexChars = new char[color.length * 2];
399
for (int i = 0; i < color.length; i++) {
401
hexChars[i * 2] = HEX[x >>> 4];
402
hexChars[i * 2 + 1] = HEX[x & 0x0F];
404
return new String(hexChars);
286
407
static void writeImageCommand(RenderedImage img,
287
408
PSDictionary imageDict, PSGenerator gen) throws IOException {
288
409
ImageEncodingHelper helper = new ImageEncodingHelper(img, true);
351
472
ImageEncodingHelper helper = new ImageEncodingHelper(img);
352
473
ColorModel cm = helper.getEncodedColorModel();
354
writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen);
475
writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen, img);