use of sun.awt.image.ByteInterleavedRaster in project jdk8u_jdk by JetBrains.
the class Raster method createInterleavedRaster.
/**
* Creates a Raster based on a PixelInterleavedSampleModel with the
* specified DataBuffer, width, height, scanline stride, pixel
* stride, and band offsets. The number of bands is inferred from
* bandOffsets.length. The upper left corner of the Raster
* is given by the location argument. If location is null, (0, 0)
* will be used.
* <p> Note that interleaved <code>DataBuffer.TYPE_INT</code>
* Rasters are not supported. To create a 1-band Raster of type
* <code>DataBuffer.TYPE_INT</code>, use
* Raster.createPackedRaster().
* @param dataBuffer the <code>DataBuffer</code> that contains the
* image data
* @param w the width in pixels of the image data
* @param h the height in pixels of the image data
* @param scanlineStride the line stride of the image data
* @param pixelStride the pixel stride of the image data
* @param bandOffsets the offsets of all bands
* @param location the upper-left corner of the <code>Raster</code>
* @return a WritableRaster object with the specified
* <code>DataBuffer</code>, width, height, scanline stride,
* pixel stride and band offsets.
* @throws RasterFormatException if <code>w</code> or <code>h</code>
* is less than or equal to zero, or computing either
* <code>location.x + w</code> or
* <code>location.y + h</code> results in integer
* overflow
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types, which are
* <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>
* @throws RasterFormatException if <code>dataBuffer</code> has more
* than one bank.
* @throws NullPointerException if <code>dataBuffer</code> is null
*/
public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer, int w, int h, int scanlineStride, int pixelStride, int[] bandOffsets, Point location) {
if (dataBuffer == null) {
throw new NullPointerException("DataBuffer cannot be null");
}
if (location == null) {
location = new Point(0, 0);
}
int dataType = dataBuffer.getDataType();
PixelInterleavedSampleModel csm = new PixelInterleavedSampleModel(dataType, w, h, pixelStride, scanlineStride, bandOffsets);
switch(dataType) {
case DataBuffer.TYPE_BYTE:
return new ByteInterleavedRaster(csm, dataBuffer, location);
case DataBuffer.TYPE_USHORT:
return new ShortInterleavedRaster(csm, dataBuffer, location);
default:
throw new IllegalArgumentException("Unsupported data type " + dataType);
}
}
use of sun.awt.image.ByteInterleavedRaster in project jdk8u_jdk by JetBrains.
the class RasterPrinterJob method printPage.
/**
* Print a page from the provided document.
* @return int Printable.PAGE_EXISTS if the page existed and was drawn and
* Printable.NO_SUCH_PAGE if the page did not exist.
* @see java.awt.print.Printable
*/
protected int printPage(Pageable document, int pageIndex) throws PrinterException {
PageFormat page;
PageFormat origPage;
Printable painter;
try {
origPage = document.getPageFormat(pageIndex);
page = (PageFormat) origPage.clone();
painter = document.getPrintable(pageIndex);
} catch (Exception e) {
PrinterException pe = new PrinterException("Error getting page or printable.[ " + e + " ]");
pe.initCause(e);
throw pe;
}
/* Get the imageable area from Paper instead of PageFormat
* because we do not want it adjusted by the page orientation.
*/
Paper paper = page.getPaper();
// if non-portrait and 270 degree landscape rotation
if (page.getOrientation() != PageFormat.PORTRAIT && landscapeRotates270) {
double left = paper.getImageableX();
double top = paper.getImageableY();
double width = paper.getImageableWidth();
double height = paper.getImageableHeight();
paper.setImageableArea(paper.getWidth() - left - width, paper.getHeight() - top - height, width, height);
page.setPaper(paper);
if (page.getOrientation() == PageFormat.LANDSCAPE) {
page.setOrientation(PageFormat.REVERSE_LANDSCAPE);
} else {
page.setOrientation(PageFormat.LANDSCAPE);
}
}
double xScale = getXRes() / 72.0;
double yScale = getYRes() / 72.0;
/* The deviceArea is the imageable area in the printer's
* resolution.
*/
Rectangle2D deviceArea = new Rectangle2D.Double(paper.getImageableX() * xScale, paper.getImageableY() * yScale, paper.getImageableWidth() * xScale, paper.getImageableHeight() * yScale);
/* Build and hold on to a uniform transform so that
* we can get back to device space at the beginning
* of each band.
*/
AffineTransform uniformTransform = new AffineTransform();
/* The scale transform is used to switch from the
* device space to the user's 72 dpi space.
*/
AffineTransform scaleTransform = new AffineTransform();
scaleTransform.scale(xScale, yScale);
/* bandwidth is multiple of 4 as the data is used in a win32 DIB and
* some drivers behave badly if scanlines aren't multiples of 4 bytes.
*/
int bandWidth = (int) deviceArea.getWidth();
if (bandWidth % 4 != 0) {
bandWidth += (4 - (bandWidth % 4));
}
if (bandWidth <= 0) {
throw new PrinterException("Paper's imageable width is too small.");
}
int deviceAreaHeight = (int) deviceArea.getHeight();
if (deviceAreaHeight <= 0) {
throw new PrinterException("Paper's imageable height is too small.");
}
/* Figure out the number of lines that will fit into
* our maximum band size. The hard coded 3 reflects the
* fact that we can only create 24 bit per pixel 3 byte BGR
* BufferedImages. FIX.
*/
int bandHeight = (int) (MAX_BAND_SIZE / bandWidth / 3);
int deviceLeft = (int) Math.rint(paper.getImageableX() * xScale);
int deviceTop = (int) Math.rint(paper.getImageableY() * yScale);
/* The device transform is used to move the band down
* the page using translates. Normally this is all it
* would do, but since, when printing, the Window's
* DIB format wants the last line to be first (lowest) in
* memory, the deviceTransform moves the origin to the
* bottom of the band and flips the origin. This way the
* app prints upside down into the band which is the DIB
* format.
*/
AffineTransform deviceTransform = new AffineTransform();
deviceTransform.translate(-deviceLeft, deviceTop);
deviceTransform.translate(0, bandHeight);
deviceTransform.scale(1, -1);
/* Create a BufferedImage to hold the band. We set the clip
* of the band to be tight around the bits so that the
* application can use it to figure what part of the
* page needs to be drawn. The clip is never altered in
* this method, but we do translate the band's coordinate
* system so that the app will see the clip moving down the
* page though it s always around the same set of pixels.
*/
BufferedImage pBand = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR);
/* Have the app draw into a PeekGraphics object so we can
* learn something about the needs of the print job.
*/
PeekGraphics peekGraphics = createPeekGraphics(pBand.createGraphics(), this);
Rectangle2D.Double pageFormatArea = new Rectangle2D.Double(page.getImageableX(), page.getImageableY(), page.getImageableWidth(), page.getImageableHeight());
peekGraphics.transform(scaleTransform);
peekGraphics.translate(-getPhysicalPrintableX(paper) / xScale, -getPhysicalPrintableY(paper) / yScale);
peekGraphics.transform(new AffineTransform(page.getMatrix()));
initPrinterGraphics(peekGraphics, pageFormatArea);
AffineTransform pgAt = peekGraphics.getTransform();
/* Update the information used to return a GraphicsConfiguration
* for this printer device. It needs to be updated per page as
* not all pages in a job may be the same size (different bounds)
* The transform is the scaling transform as this corresponds to
* the default transform for the device. The width and height are
* those of the paper, not the page format, as we want to describe
* the bounds of the device in its natural coordinate system of
* device coordinate whereas a page format may be in a rotated context.
*/
setGraphicsConfigInfo(scaleTransform, paper.getWidth(), paper.getHeight());
int pageResult = painter.print(peekGraphics, origPage, pageIndex);
debug_println("pageResult " + pageResult);
if (pageResult == Printable.PAGE_EXISTS) {
debug_println("startPage " + pageIndex);
/* We need to check if the paper size is changed.
* Note that it is not sufficient to ask for the pageformat
* of "pageIndex-1", since PageRanges mean that pages can be
* skipped. So we have to look at the actual last paper size used.
*/
Paper thisPaper = page.getPaper();
boolean paperChanged = previousPaper == null || thisPaper.getWidth() != previousPaper.getWidth() || thisPaper.getHeight() != previousPaper.getHeight();
previousPaper = thisPaper;
startPage(page, painter, pageIndex, paperChanged);
Graphics2D pathGraphics = createPathGraphics(peekGraphics, this, painter, page, pageIndex);
/* If we can convert the page directly to the
* underlying graphics system then we do not
* need to rasterize. We also may not need to
* create the 'band' if all the pages can take
* this path.
*/
if (pathGraphics != null) {
pathGraphics.transform(scaleTransform);
// user (0,0) should be origin of page, not imageable area
pathGraphics.translate(-getPhysicalPrintableX(paper) / xScale, -getPhysicalPrintableY(paper) / yScale);
pathGraphics.transform(new AffineTransform(page.getMatrix()));
initPrinterGraphics(pathGraphics, pageFormatArea);
redrawList.clear();
AffineTransform initialTx = pathGraphics.getTransform();
painter.print(pathGraphics, origPage, pageIndex);
for (int i = 0; i < redrawList.size(); i++) {
GraphicsState gstate = (GraphicsState) redrawList.get(i);
pathGraphics.setTransform(initialTx);
((PathGraphics) pathGraphics).redrawRegion(gstate.region, gstate.sx, gstate.sy, gstate.theClip, gstate.theTransform);
}
/* This is the banded-raster printing loop.
* It should be moved into its own method.
*/
} else {
BufferedImage band = cachedBand;
if (cachedBand == null || bandWidth != cachedBandWidth || bandHeight != cachedBandHeight) {
band = new BufferedImage(bandWidth, bandHeight, BufferedImage.TYPE_3BYTE_BGR);
cachedBand = band;
cachedBandWidth = bandWidth;
cachedBandHeight = bandHeight;
}
Graphics2D bandGraphics = band.createGraphics();
Rectangle2D.Double clipArea = new Rectangle2D.Double(0, 0, bandWidth, bandHeight);
initPrinterGraphics(bandGraphics, clipArea);
ProxyGraphics2D painterGraphics = new ProxyGraphics2D(bandGraphics, this);
Graphics2D clearGraphics = band.createGraphics();
clearGraphics.setColor(Color.white);
/* We need the actual bits of the BufferedImage to send to
* the native Window's code. 'data' points to the actual
* pixels. Right now these are in ARGB format with 8 bits
* per component. We need to use a monochrome BufferedImage
* for monochrome printers when this is supported by
* BufferedImage. FIX
*/
ByteInterleavedRaster tile = (ByteInterleavedRaster) band.getRaster();
byte[] data = tile.getDataStorage();
/* Loop over the page moving our band down the page,
* calling the app to render the band, and then send the band
* to the printer.
*/
int deviceBottom = deviceTop + deviceAreaHeight;
/* device's printable x,y is really addressable origin
* we address relative to media origin so when we print a
* band we need to adjust for the different methods of
* addressing it.
*/
int deviceAddressableX = (int) getPhysicalPrintableX(paper);
int deviceAddressableY = (int) getPhysicalPrintableY(paper);
for (int bandTop = 0; bandTop <= deviceAreaHeight; bandTop += bandHeight) {
/* Put the band back into device space and
* erase the contents of the band.
*/
clearGraphics.fillRect(0, 0, bandWidth, bandHeight);
/* Put the band into the correct location on the
* page. Once the band is moved we translate the
* device transform so that the band will move down
* the page on the next iteration of the loop.
*/
bandGraphics.setTransform(uniformTransform);
bandGraphics.transform(deviceTransform);
deviceTransform.translate(0, -bandHeight);
/* Switch the band from device space to user,
* 72 dpi, space.
*/
bandGraphics.transform(scaleTransform);
bandGraphics.transform(new AffineTransform(page.getMatrix()));
Rectangle clip = bandGraphics.getClipBounds();
clip = pgAt.createTransformedShape(clip).getBounds();
if ((clip == null) || peekGraphics.hitsDrawingArea(clip) && (bandWidth > 0 && bandHeight > 0)) {
/* if the client has specified an imageable X or Y
* which is off than the physically addressable
* area of the page, then we need to adjust for that
* here so that we pass only non -ve band coordinates
* We also need to translate by the adjusted amount
* so that printing appears in the correct place.
*/
int bandX = deviceLeft - deviceAddressableX;
if (bandX < 0) {
bandGraphics.translate(bandX / xScale, 0);
bandX = 0;
}
int bandY = deviceTop + bandTop - deviceAddressableY;
if (bandY < 0) {
bandGraphics.translate(0, bandY / yScale);
bandY = 0;
}
/* Have the app's painter image into the band
* and then send the band to the printer.
*/
painterGraphics.setDelegate((Graphics2D) bandGraphics.create());
painter.print(painterGraphics, origPage, pageIndex);
painterGraphics.dispose();
printBand(data, bandX, bandY, bandWidth, bandHeight);
}
}
clearGraphics.dispose();
bandGraphics.dispose();
}
debug_println("calling endPage " + pageIndex);
endPage(page, painter, pageIndex);
}
return pageResult;
}
use of sun.awt.image.ByteInterleavedRaster in project jdk8u_jdk by JetBrains.
the class PNGImageReader method decodePass.
private void decodePass(int passNum, int xStart, int yStart, int xStep, int yStep, int passWidth, int passHeight) throws IOException {
if ((passWidth == 0) || (passHeight == 0)) {
return;
}
WritableRaster imRas = theImage.getWritableTile(0, 0);
int dstMinX = imRas.getMinX();
int dstMaxX = dstMinX + imRas.getWidth() - 1;
int dstMinY = imRas.getMinY();
int dstMaxY = dstMinY + imRas.getHeight() - 1;
// Determine which pixels will be updated in this pass
int[] vals = ReaderUtil.computeUpdatedPixels(sourceRegion, destinationOffset, dstMinX, dstMinY, dstMaxX, dstMaxY, sourceXSubsampling, sourceYSubsampling, xStart, yStart, passWidth, passHeight, xStep, yStep);
int updateMinX = vals[0];
int updateMinY = vals[1];
int updateWidth = vals[2];
int updateXStep = vals[4];
int updateYStep = vals[5];
int bitDepth = metadata.IHDR_bitDepth;
int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
int bytesPerPixel = (bitDepth == 16) ? 2 : 1;
bytesPerPixel *= inputBands;
int bytesPerRow = (inputBands * passWidth * bitDepth + 7) / 8;
int eltsPerRow = (bitDepth == 16) ? bytesPerRow / 2 : bytesPerRow;
// If no pixels need updating, just skip the input data
if (updateWidth == 0) {
for (int srcY = 0; srcY < passHeight; srcY++) {
// Update count of pixels read
updateImageProgress(passWidth);
// Skip filter byte and the remaining row bytes
pixelStream.skipBytes(1 + bytesPerRow);
}
return;
}
// Backwards map from destination pixels
// (dstX = updateMinX + k*updateXStep)
// to source pixels (sourceX), and then
// to offset and skip in passRow (srcX and srcXStep)
int sourceX = (updateMinX - destinationOffset.x) * sourceXSubsampling + sourceRegion.x;
int srcX = (sourceX - xStart) / xStep;
// Compute the step factor in the source
int srcXStep = updateXStep * sourceXSubsampling / xStep;
byte[] byteData = null;
short[] shortData = null;
byte[] curr = new byte[bytesPerRow];
byte[] prior = new byte[bytesPerRow];
// Create a 1-row tall Raster to hold the data
WritableRaster passRow = createRaster(passWidth, 1, inputBands, eltsPerRow, bitDepth);
// Create an array suitable for holding one pixel
int[] ps = passRow.getPixel(0, 0, (int[]) null);
DataBuffer dataBuffer = passRow.getDataBuffer();
int type = dataBuffer.getDataType();
if (type == DataBuffer.TYPE_BYTE) {
byteData = ((DataBufferByte) dataBuffer).getData();
} else {
shortData = ((DataBufferUShort) dataBuffer).getData();
}
processPassStarted(theImage, passNum, sourceMinProgressivePass, sourceMaxProgressivePass, updateMinX, updateMinY, updateXStep, updateYStep, destinationBands);
// Handle source and destination bands
if (sourceBands != null) {
passRow = passRow.createWritableChild(0, 0, passRow.getWidth(), 1, 0, 0, sourceBands);
}
if (destinationBands != null) {
imRas = imRas.createWritableChild(0, 0, imRas.getWidth(), imRas.getHeight(), 0, 0, destinationBands);
}
// Determine if all of the relevant output bands have the
// same bit depth as the source data
boolean adjustBitDepths = false;
int[] outputSampleSize = imRas.getSampleModel().getSampleSize();
int numBands = outputSampleSize.length;
for (int b = 0; b < numBands; b++) {
if (outputSampleSize[b] != bitDepth) {
adjustBitDepths = true;
break;
}
}
// If the bit depths differ, create a lookup table per band to perform
// the conversion
int[][] scale = null;
if (adjustBitDepths) {
int maxInSample = (1 << bitDepth) - 1;
int halfMaxInSample = maxInSample / 2;
scale = new int[numBands][];
for (int b = 0; b < numBands; b++) {
int maxOutSample = (1 << outputSampleSize[b]) - 1;
scale[b] = new int[maxInSample + 1];
for (int s = 0; s <= maxInSample; s++) {
scale[b][s] = (s * maxOutSample + halfMaxInSample) / maxInSample;
}
}
}
// Limit passRow to relevant area for the case where we
// will can setRect to copy a contiguous span
boolean useSetRect = srcXStep == 1 && updateXStep == 1 && !adjustBitDepths && (imRas instanceof ByteInterleavedRaster);
if (useSetRect) {
passRow = passRow.createWritableChild(srcX, 0, updateWidth, 1, 0, 0, null);
}
// Decode the (sub)image row-by-row
for (int srcY = 0; srcY < passHeight; srcY++) {
// Update count of pixels read
updateImageProgress(passWidth);
// Read the filter type byte and a row of data
int filter = pixelStream.read();
try {
// Swap curr and prior
byte[] tmp = prior;
prior = curr;
curr = tmp;
pixelStream.readFully(curr, 0, bytesPerRow);
} catch (java.util.zip.ZipException ze) {
// TODO - throw a more meaningful exception
throw ze;
}
switch(filter) {
case PNG_FILTER_NONE:
break;
case PNG_FILTER_SUB:
decodeSubFilter(curr, 0, bytesPerRow, bytesPerPixel);
break;
case PNG_FILTER_UP:
decodeUpFilter(curr, 0, prior, 0, bytesPerRow);
break;
case PNG_FILTER_AVERAGE:
decodeAverageFilter(curr, 0, prior, 0, bytesPerRow, bytesPerPixel);
break;
case PNG_FILTER_PAETH:
decodePaethFilter(curr, 0, prior, 0, bytesPerRow, bytesPerPixel);
break;
default:
throw new IIOException("Unknown row filter type (= " + filter + ")!");
}
// Copy data into passRow byte by byte
if (bitDepth < 16) {
System.arraycopy(curr, 0, byteData, 0, bytesPerRow);
} else {
int idx = 0;
for (int j = 0; j < eltsPerRow; j++) {
shortData[j] = (short) ((curr[idx] << 8) | (curr[idx + 1] & 0xff));
idx += 2;
}
}
// True Y position in source
int sourceY = srcY * yStep + yStart;
if ((sourceY >= sourceRegion.y) && (sourceY < sourceRegion.y + sourceRegion.height) && (((sourceY - sourceRegion.y) % sourceYSubsampling) == 0)) {
int dstY = destinationOffset.y + (sourceY - sourceRegion.y) / sourceYSubsampling;
if (dstY < dstMinY) {
continue;
}
if (dstY > dstMaxY) {
break;
}
if (useSetRect) {
imRas.setRect(updateMinX, dstY, passRow);
} else {
int newSrcX = srcX;
for (int dstX = updateMinX; dstX < updateMinX + updateWidth; dstX += updateXStep) {
passRow.getPixel(newSrcX, 0, ps);
if (adjustBitDepths) {
for (int b = 0; b < numBands; b++) {
ps[b] = scale[b][ps[b]];
}
}
imRas.setPixel(dstX, dstY, ps);
newSrcX += srcXStep;
}
}
processImageUpdate(theImage, updateMinX, dstY, updateWidth, 1, updateXStep, updateYStep, destinationBands);
// processReadAborted will be called later
if (abortRequested()) {
return;
}
}
}
processPassComplete(theImage);
}
use of sun.awt.image.ByteInterleavedRaster in project jdk8u_jdk by JetBrains.
the class TexturePaintContext method getContext.
public static PaintContext getContext(BufferedImage bufImg, AffineTransform xform, RenderingHints hints, Rectangle devBounds) {
WritableRaster raster = bufImg.getRaster();
ColorModel cm = bufImg.getColorModel();
int maxw = devBounds.width;
Object val = hints.get(RenderingHints.KEY_INTERPOLATION);
boolean filter = (val == null ? (hints.get(RenderingHints.KEY_RENDERING) == RenderingHints.VALUE_RENDER_QUALITY) : (val != RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR));
if (raster instanceof IntegerInterleavedRaster && (!filter || isFilterableDCM(cm))) {
IntegerInterleavedRaster iir = (IntegerInterleavedRaster) raster;
if (iir.getNumDataElements() == 1 && iir.getPixelStride() == 1) {
return new Int(iir, cm, xform, maxw, filter);
}
} else if (raster instanceof ByteInterleavedRaster) {
ByteInterleavedRaster bir = (ByteInterleavedRaster) raster;
if (bir.getNumDataElements() == 1 && bir.getPixelStride() == 1) {
if (filter) {
if (isFilterableICM(cm)) {
return new ByteFilter(bir, cm, xform, maxw);
}
} else {
return new Byte(bir, cm, xform, maxw);
}
}
}
return new Any(raster, cm, xform, maxw, filter);
}
use of sun.awt.image.ByteInterleavedRaster in project jdk8u_jdk by JetBrains.
the class Raster method createPackedRaster.
/**
* Creates a Raster based on a SinglePixelPackedSampleModel with
* the specified DataBuffer, width, height, scanline stride, and
* band masks. The number of bands is inferred from bandMasks.length.
* The upper left corner of the Raster is given by
* the location argument. If location is null, (0, 0) will be used.
* @param dataBuffer the <code>DataBuffer</code> that contains the
* image data
* @param w the width in pixels of the image data
* @param h the height in pixels of the image data
* @param scanlineStride the line stride of the image data
* @param bandMasks an array containing an entry for each band
* @param location the upper-left corner of the <code>Raster</code>
* @return a WritableRaster object with the specified
* <code>DataBuffer</code>, width, height, scanline stride,
* and band masks.
* @throws RasterFormatException if <code>w</code> or <code>h</code>
* is less than or equal to zero, or computing either
* <code>location.x + w</code> or
* <code>location.y + h</code> results in integer
* overflow
* @throws IllegalArgumentException if <code>dataType</code> is not
* one of the supported data types, which are
* <code>DataBuffer.TYPE_BYTE</code>,
* <code>DataBuffer.TYPE_USHORT</code>
* or <code>DataBuffer.TYPE_INT</code>
* @throws RasterFormatException if <code>dataBuffer</code> has more
* than one bank.
* @throws NullPointerException if <code>dataBuffer</code> is null
*/
public static WritableRaster createPackedRaster(DataBuffer dataBuffer, int w, int h, int scanlineStride, int[] bandMasks, Point location) {
if (dataBuffer == null) {
throw new NullPointerException("DataBuffer cannot be null");
}
if (location == null) {
location = new Point(0, 0);
}
int dataType = dataBuffer.getDataType();
SinglePixelPackedSampleModel sppsm = new SinglePixelPackedSampleModel(dataType, w, h, scanlineStride, bandMasks);
switch(dataType) {
case DataBuffer.TYPE_BYTE:
return new ByteInterleavedRaster(sppsm, dataBuffer, location);
case DataBuffer.TYPE_USHORT:
return new ShortInterleavedRaster(sppsm, dataBuffer, location);
case DataBuffer.TYPE_INT:
return new IntegerInterleavedRaster(sppsm, dataBuffer, location);
default:
throw new IllegalArgumentException("Unsupported data type " + dataType);
}
}
Aggregations