source: tags/gsdl-2_70u-distribution/gsdl/src/java/org/nzdl/gsdl/GsdlCollageApplet/DisplayImages.java@ 11745

Last change on this file since 11745 was 11715, checked in by kjdon, 18 years ago

committed Shaoquns version of the applet for the branch - version 1.7

  • Property svn:keywords set to Author Date Id Revision
File size: 14.1 KB
Line 
1package org.nzdl.gsdl.GsdlCollageApplet;
2
3import java.applet.*;
4import java.awt.*;
5import java.awt.image.*;
6import java.awt.geom.*;
7import java.util.*;
8
9/**
10 * @author Katrina Edgar
11 * @author David Bainbridge
12 *
13 * Retrieves images from the download thread, determines an appropriate position
14 * for thes images onscreen ensuring maximum whitespace coverage and minimal overlap
15 * when possible. Draws images using advanced image processing techniques when applicable,
16 * such as fading the edges of an image and discolouring backgrounds. Also re-uses images
17 * from those that have previously been displayed, or are aging onscreen, in order to
18 * to create movement when no new images have been downloaded. */
19public class DisplayImages extends Thread {
20
21
22 /** Will fire a removal operation when 4 images in the collage overlap a single area */
23 static final int NO_IMAGES_OF_OVERLAP = 4;
24
25 /** To determine if there are several images overlapped, can remove the
26 * layers underneath to save time in repainting */
27 boolean overlap = false;
28
29 /** Refers to download thread */
30 DownloadImages download_images_ = null;
31
32 /** Refers to applet */
33 GsdlCollageApplet app_ = null;
34
35 /** Applets width on screen */
36 public static int app_x_dim_ = 0;
37
38 /** Applets height on screen */
39 public static int app_y_dim_ = 0;
40
41 /** Background colour of the applet screen */
42 protected Color bgcolor_ = null;
43
44 /** Indicates whether java2 functionality should be used <br>
45 * If true will allow advanced image processing techniques to occur,
46 * such as fading and colouring using pixel manipulation <br>
47 * If false, images will maintain an alpha value of 1 (appear solid),
48 * newer images will simply be pasted on top of existing images <br> */
49 protected boolean is_java2_ = false;
50
51
52 /** Holds images currently on display in the applet */
53 protected Vector inuse_ = null;
54
55 /** Holds images ready to be used */
56 protected Vector inuse_ready_ = null;
57
58 /** Holds previously displayed images for re-use */
59 protected Vector notinuse_ = null;
60
61 protected Image screen_buffer_ = null;
62 protected Graphics screen_graphic_ = null;
63 protected Image finished_buffer_ = null;
64 protected Graphics finished_graphic_ = null;
65
66 Thread next_frame_ ;
67
68 String dots[] = new String[]{" ",".","..","...","....",".....","......"};
69 int dots_nums=0;
70 boolean start_paint = false;
71 /** Used to determine where to place new images on the applet to optimize
72 * whitespace coverage <br>
73 * A co-ordinate in the applet has a value of zero if it is whitespace,
74 * one if it is covered by one image, two if it is covered by two images,
75 * and so on. New images will be placed such that they cover the largest
76 * area of whitespace (zero valued co-ordinates) */
77 public static int [] [] used_space = null;
78
79
80 /**
81 * Starts the display images thread. Initialises variables using parameters and
82 * static values. Creates the blank applet screen, initialises the used space
83 * 2D array to indicate that there are no images onscreen
84 *
85 * @param app the applet to display the images on
86 * @param download_images thread from which to retrieve downloaded images
87 * @param is_java2 whether advanced image processing techniques should be used
88 * @param bgcolor the background colour of the applet screen */
89 public DisplayImages(GsdlCollageApplet app, DownloadImages download_images,
90 boolean is_java2, Color bgcolor)
91 {
92 super("DisplayImages");
93
94 // parameters saved locally
95 app_ = app;
96 is_java2_ = is_java2;
97 bgcolor_ = bgcolor;
98
99 inuse_ = new Vector();
100 notinuse_ = new Vector();
101 inuse_ready_ = new Vector();
102 download_images_ = download_images;
103 // sets width and height
104 if (is_java2_)
105 {
106 app_x_dim_ = app_.getWidth();
107 app_y_dim_ = app_.getHeight();
108 }
109 else
110 {
111 app_x_dim_ = 645;
112 app_y_dim_ = 780;
113 }
114
115 // creates initial screen
116 screen_buffer_ = app_.createImage(app_x_dim_, app_y_dim_);
117 screen_graphic_ = screen_buffer_.getGraphics();
118 screen_graphic_.setColor(bgcolor_);
119 screen_graphic_.fillRect(0,0,app_x_dim_,app_y_dim_);
120
121 finished_buffer_ = app_.createImage(app_x_dim_, app_y_dim_);
122 finished_graphic_ = finished_buffer_.getGraphics();
123
124 // initialises used space array to indicate an empty screen
125 used_space = new int [app_x_dim_][app_y_dim_];
126 for (int n=0; n < app_x_dim_; n++)
127 for (int m=0; m < app_y_dim_; m++)
128 used_space[n][m] = 0;
129
130 next_frame_ = new Thread(new Runnable(){
131 public void run() {
132
133 Thread curr_thread = Thread.currentThread();
134
135 while (curr_thread == next_frame_) {
136 try {
137 Runtime rt = Runtime.getRuntime();
138 //System.out.println("total: "+rt.totalMemory());
139 //System.out.println("free: "+rt.freeMemory());
140 rt.gc();
141 //System.out.println("**************next frame...");
142 next_frame();
143 Thread.sleep(app_. refreshDelay_);
144
145 curr_thread = Thread.currentThread();
146 } catch (Exception e) {
147 e.printStackTrace();
148 break;
149 }
150 }
151
152
153 }
154
155
156 });
157
158 next_frame_.start();
159
160
161 }
162
163 /** Determines what the user has clicked on in the applet, either an image or whitespace
164 * @param x the x co-ordinate of the mouse
165 * @param y the y co-ordinate of the mouse
166 * @return the image that the user has clicked on or null if the user has clicked whitespace */
167 public CollageImage clickedOnImage(int x, int y)
168 {
169 if (app_.verbosity() > 1)
170 {
171 System.err.print("Checking for clicked on image: ("+x+","+y+")");
172 }
173
174
175 // checks from last image down, as last images place will be at the top of the collage
176 for (int i= inuse_.size() - 1; i >= 0; i--)
177 {
178 CollageImage collage_image = (CollageImage)inuse_.elementAt(i);
179 if (collage_image.inside(x,y))
180 {
181 return collage_image;
182 }
183 }
184 // no image at these co-ordinates, just whitespace
185 return null;
186 }
187
188 /** Generates the images onscreen.
189 * Loops through the vector of currently displayed images and draws each one in turn.
190 * If the image is being drawn for the first time, its position will be determined
191 * and its alpha channel set as solid prior to drawing. <br>
192 * Drawing of the image will depend on whether or not java2 is enabled. If so then
193 * the image will be processed so that fading occurs with age, so that the edges
194 * fade faster than the rest of the image and so that white images are slightly
195 * discoloured to allow distinction. If java2 is not enabled, new images will simply
196 * be pasted on top of existing images without any special effects occuring<br>
197 * This function also deletes old images. If java2 is enabled then images are deleted
198 * once they have faded to a suitably low alpha value. If java2 is not enabled then
199 * images will be removed once there are greater than 25 images onscreen, to ensure
200 * the applet cannot be overloaded. */
201 public void display_collage()
202 {
203
204 // if there is nothing new to add
205 if (inuse_.size()==0) return;
206
207 // otherwise need to re-generate images
208 if (app_.verbosity() >= 2)
209 {
210 //system.err.println("Regenerating images");
211 }
212
213 // get each image currently onscreen inturn
214 for (int i=0; i<inuse_.size();)
215 {
216 CollageImage collage_image = (CollageImage)inuse_.elementAt(i);
217
218 if (!collage_image.isValid()){
219 continue;
220 }
221
222 int[] pixels = null;
223 // the first time the image is painted, determine its position and size
224 if (collage_image.fresh == true)
225 {
226 collage_image.process();
227 }
228
229 // advanced image processing may be used
230 if (is_java2_)
231 {
232 // conducts fading and colouring of image
233 pixels = collage_image.handlepixels(inuse_.size()-i);
234 }
235
236 if (collage_image.fresh) {
237 collage_image.fresh = false;
238 }
239
240
241 // if we remove when images have faded too much
242 if (is_java2_) {
243 if (collage_image.checkFaded(pixels)|| overlap)
244 {
245 overlap = false;
246
247 CollageImage removed_image = (CollageImage)inuse_.elementAt(i);
248 //System.out.println(removed_image.name_ + "is removed");
249 inuse_.remove(i);
250 // indicates space for this image is no longer used
251 for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++)
252 for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++)
253 if(used_space[n][m] != 0) {
254 used_space[n][m]--;
255 if (used_space[n][m] > NO_IMAGES_OF_OVERLAP)
256 overlap = true;
257 }
258
259 // sets the image as fresh and adds it to the vector of images previously seen
260 removed_image.fresh = true;
261 notinuse_.addElement(removed_image);
262 }
263 else{
264 i++;
265 }
266 }
267 else
268 if (inuse_.size() > 25 || overlap) {
269 overlap = false;
270
271 CollageImage removed_image = (CollageImage)inuse_.elementAt(i);
272 inuse_.remove(i);
273
274 // indicates space for this image is no longer used
275 for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++)
276 for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++)
277 if(used_space[n][m] != 0) {
278 used_space[n][m]--;
279 if (used_space[n][m] > NO_IMAGES_OF_OVERLAP)
280 overlap = true;
281 }
282
283 // sets the image as fresh and adds it to the vector of images previously seen
284 removed_image.fresh = true;
285 notinuse_.addElement(removed_image);
286 }
287 else{
288 i++;
289 }
290
291 }
292 }
293
294
295 /** Alters the images currently on display in the applet <br>
296 * Changes are prioritised in the following way:
297 * 1. If there are images that have been downloaded and are yet to be displayed
298 * they will be added to the list of images in use. <br>
299 * 2. Otherwise if there are images that have previously been displayed but
300 * are not currently on the applet screen, re-use one of these images. <br>
301 * 3. Otherwise if there are any images on screen at all, take the oldest and
302 * repaint it as the newest. <br>
303 * Then the collage is asked to display and repaint with the new image set. */
304
305 public void next_frame()
306 {
307 double random = Math.random();
308
309
310 if (inuse_ready_.size() > 0){
311 int pos = (int) ((inuse_ready_.size() - 1) * random);
312 CollageImage collage_image = (CollageImage) inuse_ready_.remove(pos);
313 inuse_.addElement(collage_image);
314 }
315 else if (notinuse_.size()>0)
316 {
317 int position = (int) ((notinuse_.size() - 1) * random);
318
319 CollageImage collage_image = (CollageImage)notinuse_.elementAt(position);
320 notinuse_.remove(position);
321 inuse_.addElement(collage_image);
322
323 if (app_.verbosity()>3)
324 {
325 System.err.println("Re-using an image not on screen");
326 }
327 }
328 else{
329 if (app_.verbosity()>=4)
330 System.err.println("No images in download area");
331 }
332
333 display_collage();
334
335 }
336
337
338
339 /** Paints the applet on the screen */
340 public void paint(Graphics g)
341 {
342
343 screen_graphic_.setColor(bgcolor_);
344 screen_graphic_.fillRect(0,0,app_x_dim_,app_y_dim_);
345
346 // get each image currently onscreen inturn
347
348 for (int i=0; i < inuse_.size(); i++)
349 {
350
351 CollageImage collage_image =null;
352 try{
353 collage_image = (CollageImage)inuse_.elementAt(i);
354 start_paint = true;
355 }
356 catch(Exception e){
357 System.out.println("exception in paint");
358 break;
359 }
360 // don't paint new images yet
361 if (collage_image.fresh) {
362 if (app_.verbosity()>=1) {
363 System.err.println("doing nothing... "+ collage_image.name_ +" is fresh.");
364 }
365 }
366
367 // advanced image processing may be used
368 else if (is_java2_) {
369
370 //the alphacomposite controls the blending of these two images.
371 Graphics2D sg2d = (Graphics2D)screen_graphic_;
372 sg2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
373 sg2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
374 RenderingHints.VALUE_ANTIALIAS_ON);
375 collage_image.expand();
376 sg2d.drawImage(collage_image.image_, collage_image.af_, app_);
377 }
378 // simple image collage
379 else
380 { // add the image to the collage
381
382 screen_graphic_.drawImage(collage_image.image_,
383 collage_image.xl_, collage_image.yt_,
384 collage_image.xr_, collage_image.yb_,
385 0,0,collage_image.image_x_dim_-1,
386 collage_image.image_y_dim_-1, app_);
387 }
388
389 }
390
391
392 finished_graphic_.drawImage(screen_buffer_,0,0,app_);
393
394
395 if (finished_buffer_ != null)
396 {
397 g.drawImage(finished_buffer_, 0, 0, app_);
398 if (!start_paint){
399 g.setColor(Color.white);
400 g.setFont(new Font("font",Font.PLAIN+Font.BOLD,30));
401 g.drawString("Downloading" + dots[(dots_nums++)%dots.length],app_x_dim_/3-20,app_y_dim_/2-2);
402 }
403 }
404
405
406 }
407
408 /** Runs display thread by repeatedly calling the next frame,
409 * waiting for a specified delay period between calls */
410 public void run() {
411 try {
412
413 Thread curr_thread = Thread.currentThread();
414
415 while (curr_thread == this) {
416 if (inuse_ready_.size() >= 1){
417 Thread.sleep(1000);
418 continue;
419 }
420 CollageImage collage_image = download_images_.getCollageImage();
421
422 if (collage_image !=null){
423 inuse_ready_.addElement(collage_image);
424 }
425 curr_thread = Thread.currentThread();
426 }
427
428 } catch (Exception e) {
429 e.printStackTrace();
430 System.out.println("Display images thread is interrupted");
431 }
432
433 System.out.println("Display images thread stoped");
434
435 }
436
437}
Note: See TracBrowser for help on using the repository browser.