-
Notifications
You must be signed in to change notification settings - Fork 0
/
ImageDisplay.java
executable file
·333 lines (298 loc) · 10.6 KB
/
ImageDisplay.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ImageDisplay {
JFrame frame;
JLabel lbIm1;
int[][][] imgOne;
float zoomFactor=1;
float rotationFactor=0.0f;
int counter = 0;
int timerCounter = 0;
int frameCounter = 0;
BufferedImage[] framesResult;
float prevZoomVal = 1;
float prevRotateVal = 0;
int fps;
float zoomF;
float rotation;
int nThreads = 5;
BlockingQueue<ResultWithIndex> franQueue = new LinkedBlockingQueue<>();
// Modify the height and width values here to read and display an image with
// different dimensions.
int width = 512;
int height = 512;
// Helper class to store result with index
static class ResultWithIndex {
int index;
BufferedImage result;
public ResultWithIndex(int index, BufferedImage result) {
this.index = index;
this.result = result;
}
}
/** Read Image RGB
* Reads the image of given width and height at the given imgPath into the provided BufferedImage.
*/
private void readImageRGB(int width, int height, String imgPath)
{
try
{
int frameLength = width*height*3;
File file = new File(imgPath);
RandomAccessFile raf = new RandomAccessFile(file, "r");
raf.seek(0);
long len = frameLength;
byte[] bytes = new byte[(int) len];
raf.read(bytes);
int ind = 0;
imgOne = new int[width][height][3];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
imgOne[x][y][0] = bytes[ind] & 0xFF; // Red
imgOne[x][y][1] = bytes[ind + height * width] & 0xFF; // Green
imgOne[x][y][2] = bytes[ind + height * width * 2] & 0xFF; // Blue
ind++;
}
}
raf.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
public BufferedImage zoom(float zoomFactor, float angle){
int[][][] temp = new int[width][height][3];
BufferedImage rbuf = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int newHeight = height;
int newWidth = width;
if(zoomFactor < 1){
newWidth = (int) (width * zoomFactor);
newHeight = (int) (height * zoomFactor);
for(int y=0; y<newHeight; y++){
for(int x=0; x<newWidth; x++){
// pixels average range
int startX = Math.max(0, (int)(x / zoomFactor - 1));
int startY = Math.max(0, (int)(y / zoomFactor - 1));
int endX = Math.min(width - 1, startX + 3);
int endY = Math.min(height - 1, startY + 3);
int totalRed = 0;
int totalGreen = 0;
int totalBlue = 0;
int pixelsTotal = 0;
// pixels average
for (int j = startY; j < endY; j++) {
for (int i = startX; i < endX; i++) {
int originX = Math.min(i, width - 1);
int originY = Math.min(j, height - 1);
int r = imgOne[originX][originY][0];
int g = imgOne[originX][originY][1];
int b = imgOne[originX][originY][2];
totalRed += r;
totalGreen += g;
totalBlue += b;
pixelsTotal+=1;
}
}
// average RGB values
int avgRed = totalRed / pixelsTotal;
int avgGreen = totalGreen / pixelsTotal;
int avgBlue = totalBlue / pixelsTotal;
int xCord = (width - newWidth) / 2;
int yCord = (height - newHeight) / 2;
temp[x+xCord][y+yCord][0] = avgRed;
temp[x+xCord][y+yCord][1] = avgGreen;
temp[x+xCord][y+yCord][2] = avgBlue;
}
}
for(int y=0; y<height; y++){
for(int x=0; x<width; x++){
float radians = (float)Math.toRadians(angle);
int rotatedX = (int) (Math.cos(radians) * (x - width / 2) - Math.sin(radians) * (y - height / 2) + width / 2);
int rotatedY = (int) (Math.sin(radians) * (x - width / 2) + Math.cos(radians) * (y - height / 2) + height / 2);
if (rotatedX >= 0 && rotatedX < width && rotatedY >= 0 && rotatedY < height){
int r = temp[rotatedX][rotatedY][0];
int g = temp[rotatedX][rotatedY][1];
int b = temp[rotatedX][rotatedY][2];
int pixVal = (255 << 24) | (r << 16) | (g << 8) | b;
rbuf.setRGB(x, y, pixVal);
}
}
}
}
else{
for(int y=0; y<newHeight; y++){
for(int x=0; x<newWidth; x++){
int originX = (int) ((x - width / 2) / zoomFactor + width / 2);
int originY = (int) ((y - height / 2) / zoomFactor + height / 2);
float radians = (float)Math.toRadians(angle);
int rotatedX = (int) (Math.cos(radians) * (originX - width / 2) - Math.sin(radians) * (originY - height / 2) + width / 2);
int rotatedY = (int) (Math.sin(radians) * (originX - width / 2) + Math.cos(radians) * (originY - height / 2) + height / 2);
if (rotatedX >= 0 && rotatedX < width && rotatedY >= 0 && rotatedY < height){
int r = imgOne[rotatedX][rotatedY][0];
int g = imgOne[rotatedX][rotatedY][1];
int b = imgOne[rotatedX][rotatedY][2];
int pixVal = (255 << 24) | (r << 16) | (g << 8) | b;
rbuf.setRGB(x, y, pixVal);
}
}
}
}
return rbuf;
}
public void frames(){
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
prevZoomVal = zoomFactor;
prevRotateVal = rotationFactor;
counter++;
zoomFactor = 1 + (counter * zoomF);
rotationFactor += rotation;
float zoomCalcFactor = (zoomFactor-prevZoomVal)/fps;
float rotataionCalcFactor = (rotationFactor-prevRotateVal)/fps;
BufferedImage[] framesArray = new BufferedImage[fps];
int k = 0;
for(int i=0; i<fps; i++){
// zoomSequence[i] = zoomCalcFactor*k;
// rotationSequence[i] = rotataionCalcFactor*k;
// k+=1;
framesArray[i] = new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);
final int kk = k;
k+=1;
frameCounter++;
final int gC = frameCounter;
executor.execute(new Runnable() {
@Override
public void run() {
BufferedImage img;
// System.out.println("PrevZ: "+prevZoomVal+" PrevR: "+prevRotateVal+" Counter: "+kk+" ZoomFactor: "+zoomFactor+" rotationFactor: "+rotationFactor);
// System.out.println(counter);
img= zoom(prevZoomVal+zoomCalcFactor*kk, ((rotataionCalcFactor*kk)+prevRotateVal));
// System.out.println(gC);
try {
franQueue.put(new ResultWithIndex(gC, img));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
// public void MultiTFrames(){
// ExecutorService executor = Executors.newFixedThreadPool(nThreads);
// for (int i = 0; i < nThreads; i++) {
// prevZoomVal = zoomFactor;
// prevRotateVal = rotationFactor;
// counter++;
// zoomFactor = 1 + (counter * zoomF);
// rotationFactor += rotation;
// float arg1Zoom = zoomFactor;
// float arg2Rotate = rotationFactor;
// float arg4PreR = prevRotateVal;
// float arg5PreZ = prevZoomVal;
// int c = counter;
// executor.execute(new Runnable() {
// @Override
// public void run() {
// System.out.println("PrevZ: "+arg5PreZ+" PrevR: "+arg4PreR+" Counter: "+c+" ZoomFactor: "+arg1Zoom+" rotationFactor: "+arg2Rotate);
// BufferedImage[] frame = frames(arg1Zoom, arg2Rotate, fps, arg4PreR, arg5PreZ);
// try{
// franQueue.put(new ResultWithIndex(c, frame));
// }
// catch(InterruptedException e){
// e.printStackTrace();
// }
// }
// });
// }
// executor.shutdown();
// try {
// executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
// } catch (InterruptedException ex) {
// ex.printStackTrace();
// }
// }
public void showIms(String[] args){
// Read in the specified image
readImageRGB(width, height, args[0]);
// Use label to display the image
frame = new JFrame();
GridBagLayout gLayout = new GridBagLayout();
frame.getContentPane().setLayout(gLayout);
zoomF = Float.parseFloat(args[1])-1;
rotation = -Float.parseFloat(args[2]);
fps = Integer.parseInt(args[3]);
BufferedImage im1 = zoom(zoomFactor, rotationFactor);
lbIm1 = new JLabel(new ImageIcon(im1));
frames();
Timer timer = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//framesResult = frames(zoomFactor, rotationFactor, fps);
timerCounter+=1;
// ResultWithIndex result = (ResultWithIndex) franQueue.stream().filter(r -> ((ResultWithIndex) r).index == timerCounter).findFirst().orElse(null);
// framesResult = result.result;
// Display each frame separately with a delay
for (int i = 0; i < fps; i++) {
timerCounter+=1;
ResultWithIndex result = (ResultWithIndex) franQueue.stream().filter(r -> ((ResultWithIndex) r).index == timerCounter).findFirst().orElse(null);
Timer frameTimer = new Timer(i * 1000 / fps, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
lbIm1.setIcon(new ImageIcon(result.result));
frame.revalidate();
frame.repaint();
result.result = null;
}
});
frameTimer.setRepeats(false); // Ensure each frame is displayed only once
frameTimer.start();
}
}
});
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(() -> {
// MultiTFrames();
frames();
frames();
}, 0, 1, TimeUnit.SECONDS);
// MultiTFrames();
timer.start();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.CENTER;
c.weightx = 0.5;
c.gridx = 0;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 1;
frame.getContentPane().add(lbIm1, c);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) {
ImageDisplay ren = new ImageDisplay();
ren.showIms(args);
}
}