|
|
@ -134,7 +134,7 @@ public class RasterPlotter {
|
|
|
|
* background color.
|
|
|
|
* background color.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public final void clear() {
|
|
|
|
public final void clear() {
|
|
|
|
// fill grid with background color
|
|
|
|
// fill grid with background color
|
|
|
|
final int bgR = (int) (this.backgroundCol >> 16);
|
|
|
|
final int bgR = (int) (this.backgroundCol >> 16);
|
|
|
|
final int bgG = (int) ((this.backgroundCol >> 8) & 0xff);
|
|
|
|
final int bgG = (int) ((this.backgroundCol >> 8) & 0xff);
|
|
|
|
final int bgB = (int) (this.backgroundCol & 0xff);
|
|
|
|
final int bgB = (int) (this.backgroundCol & 0xff);
|
|
|
@ -212,22 +212,22 @@ public class RasterPlotter {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void setColor(final long c) {
|
|
|
|
public void setColor(final long c) {
|
|
|
|
if (this.defaultMode == DrawMode.MODE_SUB) {
|
|
|
|
if (this.defaultMode == DrawMode.MODE_SUB) {
|
|
|
|
final int r = (int) (c >> 16);
|
|
|
|
final int r = (int) (c >> 16);
|
|
|
|
final int g = (int) ((c >> 8) & 0xff);
|
|
|
|
final int g = (int) ((c >> 8) & 0xff);
|
|
|
|
final int b = (int) (c & 0xff);
|
|
|
|
final int b = (int) (c & 0xff);
|
|
|
|
this.defaultColR = (g + b) >>> 1; // / 2;
|
|
|
|
this.defaultColR = (g + b) >>> 1; // / 2;
|
|
|
|
this.defaultColG = (r + b) >>> 1; // / 2;
|
|
|
|
this.defaultColG = (r + b) >>> 1; // / 2;
|
|
|
|
this.defaultColB = (r + g) >>> 1; // / 2;
|
|
|
|
this.defaultColB = (r + g) >>> 1; // / 2;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
this.defaultColR = (int) (c >> 16);
|
|
|
|
this.defaultColR = (int) (c >> 16);
|
|
|
|
this.defaultColG = (int) ((c >> 8) & 0xff);
|
|
|
|
this.defaultColG = (int) ((c >> 8) & 0xff);
|
|
|
|
this.defaultColB = (int) (c & 0xff);
|
|
|
|
this.defaultColB = (int) (c & 0xff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void plot(final int x, final int y) {
|
|
|
|
public void plot(final int x, final int y) {
|
|
|
|
plot(x, y, 100);
|
|
|
|
plot(x, y, 100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void plot(final int x, final int y, final int intensity) {
|
|
|
|
public void plot(final int x, final int y, final int intensity) {
|
|
|
@ -880,12 +880,12 @@ public class RasterPlotter {
|
|
|
|
cmap[i++] = cc.intValue();
|
|
|
|
cmap[i++] = cc.intValue();
|
|
|
|
if (i > 255) break;
|
|
|
|
if (i > 255) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int bitCount = 1;
|
|
|
|
int bitCount = 1;
|
|
|
|
while ((colors.size() - 1) >> bitCount != 0) bitCount *= 2;
|
|
|
|
while ((colors.size() - 1) >> bitCount != 0) bitCount *= 2;
|
|
|
|
|
|
|
|
|
|
|
|
IndexColorModel cm = new IndexColorModel(bitCount, colors.size(), cmap, 0, DataBuffer.TYPE_BYTE, null);
|
|
|
|
IndexColorModel cm = new IndexColorModel(bitCount, colors.size(), cmap, 0, DataBuffer.TYPE_BYTE, null);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
byte [] data = null;
|
|
|
|
byte [] data = null;
|
|
|
|
int bytesPerRow = this.getWidth()/8 + (this.getWidth()%8!=0?1:0);
|
|
|
|
int bytesPerRow = this.getWidth()/8 + (this.getWidth()%8!=0?1:0);
|
|
|
@ -894,12 +894,12 @@ public class RasterPlotter {
|
|
|
|
WritableRaster wr = Raster.createPackedRaster(db, this.getWidth(), this.getHeight(), 1, null);
|
|
|
|
WritableRaster wr = Raster.createPackedRaster(db, this.getWidth(), this.getHeight(), 1, null);
|
|
|
|
BufferedImage dest = new BufferedImage(cm, wr, false, null);
|
|
|
|
BufferedImage dest = new BufferedImage(cm, wr, false, null);
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
BufferedImage dest = new BufferedImage(this.getWidth(), this.getHeight(), cm.getPixelSize() < 8 ? BufferedImage.TYPE_BYTE_BINARY : BufferedImage.TYPE_BYTE_INDEXED, cm);
|
|
|
|
BufferedImage dest = new BufferedImage(this.getWidth(), this.getHeight(), cm.getPixelSize() < 8 ? BufferedImage.TYPE_BYTE_BINARY : BufferedImage.TYPE_BYTE_INDEXED, cm);
|
|
|
|
dest.createGraphics().drawImage(this.getImage(), 0, 0, null);
|
|
|
|
dest.createGraphics().drawImage(this.getImage(), 0, 0, null);
|
|
|
|
return dest;
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static BufferedImage convertToIndexed(BufferedImage src) {
|
|
|
|
public static BufferedImage convertToIndexed(BufferedImage src) {
|
|
|
|
BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
|
|
|
|
BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
|
|
|
|
dest.createGraphics().drawImage(src,0,0, null);
|
|
|
|
dest.createGraphics().drawImage(src,0,0, null);
|
|
|
@ -913,18 +913,18 @@ public class RasterPlotter {
|
|
|
|
* @return a ByteBuffer instance containing encoded data, or empty if an error occured or target format is not supported.
|
|
|
|
* @return a ByteBuffer instance containing encoded data, or empty if an error occured or target format is not supported.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public static ByteBuffer exportImage(final BufferedImage image, final String targetExt) {
|
|
|
|
public static ByteBuffer exportImage(final BufferedImage image, final String targetExt) {
|
|
|
|
// generate an byte array from the given image
|
|
|
|
// generate an byte array from the given image
|
|
|
|
final ByteBuffer baos = new ByteBuffer();
|
|
|
|
final ByteBuffer baos = new ByteBuffer();
|
|
|
|
ImageIO.setUseCache(false); // because we write into ram here
|
|
|
|
ImageIO.setUseCache(false); // because we write into ram here
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
/* When no ImageIO writer is found image might no be written*/
|
|
|
|
/* When no ImageIO writer is found image might no be written*/
|
|
|
|
ImageIO.write(image, targetExt, baos);
|
|
|
|
ImageIO.write(image, targetExt, baos);
|
|
|
|
return baos;
|
|
|
|
return baos;
|
|
|
|
} catch (final IOException e) {
|
|
|
|
} catch (final IOException e) {
|
|
|
|
// should not happen
|
|
|
|
// should not happen
|
|
|
|
ConcurrentLog.logException(e);
|
|
|
|
ConcurrentLog.logException(e);
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public ByteBuffer exportPng() {
|
|
|
|
public ByteBuffer exportPng() {
|
|
|
@ -950,12 +950,12 @@ public class RasterPlotter {
|
|
|
|
* @throws IOException
|
|
|
|
* @throws IOException
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public void save(File file, String type) throws IOException {
|
|
|
|
public void save(File file, String type) throws IOException {
|
|
|
|
try (
|
|
|
|
try (
|
|
|
|
/* Automatically closed by this try-with-resources statement */
|
|
|
|
/* Automatically closed by this try-with-resources statement */
|
|
|
|
final FileOutputStream fos = new FileOutputStream(file);
|
|
|
|
final FileOutputStream fos = new FileOutputStream(file);
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
ImageIO.write(this.image, type, fos);
|
|
|
|
ImageIO.write(this.image, type, fos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -969,9 +969,10 @@ public class RasterPlotter {
|
|
|
|
f.pack();
|
|
|
|
f.pack();
|
|
|
|
f.setVisible(true);
|
|
|
|
f.setVisible(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* The following code was transformed from a library, coded by J. David Eisenberg, version 1.5, 19 Oct 2003 (C) LGPL
|
|
|
|
* The following code was transformed from a library, coded by J. David Eisenberg, version 1.5, 19 Oct 2003 (C) LGPL
|
|
|
|
|
|
|
|
* see: http://catcode.com/pngencoder/index.html
|
|
|
|
* This code was very strongly transformed into the following very short method for an ultra-fast png generation.
|
|
|
|
* This code was very strongly transformed into the following very short method for an ultra-fast png generation.
|
|
|
|
* These changes had been made 23.10.2012 by [MC] to the original code:
|
|
|
|
* These changes had been made 23.10.2012 by [MC] to the original code:
|
|
|
|
* For the integration into YaCy this class was adopted to YaCy graphics by Michael Christen:
|
|
|
|
* For the integration into YaCy this class was adopted to YaCy graphics by Michael Christen:
|
|
|
@ -986,7 +987,7 @@ public class RasterPlotter {
|
|
|
|
* - after all enhancements all class objects were removed; result is just one short static method
|
|
|
|
* - after all enhancements all class objects were removed; result is just one short static method
|
|
|
|
* - made objects final where possible
|
|
|
|
* - made objects final where possible
|
|
|
|
* - removed the PixelGrabber call and replaced it with a call to this.frame which is just a byte[]
|
|
|
|
* - removed the PixelGrabber call and replaced it with a call to this.frame which is just a byte[]
|
|
|
|
* - added more speed woodoo like a buffer around the deflater which makes this much faster
|
|
|
|
* - added more speed voodoo like a buffer around the deflater which makes this much faster
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
private static final byte IHDR[] = {73, 72, 68, 82};
|
|
|
|
private static final byte IHDR[] = {73, 72, 68, 82};
|
|
|
@ -997,10 +998,10 @@ public class RasterPlotter {
|
|
|
|
if (this.frame == null) return exportImage(this.getImage(), "png").getBytes();
|
|
|
|
if (this.frame == null) return exportImage(this.getImage(), "png").getBytes();
|
|
|
|
final int width = image.getWidth(null);
|
|
|
|
final int width = image.getWidth(null);
|
|
|
|
final int height = image.getHeight(null);
|
|
|
|
final int height = image.getHeight(null);
|
|
|
|
|
|
|
|
|
|
|
|
final Deflater scrunch = new Deflater(compressionLevel);
|
|
|
|
final Deflater scrunch = new Deflater(compressionLevel);
|
|
|
|
ByteBuffer outBytes = new ByteBuffer(1024);
|
|
|
|
ByteBuffer outBytes = new ByteBuffer(1024);
|
|
|
|
final OutputStream compBytes = new BufferedOutputStream(new DeflaterOutputStream(outBytes, scrunch));
|
|
|
|
final OutputStream compBytes = new BufferedOutputStream(new DeflaterOutputStream(outBytes, scrunch, 2048, false), 16384);
|
|
|
|
int i = 0;
|
|
|
|
int i = 0;
|
|
|
|
for (int row = 0; row < height; row++) {
|
|
|
|
for (int row = 0; row < height; row++) {
|
|
|
|
compBytes.write(0);
|
|
|
|
compBytes.write(0);
|
|
|
@ -1013,44 +1014,48 @@ public class RasterPlotter {
|
|
|
|
|
|
|
|
|
|
|
|
// finally write the result of the concurrent calculation into an DeflaterOutputStream to compress the png
|
|
|
|
// finally write the result of the concurrent calculation into an DeflaterOutputStream to compress the png
|
|
|
|
final int nCompressed = outBytes.length();
|
|
|
|
final int nCompressed = outBytes.length();
|
|
|
|
final byte[] pngBytes = new byte[nCompressed + 57]; // yes thats the exact size, not too less, not too much. No resizing needed.
|
|
|
|
final byte[] png = new byte[nCompressed + 57]; // yes thats the exact size, not too less, not too much. No resizing needed.
|
|
|
|
int bytePos = writeBytes(pngBytes, new byte[]{-119, 80, 78, 71, 13, 10, 26, 10}, 0);
|
|
|
|
int next = writeBytes(png, new byte[]{-119, 80, 78, 71, 13, 10, 26, 10}, 0);
|
|
|
|
final int startPos = bytePos = writeInt4(pngBytes, 13, bytePos);
|
|
|
|
final int startPos = next = writeInt4(png, 13, next);
|
|
|
|
bytePos = writeBytes(pngBytes, IHDR, bytePos);
|
|
|
|
next = writeBytes(png, IHDR, next);
|
|
|
|
bytePos = writeInt4(pngBytes, width, bytePos);
|
|
|
|
next = writeInt4(png, width, next);
|
|
|
|
bytePos = writeInt4(pngBytes, height, bytePos);
|
|
|
|
next = writeInt4(png, height, next);
|
|
|
|
bytePos = writeBytes(pngBytes, new byte[]{8, 2, 0, 0, 0}, bytePos);
|
|
|
|
next = writeBytes(png, new byte[]{8, 2, 0, 0, 0}, next);
|
|
|
|
final CRC32 crc = new CRC32();
|
|
|
|
final CRC32 crc = new CRC32();
|
|
|
|
crc.reset();
|
|
|
|
crc.reset();
|
|
|
|
crc.update(pngBytes, startPos, bytePos - startPos);
|
|
|
|
crc.update(png, startPos, next - startPos);
|
|
|
|
bytePos = writeInt4(pngBytes, (int) crc.getValue(), bytePos);
|
|
|
|
next = writeInt4(png, (int) crc.getValue(), next);
|
|
|
|
crc.reset();
|
|
|
|
crc.reset();
|
|
|
|
bytePos = writeInt4(pngBytes, nCompressed, bytePos);
|
|
|
|
next = writeInt4(png, nCompressed, next);
|
|
|
|
bytePos = writeBytes(pngBytes, IDAT, bytePos);
|
|
|
|
next = writeBytes(png, IDAT, next);
|
|
|
|
crc.update(IDAT);
|
|
|
|
crc.update(IDAT);
|
|
|
|
outBytes.copyTo(pngBytes, bytePos);
|
|
|
|
outBytes.copyTo(png, next);
|
|
|
|
outBytes.close();
|
|
|
|
outBytes.close();
|
|
|
|
outBytes = null;
|
|
|
|
outBytes = null;
|
|
|
|
crc.update(pngBytes, bytePos, nCompressed);
|
|
|
|
crc.update(png, next, nCompressed);
|
|
|
|
bytePos += nCompressed;
|
|
|
|
next += nCompressed;
|
|
|
|
bytePos = writeInt4(pngBytes, (int) crc.getValue(), bytePos);
|
|
|
|
next = writeInt4(png, (int) crc.getValue(), next);
|
|
|
|
bytePos = writeInt4(pngBytes, 0, bytePos);
|
|
|
|
next = writeInt4(png, 0, next);
|
|
|
|
bytePos = writeBytes(pngBytes, IEND, bytePos);
|
|
|
|
next = writeBytes(png, IEND, next);
|
|
|
|
crc.reset();
|
|
|
|
crc.reset();
|
|
|
|
crc.update(IEND);
|
|
|
|
crc.update(IEND);
|
|
|
|
bytePos = writeInt4(pngBytes, (int) crc.getValue(), bytePos);
|
|
|
|
next = writeInt4(png, (int) crc.getValue(), next);
|
|
|
|
return pngBytes;
|
|
|
|
return png;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private final static int writeInt4(final byte[] target, final int n, final int offset) {
|
|
|
|
private final static int writeInt4(final byte[] target, final int n, int pos) {
|
|
|
|
return writeBytes(target, new byte[]{(byte) ((n >> 24) & 0xff), (byte) ((n >> 16) & 0xff), (byte) ((n >> 8) & 0xff), (byte) (n & 0xff)}, offset);
|
|
|
|
target[pos++] = (byte) ((n >> 24) & 0xff);
|
|
|
|
|
|
|
|
target[pos++] = (byte) ((n >> 16) & 0xff);
|
|
|
|
|
|
|
|
target[pos++] = (byte) ((n >> 8) & 0xff);
|
|
|
|
|
|
|
|
target[pos++] = (byte) ( n & 0xff);
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private final static int writeBytes(final byte[] target, final byte[] data, final int offset) {
|
|
|
|
private final static int writeBytes(final byte[] target, final byte[] data, final int pos) {
|
|
|
|
System.arraycopy(data, 0, target, offset, data.length);
|
|
|
|
System.arraycopy(data, 0, target, pos, data.length);
|
|
|
|
return offset + data.length;
|
|
|
|
return pos + data.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void main(final String[] args) {
|
|
|
|
public static void main(final String[] args) {
|
|
|
|
// go into headless awt mode
|
|
|
|
// go into headless awt mode
|
|
|
|
System.setProperty("java.awt.headless", "true");
|
|
|
|
System.setProperty("java.awt.headless", "true");
|
|
|
@ -1060,14 +1065,14 @@ public class RasterPlotter {
|
|
|
|
final File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "testimage.png");
|
|
|
|
final File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "testimage.png");
|
|
|
|
try ( /* Automatically closed by this try-with-resources statement */
|
|
|
|
try ( /* Automatically closed by this try-with-resources statement */
|
|
|
|
final FileOutputStream fos = new FileOutputStream(file);
|
|
|
|
final FileOutputStream fos = new FileOutputStream(file);
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
System.out.println("Writing file " + file);
|
|
|
|
System.out.println("Writing file " + file);
|
|
|
|
ImageIO.write(m.getImage(), "png", fos);
|
|
|
|
ImageIO.write(m.getImage(), "png", fos);
|
|
|
|
} catch (final IOException e) {
|
|
|
|
} catch (final IOException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ConcurrentLog.shutdown();
|
|
|
|
ConcurrentLog.shutdown();
|
|
|
|
|
|
|
|
|
|
|
|
// open file automatically, works only on Mac OS X
|
|
|
|
// open file automatically, works only on Mac OS X
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
Process p = null;
|
|
|
|
Process p = null;
|
|
|
|