Free Starter Classes MIT License
package graphics;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.StringWriter;
import java.util.logging.Logger;
public class TwoColorImageUtil {
private static Logger logger = Logger.getLogger(TwoColorImageUtil.class.getName());
public static void renderToGraphics2D(TwoColorImage twoColorImage, Graphics2D graphics2D) {
boolean pixels[][] = twoColorImage.getPixels();
Color highlight = Color.CYAN;
Color fill = Color.BLACK;
for (int y=0; y<pixels[0].length; y++) {
for (int x=0; x<pixels.length; x++) {
if (pixels[x][y]) {
graphics2D.setColor(highlight);
} else {
graphics2D.setColor(fill);
}
graphics2D.drawLine(x, y, x, y);
}
}
}
public static BufferedImage renderTwoColorImage(TwoColorImage twoColorImage) {
BufferedImage bufferedImage = new BufferedImage(
twoColorImage.getWidth(),twoColorImage.getHeight(),BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = bufferedImage.createGraphics();
renderToGraphics2D(twoColorImage, graphics2D);
return bufferedImage;
}
public static String renderAscii(TwoColorImage image) {
boolean pixels[][] = image.getPixels();
final StringWriter stringWriter = new StringWriter();
for (int y=0; y<pixels[0].length; y++) {
for (int x=0; x<pixels.length; x++) {
if (pixels[x][y]) {
stringWriter.append("X");
} else {
stringWriter.append("0");
}
}
stringWriter.append("\n");
}
return stringWriter.toString();
}
public static void main(String args[]) {
logger.info("Testing Ascii Render");
TwoColorImage image = new TwoColorImage(20,10);
image.drawRectangeCoordinates(5, 5, 9, 9);
System.out.println(renderAscii(image));
}
}
package graphics;
public class TwoColorImage {
boolean pixels[][];
public int getWidth() {
return pixels.length;
}
public int getHeight() {
return pixels[0].length;
}
public TwoColorImage(int width, int height) {
pixels = new boolean[width][height];
}
public TwoColorImage(boolean pixels[][]) {
this.pixels = pixels;
}
public boolean[][] getPixels() {
return pixels;
}
public void turnPixelOn(int x, int y) {
pixels[x][y] = true;
}
public void turnPixelOff(int x, int y) {
pixels[x][y] = true;
}
public void drawRectangeCoordinates(int x1, int y1, int x2, int y2) {
for (int x=x1; x<=x2; x++) {
for (int y=y1; y<=y2; y++) {
if (x==x1 || x==x2 || y==y1 || y==y2) {
turnPixelOn(x, y);
}
}
}
}
public void drawRectangeFilledCoordinates(int x1, int y1, int x2, int y2) {
for (int x=x1; x<=x2; x++) {
for (int y=y1; y<=y2; y++) {
turnPixelOn(x, y);
}
}
}
}
Black and White Binary images have the potential for much faster data throughput and processing. A lot can be said with two colors, easy to not fully appreciate the power in that.
Subsystem seems to make it extremely difficult to draw individual pixels which is highly annoying, forces people to rely upon libraries that are prebuilt that are not always adequately maintained.
Four color images? A lot of power in two bits to represent something rather than 16, 32, or 64.
drawCircle(0,0,20,20) is a lot more compressed version than a full image. I wonder if other compression mechanisms can utilize similar. Commands to recreate many times much smaller and simpler than replicating the entire image.
Problem with limited from drawing on pixels having to rely upon libraries to draw is potential for the libraries limiting in non ideal ways. We got you covered plus closed source is not always adequate we got you covered in.
System that makes binary images difficult might not be all throughput amped. Means well can lead to hands tied in non ideal ways. Or should I say non ideal for some.
Added the following (MIT License as well)
public static void renderToGraphics2DTransparent(TwoColorImage twoColorImage, Graphics2D graphics2D) {
boolean pixels[][] = twoColorImage.getPixels();
Color highlight = Color.CYAN;
graphics2D.setColor(highlight);
for (int y=0; y<pixels[0].length; y++) {
for (int x=0; x<pixels.length; x++) {
if (pixels[x][y]) {
graphics2D.drawLine(x, y, x, y);
}
}
}
}
This one draws on top of an image that already exists and does not black out the background. Both methods are useful.
Greater network bandwidth with increased speed for rendering binary or four color images could be a lot of power. Power that could likely be turned up at critical times. Slow workflow can be weak for enabling greater workflow at times.
64 threads processing binary two color images vs 64 bit? Much smaller file size has the potential for much faster verification.
Potential for the images to be encoded in a wasteful way. A way that raises comprehension is sometimes upsold to wasteful. I do not consider it as such. Able to log an image is power. Comprehension images render line by line is powerful. Small pieces done right have the potential for large reproduction that is powerful.
The future brings gains equals we have the potential to see things with more refined microscopes, more people looking at the problems. Has the potential to increase gains in more than one direction. Like Comprehension Amplification and faster Throughput, both can benefit each other with out being strictly tied to the same implementation.
Like a version with great amount of logging and a sped up version that doesn’t need all the conditions around logging.
Appears I have a nasty bug in the following code
// Method that runs a set of Parallel tasks and then blocks/sleeps/polls until all
// queued threads are complete
public static ProcessComplete runParallelProcess(String processName, ArrayList<Runnable> parallelProcessList,
boolean enableLog)
{
log(enableLog,processName+" started");
final ConcurrentHashMap<Integer, Boolean> completedMap = new ConcurrentHashMap<>();
try {
for (int i=0; i<parallelProcessList.size(); i++) {
Runnable step = parallelProcessList.get(i);
log(enableLog,processName+" queueing step "+i);
final int stepId=i;
ThreadUtil.addTask(() -> {
step.run();
completedMap.put(stepId, true);
});
}
boolean waiting=true;
while (waiting) {
if (completedMap.size()==parallelProcessList.size())
{
waiting=false;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
log(enableLog,processName+" finished successfully");
return new ProcessComplete(true, true);
} catch (Exception e) {
return new ProcessComplete(true, false);
}
}
For some reason the method does not block adequately. It is supposed to required all threads to complete yet might be some issue with class instance versioning.
Ideally should wait for all subtasks to complete but it seems like it is showing as complete and then when I access those same objects after tasks have completed I am showing some not complete.
Slowing the process down might lead to better ability to debug and thus speed ups.
Seems to be an issue with versioning, I switched to using a ConcurrentHashMap where I added the results and seems to be working, need to check closer. Maybe not appears to still have a bug.
Seems to be working better when I blocked waiting on the complete ConcurrentHashmap in the same app. I am not sure why that is.
That said I am now redrawing 2D images much faster than before.
Multithread approach using a Threadpool and Non Virtualized threads likely is leading to some performance losses. I tried to use ofVirtual but seemed to have a problem even with the new JDK, might be a preview feature.
https://developer.okta.com/blog/2022/08/26/state-of-java-project-loom
Realtime Systems and Game Programming require ultra low latency. Operating System threads take time to spin up at least from what I am seeing performance wise. Capitalizing on an already running thread is like using a wheel to crush grain. One that is already moving is much easier to crush grain.
Thus if you have 4 processing cores that all are trying to do work efficiently, having reduced need to spin up memory calls and more function calls around them for creation seems like it will help. Plus Energy Efficient processors don’t always like their extra cores running when not necessary thus utilization turned on and off potential for cold start greater activation energy.
Launch 4 threads then processor completes then processor powers down those cores. Then launch 4 threads again have to turn back on those cores and so on. Thus keeping the extra cores spinning likely could lead to more efficient output specifically when doing very short repetitive workloads like rendering frames or rendering output for Real Time Systems.
Might not be exactly how it works, someone that knows the JVM and those that understand the CPU architectures could likely speak this better than I currently am.
Might be a trick to using preview features for the new JDK, tried building with Maven and ran into an issue therefore switching back until I figure out how to test preview features.
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>19</release>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
</plugins>