org.apache.xmlgraphics.ps.PSImageUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: PSImageUtils.java 1792872 2017-04-27 12:30:09Z ssteiner $ */
package org.apache.xmlgraphics.ps;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.color.ColorSpace;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import org.apache.commons.io.IOUtils;
import org.apache.xmlgraphics.util.io.ASCII85OutputStream;
import org.apache.xmlgraphics.util.io.Finalizable;
import org.apache.xmlgraphics.util.io.FlateEncodeOutputStream;
import org.apache.xmlgraphics.util.io.RunLengthEncodeOutputStream;
// CSOFF: HideUtilityClassConstructor
/**
* Utility code for rendering images in PostScript.
*/
public class PSImageUtils {
public PSImageUtils() {
}
/**
* Writes a bitmap image to the PostScript stream.
* @param img the bitmap image as a byte array
* @param imgDim the dimensions of the image
* @param imgDescription the name of the image
* @param targetRect the target rectangle to place the image in
* @param isJPEG true if "img" contains a DCT-encoded images, false if "img" contains the
* decoded bitmap
* @param colorSpace the color space of the image
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
* @deprecated Please use the variant with the more versatile ImageEncoder as parameter
*/
public static void writeImage(final byte[] img,
Dimension imgDim, String imgDescription,
Rectangle2D targetRect,
final boolean isJPEG, ColorSpace colorSpace,
PSGenerator gen) throws IOException {
ImageEncoder encoder = new ImageEncoder() {
public void writeTo(OutputStream out) throws IOException {
out.write(img);
}
public String getImplicitFilter() {
if (isJPEG) {
return "<< >> /DCTDecode";
} else {
return null;
}
}
};
writeImage(encoder, imgDim, imgDescription, targetRect, colorSpace, 8, false, gen);
}
/**
* Writes a bitmap image to the PostScript stream.
* @param encoder the image encoder
* @param imgDim the dimensions of the image
* @param imgDescription the name of the image
* @param targetRect the target rectangle to place the image in
* @param colorSpace the color space of the image
* @param bitsPerComponent the number of bits per component
* @param invertImage true if the image shall be inverted
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
*/
public static void writeImage(ImageEncoder encoder,
Dimension imgDim, String imgDescription,
Rectangle2D targetRect,
ColorSpace colorSpace, int bitsPerComponent, boolean invertImage,
PSGenerator gen) throws IOException {
gen.saveGraphicsState();
translateAndScale(gen, null, targetRect);
gen.commentln("%AXGBeginBitmap: " + imgDescription);
gen.writeln("{{");
// Template: (RawData is used for the EOF signal only)
// gen.write("/RawData currentfile filter def");
// gen.write("/Data RawData [...] def");
String implicitFilter = encoder.getImplicitFilter();
if (implicitFilter != null) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData " + implicitFilter + " filter def");
} else {
if (gen.getPSLevel() >= 3) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData /FlateDecode filter def");
} else {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData /RunLengthDecode filter def");
}
}
PSDictionary imageDict = new PSDictionary();
imageDict.put("/DataSource", "Data");
imageDict.put("/BitsPerComponent", Integer.toString(bitsPerComponent));
writeImageCommand(imageDict, imgDim, colorSpace, invertImage, gen);
/* the following two lines could be enabled if something still goes wrong
* gen.write("Data closefile");
* gen.write("RawData flushfile");
*/
gen.writeln("} stopped {handleerror} if");
gen.writeln(" RawData flushfile");
gen.writeln("} exec");
compressAndWriteBitmap(encoder, gen);
gen.newLine();
gen.commentln("%AXGEndBitmap");
gen.restoreGraphicsState();
}
public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription,
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen) throws IOException {
writeImage(encoder, imgDim, imgDescription, targetRect, colorModel, gen, null);
}
/**
* Writes a bitmap image to the PostScript stream.
* @param encoder the image encoder
* @param imgDim the dimensions of the image
* @param imgDescription the name of the image
* @param targetRect the target rectangle to place the image in
* @param colorModel the color model of the image
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
*/
public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription,
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen, RenderedImage ri)
throws IOException {
gen.saveGraphicsState();
translateAndScale(gen, null, targetRect);
gen.commentln("%AXGBeginBitmap: " + imgDescription);
gen.writeln("{{");
String implicitFilter = encoder.getImplicitFilter();
if (implicitFilter != null) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData " + implicitFilter + " filter def");
} else {
if (gen.getPSLevel() >= 3) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData /FlateDecode filter def");
} else {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData /RunLengthDecode filter def");
}
}
PSDictionary imageDict = new PSDictionary();
imageDict.put("/DataSource", "Data");
populateImageDictionary(imgDim, colorModel, imageDict);
if (ri != null) {
DataBuffer buffer = ri.getData().getDataBuffer();
if (!(buffer instanceof DataBufferByte)) {
imageDict.put("/BitsPerComponent", 8);
}
}
writeImageCommand(imageDict, colorModel, gen);
/*
* the following two lines could be enabled if something still goes wrong
* gen.write("Data closefile");
* gen.write("RawData flushfile");
*/
gen.writeln("} stopped {handleerror} if");
gen.writeln(" RawData flushfile");
gen.writeln("} exec");
compressAndWriteBitmap(encoder, gen);
gen.newLine();
gen.commentln("%AXGEndBitmap");
gen.restoreGraphicsState();
}
/**
* Writes a bitmap image to the PostScript stream.
* @param encoder the image encoder
* @param imgDim the dimensions of the image
* @param imgDescription the name of the image
* @param targetRect the target rectangle to place the image in
* @param colorModel the color model of the image
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
*/
public static void writeImage(ImageEncoder encoder, Dimension imgDim, String imgDescription,
Rectangle2D targetRect, ColorModel colorModel, PSGenerator gen, RenderedImage ri,
Color maskColor)
throws IOException {
gen.saveGraphicsState();
translateAndScale(gen, null, targetRect);
gen.commentln("%AXGBeginBitmap: " + imgDescription);
gen.writeln("{{");
String implicitFilter = encoder.getImplicitFilter();
if (implicitFilter != null) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData " + implicitFilter + " filter def");
} else {
if (gen.getPSLevel() >= 3) {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData /FlateDecode filter def");
} else {
gen.writeln("/RawData currentfile /ASCII85Decode filter def");
gen.writeln("/Data RawData /RunLengthDecode filter def");
}
}
PSDictionary imageDict = new PSDictionary();
imageDict.put("/DataSource", "Data");
populateImageDictionary(imgDim, colorModel, imageDict, maskColor);
if (ri != null) {
DataBuffer buffer = ri.getData().getDataBuffer();
if (!(buffer instanceof DataBufferByte)) {
imageDict.put("/BitsPerComponent", 8);
}
}
writeImageCommand(imageDict, colorModel, gen);
/*
* the following two lines could be enabled if something still goes wrong
* gen.write("Data closefile");
* gen.write("RawData flushfile");
*/
gen.writeln("} stopped {handleerror} if");
gen.writeln(" RawData flushfile");
gen.writeln("} exec");
compressAndWriteBitmap(encoder, gen);
gen.newLine();
gen.commentln("%AXGEndBitmap");
gen.restoreGraphicsState();
}
private static ColorModel populateImageDictionary(Dimension imgDim, ColorModel colorModel,
PSDictionary imageDict) {
imageDict.put("/ImageType", "1");
colorModel = writeImageDictionary(imgDim, imageDict, colorModel);
return colorModel;
}
private static ColorModel populateImageDictionary(Dimension imgDim, ColorModel colorModel,
PSDictionary imageDict, Color maskColor) {
imageDict.put("/ImageType", "4");
colorModel = writeImageDictionary(imgDim, imageDict, colorModel);
imageDict.put("/MaskColor", String.format("[ %d %d %d ]", maskColor.getRed(),
maskColor.getGreen(), maskColor.getBlue()));
return colorModel;
}
private static ColorModel writeImageDictionary(Dimension imgDim, PSDictionary imageDict,
ColorModel colorModel) {
String w = Integer.toString(imgDim.width);
String h = Integer.toString(imgDim.height);
imageDict.put("/Width", w);
imageDict.put("/Height", h);
boolean invertColors = false;
String decodeArray = getDecodeArray(colorModel.getNumColorComponents(), invertColors);
int bitsPerComp = colorModel.getComponentSize(0);
// Setup scanning for left-to-right and top-to-bottom
imageDict.put("/ImageMatrix", "[" + w + " 0 0 " + h + " 0 0]");
if ((colorModel instanceof IndexColorModel)) {
IndexColorModel indexColorModel = (IndexColorModel) colorModel;
int c = indexColorModel.getMapSize();
int hival = c - 1;
if (hival > 4095) {
throw new UnsupportedOperationException("hival must not go beyond 4095");
}
bitsPerComp = indexColorModel.getPixelSize();
int ceiling = ((int) Math.pow(2, bitsPerComp)) - 1;
decodeArray = "[0 " + ceiling + "]";
}
imageDict.put("/BitsPerComponent", Integer.toString(bitsPerComp));
imageDict.put("/Decode", decodeArray);
return colorModel;
}
private static String getDecodeArray(int numComponents, boolean invertColors) {
String decodeArray;
StringBuffer sb = new StringBuffer("[");
for (int i = 0; i < numComponents; i++) {
if (i > 0) {
sb.append(" ");
}
if (invertColors) {
sb.append("1 0");
} else {
sb.append("0 1");
}
}
sb.append("]");
decodeArray = sb.toString();
return decodeArray;
}
private static void prepareColorspace(PSGenerator gen, ColorSpace colorSpace)
throws IOException {
gen.writeln(getColorSpaceName(colorSpace) + " setcolorspace");
}
private static void prepareColorSpace(PSGenerator gen, ColorModel cm) throws IOException {
//Prepare color space
if ((cm instanceof IndexColorModel)) {
ColorSpace cs = cm.getColorSpace();
IndexColorModel im = (IndexColorModel)cm;
boolean isDeviceGray;
int c = im.getMapSize();
int[] palette = new int[c];
im.getRGBs(palette);
byte[] reds = new byte[c];
byte[] greens = new byte[c];
byte[] blues = new byte[c];
im.getReds(reds);
im.getGreens(greens);
im.getBlues(blues);
int hival = c - 1;
if (hival > 4095) {
throw new UnsupportedOperationException("hival must not go beyond 4095");
}
isDeviceGray = Arrays.equals(reds, blues) && Arrays.equals(blues, greens);
if (isDeviceGray) {
gen.write("[/Indexed " + "/DeviceGray");
} else {
gen.write("[/Indexed " + getColorSpaceName(cs));
}
gen.writeln(" " + Integer.toString(hival));
gen.write(" <");
if (isDeviceGray) {
gen.write(toHexString(blues));
} else {
for (int i = 0; i < c; i++) {
if (i > 0) {
if ((i % 8) == 0) {
gen.newLine();
gen.write(" ");
} else {
gen.write(" ");
}
}
gen.write(rgb2Hex(palette[i]));
}
}
gen.writeln(">");
gen.writeln("] setcolorspace");
} else {
gen.writeln(getColorSpaceName(cm.getColorSpace()) + " setcolorspace");
}
}
static String toHexString(byte[] color) {
char[] hexChars = new char[color.length * 2];
int x;
for (int i = 0; i < color.length; i++) {
x = color[i] & 0xFF;
hexChars[i * 2] = HEX[x >>> 4];
hexChars[i * 2 + 1] = HEX[x & 0x0F];
}
return new String(hexChars);
}
static void writeImageCommand(RenderedImage img,
PSDictionary imageDict, PSGenerator gen) throws IOException {
ImageEncodingHelper helper = new ImageEncodingHelper(img, true);
ColorModel cm = helper.getEncodedColorModel();
Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
populateImageDictionary(imgDim, cm, imageDict);
writeImageCommand(imageDict, cm, gen);
}
static void writeImageCommand(PSDictionary imageDict, ColorModel cm, PSGenerator gen)
throws IOException {
prepareColorSpace(gen, cm);
gen.write(imageDict.toString());
gen.writeln(" image");
}
static void writeImageCommand(PSDictionary imageDict,
Dimension imgDim, ColorSpace colorSpace, boolean invertImage,
PSGenerator gen) throws IOException {
imageDict.put("/ImageType", "1");
imageDict.put("/Width", Integer.toString(imgDim.width));
imageDict.put("/Height", Integer.toString(imgDim.height));
String decodeArray = getDecodeArray(colorSpace.getNumComponents(), invertImage);
imageDict.put("/Decode", decodeArray);
// Setup scanning for left-to-right and top-to-bottom
imageDict.put("/ImageMatrix", "[" + imgDim.width + " 0 0 " + imgDim.height + " 0 0]");
prepareColorspace(gen, colorSpace);
gen.write(imageDict.toString());
gen.writeln(" image");
}
private static final char[] HEX = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
private static String rgb2Hex(int rgb) {
StringBuffer sb = new StringBuffer();
for (int i = 5; i >= 0; i--) {
int shift = i * 4;
int n = (rgb & (15 << shift)) >> shift;
sb.append(HEX[n % 16]);
}
return sb.toString();
}
/**
* Renders a bitmap image to PostScript.
* @param img image to render
* @param x x position
* @param y y position
* @param w width
* @param h height
* @param gen PS generator
* @throws IOException In case of an I/O problem while rendering the image
*/
public static void renderBitmapImage(RenderedImage img,
float x, float y, float w, float h, PSGenerator gen, Color mask)
throws IOException {
Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
ImageEncoder encoder = ImageEncodingHelper.createRenderedImageEncoder(img);
Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
String imgDescription = img.getClass().getName();
ImageEncodingHelper helper = new ImageEncodingHelper(img);
ColorModel cm = helper.getEncodedColorModel();
if (mask == null) {
writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen, img);
} else {
writeImage(encoder, imgDim, imgDescription, targetRect, cm, gen, img, mask);
}
}
/**
* Writes a bitmap image as a PostScript form enclosed by DSC resource wrappers to the
* PostScript file.
* @param img the raw bitmap data
* @param imgDim the dimensions of the image
* @param formName the name of the PostScript form to use
* @param imageDescription a description of the image added as a DSC Title comment
* @param isJPEG true if "img" contains a DCT-encoded images, false if "img" contains the
* decoded bitmap
* @param colorSpace the color space of the image
* @param gen the PostScript generator
* @return a PSResource representing the form for resource tracking
* @throws IOException In case of an I/O exception
* @deprecated Please use {@link FormGenerator}
*/
public static PSResource writeReusableImage(final byte[] img,
Dimension imgDim, String formName, String imageDescription,
final boolean isJPEG, ColorSpace colorSpace,
PSGenerator gen) throws IOException {
ImageEncoder encoder = new ImageEncoder() {
public void writeTo(OutputStream out) throws IOException {
out.write(img);
}
public String getImplicitFilter() {
if (isJPEG) {
return "<< >> /DCTDecode";
} else {
return null;
}
}
};
return writeReusableImage(encoder, imgDim, formName,
imageDescription, colorSpace, false, gen);
}
/**
* Writes a bitmap image as a PostScript form enclosed by DSC resource wrappers to the
* PostScript file.
* @param encoder the ImageEncoder that will provide the raw bitmap data
* @param imgDim the dimensions of the image
* @param formName the name of the PostScript form to use
* @param imageDescription a description of the image added as a DSC Title comment
* @param colorSpace the color space of the image
* @param invertImage true if the image shall be inverted
* @param gen the PostScript generator
* @return a PSResource representing the form for resource tracking
* @throws IOException In case of an I/O exception
* @deprecated Please use {@link FormGenerator}
*/
protected static PSResource writeReusableImage(ImageEncoder encoder,
Dimension imgDim,
String formName, String imageDescription,
ColorSpace colorSpace, boolean invertImage,
PSGenerator gen) throws IOException {
if (gen.getPSLevel() < 2) {
throw new UnsupportedOperationException(
"Reusable images requires at least Level 2 PostScript");
}
String dataName = formName + ":Data";
gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, formName);
if (imageDescription != null) {
gen.writeDSCComment(DSCConstants.TITLE, imageDescription);
}
String additionalFilters;
String implicitFilter = encoder.getImplicitFilter();
if (implicitFilter != null) {
additionalFilters = "/ASCII85Decode filter " + implicitFilter + " filter";
} else {
if (gen.getPSLevel() >= 3) {
additionalFilters = "/ASCII85Decode filter /FlateDecode filter";
} else {
additionalFilters = "/ASCII85Decode filter /RunLengthDecode filter";
}
}
gen.writeln("/" + formName);
gen.writeln("<< /FormType 1");
gen.writeln(" /BBox [0 0 " + imgDim.width + " " + imgDim.height + "]");
gen.writeln(" /Matrix [1 0 0 1 0 0]");
gen.writeln(" /PaintProc {");
gen.writeln(" pop");
gen.writeln(" gsave");
if (gen.getPSLevel() == 2) {
gen.writeln(" userdict /i 0 put"); //rewind image data
} else {
gen.writeln(" " + dataName + " 0 setfileposition"); //rewind image data
}
String dataSource;
if (gen.getPSLevel() == 2) {
dataSource = "{ " + dataName + " i get /i i 1 add store } bind";
} else {
dataSource = dataName;
}
PSDictionary imageDict = new PSDictionary();
imageDict.put("/DataSource", dataSource);
imageDict.put("/BitsPerComponent", Integer.toString(8));
writeImageCommand(imageDict, imgDim, colorSpace, invertImage, gen);
gen.writeln(" grestore");
gen.writeln(" } bind");
gen.writeln(">> def");
gen.writeln("/" + dataName + " currentfile");
gen.writeln(additionalFilters);
if (gen.getPSLevel() == 2) {
//Creates a data array from the inline file
gen.writeln("{ /temp exch def ["
+ " { temp 16384 string readstring not {exit } if } loop ] } exec");
} else {
gen.writeln("/ReusableStreamDecode filter");
}
compressAndWriteBitmap(encoder, gen);
gen.writeln("def");
gen.writeDSCComment(DSCConstants.END_RESOURCE);
PSResource res = new PSResource(PSResource.TYPE_FORM, formName);
gen.getResourceTracker().registerSuppliedResource(res);
return res;
}
/**
* Paints a reusable image (previously added as a PostScript form).
* @param formName the name of the PostScript form implementing the image
* @param targetRect the target rectangle to place the image in
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
* @deprecated Please use {@link #paintForm(PSResource, Dimension2D, Rectangle2D, PSGenerator)}
* instead.
*/
public static void paintReusableImage(
String formName,
Rectangle2D targetRect,
PSGenerator gen) throws IOException {
PSResource form = new PSResource(PSResource.TYPE_FORM, formName);
paintForm(form, null, targetRect, gen);
}
/**
* Paints a reusable image (previously added as a PostScript form).
* @param form the PostScript form resource implementing the image
* @param targetRect the target rectangle to place the image in
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
* @deprecated Please use {@link #paintForm(PSResource, Dimension2D, Rectangle2D, PSGenerator)}
* instead.
*/
public static void paintForm(
PSResource form,
Rectangle2D targetRect,
PSGenerator gen) throws IOException {
paintForm(form, null, targetRect, gen);
}
/**
* Paints a reusable image (previously added as a PostScript form).
* @param form the PostScript form resource implementing the image
* @param formDimensions the original dimensions of the form
* @param targetRect the target rectangle to place the image in
* @param gen the PostScript generator
* @throws IOException In case of an I/O exception
*/
public static void paintForm(
PSResource form,
Dimension2D formDimensions,
Rectangle2D targetRect,
PSGenerator gen) throws IOException {
gen.saveGraphicsState();
translateAndScale(gen, formDimensions, targetRect);
gen.writeln(form.getName() + " execform");
gen.getResourceTracker().notifyResourceUsageOnPage(form);
gen.restoreGraphicsState();
}
private static String getColorSpaceName(ColorSpace colorSpace) {
if (colorSpace.getType() == ColorSpace.TYPE_CMYK) {
return "/DeviceCMYK";
} else if (colorSpace.getType() == ColorSpace.TYPE_GRAY) {
return "/DeviceGray";
} else {
return "/DeviceRGB";
}
}
static void compressAndWriteBitmap(ImageEncoder encoder, PSGenerator gen)
throws IOException {
OutputStream out = gen.getOutputStream();
out = new ASCII85OutputStream(out);
String implicitFilter = encoder.getImplicitFilter();
if (implicitFilter != null) {
//nop
} else {
if (gen.getPSLevel() >= 3) {
out = new FlateEncodeOutputStream(out);
} else {
out = new RunLengthEncodeOutputStream(out);
}
}
encoder.writeTo(out);
if (out instanceof Finalizable) {
((Finalizable)out).finalizeStream();
} else {
out.flush();
}
gen.newLine(); //Just to be sure
}
/**
* Generates commands to modify the current transformation matrix so an image fits
* into a given rectangle.
* @param gen the PostScript generator
* @param imageDimensions the image's dimensions
* @param targetRect the target rectangle
* @throws IOException if an I/O error occurs
*/
public static void translateAndScale(PSGenerator gen,
Dimension2D imageDimensions, Rectangle2D targetRect)
throws IOException {
gen.writeln(gen.formatDouble(targetRect.getX()) + " "
+ gen.formatDouble(targetRect.getY()) + " translate");
if (imageDimensions == null) {
imageDimensions = new Dimension(1, 1);
}
double sx = targetRect.getWidth() / imageDimensions.getWidth();
double sy = targetRect.getHeight() / imageDimensions.getHeight();
if (sx != 1 || sy != 1) {
gen.writeln(gen.formatDouble(sx) + " "
+ gen.formatDouble(sy) + " scale");
}
}
/**
* Extracts a packed RGB integer array of a RenderedImage.
* @param img the image
* @param startX the starting X coordinate
* @param startY the starting Y coordinate
* @param w the width of the cropped image
* @param h the height of the cropped image
* @param rgbArray the prepared integer array to write to
* @param offset offset in the target array
* @param scansize width of a row in the target array
* @return the populated integer array previously passed in as rgbArray parameter
*/
public static int[] getRGB(RenderedImage img,
int startX, int startY,
int w, int h,
int[] rgbArray, int offset, int scansize) {
Raster raster = img.getData();
int yoff = offset;
int off;
Object data;
int nbands = raster.getNumBands();
int dataType = raster.getDataBuffer().getDataType();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
data = new byte[nbands];
break;
case DataBuffer.TYPE_USHORT:
data = new short[nbands];
break;
case DataBuffer.TYPE_INT:
data = new int[nbands];
break;
case DataBuffer.TYPE_FLOAT:
data = new float[nbands];
break;
case DataBuffer.TYPE_DOUBLE:
data = new double[nbands];
break;
default:
throw new IllegalArgumentException("Unknown data buffer type: "
+ dataType);
}
if (rgbArray == null) {
rgbArray = new int[offset + h * scansize];
}
ColorModel colorModel = img.getColorModel();
for (int y = startY; y < startY + h; y++, yoff += scansize) {
off = yoff;
for (int x = startX; x < startX + w; x++) {
rgbArray[off++] = colorModel.getRGB(raster.getDataElements(x, y, data));
}
}
return rgbArray;
}
/**
* Places an EPS file in the PostScript stream.
* @param rawEPS byte array containing the raw EPS data
* @param name name for the EPS document
* @param x x-coordinate of viewport in points
* @param y y-coordinate of viewport in points
* @param w width of viewport in points
* @param h height of viewport in points
* @param bboxx x-coordinate of EPS bounding box in points
* @param bboxy y-coordinate of EPS bounding box in points
* @param bboxw width of EPS bounding box in points
* @param bboxh height of EPS bounding box in points
* @param gen the PS generator
* @throws IOException in case an I/O error happens during output
* @deprecated Please use the variant with the InputStream as parameter
*/
public static void renderEPS(byte[] rawEPS, String name,
float x, float y, float w, float h,
float bboxx, float bboxy, float bboxw, float bboxh,
PSGenerator gen) throws IOException {
renderEPS(new java.io.ByteArrayInputStream(rawEPS), name,
new Rectangle2D.Float(x, y, w, h),
new Rectangle2D.Float(bboxx, bboxy, bboxw, bboxh),
gen);
}
/**
* Places an EPS file in the PostScript stream.
* @param in the InputStream that contains the EPS stream
* @param name name for the EPS document
* @param viewport the viewport in points in which to place the EPS
* @param bbox the EPS bounding box in points
* @param gen the PS generator
* @throws IOException in case an I/O error happens during output
*/
public static void renderEPS(InputStream in, String name,
Rectangle2D viewport, Rectangle2D bbox,
PSGenerator gen) throws IOException {
gen.getResourceTracker().notifyResourceUsageOnPage(PSProcSets.EPS_PROCSET);
gen.writeln("%AXGBeginEPS: " + name);
gen.writeln("BeginEPSF");
gen.writeln(gen.formatDouble(viewport.getX())
+ " " + gen.formatDouble(viewport.getY()) + " translate");
gen.writeln("0 " + gen.formatDouble(viewport.getHeight()) + " translate");
gen.writeln("1 -1 scale");
double sx = viewport.getWidth() / bbox.getWidth();
double sy = viewport.getHeight() / bbox.getHeight();
if (sx != 1 || sy != 1) {
gen.writeln(gen.formatDouble(sx) + " " + gen.formatDouble(sy) + " scale");
}
if (bbox.getX() != 0 || bbox.getY() != 0) {
gen.writeln(gen.formatDouble(-bbox.getX())
+ " " + gen.formatDouble(-bbox.getY()) + " translate");
}
gen.writeln(gen.formatDouble(bbox.getX())
+ " " + gen.formatDouble(bbox.getY())
+ " " + gen.formatDouble(bbox.getWidth())
+ " " + gen.formatDouble(bbox.getHeight()) + " re clip");
gen.writeln("newpath");
PSResource res = new PSResource(PSResource.TYPE_FILE, name);
gen.getResourceTracker().registerSuppliedResource(res);
gen.getResourceTracker().notifyResourceUsageOnPage(res);
gen.writeDSCComment(DSCConstants.BEGIN_DOCUMENT, res.getName());
IOUtils.copy(in, gen.getOutputStream());
gen.newLine();
gen.writeDSCComment(DSCConstants.END_DOCUMENT);
gen.writeln("EndEPSF");
gen.writeln("%AXGEndEPS");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy