diff --git a/.gitignore b/.gitignore index 5be812d..8b94528 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ target/ +pictures/ .settings/ .project .classpath \ No newline at end of file diff --git a/README.md b/README.md index 40290de..5e6eb90 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,17 @@ DEVICE=1 # 30 = All Prefix related implementations at once # 31 - 32 = Prefix1 - Prefix2 respectively # 40 = Rauschfilter (Spawns a javafx window) +# 50 = Mandelbrot (Spawns a javafx window) +# 60 = RGBHistogramm (Spawns a javafx window) # DEFAULT = 0 TARGET=31 # Parameter for various tasks (e.g. if N should be shifted 3 times, MULTI_PARAM should be 3) # Targes 2X and 3X depend on this parameter (1 << MULTI_PARAM) # Target 4X (N to the left and right of x_0) -# DEFAULT = 25 +# Target 50 Zoom Factor (20 should be used to get good results) +# Target 60 filename of a picture (Place in folder $PROJECT_ROOT/pictures/my_pic.jpg) [jpg,bmp,png] +# DEFAULT = 25 / "lena.bmp" MULTI_PARAM=3 mvn -B clean compile assembly:single && java -jar target/*.jar $DEVICE $TARGET $MULTI_PARAM diff --git a/src/main/java/edu/thi/phga/aparapi_test/App.java b/src/main/java/edu/thi/phga/aparapi_test/App.java index 0f519a4..ead2b2c 100644 --- a/src/main/java/edu/thi/phga/aparapi_test/App.java +++ b/src/main/java/edu/thi/phga/aparapi_test/App.java @@ -7,6 +7,7 @@ public class App { public static int choice; public static OpenCLDevice device; public static int multiParam; + public static String selectedImage; private static void printHeader(final String txt) { final String spacer = "######################################################################"; @@ -20,15 +21,24 @@ public class App { App.choice = Integer.parseInt(args[0]) - 1; } App.device = Devices.selectDevice(); + App.device.setMaxWorkGroupSize(256); // used for 2D, 3D derive + App.device.setMaxWorkItemSize(0, 256); // used for 1D + App.device.setMaxWorkItemSize(1, 16); // used for 2D int target = 0; if (args.length > 1) { target = Integer.parseInt(args[1]); } App.multiParam = 25; + App.selectedImage = "lena.bmp"; if (args.length > 2) { - App.multiParam = Integer.parseInt(args[2]); + if (target >= 60 && target < 70) + App.selectedImage = args[2]; + else { + App.multiParam = Integer.parseInt(args[2]); + } } + App.selectedImage = "file:./pictures/" + App.selectedImage; final int[] b; switch (target) { case 0: @@ -116,6 +126,10 @@ public class App { System.out.println("Spawning window Mandelbrot"); Application.launch(Mandelbrot.class); break; + case 60: + System.out.println("Spawning window RGBHistogramm"); + Application.launch(RGBHistogramm.class); + break; } } } diff --git a/src/main/java/edu/thi/phga/aparapi_test/OpenCLGetMemoryInfo.java b/src/main/java/edu/thi/phga/aparapi_test/OpenCLGetMemoryInfo.java index 14f49ba..531e2f6 100644 --- a/src/main/java/edu/thi/phga/aparapi_test/OpenCLGetMemoryInfo.java +++ b/src/main/java/edu/thi/phga/aparapi_test/OpenCLGetMemoryInfo.java @@ -5,11 +5,16 @@ import com.aparapi.device.Device; public class OpenCLGetMemoryInfo { public static void getInfo() { int localMem = (int) App.device.getLocalMemSize(); + int maxAlloc = (int) App.device.getMaxMemAllocSize(); + int maxWISize1 = (int) App.device.getMaxWorkItemSize()[0]; + int maxWISize2 = (int) App.device.getMaxWorkItemSize()[1]; + int maxWISize3 = (int) App.device.getMaxWorkItemSize()[2]; int maxWGSize = App.device.getMaxWorkGroupSize(); int localSize = Math.min(maxWGSize, localMem / 4); - System.out.printf("Memsize: %d, Max-WGSize: %d, LocalSize: %d\n", - localMem, maxWGSize, localSize); + System.out.printf("LocalMemsize: %d KB\nMaxMemAlloc: %dMB\n" + + "MaxWorkItemSizes Dim(1,2,3): %d, %d, %d\nMax-WGSize: %d\nLocalSize: %d\n", + localMem / 1024, maxAlloc / 1024 / 1024, maxWISize1, maxWISize2, maxWISize3, maxWGSize, localSize); } } diff --git a/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix1.java b/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix1.java index 88190df..88a42f0 100644 --- a/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix1.java +++ b/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix1.java @@ -10,7 +10,7 @@ public class OpenCLPrefix1 { int N = a.length; int b[] = new int[N * 2]; java.util.Arrays.fill(b, 1); - Range r = Range.create(App.device, N, 4); + Range r = Range.create(App.device, N); OpenCLPrefix1Kernel k = new OpenCLPrefix1Kernel(b); k.setExplicit(true); k.setStepSize(1); diff --git a/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix2.java b/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix2.java index 920fe96..b735623 100644 --- a/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix2.java +++ b/src/main/java/edu/thi/phga/aparapi_test/OpenCLPrefix2.java @@ -18,7 +18,9 @@ public class OpenCLPrefix2 { int N = a.length; int b[] = new int[N]; java.util.Arrays.fill(b, 1); - Range r = Range.create(App.device, N, 4); + Range r = Range.create(App.device, N); + System.out.println("Range: " + r); + OpenCLPrefix2Kernel k = new OpenCLPrefix2Kernel(a, b); k.setExplicit(true); k.setStepSize(1); diff --git a/src/main/java/edu/thi/phga/aparapi_test/RGBHistogramm.java b/src/main/java/edu/thi/phga/aparapi_test/RGBHistogramm.java new file mode 100644 index 0000000..1e18357 --- /dev/null +++ b/src/main/java/edu/thi/phga/aparapi_test/RGBHistogramm.java @@ -0,0 +1,113 @@ +package edu.thi.phga.aparapi_test; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import com.aparapi.Range; + +import javafx.application.Application; +import javafx.geometry.Bounds; +import javafx.geometry.Rectangle2D; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.effect.BlendMode; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.image.PixelFormat; +import javafx.scene.layout.HBox; +import javafx.scene.paint.Color; +import javafx.stage.Screen; +import javafx.stage.Stage; + +public class RGBHistogramm extends Application { + private static String DATEI = App.selectedImage; + private static Rectangle2D screen = Screen.getPrimary().getBounds(); + private static final int HGAP = 10; + // Abstand Bild/Histogramm + private static final int MIN_HISTO_WIDTH = 256; + private static final int MAX_HISTO_WIDTH = 512; + private int[] r = new int[256]; + private int[] g = new int[256]; + private int[] b = new int[256]; + + @Override + public void start(Stage stage) { + System.out.println("File: " + DATEI); + Image image = new Image(DATEI); + int w = (int) image.getWidth(); + int h = (int) image.getHeight(); + int[] pixel = new int[w * h]; + System.out.println("Image: " + w + "x" + h); + + image.getPixelReader().getPixels( + 0, 0, w, h, PixelFormat.getIntArgbInstance(), pixel, 0, w + ); + Range range = Range.create2D(App.device, w, h); + System.out.println("Range: " + range); + + // for (int i = 0; i < 20; i++) { + // // 1111 1111 0000 0000 + // int col = 0xff00; + // int val = (col & pixel[i]) >> 8; + // // int res = val / col; + // System.out.printf("%d: %x & %x = %d (%x)\n", pixel[i], pixel[i], + // col, val, val); + // } + + new RGBHistogrammKernel(pixel, r, g, b).execute(range); + + ImageView view = scale(image); + HBox hbox = new HBox(HGAP, view, histogram(view)); + + stage.setScene(new Scene(hbox)); + stage.setTitle("KAO: RGB-Histogram (" + DATEI + ")[" + w + "x" + h + "]"); + stage.setResizable(false); + stage.sizeToScene(); + stage.show(); + } + private ImageView scale(Image image) { + // Skaliere das Bild so, dass es auf den Bildschirm passt + // und für das Histogramm wenigstens die minimale Breite bleibt. + ImageView view = new ImageView(image); + double maxWidth = screen.getWidth () * 0.7 - HGAP - MIN_HISTO_WIDTH; + double maxHeight = screen.getHeight() * 0.8; + if (image.getWidth () > maxWidth ) view.setFitWidth (maxWidth ); + if (image.getHeight() > maxHeight) view.setFitHeight(maxHeight); + view.setPreserveRatio(true); + return view; + } + + private Node histogram(ImageView view) { + Bounds scaledImage = view.getBoundsInParent(); + double deltaW = screen.getWidth() - scaledImage.getWidth(); + double width = Math.min(deltaW, MAX_HISTO_WIDTH); + double height = scaledImage.getHeight(); + Canvas histo = new Canvas(width, height); + // Ermittle für die y-Skalierung den maximalen Häufigkeitswert. + int max = Stream.of(r, g, b) + .flatMapToInt(IntStream::of) + .max() + .getAsInt(); + draw(histo, width / 256, height / max); + return histo; + } + + private void draw(Canvas histo, double xScale, double yScale) { + GraphicsContext graphics = histo.getGraphicsContext2D(); + graphics.setLineWidth(3); + graphics.setGlobalBlendMode(BlendMode.ADD); + double[] x = new double[256], y = new double[256]; + Arrays.parallelSetAll(x, i -> i * xScale); + var pairs = Map.of(r, Color.RED, g, Color.GREEN, b, Color.BLUE); + double h = histo.getHeight(); + for (var pair : pairs.entrySet()) { + Arrays.parallelSetAll(y, i -> h - pair.getKey()[i] * yScale); + graphics.setStroke(pair.getValue()); + graphics.strokePolyline(x, y, 256); + } + } +} diff --git a/src/main/java/edu/thi/phga/aparapi_test/RGBHistogrammKernel.java b/src/main/java/edu/thi/phga/aparapi_test/RGBHistogrammKernel.java new file mode 100644 index 0000000..fa9ec7a --- /dev/null +++ b/src/main/java/edu/thi/phga/aparapi_test/RGBHistogrammKernel.java @@ -0,0 +1,38 @@ +package edu.thi.phga.aparapi_test; + +import com.aparapi.Kernel; + +public class RGBHistogrammKernel extends Kernel { + private int[] pixel; + private int[] r; + private int[] g; + private int[] b; + + public RGBHistogrammKernel(int[] pixel, int[] r, int[] g, int[] b) { + this.pixel = pixel; + this.r = r; + this.g = g; + this.b = b; + } + + @Override + public void run() { + int x = getGlobalId(0); + int y = getGlobalId(1); + + // int redM = 0x00ff0000; + // int greenM = 0x0000ff00; + // int blueM = 0x000000ff; + + int index = y * getGlobalSize(0) + x; + + // atomicAdd(r,(pixel[index] & redM) >> 16, 1); + // atomicAdd(g,(pixel[index] & greenM) >> 8, 1); + // atomicAdd(b, pixel[index] & blueM, 1); + + int cp = pixel[index]; + atomicAdd(r, (cp >> 16) & 0xff, 1); + atomicAdd(g, (cp >> 8) & 0xff, 1); + atomicAdd(b, cp & 0xff, 1); + } +}