Skip to content

Commit cdbec96

Browse files
committed
init
0 parents  commit cdbec96

File tree

9 files changed

+266
-0
lines changed

9 files changed

+266
-0
lines changed

Readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Async image processing
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.image.imageprocessing.filter;
2+
3+
import java.awt.*;
4+
import java.awt.image.BufferedImage;
5+
6+
public class GreyScaleFilter implements ImageFilter{
7+
8+
@Override
9+
public BufferedImage filter(BufferedImage originalImage){
10+
int width = originalImage.getWidth();
11+
int height = originalImage.getHeight();
12+
13+
BufferedImage grayscaleImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
14+
15+
for (int y = 0; y < height; y++) {
16+
for (int x = 0; x < width; x++) {
17+
int rgb = originalImage.getRGB(x, y);
18+
19+
int r = (rgb >> 16) & 0xFF;
20+
int g = (rgb >> 8) & 0xFF;
21+
int b = rgb & 0xFF;
22+
int gray = (int) (0.2126 * r + 0.7152 * g + 0.0722 * b);
23+
int newRgb = new Color(gray, gray, gray).getRGB();
24+
grayscaleImage.setRGB(x, y, newRgb);
25+
}
26+
}
27+
return grayscaleImage;
28+
}
29+
30+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.image.imageprocessing.filter;
2+
3+
import java.awt.image.BufferedImage;
4+
5+
public interface ImageFilter {
6+
BufferedImage filter(BufferedImage image);
7+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.image.imageprocessing.image;
2+
3+
import javafx.animation.AnimationTimer;
4+
import javafx.application.Platform;
5+
import javafx.embed.swing.SwingFXUtils;
6+
import javafx.scene.Group;
7+
import javafx.scene.Scene;
8+
import javafx.scene.canvas.Canvas;
9+
import javafx.scene.canvas.GraphicsContext;
10+
import javafx.scene.layout.StackPane;
11+
import javafx.stage.Stage;
12+
13+
import java.util.Queue;
14+
import java.util.concurrent.LinkedBlockingQueue;
15+
16+
public class DrawMultipleImagesOnCanvas {
17+
18+
private static DrawMultipleImagesOnCanvas instance;
19+
private Queue<ImageData> queue = new LinkedBlockingQueue<>();
20+
private GraphicsContext gc;
21+
private boolean isDrawing = false;
22+
23+
public static DrawMultipleImagesOnCanvas getInstance(){
24+
if(instance == null){
25+
return new DrawMultipleImagesOnCanvas();
26+
}
27+
return instance;
28+
}
29+
30+
public void addImageToQueue(ImageData image){
31+
queue.offer(image);
32+
}
33+
34+
public void initialize(Stage primaryStage){
35+
Canvas canvas = new Canvas(1920, 1080);
36+
this.gc = canvas.getGraphicsContext2D();
37+
this.gc.clearRect(0,0, 1920, 1080);
38+
39+
new AnimationTimer() {
40+
@Override
41+
public void handle(long now) {
42+
// Todo: poll the image from queue, spin a thread and draw
43+
if (!isDrawing && !queue.isEmpty()) {
44+
new Thread(() -> {
45+
try{
46+
drawNextImage();
47+
}finally {
48+
isDrawing = false;
49+
}
50+
}).start();
51+
}
52+
}
53+
}.start();
54+
55+
StackPane stack = new StackPane(canvas);
56+
Scene scene = new Scene(stack, 1920, 1080);
57+
primaryStage.setScene(scene);
58+
primaryStage.setTitle("Canvas Example");
59+
primaryStage.show();
60+
}
61+
62+
private void drawNextImage(){
63+
ImageData imageData = queue.poll();
64+
Platform.runLater(() -> {
65+
if(imageData != null){
66+
this.gc.drawImage(SwingFXUtils.toFXImage(imageData.getImage(), null),
67+
imageData.getI(), imageData.getJ(), imageData.getX(), imageData.getY());
68+
System.out.println("Drawing using thread "+Thread.currentThread().getName());
69+
System.out.println(String.format("Drawing image at i: %s, j: %s", imageData.getI(), imageData.getJ()));
70+
}
71+
});
72+
}
73+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.image.imageprocessing.image;
2+
3+
import java.awt.image.BufferedImage;
4+
5+
public class ImageData {
6+
7+
public int getI() {
8+
return i;
9+
}
10+
11+
public void setI(int i) {
12+
this.i = i;
13+
}
14+
15+
public BufferedImage getImage() {
16+
return image;
17+
}
18+
19+
public void setImage(BufferedImage image) {
20+
this.image = image;
21+
}
22+
23+
public int getJ() {
24+
return j;
25+
}
26+
27+
public void setJ(int j) {
28+
this.j = j;
29+
}
30+
31+
public int getX() {
32+
return x;
33+
}
34+
35+
public void setX(int x) {
36+
this.x = x;
37+
}
38+
39+
public int getY() {
40+
return y;
41+
}
42+
43+
public void setY(int y) {
44+
this.y = y;
45+
}
46+
47+
public ImageData(BufferedImage image, int i, int j, int x, int y) {
48+
this.image = image;
49+
this.i = i;
50+
this.j = j;
51+
this.x = x;
52+
this.y = y;
53+
}
54+
55+
private BufferedImage image;
56+
private int i;
57+
private int j;
58+
private int x;
59+
private int y;
60+
61+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.image.imageprocessing.io;
2+
3+
import javax.imageio.ImageIO;
4+
import java.awt.image.BufferedImage;
5+
import java.io.File;
6+
7+
public class FileImageIO implements ImageReadInf {
8+
9+
@Override
10+
public <T> BufferedImage readImage(T src){
11+
try{
12+
String path = (String) src;
13+
File imageFile = new File(path);
14+
return ImageIO.read(imageFile);
15+
}catch (Exception ex){
16+
System.err.println("Not able to read the image");
17+
return null;
18+
}
19+
}
20+
21+
@Override
22+
public void sendImage(BufferedImage src){
23+
// Todo: implement this fucntion to store the imageFile
24+
}
25+
26+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.image.imageprocessing.io;
2+
3+
import java.awt.image.BufferedImage;
4+
5+
public interface ImageReadInf {
6+
<T> BufferedImage readImage(T src);
7+
8+
void sendImage(BufferedImage image);
9+
}
3.6 MB
Loading
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.image.imageprocessing.processor;
2+
3+
import com.image.imageprocessing.filter.ImageFilter;
4+
import com.image.imageprocessing.image.DrawMultipleImagesOnCanvas;
5+
import com.image.imageprocessing.image.ImageData;
6+
7+
import java.awt.image.BufferedImage;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import java.util.concurrent.Callable;
11+
import java.util.concurrent.ExecutorService;
12+
import java.util.concurrent.Executors;
13+
import java.util.concurrent.Future;
14+
15+
public class ImageProcessor {
16+
17+
private ExecutorService executorService;
18+
private DrawMultipleImagesOnCanvas drawFn;
19+
20+
public ImageProcessor(){
21+
executorService = Executors.newFixedThreadPool(100);
22+
}
23+
24+
public void processImage(BufferedImage image, int num, ImageFilter imageFilter, DrawMultipleImagesOnCanvas drawFn){
25+
int numHorizontalImages = image.getWidth() / num;
26+
int numVerticalImages = image.getHeight() / num;
27+
28+
List<Future<ImageData>> futures = new ArrayList<>();
29+
30+
for (int i = 0; i<numHorizontalImages; i++){
31+
for(int j=0; j<numVerticalImages; j++){
32+
BufferedImage subImage = image.getSubimage(i*num, j*num, num, num);
33+
int finalI = i;
34+
int finalJ = j;
35+
Future<ImageData> future = executorService.submit(new Callable<ImageData>() {
36+
@Override
37+
public ImageData call(){
38+
BufferedImage result = imageFilter.filter(subImage);
39+
ImageData imageData = new ImageData(result, finalI *num, finalJ *num, num, num);
40+
41+
drawFn.addImageToQueue(imageData);
42+
return imageData;
43+
}
44+
});
45+
futures.add(future);
46+
}
47+
}
48+
49+
for (Future<ImageData> future : futures) {
50+
try {
51+
future.get();
52+
} catch (Exception ex) {
53+
System.err.println("Not able to push the image into the queue");
54+
}
55+
}
56+
57+
}
58+
59+
}

0 commit comments

Comments
 (0)