From d5d64019e57d64944d4b2aa188bd33cb0c56c524 Mon Sep 17 00:00:00 2001 From: Michael Peter Christen Date: Thu, 25 Oct 2012 16:05:04 +0200 Subject: [PATCH] - added a method for the RasterPlotter to draw arrow endings to lines - replaced the dot in the NetworkGraph with arrows - enhanced the image drawing speed using pre-computed color values - added more attention for OOM cases during very large image painting --- htroot/AccessPicture_p.java | 30 +++-- htroot/WebStructurePicture_p.java | 2 +- htroot/imagetest.java | 8 +- source/net/yacy/dbtest.java | 2 +- source/net/yacy/peers/graphics/Banner.java | 4 +- .../net/yacy/peers/graphics/NetworkGraph.java | 17 +-- .../yacy/peers/graphics/ProfilingGraph.java | 14 +- .../net/yacy/visualization/ChartPlotter.java | 32 +++-- .../net/yacy/visualization/GraphPlotter.java | 15 ++- .../yacy/visualization/HexGridPlotter.java | 20 +-- source/net/yacy/visualization/PngEncoder.java | 39 +++--- .../net/yacy/visualization/RasterPlotter.java | 122 +++++++++++++----- 12 files changed, 186 insertions(+), 119 deletions(-) diff --git a/htroot/AccessPicture_p.java b/htroot/AccessPicture_p.java index 7bef33958..34aa0257c 100644 --- a/htroot/AccessPicture_p.java +++ b/htroot/AccessPicture_p.java @@ -87,7 +87,11 @@ public class AccessPicture_p { // draw home peer final int centerx = (picture.gridWidth() >> 1) - 1; final int centery = picture.gridHeight() >> 1; - picture.setColor(color_dot); + long color_dot_l = Long.parseLong(color_dot, 16); + long color_text_l = Long.parseLong(color_text, 16); + long color_line_l = Long.parseLong(color_line, 16); + long color_grid_l = Long.parseLong(color_grid, 16); + picture.setColor(color_dot_l); picture.gridDot(centerx, centery, 5, true, 100); if (corona) { for (int i = 0; i < 6; i++) { @@ -97,7 +101,7 @@ public class AccessPicture_p { picture.gridDot(centerx, centery, 50, false, 100); } //picture.gridDot(centerx, centery, 31, false); - picture.setColor(color_text); + picture.setColor(color_text_l); picture.gridPrint(centerx, centery, 5, "THIS YACY PEER", "\"" + sb.peers.myName().toUpperCase() + "\"", 0); // left column: collect data for access from outside @@ -128,10 +132,10 @@ public class AccessPicture_p { // draw left column: access from outside for (int i = 0; i < hosts.length; i++) { if (hosts[i] != null) { - picture.setColor(color_dot); + picture.setColor(color_dot_l); picture.gridDot(gridLeft, i * 2 + 1, 7, false, 100); picture.gridDot(gridLeft, i * 2 + 1, 8, false, 100); - picture.setColor(color_text); + picture.setColor(color_text_l); picture.gridPrint(gridLeft, i * 2 + 1, 8, hosts[i].toUpperCase(), "COUNT = " + count[i] + ", TIME > " + ((time[i] >= 60000) ? ((time[i] / 60000) + " MINUTES") : ((time[i] / 1000) + " SECONDS")), -1); if (corona) { picture.gridLine((centerx - gridLeft) / 2 - 2, i * 2 + 1, gridLeft, i * 2 + 1, @@ -139,7 +143,7 @@ public class AccessPicture_p { picture.gridLine(centerx, centery, (centerx - gridLeft) / 2 - 2, i * 2 + 1, color_line, 100, "AAAAAA", 100, 12, 11 - coronaangle / 30, 0, true); } else { - picture.setColor(color_line); + picture.setColor(color_line_l); picture.gridLine(gridLeft, i * 2 + 1, (centerx - gridLeft) / 2, i * 2 + 1); picture.gridLine(centerx, centery, (centerx - gridLeft) / 2, i * 2 + 1); } @@ -163,10 +167,10 @@ public class AccessPicture_p { // draw right column: access to outside for (int i = 0; i < hosts.length; i++) { if (hosts[i] != null) { - picture.setColor(color_dot); + picture.setColor(color_dot_l); picture.gridDot(gridRight, i * 2 + 1, 7, false, 100); picture.gridDot(gridRight, i * 2 + 1, 8, false, 100); - picture.setColor(color_text); + picture.setColor(color_text_l); picture.gridPrint(gridRight, i * 2 + 1, 8, hosts[i].toUpperCase(), count[i] + " BYTES, " + time[i] + " MS DUE", 1); if (corona) { picture.gridLine(gridRight, i * 2 + 1, centerx + (gridRight - centerx) / 2 + 2, i * 2 + 1, @@ -174,7 +178,7 @@ public class AccessPicture_p { picture.gridLine(centerx, centery, centerx + (gridRight - centerx) / 2 + 2, i * 2 + 1, color_line, 100, "AAAAAA", 100, 12, coronaangle / 30, 0, true); } else { - picture.setColor(color_line); + picture.setColor(color_line_l); picture.gridLine(gridRight, i * 2 + 1, centerx + (gridRight - centerx) / 2, i * 2 + 1); picture.gridLine(centerx, centery, centerx + (gridRight - centerx) / 2, i * 2 + 1); } @@ -182,24 +186,24 @@ public class AccessPicture_p { } // print headline - picture.setColor(color_text); + picture.setColor(color_text_l); PrintTool.print(picture, 2, 6, 0, "YACY NODE ACCESS GRID", -1); PrintTool.print(picture, width - 2, 6, 0, "SNAPSHOT FROM " + new Date().toString().toUpperCase(), 1); // print legend - picture.setColor(color_grid); + picture.setColor(color_grid_l); picture.gridLine(gridLeft, 0, centerx - 3, 0); picture.gridLine(gridLeft, 0, gridLeft, picture.gridHeight() - 1); picture.gridLine(centerx - 3, 0, centerx - 3, picture.gridHeight() - 1); - picture.setColor(color_dot); + picture.setColor(color_dot_l); picture.gridLine(gridLeft, picture.gridHeight() - 1, centerx - 3, picture.gridHeight() - 1); picture.gridPrint(gridLeft, picture.gridHeight() - 1, 8, "", "INCOMING CONNECTIONS", -1); - picture.setColor(color_grid); + picture.setColor(color_grid_l); picture.gridLine(centerx + 3, 0, gridRight, 0); picture.gridLine(centerx + 3, 0, centerx + 3, picture.gridHeight() - 1); picture.gridLine(gridRight, 0, gridRight, picture.gridHeight() - 1); - picture.setColor(color_dot); + picture.setColor(color_dot_l); picture.gridLine(centerx + 3, picture.gridHeight() - 1, gridRight, picture.gridHeight() - 1); picture.gridPrint(gridRight, picture.gridHeight() - 1, 8, "", "OUTGOING CONNECTIONS", 1); diff --git a/htroot/WebStructurePicture_p.java b/htroot/WebStructurePicture_p.java index 275177058..4f79bd618 100644 --- a/htroot/WebStructurePicture_p.java +++ b/htroot/WebStructurePicture_p.java @@ -139,7 +139,7 @@ public class WebStructurePicture_p { graphPicture = graph.draw(width, height, 40, 40, 16, 16, 12, 6, color_back, color_dot0, color_dota, color_line, color_lineend, color_text); } // print headline - graphPicture.setColor(color_text); + graphPicture.setColor(Long.parseLong(color_text, 16)); PrintTool.print(graphPicture, 2, 8, 0, "YACY WEB-STRUCTURE ANALYSIS", -1); if (hosts != null) PrintTool.print(graphPicture, 2, 16, 0, "LINK ENVIRONMENT OF DOMAIN " + hosts.toUpperCase(), -1); PrintTool.print(graphPicture, width - 2, 8, 0, "SNAPSHOT FROM " + new Date().toString().toUpperCase(), 1); diff --git a/htroot/imagetest.java b/htroot/imagetest.java index 89051c38d..ad2d0b836 100644 --- a/htroot/imagetest.java +++ b/htroot/imagetest.java @@ -46,7 +46,7 @@ public class imagetest { img.dot(620, 200, 90, true, 100); img.setColor(RasterPlotter.RED); img.arc(300, 270, 30, 70, 100); - img.setColor("330000"); + img.setColor(Long.parseLong("330000", 16)); img.arc(220, 110, 50, 90, 30, 110); img.arc(210, 120, 50, 90, 30, 110); img.setColor(RasterPlotter.GREY); @@ -57,7 +57,7 @@ public class imagetest { img.setColor(i); img.dot(10 + 14 * (int) (i / 16), 200 + 14 * (int) (i % 16), 6, true, 100); } - img.setColor("008000"); + img.setColor(Long.parseLong("008000", 16)); img.dot(10 + 14 * 8, 200 + 14 * 8, 90, true, 100); /* for (long r = 0; r < 256; r = r + 16) { @@ -68,9 +68,9 @@ public class imagetest { } } }*/ - img.setColor("0000A0"); + img.setColor(Long.parseLong("0000A0", 16)); img.arc(550, 400, 40, 81, 100); - img.setColor("010100"); + img.setColor(Long.parseLong("010100", 16)); for (int i = 0; i <= 360; i++) { img.arc(550, 400, 40, 41 + i/9, 0, i); } diff --git a/source/net/yacy/dbtest.java b/source/net/yacy/dbtest.java index e8ace461c..5652d91fc 100644 --- a/source/net/yacy/dbtest.java +++ b/source/net/yacy/dbtest.java @@ -461,7 +461,7 @@ final class memprofiler extends Thread { int seconds0 = 0, kilobytes0 = 0; int seconds1 = 0, kilobytes1 = 0; while (this.run) { - this.memChart.setColor("FF0000"); + this.memChart.setColor(Long.parseLong("FF0000", 16)); seconds1 = (int) ((System.currentTimeMillis() - this.start) / 1000); kilobytes1 = (int) (MemoryControl.used() / 1024); this.memChart.chartLine(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_LEFT, seconds0, kilobytes0, seconds1, kilobytes1); diff --git a/source/net/yacy/peers/graphics/Banner.java b/source/net/yacy/peers/graphics/Banner.java index 3969ec856..61a9a33cb 100644 --- a/source/net/yacy/peers/graphics/Banner.java +++ b/source/net/yacy/peers/graphics/Banner.java @@ -79,7 +79,7 @@ public final class Banner { final int width = data.getWidth(); // draw description - bannerPicture.setColor(data.getTextcolor()); + bannerPicture.setColor(Long.parseLong(data.getTextcolor(), 16)); PrintTool.print(bannerPicture, 100, 12, 0, "PEER: " + addTrailingBlanks(data.getName(), exprlength), -1); PrintTool.print(bannerPicture, 100, 22, 0, "LINKS: " + addBlanksAndDots(data.getLinks(), exprlength), -1); PrintTool.print(bannerPicture, 100, 32, 0, "WORDS: " + addBlanksAndDots(data.getWords(), exprlength), -1); @@ -100,7 +100,7 @@ public final class Banner { final String bordercolor = data.getBordercolor(); if (bordercolor != null && !bordercolor.isEmpty()) { - bannerPicture.setColor(bordercolor); + bannerPicture.setColor(Long.parseLong(bordercolor, 16)); bannerPicture.line(0, 0, 0, height - 1, 100); bannerPicture.line(0, 0, width - 1, 0, 100); bannerPicture.line(width - 1, 0, width - 1, height - 1, 100); diff --git a/source/net/yacy/peers/graphics/NetworkGraph.java b/source/net/yacy/peers/graphics/NetworkGraph.java index 6c5206801..369439ced 100644 --- a/source/net/yacy/peers/graphics/NetworkGraph.java +++ b/source/net/yacy/peers/graphics/NetworkGraph.java @@ -193,7 +193,7 @@ public class NetworkGraph { final int outerradius = maxradius - 20; // draw network circle - networkPicture.setColor(COL_DHTCIRCLE); + networkPicture.setColor(Long.parseLong(COL_DHTCIRCLE, 16)); networkPicture.arc(width / 2, height / 2, innerradius - 20, innerradius + 20, 100); //System.out.println("Seed Maximum distance is " + yacySeed.maxDHTDistance); @@ -301,7 +301,7 @@ public class NetworkGraph { } // draw description - networkPicture.setColor(COL_HEADLINE); + networkPicture.setColor(Long.parseLong(COL_HEADLINE, 16)); PrintTool.print(networkPicture, 2, 6, 0, "YACY NETWORK '" + networkName.toUpperCase() + "'", -1); PrintTool.print(networkPicture, 2, 14, 0, networkTitle.toUpperCase(), -1); PrintTool.print(networkPicture, width - 2, 6, 0, "SNAPSHOT FROM " + new Date().toString().toUpperCase(), 1); @@ -317,12 +317,13 @@ public class NetworkGraph { final int angleMy = cyc + (int) (360.0d * Distribution.horizontalDHTPosition(ASCII.getBytes(mySeed.hash)) / DOUBLE_LONG_MAX_VALUE); final int angleOther = cyc + (int) (360.0d * Distribution.horizontalDHTPosition(ASCII.getBytes(otherSeed.hash)) / DOUBLE_LONG_MAX_VALUE); // draw line + Long colorLine_l = Long.parseLong(colorLine, 16); img.arcLine(centerX, centerY, innerradius, innerradius - 20, angleMy, !out, - colorLine, null, 12, (coronaangle < 0) ? -1 : coronaangle / 30, 2, true); + colorLine_l, null, 12, (coronaangle < 0) ? -1 : coronaangle / 30, 2, true); img.arcLine(centerX, centerY, innerradius, innerradius - 20, angleOther, out, - colorLine, null, 12, (coronaangle < 0) ? -1 : coronaangle / 30, 2, true); + colorLine_l, null, 12, (coronaangle < 0) ? -1 : coronaangle / 30, 2, true); img.arcConnect(centerX, centerY, innerradius - 20, angleMy, angleOther, out, - colorLine, 100, null, 100, 12, (coronaangle < 0) ? -1 : coronaangle / 30, 2, true); + colorLine_l, 100, null, 100, 12, (coronaangle < 0) ? -1 : coronaangle / 30, 2, true); } private static class drawNetworkPicturePeerJob { @@ -364,12 +365,12 @@ public class NetworkGraph { if (this.colorDot.equals(COL_MYPEER_DOT)) dotsize = dotsize + 4; if (dotsize > 18) dotsize = 18; // draw dot - this.img.setColor(this.colorDot); + this.img.setColor(Long.parseLong(this.colorDot, 16)); this.img.arcDot(this.centerX, this.centerY, this.innerradius, angle, dotsize); // draw line to text - this.img.arcLine(this.centerX, this.centerY, this.innerradius + 18, this.innerradius + linelength, angle, true, this.colorLine, "444444", 12, this.coronaangle / 30, 0, true); + this.img.arcLine(this.centerX, this.centerY, this.innerradius + 18, this.innerradius + linelength, angle, true, Long.parseLong(this.colorLine, 16), Long.parseLong("444444", 16), 12, this.coronaangle / 30, 0, true); // draw text - this.img.setColor(this.colorText); + this.img.setColor(Long.parseLong(this.colorText, 16)); PrintTool.arcPrint(this.img, this.centerX, this.centerY, this.innerradius + linelength, angle, name); // draw corona around dot for crawling activity diff --git a/source/net/yacy/peers/graphics/ProfilingGraph.java b/source/net/yacy/peers/graphics/ProfilingGraph.java index b4b91c65c..7c8cb5a46 100644 --- a/source/net/yacy/peers/graphics/ProfilingGraph.java +++ b/source/net/yacy/peers/graphics/ProfilingGraph.java @@ -121,9 +121,9 @@ public class ProfilingGraph { bytes = ((Long) event.payload).longValue(); x1 = (int) (time/1000); y1 = (int) (bytes / 1024 / 1024); - chart.setColor("AAAAFF"); + chart.setColor(Long.parseLong("AAAAFF", 16)); chart.chartDot(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_RIGHT, x1, y1, 2, null, 0); - chart.setColor("0000FF"); + chart.setColor(Long.parseLong("0000FF", 16)); if (x0 < 0) chart.chartLine(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_RIGHT, x0, y0, x1, y1); x0 = x1; y0 = y1; } @@ -142,9 +142,9 @@ public class ProfilingGraph { words = (int) ((Long) event.payload).longValue(); x1 = (int) (time/1000); y1 = words; - chart.setColor("228822"); + chart.setColor(Long.parseLong("228822", 16)); chart.chartDot(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_LEFT, x1, y1, 2, null, 315); - chart.setColor("008800"); + chart.setColor(Long.parseLong("008800", 16)); if (x0 < 0) chart.chartLine(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_LEFT, x0, y0, x1, y1); x0 = x1; y0 = y1; } @@ -162,9 +162,9 @@ public class ProfilingGraph { ppm = (int) ((Long) event.payload).longValue(); x1 = (int) (time/1000); y1 = ppm; - chart.setColor("AA8888"); + chart.setColor(Long.parseLong("AA8888", 16)); if (x0 < 0) chart.chartLine(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_ANOT0, x0, y0, x1, y1); - chart.setColor("AA2222"); + chart.setColor(Long.parseLong("AA2222", 16)); chart.chartDot(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_ANOT0, x1, y1, 2, ppm + " PPM", 0); x0 = x1; y0 = y1; } @@ -184,7 +184,7 @@ public class ProfilingGraph { x1 = (int) (time/1000); y1 = Math.abs((ping.outgoing ? ping.toPeer : ping.fromPeer).hashCode()) % vspace; pingPeer = ping.outgoing ? "-> " + ping.toPeer.toUpperCase() : "<- " + ping.fromPeer.toUpperCase(); - chart.setColor("444444"); + chart.setColor(Long.parseLong("444444", 16)); chart.chartDot(ChartPlotter.DIMENSION_BOTTOM, ChartPlotter.DIMENSION_ANOT2, x1, y1, 2, pingPeer + (ping.newPeers > 0 ? "(+" + ping.newPeers + ")" : ""), 0); x0 = x1; y0 = y1; } diff --git a/source/net/yacy/visualization/ChartPlotter.java b/source/net/yacy/visualization/ChartPlotter.java index c1754554d..c753b97f8 100644 --- a/source/net/yacy/visualization/ChartPlotter.java +++ b/source/net/yacy/visualization/ChartPlotter.java @@ -31,6 +31,9 @@ import java.io.IOException; import javax.imageio.ImageIO; +import net.yacy.kelondro.logging.Log; +import net.yacy.kelondro.util.ByteBuffer; + public class ChartPlotter extends RasterPlotter { @@ -66,11 +69,11 @@ public class ChartPlotter extends RasterPlotter { //this.backgroundColor = backgroundColor; //this.foregroundColor = foregroundColor; if (name != null) { - this.setColor(foregroundColor); + if (foregroundColor != null) this.setColor(Long.parseLong(foregroundColor, 16)); PrintTool.print(this, width / 2 - name.length() * 3, 6, 0, name, -1); } if (subline != null) { - this.setColor(lightColor); + if (lightColor != null) this.setColor(Long.parseLong(lightColor, 16)); PrintTool.print(this, width / 2 - subline.length() * 3, 14, 0, subline, -1); } } @@ -110,18 +113,20 @@ public class ChartPlotter extends RasterPlotter { final int y = (top) ? this.topborder : this.height - this.bottomborder; int x = this.leftborder; int s = offset; + Long colorScale_l = colorScale == null ? null : Long.parseLong(colorScale, 16); + Long colorNaming_l = colorNaming == null ? null : Long.parseLong(colorNaming, 16); while (x < this.width - this.rightborder) { if ((colorScale != null) && (x > this.leftborder) && (x < (this.width - this.rightborder))) { - setColor(colorScale); + setColor(colorScale_l); line(x, this.topborder, x, this.height - this.bottomborder, 100); } - setColor(colorNaming); + setColor(colorNaming_l); line(x, y - 3, x, y + 3, 100); PrintTool.print(this, x, (top) ? y - 3 : y + 9, 0, Integer.toString(s), -1); x += pixelperscale; s += scale; } - setColor(colorNaming); + setColor(colorNaming_l); PrintTool.print(this, this.width - this.rightborder, (top) ? y - 9 : y + 15, 0, name, 1); line(this.leftborder - 4, y, this.width - this.rightborder + 4, y, 100); } @@ -134,12 +139,14 @@ public class ChartPlotter extends RasterPlotter { int s = offset; String s1; int s1max = 0; + Long colorScale_l = colorScale == null ? null : Long.parseLong(colorScale, 16); + Long colorNaming_l = colorNaming == null ? null : Long.parseLong(colorNaming, 16); while (y > this.topborder) { if ((colorScale != null) && (y > this.topborder) && (y < (this.height - this.bottomborder))) { - setColor(colorScale); + setColor(colorScale_l); line(this.leftborder, y, this.width - this.rightborder, y, 100); } - setColor(colorNaming); + setColor(colorNaming_l); line(x - 3, y, x + 3, y, 100); s1 = (s >= 1000000 && s % 10000 == 0) ? Integer.toString(s / 1000000) + "M" : (s >= 1000 && s % 1000 == 0) ? Integer.toString(s / 1000) + "K" : Integer.toString(s); if (s1.length() > s1max) s1max = s1.length(); @@ -147,7 +154,7 @@ public class ChartPlotter extends RasterPlotter { y -= pixelperscale; s += scale; } - setColor(colorNaming); + setColor(colorNaming_l); PrintTool.print(this, (left) ? x - s1max * 6 - 6 : x + s1max * 6 + 9, this.topborder, 90, name, 1); line(x, this.topborder - 4, x, this.height - this.bottomborder + 4, 100); } @@ -164,10 +171,10 @@ public class ChartPlotter extends RasterPlotter { //ip.declareDimension(DIMENSION_TOP, 10, 40, "000000", null, "count"); ip.declareDimension(DIMENSION_LEFT, 50, 40, 0, green, scale , "PPM [PAGES/MINUTE]"); ip.declareDimension(DIMENSION_RIGHT, 100, 20, 0, blue, scale, "MEMORY/MEGABYTE"); - ip.setColor(green); + ip.setColor(Long.parseLong(green, 16)); ip.chartDot(DIMENSION_BOTTOM, DIMENSION_LEFT, -160, 100, 5, null, 0); ip.chartLine(DIMENSION_BOTTOM, DIMENSION_LEFT, -160, 100, -130, 200); - ip.setColor(blue); + ip.setColor(Long.parseLong(blue, 16)); ip.chartDot(DIMENSION_BOTTOM, DIMENSION_RIGHT, -50, 300, 2, null, 0); ip.chartLine(DIMENSION_BOTTOM, DIMENSION_RIGHT, -80, 100, -50, 300); //ip.print(100, 100, 0, "TEXT", true); @@ -177,10 +184,11 @@ public class ChartPlotter extends RasterPlotter { final File file = new File("/Users/admin/Desktop/testimage.png"); try { final FileOutputStream fos = new FileOutputStream(file); - ImageIO.write(ip.getImage(), "png", fos); + fos.write(RasterPlotter.exportImage(ip.getImage(), "png").getBytes()); + //ImageIO.write(ip.getImage(), "png", fos); fos.close(); } catch (final IOException e) {} - + Log.shutdown(); } } diff --git a/source/net/yacy/visualization/GraphPlotter.java b/source/net/yacy/visualization/GraphPlotter.java index 3af2de7aa..5731bfc53 100644 --- a/source/net/yacy/visualization/GraphPlotter.java +++ b/source/net/yacy/visualization/GraphPlotter.java @@ -319,22 +319,27 @@ public class GraphPlotter implements Cloneable { String name; Point c; int x, y; + Long color_dot0_l = Long.parseLong(color_dot0, 16); + Long color_dota_l = Long.parseLong(color_dota, 16); + Long color_line_l = Long.parseLong(color_line, 16); + Long color_lineend_l = Long.parseLong(color_lineend, 16); + Long color_text_l = Long.parseLong(color_text, 16); while (i.hasNext()) { entry = i.next(); name = entry.getKey(); c = entry.getValue(); x = (xfactor == 0.0) ? raster(width / 2, xraster) : leftborder + raster((c.x - this.leftmost) * xfactor, xraster); y = (yfactor == 0.0) ? raster(height / 2, yraster) : height - bottomborder - raster((c.y - this.bottommost) * yfactor, yraster); - image.setColor(c.layer == 0 ? color_dot0 : color_dota); + image.setColor(c.layer == 0 ? color_dot0_l : color_dota_l); image.dot(x, y, 6, true, 100); - image.setColor(color_text); + image.setColor(color_text_l); PrintTool.print(image, x, y + 10, 0, name.toUpperCase(), 0 /*x < 2 * width / 5 ? 1 : x > 3 * width / 5 ? -1 : 0*/); } // draw lines final Iterator j = this.edges.iterator(); Point[] border; - image.setColor(color_line); + image.setColor(color_line_l); int x0, x1, y0, y1; while (j.hasNext()) { border = getEdge(j.next()); @@ -353,8 +358,8 @@ public class GraphPlotter implements Cloneable { y0 = height - bottomborder - raster((border[0].y - this.bottommost) * yfactor, yraster); y1 = height - bottomborder - raster((border[1].y - this.bottommost) * yfactor, yraster); } - // draw the line, with the dot at the beginning of the line - image.lineDot(x1, y1, x0, y0, 3, 4, color_line, color_lineend); + // draw the line, with an errow at the end of the line + image.lineArrow(x0, y0, x1, y1, 6, 5, color_line_l, color_lineend_l); } return image; } diff --git a/source/net/yacy/visualization/HexGridPlotter.java b/source/net/yacy/visualization/HexGridPlotter.java index 95cff525c..274c34b21 100644 --- a/source/net/yacy/visualization/HexGridPlotter.java +++ b/source/net/yacy/visualization/HexGridPlotter.java @@ -64,7 +64,7 @@ public class HexGridPlotter extends RasterPlotter { } public void drawGrid(final String colorNaming) { - setColor(colorNaming); + setColor(Long.parseLong(colorNaming, 16)); int x0, y0, x1, y1; for (int i = 0; i < this.gwidth; i++) { x0 = projectionX(i, -1); @@ -133,14 +133,16 @@ public class HexGridPlotter extends RasterPlotter { int y1 = projectionY(By); int horizontal; int dotc = 0; + Long colorLine_l = colorLine == null ? null : Long.parseLong(colorLine, 16); + Long colorDot_l = colorDot == null ? null : Long.parseLong(colorDot, 16); while (x1 != x0 || y1 != y0) { horizontal = 0; if (x1 > x0) {x1--; horizontal++;} else if (x1 < x0) {x1++; horizontal++;} if (y1 > y0) {y1--; horizontal++;} else if (y1 < y0) {y1++; horizontal++;} - if (colorLine != null) this.setColor(colorLine); + if (colorLine != null) this.setColor(colorLine_l); plot(x1, y1, (horizontal == 2) ? intensityLine : intensityLine * 8 / 10); if (dotc == dotPos) { - if (colorDot != null) this.setColor(colorDot); + if (colorDot != null) this.setColor(colorDot_l); if (dotRadius == 0) this.plot(x1, y1, intensityDot); else if (dotRadius > 0) this.dot(x1, y1, dotRadius, dotFilled, intensityDot); } @@ -155,17 +157,17 @@ public class HexGridPlotter extends RasterPlotter { final HexGridPlotter picture = new HexGridPlotter(640, 480, DrawMode.MODE_SUB, "FFFFFF", 18); picture.drawGrid("555555"); - picture.setColor("33ff33"); + picture.setColor(Long.parseLong("33ff33", 16)); picture.gridDot(0, 0, 5, true, 100); picture.gridPrint(0, 0, 5, "", "0,0", -1); for (int i = 1; i < picture.gridHeight() -1; i++) { - picture.setColor("33ff33");picture.gridDot(0, i, 3, true, 100); - picture.setColor("334433");picture.gridPrint(0, i, 3, "", "0," + i, -1); + picture.setColor(Long.parseLong("33ff33", 16));picture.gridDot(0, i, 3, true, 100); + picture.setColor(Long.parseLong("334433", 16));picture.gridPrint(0, i, 3, "", "0," + i, -1); } for (int i = 1; i < picture.gridWidth() -1; i++) { - picture.setColor("33ff33");picture.gridDot(i, 0, 3, true, 100); - picture.setColor("334433");picture.gridPrint315(i, 0, 3, i + ",0"); + picture.setColor(Long.parseLong("33ff33", 16));picture.gridDot(i, 0, 3, true, 100); + picture.setColor(Long.parseLong("334433", 16));picture.gridPrint315(i, 0, 3, i + ",0"); } - picture.setColor("33ff33"); + picture.setColor(Long.parseLong("33ff33", 16)); picture.gridDot(0, picture.gheight - 1, 5, true, 100); picture.gridPrint(0, picture.gheight - 1, 5, "0, grid.gheight - 1", "", -1); picture.gridDot(picture.gwidth - 1, 0, 5, true, 100); picture.gridPrint(picture.gwidth - 1, 0, 5, "", "grid.gwidth - 1, 0", -1); picture.gridDot(picture.gwidth - 1, picture.gheight - 1, 5, true, 100); picture.gridPrint(picture.gwidth - 1, picture.gheight - 1, 5, "grid.gwidth - 1, grid.gheight - 1", "", 1); diff --git a/source/net/yacy/visualization/PngEncoder.java b/source/net/yacy/visualization/PngEncoder.java index 5b8954e31..1ee1d513c 100644 --- a/source/net/yacy/visualization/PngEncoder.java +++ b/source/net/yacy/visualization/PngEncoder.java @@ -81,7 +81,7 @@ public class PngEncoder extends Object { final int width = image.getWidth(null); final int height = image.getHeight(null); - final TreeMap scan = new TreeMap(); + final TreeMap scan = new TreeMap(); if (height > 80) { // prepare an input list for concurrent PixelGrabber computation final BlockingQueue grabberInput = new LinkedBlockingQueue(); @@ -95,7 +95,7 @@ public class PngEncoder extends Object { } // do the PixelGrabber computation and allocate the result in the right order ArrayList ts = new ArrayList(); - int tc = Math.min(grabberInput.size() / 40, Runtime.getRuntime().availableProcessors()); + int tc = Math.max(2, Math.min(1 + grabberInput.size() / 40, Runtime.getRuntime().availableProcessors())); for (int i = 0; i < tc; i++) { grabberInput.add(POISON_IN); Thread t = new Thread() { @@ -126,9 +126,7 @@ public class PngEncoder extends Object { final Deflater scrunch = new Deflater(compressionLevel); ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024); final DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes, scrunch); - for (Map.Entry entry: scan.entrySet()) { - compBytes.write(entry.getValue().scan, 0, entry.getValue().count); - } + for (Map.Entry entry: scan.entrySet()) compBytes.write(entry.getValue()); compBytes.close(); final byte[] compressedLines = outBytes.toByteArray(); outBytes.close(); @@ -171,28 +169,23 @@ public class PngEncoder extends Object { return offset + data.length; } - private final static void pixelGrabber(final Image image, final int width, int y, int nRows, TreeMap scan) throws IOException { + private final static void pixelGrabber(final Image image, final int width, int y, int nRows, TreeMap scan) throws IOException { int[] pixels = new int[width * nRows]; PixelGrabber pg = new PixelGrabber(image, 0, y, width, nRows, pixels, 0, width); try {pg.grabPixels();} catch (InterruptedException e) {throw new IOException("interrupted waiting for pixels!");} if ((pg.getStatus() & ImageObserver.ABORT) != 0) throw new IOException("image fetch aborted or errored"); - byte[] scanLines = new byte[width * nRows * 4]; // the scan lines to be compressed - int scanPos = 0; // where we are in the scan lines - for (int i = 0; i < width * nRows; i++) { - if (i % width == 0) scanLines[scanPos++] = (byte) 0; - scanLines[scanPos++] = (byte) ((pixels[i] >> 16) & 0xff); - scanLines[scanPos++] = (byte) ((pixels[i] >> 8) & 0xff); - scanLines[scanPos++] = (byte) ((pixels[i]) & 0xff); - } - synchronized (scan) {scan.put(y, new ScanLines(scanLines, scanPos));} - } - - private static class ScanLines { - protected byte[] scan; - protected int count; - public ScanLines(final byte[] scan, final int count) { - this.scan = scan; - this.count = count; + try { + ByteArrayOutputStream scanLines = new ByteArrayOutputStream(width * nRows * 3 + width); + for (int i = 0; i < width * nRows; i++) { + if (i % width == 0) scanLines.write(0); + scanLines.write((pixels[i] >> 16) & 0xff); + scanLines.write((pixels[i] >> 8) & 0xff); + scanLines.write((pixels[i]) & 0xff); + } + synchronized (scan) {scan.put(y, scanLines.toByteArray());} + scanLines.close(); + } catch (OutOfMemoryError e) { + throw new IOException("out of memory, needed bytes: " + width * nRows * 4); } } diff --git a/source/net/yacy/visualization/RasterPlotter.java b/source/net/yacy/visualization/RasterPlotter.java index 6c8adfb1f..74d447f29 100644 --- a/source/net/yacy/visualization/RasterPlotter.java +++ b/source/net/yacy/visualization/RasterPlotter.java @@ -69,7 +69,7 @@ public class RasterPlotter { protected final int width, height; private final int[] cc; - private BufferedImage image; + private BufferedImage image; private final WritableRaster grid; private int defaultColR, defaultColG, defaultColB; private final long backgroundCol; @@ -90,9 +90,23 @@ public class RasterPlotter { this.defaultMode = drawMode; try { this.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + /* + byte[] frame = new byte[width * height * 3]; + DataBuffer videoBuffer = new DataBufferByte(frame, frame.length); + ComponentSampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 3, width*3, new int[] {2,1,0}); + Raster raster = Raster.createRaster(sampleModel, videoBuffer, null); + this.image.setData(raster); + */ } catch (final OutOfMemoryError e) { - this.image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - //throw new RuntimeException(RasterPlotter.class.getSimpleName() + ": not enough memory (" + MemoryControl.available() + ") available"); + try { + this.image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_INDEXED); + } catch (final OutOfMemoryError ee) { + try { + this.image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY); + } catch (final OutOfMemoryError eee) { + this.image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); + } + } } clear(); this.grid = this.image.getRaster(); @@ -156,10 +170,6 @@ public class RasterPlotter { } - public void setColor(final String s) { - setColor(Long.parseLong(s, 16)); - } - public void plot(final int x, final int y) { plot(x, y, 100); } @@ -229,8 +239,8 @@ public class RasterPlotter { public void line( int Ax, int Ay, final int Bx, final int By, - final String colorLine, final int intensityLine, - final String colorDot, final int intensityDot, final int dotDist, final int dotPos, final int dotRadius, final boolean dotFilled + final Long colorLine, final int intensityLine, + final Long colorDot, final int intensityDot, final int dotDist, final int dotPos, final int dotRadius, final boolean dotFilled ) { // Bresenham's line drawing algorithm int dX = Math.abs(Bx-Ax); @@ -287,33 +297,77 @@ public class RasterPlotter { } } - public void lineDot(final int x0, final int y0, final int x1, final int y1, final int radius, final int distance, final String lineColor, final String dotColor) { - lineDot(x0, y0, x1, y1, radius, distance, Long.parseLong(lineColor, 16), Long.parseLong(dotColor, 16)); + /** + * draw a line with a dot at the end + * @param x0 start point + * @param y0 start point + * @param x1 end point + * @param y1 end point + * @param radius radius of the dot + * @param padding the distance of the dot border to the end point + * @param lineColor the color of the line + * @param dotColor the color of the dot + */ + public void lineDot(final int x0, final int y0, final int x1, final int y1, final int radius, final int padding, final long lineColor, final long dotColor) { + final double dx = x1 - x0; // distance of points, x component + final double dy = y1 - y0; // distance of points, y component + final double angle = Math.atan2(dy, dx); // the angle of the line between the points + final double d = Math.sqrt((dx * dx + dy * dy)); // the distance between the points (Pythagoras) + final double ddotcenter = d - radius - padding; // distance from {x0, y0} to dot center near {x1, y1} + final double ddotborder = ddotcenter - radius; // distance to point {x3, y3} at border of dot center at {x2, y2} + final double xn = Math.cos(angle); // normalized vector component x + final double yn = Math.sin(angle); // normalized vector component y + final int x2 = x0 + ((int) (ddotcenter * xn)); // dot center, x component + final int y2 = y0 + ((int) (ddotcenter * yn)); // dot center, y component + final int x3 = x0 + ((int) (ddotborder * xn)); // dot border, x component + final int y3 = y0 + ((int) (ddotborder * yn)); // dot border, y component + setColor(lineColor); line(x0, y0, x3, y3, 100); // draw line from {x0, y0} to dot border + setColor(dotColor); dot(x2, y2, radius, true, 100); // draw dot at {x2, y2} } - public void lineDot(final int x0, final int y0, final int x1, final int y1, final int radius, final int distance, final long lineColor, final long dotColor) { - // draw a line with a dot at the end. - // the radius value is the radius of the dot - // the distance value is the distance of the dot border to the endpoint - - // compute first the angle of the line between the points - final double angle = (x1 - x0 > 0) ? Math.atan(((double) (y0 - y1)) / ((double) (x1 - x0))) : Math.PI - Math.atan(((double) (y0 - y1)) / ((double) (x0 - x1))); - // now find two more points in between - // first calculate the radius' of the points - final double ra = Math.sqrt(((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1))); // from a known point x1, y1 - final double rb = ra - radius - distance; - final double rc = rb - radius; - // the points are on a circle with radius rb and rc - final int x2 = x0 + ((int) (rb * Math.cos(angle))); - final int y2 = y0 - ((int) (rb * Math.sin(angle))); - final int x3 = x0 + ((int) (rc * Math.cos(angle))); - final int y3 = y0 - ((int) (rc * Math.sin(angle))); + /** + * draw a line with an arrow at the end + * @param x0 start point + * @param y0 start point + * @param x1 end point + * @param y1 end point + * @param sidelength the side length of the arrow tip (all 3 sides are equal) + * @param padding the distance of the arrow tip to the end point + * @param lineColor the color of the line + * @param arrowColor the color of the arrow tip + */ + public void lineArrow(final int x0, final int y0, final int x1, final int y1, final int sidelength, final int padding, final long lineColor, final long arrowColor) { + final double dx = x1 - x0; // distance of points, x component + final double dy = y1 - y0; // distance of points, y component + final double angle = Math.atan2(dy, dx); // the angle of the line between the points + final double d = Math.sqrt((dx * dx + dy * dy)); // the distance between the points (Pythagoras) + final double arrowtip = d - padding; // the distance from {x0, y0} to the arrow tip + final double arrowlength = TL * sidelength; // the length of the arrow (distance from base to tip) + final double arrowbase = arrowtip - arrowlength; // the distance from {x0, y0} to the arrow base + final double xn = Math.cos(angle); // normalized vector component x + final double yn = Math.sin(angle); // normalized vector component y + final int xt = x0 + ((int) (arrowtip * xn)); // arrow tip point component x + final int yt = y0 + ((int) (arrowtip * yn)); // arrow tip point component y + final double xb = x0 + arrowbase * xn; // arrow base point component x + final double yb = y0 + arrowbase * yn; // arrow base point component y + final double sl2 = sidelength / 2.0; // half of the side length + final double xk = sl2 * Math.cos(angle + PI2); // point at 90 degree on arrow direction to left side, vector component x + final double yk = sl2 * Math.sin(angle + PI2); // point at 90 degree on arrow direction to left side, vector component y + final int x2 = (int) (xb + xk); + final int y2 = (int) (yb + yk); + final int x3 = (int) (xb - xk); + final int y3 = (int) (yb - yk); setColor(lineColor); - line(x0, y0, x3, y3, 100); - setColor(dotColor); - dot(x2, y2, radius, true, 100); + line(x0, y0, (int) xb, (int) yb, 100); // draw line from {x0, y0} to arrow base + setColor(arrowColor); + line(x2, y2, x3, y3, 100); // base line + line(x2, y2, xt, yt, 100); // left line + line(x3, y3, xt, yt, 100); // right line } + private final static double TL = Math.sqrt(3) / 2; + private final static double PI2 = Math.PI / 2; + public int[] getColor(final int x, final int y) { final int[] c = new int[3]; return this.grid.getPixel(x, y, c); @@ -342,7 +396,7 @@ public class RasterPlotter { } public void arcLine(final int cx, final int cy, final int innerRadius, final int outerRadius, final double angle, final boolean in, - final String colorLine, final String colorDot, final int dotDist, final int dotPos, final int dotRadius, final boolean dotFilled) { + final Long colorLine, final Long colorDot, final int dotDist, final int dotPos, final int dotRadius, final boolean dotFilled) { final double a = PI180 * angle; final double cosa = Math.cos(a); final double sina = Math.sin(a); @@ -374,8 +428,8 @@ public class RasterPlotter { } public void arcConnect(final int cx, final int cy, final int arcRadius, final double angle1, final double angle2, final boolean in, - final String colorLine, final int intensityLine, - final String colorDot, final int intensityDot, final int dotDist, final int dotPos, final int dotRadius, final boolean dotFilled) { + final Long colorLine, final int intensityLine, + final Long colorDot, final int intensityDot, final int dotDist, final int dotPos, final int dotRadius, final boolean dotFilled) { final double a1 = PI180 * angle1; final double a2 = PI180 * angle2; final int x1 = cx + (int) (arcRadius * Math.cos(a1));