1 | package org.nzdl.gsdl.GsdlCollageApplet;
|
---|
2 |
|
---|
3 | import java.applet.*;
|
---|
4 | import java.awt.*;
|
---|
5 | import java.awt.image.*;
|
---|
6 | import java.awt.geom.*;
|
---|
7 | import 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 these 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. */
|
---|
19 | public class DisplayImages extends Thread {
|
---|
20 |
|
---|
21 | /** Decrements the alpha value between adjacent rows on the edge of an image<br>
|
---|
22 | * Used to fade the edges faster than the rest of the image <br>
|
---|
23 | * Only used when java2 parameter is true and advanced image processing
|
---|
24 | * techniques may be applied */
|
---|
25 | static final int FADEVALUE = 3;
|
---|
26 | /** Defines the number of shades of white used to colour the backgrounds of white images <br>
|
---|
27 | * These colours are used because when several white images appear in the collage
|
---|
28 | * simultaneously it is difficult to distinguish their edges<br>
|
---|
29 | * Only used when java2 parameter is true and advanced image processing
|
---|
30 | * techniques may be applied */
|
---|
31 | static final int NO_OF_COLORS = 7;
|
---|
32 |
|
---|
33 | /** Will fire a removal operation when 4 images in the collage overlap a single area */
|
---|
34 | static final int NO_IMAGES_OF_OVERLAP = 4;
|
---|
35 |
|
---|
36 | /** To determine if there are several images overlapped, can remove the
|
---|
37 | * layers underneath to save time in repainting */
|
---|
38 | boolean overlap = false;
|
---|
39 |
|
---|
40 | /** Refers to download thread */
|
---|
41 | DownloadImages download_images_ = null;
|
---|
42 | /** Refers to applet */
|
---|
43 | GsdlCollageApplet app_ = null;
|
---|
44 | /** Applets width on screen */
|
---|
45 | public static int app_x_dim_ = 0;
|
---|
46 | /** Applets height on screen */
|
---|
47 | public static int app_y_dim_ = 0;
|
---|
48 |
|
---|
49 | /** Background colour of the applet screen */
|
---|
50 | Color bgcolor_ = null;
|
---|
51 | /** Indicates whether java2 functionality should be used <br>
|
---|
52 | * If true will allow advanced image processing techniques to occur,
|
---|
53 | * such as fading and colouring using pixel manipulation <br>
|
---|
54 | * If false, images will maintain an alpha value of 1 (appear solid),
|
---|
55 | * newer images will simply be pasted on top of existing images <br> */
|
---|
56 | boolean is_java2_ = false;
|
---|
57 | /** Holds images currently on display in the applet */
|
---|
58 | Vector inuse_ = null;
|
---|
59 | /** Holds previously displayed images for re-use */
|
---|
60 | Vector notinuse_ = null;
|
---|
61 |
|
---|
62 | Image screen_buffer_ = null;
|
---|
63 | Graphics screen_graphic_ = null;
|
---|
64 | Image finished_buffer_ = null;
|
---|
65 | Graphics finished_graphic_ = null;
|
---|
66 |
|
---|
67 | /** Used to determine where to place new images on the applet to optimize
|
---|
68 | * whitespace coverage <br>
|
---|
69 | * A co-ordinate in the applet has a value of zero if it is whitespace,
|
---|
70 | * one if it is covered by one image, two if it is covered by two images,
|
---|
71 | * and so on. New images will be placed such that they cover the largest
|
---|
72 | * area of whitespace (zero valued co-ordinates) */
|
---|
73 | public static int [] [] used_space = null;
|
---|
74 |
|
---|
75 | /** Defines the shades of white used to colour the backgrounds of white images <br>
|
---|
76 | * These colours are used because when several white images appear in the collage
|
---|
77 | * simultaneously it is difficult to distinguish their edges<br>
|
---|
78 | * Only used when java2 parameter is true and advanced image processing
|
---|
79 | * techniques may be applied */
|
---|
80 | int colorMask [] = {0xF8FFFF, 0xFFF8FF, 0xFFFFF8, 0xF8F8FF, 0xFFF8F8, 0xF8FFF8, 0xFAFAFA};
|
---|
81 |
|
---|
82 | /**
|
---|
83 | * Starts the display images thread. Initialises variables using parameters and
|
---|
84 | * static values. Creates the blank applet screen, initialises the used space
|
---|
85 | * 2D array to indicate that there are no images onscreen
|
---|
86 | *
|
---|
87 | * @param app the applet to display the images on
|
---|
88 | * @param download_images thread from which to retrieve downloaded images
|
---|
89 | * @param is_java2 whether advanced image processing techniques should be used
|
---|
90 | * @param bgcolor the background colour of the applet screen */
|
---|
91 | public DisplayImages(GsdlCollageApplet app,
|
---|
92 | DownloadImages download_images, boolean is_java2, Color bgcolor)
|
---|
93 | {
|
---|
94 | super("DisplayImages");
|
---|
95 |
|
---|
96 | // parameters saved locally
|
---|
97 | app_ = app;
|
---|
98 | download_images_ = download_images;
|
---|
99 | is_java2_ = is_java2;
|
---|
100 | bgcolor_ = bgcolor;
|
---|
101 |
|
---|
102 | inuse_ = new Vector();
|
---|
103 | notinuse_ = new Vector();
|
---|
104 |
|
---|
105 | // sets width and height
|
---|
106 | if (is_java2_)
|
---|
107 | {
|
---|
108 | app_x_dim_ = app_.getWidth();
|
---|
109 | app_y_dim_ = app_.getHeight();
|
---|
110 | }
|
---|
111 | else
|
---|
112 | {
|
---|
113 | app_x_dim_ = 645;
|
---|
114 | app_y_dim_ = 780;
|
---|
115 | }
|
---|
116 |
|
---|
117 | // creates initial screen
|
---|
118 | screen_buffer_ = app_.createImage(app_x_dim_, app_y_dim_);
|
---|
119 | screen_graphic_ = screen_buffer_.getGraphics();
|
---|
120 | screen_graphic_.setColor(bgcolor_);
|
---|
121 | screen_graphic_.fillRect(0,0,app_x_dim_,app_y_dim_);
|
---|
122 |
|
---|
123 | finished_buffer_ = app_.createImage(app_x_dim_, app_y_dim_);
|
---|
124 | finished_graphic_ = finished_buffer_.getGraphics();
|
---|
125 |
|
---|
126 | // initialises used space array to indicate an empty screen
|
---|
127 | used_space = new int [app_x_dim_][app_y_dim_];
|
---|
128 | for (int n=0; n < app_x_dim_; n++)
|
---|
129 | for (int m=0; m < app_y_dim_; m++)
|
---|
130 | used_space[n][m] = 0;
|
---|
131 |
|
---|
132 | }
|
---|
133 |
|
---|
134 | /** Determines what the user has clicked on in the applet, either an image or whitespace
|
---|
135 | * @param x the x co-ordinate of the mouse
|
---|
136 | * @param y the y co-ordinate of the mouse
|
---|
137 | * @return the image that the user has clicked on or null if the user has clicked whitespace */
|
---|
138 | public CollageImage clickedOnImage(int x, int y)
|
---|
139 | {
|
---|
140 | if (app_.verbosity() > 1)
|
---|
141 | {
|
---|
142 | System.err.print("Checking for clicked on image: ("+x+","+y+")");
|
---|
143 | }
|
---|
144 |
|
---|
145 | int no_images = inuse_.size() - 1;
|
---|
146 | // checks from last image down, as last images place will be at the top of the collage
|
---|
147 | for (int i= no_images; i >= 0; i--)
|
---|
148 | {
|
---|
149 | CollageImage collage_image = (CollageImage)inuse_.elementAt(i);
|
---|
150 | if (collage_image.inside(x,y))
|
---|
151 | {
|
---|
152 | return collage_image;
|
---|
153 | }
|
---|
154 | }
|
---|
155 | // no image at these co-ordinates, just whitespace
|
---|
156 | return null;
|
---|
157 | }
|
---|
158 |
|
---|
159 | /** Generates the images onscreen.
|
---|
160 | * Loops through the vector of currently displayed images and draws each one in turn.
|
---|
161 | * If the image is being drawn for the first time, its position will be determined
|
---|
162 | * and its alpha channel set as solid prior to drawing. <br>
|
---|
163 | * Drawing of the image will depend on whether or not java2 is enabled. If so then
|
---|
164 | * the image will be processed so that fading occurs with age, so that the edges
|
---|
165 | * fade faster than the rest of the image and so that white images are slightly
|
---|
166 | * discoloured to allow distinction. If java2 is not enabled, new images will simply
|
---|
167 | * be pasted on top of existing images without any special effects occuring<br>
|
---|
168 | * This function also deletes old images. If java2 is enabled then images are deleted
|
---|
169 | * once they have faded to a suitably low alpha value. If java2 is not enabled then
|
---|
170 | * images will be removed once there are greater than 25 images onscreen, to ensure
|
---|
171 | * the applet cannot be overloaded. */
|
---|
172 | public synchronized void display_collage()
|
---|
173 | {
|
---|
174 | // get the number of images currently in the collage
|
---|
175 | final int no_images = inuse_.size();
|
---|
176 |
|
---|
177 | // if there is nothing new to add
|
---|
178 | if (no_images==0) return;
|
---|
179 |
|
---|
180 |
|
---|
181 | // otherwise need to re-generate images
|
---|
182 | if (app_.verbosity() > 3)
|
---|
183 | {
|
---|
184 | System.err.print("Regenerating images:");
|
---|
185 | }
|
---|
186 |
|
---|
187 | // get each image currently onscreen inturn
|
---|
188 | for (int i=0; i<no_images; i++)
|
---|
189 | {
|
---|
190 | CollageImage collage_image = (CollageImage)inuse_.elementAt(i);
|
---|
191 |
|
---|
192 | Image image = collage_image.image_;
|
---|
193 | // images x and y dimensions
|
---|
194 | int image_x_dim = image.getWidth(app_);
|
---|
195 | int image_y_dim = image.getHeight(app_);
|
---|
196 |
|
---|
197 | if ((image_x_dim>0) && (image_y_dim>0))
|
---|
198 | {
|
---|
199 | // the first time the image is painted, determine its position and size
|
---|
200 | if (collage_image.fresh == true)
|
---|
201 | {
|
---|
202 | // first time => randomly place doc
|
---|
203 | collage_image.setDimensions(image_x_dim,image_y_dim);
|
---|
204 |
|
---|
205 | // places and sizes the image
|
---|
206 | MyAffineTransform af = new MyAffineTransform(image_x_dim,image_y_dim);
|
---|
207 |
|
---|
208 | // sets location & size of collage image
|
---|
209 | collage_image.setAffineTransform(af, is_java2_);
|
---|
210 |
|
---|
211 | if (is_java2_) {
|
---|
212 |
|
---|
213 | collage_image.image_ = restoreAlpha(collage_image.image_, 0, 0,
|
---|
214 | collage_image.image_x_dim_, collage_image.image_y_dim_);
|
---|
215 | }
|
---|
216 |
|
---|
217 |
|
---|
218 | }
|
---|
219 |
|
---|
220 | // advanced image processing may be used
|
---|
221 | if (is_java2_)
|
---|
222 | {
|
---|
223 | // conducts fading and colouring of image
|
---|
224 | Image img = handlepixels(collage_image.image_, 0, 0, collage_image.image_x_dim_,
|
---|
225 | collage_image.image_y_dim_, i, collage_image.fresh );
|
---|
226 | collage_image.image_ = img;
|
---|
227 |
|
---|
228 | }
|
---|
229 | if (collage_image.fresh)
|
---|
230 | collage_image.fresh = false;
|
---|
231 |
|
---|
232 | }
|
---|
233 | //finished_graphic_.drawImage(screen_buffer_,0,0,app_);
|
---|
234 |
|
---|
235 | }
|
---|
236 |
|
---|
237 | // draws the finished image onscreen
|
---|
238 | finished_graphic_.drawImage(screen_buffer_,0,0,app_);
|
---|
239 | remove_old_images();
|
---|
240 | }
|
---|
241 |
|
---|
242 | /** loops through removing oldest images and reduces number of images if excessive overlap is occuring */
|
---|
243 | void remove_old_images() {
|
---|
244 |
|
---|
245 | // loops through removing oldest images that have almost faded completely
|
---|
246 | // and restricting the size of a simple collage to 25 images
|
---|
247 | int i=0;
|
---|
248 | while (i<inuse_.size())
|
---|
249 | {
|
---|
250 | CollageImage collage_image = (CollageImage)inuse_.elementAt(i);
|
---|
251 |
|
---|
252 | // if we remove when images have faded too much
|
---|
253 | if (is_java2_) {
|
---|
254 | if (checkFaded(collage_image.image_, 0, 0, collage_image.image_x_dim_, collage_image.image_y_dim_) || overlap)
|
---|
255 | {
|
---|
256 | overlap = false;
|
---|
257 |
|
---|
258 | CollageImage removed_image = (CollageImage)inuse_.elementAt(i);
|
---|
259 | inuse_.removeElementAt(i);
|
---|
260 |
|
---|
261 | // restores alpha channel to represent a solid image
|
---|
262 | Image img = restoreAlpha(removed_image.image_, 0, 0, removed_image.image_x_dim_, removed_image.image_y_dim_);
|
---|
263 |
|
---|
264 | // indicates space for this image is no longer used
|
---|
265 | for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++)
|
---|
266 | for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++)
|
---|
267 | if(used_space[n][m] != 0) {
|
---|
268 | used_space[n][m]--;
|
---|
269 | if (used_space[n][m] > NO_IMAGES_OF_OVERLAP)
|
---|
270 | overlap = true;
|
---|
271 | }
|
---|
272 |
|
---|
273 | // sets the image as fresh and adds it to the vector of images previously seen
|
---|
274 | removed_image.image_ = img;
|
---|
275 | removed_image.fresh = true;
|
---|
276 | notinuse_.addElement(removed_image);
|
---|
277 | }
|
---|
278 | else {
|
---|
279 | i++;
|
---|
280 | }
|
---|
281 | }
|
---|
282 | // if we remove to prevent too many images being displayed simultaneously
|
---|
283 | else {
|
---|
284 | if (inuse_.size() > 25 || overlap) {
|
---|
285 | overlap = false;
|
---|
286 |
|
---|
287 | CollageImage removed_image = (CollageImage)inuse_.elementAt(i);
|
---|
288 | inuse_.removeElementAt(i);
|
---|
289 |
|
---|
290 | // indicates space for this image is no longer used
|
---|
291 | for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++)
|
---|
292 | for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++)
|
---|
293 | if(used_space[n][m] != 0) {
|
---|
294 | used_space[n][m]--;
|
---|
295 | if (used_space[n][m] > NO_IMAGES_OF_OVERLAP)
|
---|
296 | overlap = true;
|
---|
297 | }
|
---|
298 |
|
---|
299 | // sets the image as fresh and adds it to the vector of images previously seen
|
---|
300 | removed_image.fresh = true;
|
---|
301 | notinuse_.addElement(removed_image);
|
---|
302 | }
|
---|
303 | else {
|
---|
304 | i++;
|
---|
305 | }
|
---|
306 | }
|
---|
307 | }
|
---|
308 |
|
---|
309 | }
|
---|
310 |
|
---|
311 | /** Alters the images currently on display in the applet <br>
|
---|
312 | * Changes are prioritised in the following way:
|
---|
313 | * 1. If there are images that have been downloaded and are yet to be displayed
|
---|
314 | * they will be added to the list of images in use. <br>
|
---|
315 | * 2. Otherwise if there are images that have previously been displayed but
|
---|
316 | * are not currently on the applet screen, re-use one of these images. <br>
|
---|
317 | * 3. Otherwise if there are any images on screen at all, take the oldest and
|
---|
318 | * repaint it as the newest. <br>
|
---|
319 | * Then the collage is asked to display and repaint with the new image set. */
|
---|
320 | void next_frame()
|
---|
321 | {
|
---|
322 | double random = Math.random();
|
---|
323 |
|
---|
324 | // if there is a new image in the downloaded vector
|
---|
325 | if (download_images_.size()>0)
|
---|
326 | {
|
---|
327 | int position = (int) ((download_images_.size() - 1) * random);
|
---|
328 | Image image;
|
---|
329 |
|
---|
330 | // get the image and it's associated url
|
---|
331 | DownloadImages.ImageUrlTriple iutriple = download_images_.retrieve(position);
|
---|
332 | image = iutriple.image();
|
---|
333 | String from_url = iutriple.url();
|
---|
334 | String img_name = iutriple.name();
|
---|
335 |
|
---|
336 | // prepare the image for collaging
|
---|
337 | app_.prepareImage(image,app_);
|
---|
338 | CollageImage collage_image = new CollageImage(image,from_url,img_name);
|
---|
339 |
|
---|
340 | // add it to the vector of images currently in use
|
---|
341 | inuse_.addElement(collage_image);
|
---|
342 |
|
---|
343 | if (app_.verbosity()>3)
|
---|
344 | {
|
---|
345 | System.err.println("Using a downloaded image");
|
---|
346 | }
|
---|
347 | }
|
---|
348 | // use an image that has already been displayed but is no longer in the collage
|
---|
349 | else if (notinuse_.size()>0)
|
---|
350 | {
|
---|
351 | int position = (int) ((notinuse_.size() - 1) * random);
|
---|
352 | Image image;
|
---|
353 |
|
---|
354 | CollageImage collage_image = (CollageImage)notinuse_.elementAt(position);
|
---|
355 | notinuse_.removeElementAt(position);
|
---|
356 | inuse_.addElement(collage_image);
|
---|
357 |
|
---|
358 | if (app_.verbosity()>3)
|
---|
359 | {
|
---|
360 | System.err.println("Re-using an image not on screen");
|
---|
361 | }
|
---|
362 | }
|
---|
363 | // otherwise repaint the first image as the last image
|
---|
364 | else if (inuse_.size() > 0)
|
---|
365 | {
|
---|
366 | CollageImage removed_image = (CollageImage)inuse_.elementAt(0);
|
---|
367 |
|
---|
368 | // empty the picture from the grid
|
---|
369 | for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++)
|
---|
370 | for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++)
|
---|
371 | used_space[n][m]--;
|
---|
372 |
|
---|
373 | // reset the alpha and add it
|
---|
374 | removed_image.fresh = true;
|
---|
375 |
|
---|
376 | if (is_java2_) {
|
---|
377 | removed_image.image_ = restoreAlpha(removed_image.image_, 0, 0,
|
---|
378 | removed_image.image_x_dim_, removed_image.image_y_dim_);
|
---|
379 | }
|
---|
380 |
|
---|
381 | notinuse_.addElement(removed_image);
|
---|
382 | inuse_.removeElementAt(0);
|
---|
383 |
|
---|
384 | if (app_.verbosity()>3)
|
---|
385 | {
|
---|
386 | System.err.println("Removing oldest image");
|
---|
387 | }
|
---|
388 | }
|
---|
389 | else
|
---|
390 | {
|
---|
391 | if (app_.verbosity()>3)
|
---|
392 | System.err.println("no images in download area");
|
---|
393 | }
|
---|
394 |
|
---|
395 | display_collage();
|
---|
396 | }
|
---|
397 |
|
---|
398 | /** Adjusts the colour and alpha value of an individual pixel <br>
|
---|
399 | * If the image is being drawn for the first time, the RGB values are
|
---|
400 | * extracted. If the pixel is close to white (RGB > 250) then an offwhite
|
---|
401 | * colour is applied to this pixel.
|
---|
402 | * This is done because when several white images appear in the collage
|
---|
403 | * simultaneously it is difficult to distinguish their edges. <br>
|
---|
404 | * This function also fades the alpha value of the pixel as the image ages.
|
---|
405 | * The alpha value is more heavily decremented as pixels get closer to the
|
---|
406 | * edge of the image
|
---|
407 | *
|
---|
408 | * @param pixel the pixel to manipulate
|
---|
409 | * @param p the position of the image in collage (representative of age)
|
---|
410 | * @param fresh indicates whether or not the image is being drawn for the first time
|
---|
411 | * @param edge indicates whether or not this pixel is near the edge of the image
|
---|
412 | * @param fade the amount by which to fade this pixel
|
---|
413 | * @return the adjusted pixel as an int */
|
---|
414 | public int handlesinglepixel(int pixel, int p, boolean fresh, boolean edge, int fade) {
|
---|
415 |
|
---|
416 | int newpixel = 0;
|
---|
417 |
|
---|
418 | //changes the colour of the picture, only when first drawn
|
---|
419 | //and only if the pixel is close to white
|
---|
420 | if (fresh) {
|
---|
421 |
|
---|
422 | int red = (pixel >> 16) & 0xff;
|
---|
423 | int green = (pixel >> 8) & 0xff;
|
---|
424 | int blue = (pixel ) & 0xff;
|
---|
425 |
|
---|
426 | if (red >= 250 && green >= 250 && blue >= 250) {
|
---|
427 |
|
---|
428 | int c = colorMask[((int) (p%NO_OF_COLORS))];
|
---|
429 |
|
---|
430 | red = (c >> 16) & 0xff;
|
---|
431 | green = (c >> 8) & 0xff;
|
---|
432 | blue = (c) & 0xff;
|
---|
433 | }
|
---|
434 |
|
---|
435 | newpixel |= (red << 16) & 0x00ff0000;
|
---|
436 | newpixel |= (green << 8) & 0x0000ff00;
|
---|
437 | newpixel |= blue & 0x000000ff;
|
---|
438 | }
|
---|
439 |
|
---|
440 | else {
|
---|
441 | newpixel |= pixel & 0x00ffffff;
|
---|
442 | }
|
---|
443 |
|
---|
444 | int alpha = (pixel >> 24) & 0xff;
|
---|
445 |
|
---|
446 | if (edge) {
|
---|
447 | // fade the edges more...
|
---|
448 | alpha = fade;
|
---|
449 | }
|
---|
450 | else if (alpha > 10 && !fresh) {
|
---|
451 | alpha -= 10;
|
---|
452 | }
|
---|
453 |
|
---|
454 | newpixel |= (alpha << 24) & 0xff000000;
|
---|
455 |
|
---|
456 | return (newpixel);
|
---|
457 | }
|
---|
458 |
|
---|
459 | /** Fades and colours the image on a pixel-by-pixel basis <br>
|
---|
460 | * First it grabs the pixels of the entire image and stores them in a 2D array.
|
---|
461 | * Then a bound is calculated to indicate the point from which edge
|
---|
462 | * fading should occur. The position of the bound will change in proportion
|
---|
463 | * to the age of the image so that older images have a larger faded edge.
|
---|
464 | * The area within the bounds, that forms the center of the image, is processed
|
---|
465 | * first and faded by a standard alpha value. Then each edge of the image
|
---|
466 | * is processed separately, creating a gradient fade from the true edge to the
|
---|
467 | * position of the bound. <br>
|
---|
468 | * The faded pixel array is then turned into a new image a returned.
|
---|
469 | *
|
---|
470 | * @param img the image that requires processing
|
---|
471 | * @param x the x co-ordinate of the image
|
---|
472 | * @param y the y co-ordinate of the image
|
---|
473 | * @param w the width of the image
|
---|
474 | * @param h the height of the image
|
---|
475 | * @param p the position of the image in the applet (indicates age)
|
---|
476 | * @param fresh whether the image is being processed for the first time */
|
---|
477 | public Image handlepixels(Image img, int x, int y, int w, int h, int p, boolean fresh) {
|
---|
478 |
|
---|
479 | // declare an array to hold the pixels
|
---|
480 | int[] pixels = new int[w * h];
|
---|
481 |
|
---|
482 | // get the pixels of the image into the pixels array
|
---|
483 | PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
|
---|
484 | try {
|
---|
485 | pg.grabPixels();
|
---|
486 |
|
---|
487 | } catch (InterruptedException e) {
|
---|
488 | System.err.println("interrupted waiting for pixels!");
|
---|
489 | return img;
|
---|
490 | }
|
---|
491 | // check for any failures
|
---|
492 | if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
|
---|
493 | System.err.println("image fetch aborted or errored");
|
---|
494 | return img;
|
---|
495 | }
|
---|
496 |
|
---|
497 | // calculates the bound from which fading should begin
|
---|
498 | double bound = (inuse_.size() - p) * 0.01;
|
---|
499 | if (w > h)
|
---|
500 | bound *= w;
|
---|
501 | else
|
---|
502 | bound *= h;
|
---|
503 | int upperboundheight = h - (int) bound;
|
---|
504 | int upperboundwidth = w - (int) bound;
|
---|
505 | int lowerbound = (int) bound;
|
---|
506 |
|
---|
507 | // loop through every pixel in the picture and handle it
|
---|
508 | for (int j = lowerbound; j < upperboundheight; j++) {
|
---|
509 | for (int i = lowerbound; i < upperboundwidth; i++) {
|
---|
510 | // width and height: x+i y+j
|
---|
511 | pixels[j * w + i] = handlesinglepixel(pixels[j * w + i], p, fresh, false, 255);
|
---|
512 | }
|
---|
513 | }
|
---|
514 |
|
---|
515 | int fade = 0;
|
---|
516 | int fader = 0;
|
---|
517 | int corealpha = (pixels[(h/2) * w + (w/2)] >> 24) & 0xff;
|
---|
518 |
|
---|
519 | // top edge
|
---|
520 | for (int n = lowerbound; n >= 0; n--) {
|
---|
521 | fader = corealpha - fade;
|
---|
522 | if (fader < 0)
|
---|
523 | fader = 0;
|
---|
524 |
|
---|
525 | for (int m = 0; m < w; m++)
|
---|
526 | pixels[n * w + m] = handlesinglepixel(pixels[n * w + m], p, fresh, true, fader);
|
---|
527 |
|
---|
528 | fade+= FADEVALUE;
|
---|
529 | }
|
---|
530 |
|
---|
531 | // bottom edge
|
---|
532 | fade = 0;
|
---|
533 | for (int n = upperboundheight; n < h; n++) {
|
---|
534 | fader = corealpha - fade;
|
---|
535 | if (fader < 0)
|
---|
536 | fader = 0;
|
---|
537 | for (int m = 0; m < w; m++)
|
---|
538 | pixels[n * w + m] = handlesinglepixel(pixels[n * w + m], p, fresh, true, fader);
|
---|
539 |
|
---|
540 | fade += FADEVALUE;
|
---|
541 | }
|
---|
542 |
|
---|
543 | // left edge
|
---|
544 | fade = 0;
|
---|
545 | for (int n = lowerbound; n >= 0; n--) {
|
---|
546 | fader = corealpha - fade;
|
---|
547 | if (fader < 0)
|
---|
548 | fader = 0;
|
---|
549 | for (int m = 0; m < h; m++) {
|
---|
550 | if ( m < lowerbound && n > m);
|
---|
551 | else if ( m > upperboundheight && n > (h - m));
|
---|
552 | else
|
---|
553 | pixels[m * w + n] = handlesinglepixel(pixels[m * w + n], p, fresh, true, fader);
|
---|
554 | }
|
---|
555 | fade += FADEVALUE;
|
---|
556 | }
|
---|
557 |
|
---|
558 | // right edge
|
---|
559 | fade = 0;
|
---|
560 | for (int n = upperboundwidth; n < w; n++) {
|
---|
561 | fader = corealpha - fade;
|
---|
562 | if (fader < 0)
|
---|
563 | fader = 0;
|
---|
564 | for (int m = 0; m < h; m++) {
|
---|
565 | if ( m < lowerbound && (w - n) > m);
|
---|
566 | else if ( m > upperboundheight && (w - n) > (h - m));
|
---|
567 | else
|
---|
568 | pixels[m * w + n] = handlesinglepixel(pixels[m * w + n], p, fresh, true, fader);
|
---|
569 | }
|
---|
570 |
|
---|
571 | fade += FADEVALUE;
|
---|
572 | }
|
---|
573 |
|
---|
574 | // set the pixels of the whole picture to the pixels array
|
---|
575 | pg.setPixels(0, 0, w, h, pg.getColorModel(), pixels, 0, w);
|
---|
576 |
|
---|
577 | // create the new image and return it
|
---|
578 | return( app_.createImage(new MemoryImageSource(w, h, pixels, 0, w)) );
|
---|
579 |
|
---|
580 | }
|
---|
581 |
|
---|
582 | /** Resets the alpha channel of an image so that it appears solid
|
---|
583 | *
|
---|
584 | * @param img the image to restore
|
---|
585 | * @param x the x co-ordinate of the image
|
---|
586 | * @param y the y co-ordinate of the image
|
---|
587 | * @param w the width of the image
|
---|
588 | * @param h the height of the image */
|
---|
589 | public Image restoreAlpha(Image img, int x, int y, int w, int h) {
|
---|
590 |
|
---|
591 | // declare an array to hold the pixels
|
---|
592 | int[] pixels = new int[w * h];
|
---|
593 |
|
---|
594 | // get the pixels of the image into the pixels array
|
---|
595 | PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
|
---|
596 | try {
|
---|
597 | pg.grabPixels();
|
---|
598 |
|
---|
599 | } catch (InterruptedException e) {
|
---|
600 | System.err.println("interrupted waiting for pixels!");
|
---|
601 | return img;
|
---|
602 | }
|
---|
603 | // check for any failures
|
---|
604 | if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
|
---|
605 | System.err.println("image fetch aborted or errored");
|
---|
606 | return img;
|
---|
607 | }
|
---|
608 |
|
---|
609 | // loop through every pixel in the picture and handle it
|
---|
610 | for (int j = 0; j < h; j++) {
|
---|
611 | for (int i = 0; i < w; i++) {
|
---|
612 | pixels[j * w + i] |= (255 << 24) & 0xff000000;
|
---|
613 | }
|
---|
614 | }
|
---|
615 |
|
---|
616 | // set the pixels of the whole picture to the pixels array
|
---|
617 | pg.setPixels(0, 0, w, h, pg.getColorModel(), pixels, 0, w);
|
---|
618 |
|
---|
619 | // create the new image and return it
|
---|
620 | return( app_.createImage(new MemoryImageSource(w, h, pixels, 0, w)) );
|
---|
621 |
|
---|
622 | }
|
---|
623 |
|
---|
624 | /** Checks whether an image has faded to the point where it must be removed
|
---|
625 | * from the collage.
|
---|
626 | *
|
---|
627 | * @param img the image to restore
|
---|
628 | * @param x the x co-ordinate of the image
|
---|
629 | * @param y the y co-ordinate of the image
|
---|
630 | * @param w the width of the image
|
---|
631 | * @param h the height of the image */
|
---|
632 | public boolean checkFaded (Image img, int x, int y, int w, int h) {
|
---|
633 |
|
---|
634 | if (w == 0 || h == 0)
|
---|
635 | return false;
|
---|
636 |
|
---|
637 | // declare an array to hold the pixels
|
---|
638 | int[] pixels = new int[w * h];
|
---|
639 |
|
---|
640 | // get the pixels of the image into the pixels array
|
---|
641 | PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w);
|
---|
642 | try {
|
---|
643 | pg.grabPixels();
|
---|
644 |
|
---|
645 | } catch (InterruptedException e) {
|
---|
646 | System.err.println("interrupted waiting for pixels!");
|
---|
647 | return false;
|
---|
648 | }
|
---|
649 | // check for any failures
|
---|
650 | if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
|
---|
651 | System.err.println("image fetch aborted or errored");
|
---|
652 | return false;
|
---|
653 | }
|
---|
654 |
|
---|
655 | // get the alpha value of the middle pixel of the image
|
---|
656 | int corealpha = (pixels[(h/2) * w + (w/2)] >> 24) & 0xff;
|
---|
657 |
|
---|
658 | if (corealpha < 50)
|
---|
659 | return true;
|
---|
660 |
|
---|
661 | return false;
|
---|
662 |
|
---|
663 | }
|
---|
664 |
|
---|
665 | /** Paints the applet on the screen */
|
---|
666 | public synchronized void paint(Graphics g)
|
---|
667 | {
|
---|
668 | //System.err.println("......" + is_java2_);
|
---|
669 |
|
---|
670 | screen_graphic_.setColor(bgcolor_);
|
---|
671 | screen_graphic_.fillRect(0,0,app_x_dim_,app_y_dim_);
|
---|
672 |
|
---|
673 | int n = inuse_.size();
|
---|
674 |
|
---|
675 | // get each image currently onscreen inturn
|
---|
676 | for (int i=0; i < n; i++)
|
---|
677 | {
|
---|
678 | CollageImage collage_image = (CollageImage)inuse_.elementAt(i);
|
---|
679 | // don't paint new images yet
|
---|
680 | if (collage_image.fresh)
|
---|
681 | System.err.println("doing nothing... " + i + " " + n);
|
---|
682 |
|
---|
683 | // advanced image processing may be used
|
---|
684 | else if (is_java2_)
|
---|
685 | {
|
---|
686 | // the alphacomposite controls the blending of these two images.
|
---|
687 | Graphics2D sg2d = (Graphics2D)screen_graphic_;
|
---|
688 | //sg2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
|
---|
689 | sg2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
---|
690 | RenderingHints.VALUE_ANTIALIAS_ON);
|
---|
691 | collage_image.expand();
|
---|
692 | sg2d.drawImage(collage_image.image_, collage_image.af_, app_);
|
---|
693 | }
|
---|
694 | // simple image collage
|
---|
695 | else
|
---|
696 | {
|
---|
697 | // System.err.println("patu");
|
---|
698 | // add the image to the collage
|
---|
699 | screen_graphic_.drawImage(collage_image.image_,
|
---|
700 | collage_image.xl_, collage_image.yt_,
|
---|
701 | collage_image.xr_, collage_image.yb_,
|
---|
702 | 0,0,collage_image.image_x_dim_-1,
|
---|
703 | collage_image.image_y_dim_-1, app_);
|
---|
704 |
|
---|
705 | }
|
---|
706 |
|
---|
707 |
|
---|
708 | }
|
---|
709 |
|
---|
710 |
|
---|
711 | finished_graphic_.drawImage(screen_buffer_,0,0,app_);
|
---|
712 |
|
---|
713 | if (finished_buffer_ != null)
|
---|
714 | {
|
---|
715 | g.drawImage(finished_buffer_, 0, 0, app_);
|
---|
716 | }
|
---|
717 | }
|
---|
718 |
|
---|
719 | /** Runs display thread by repeatedly calling the next frame,
|
---|
720 | * waiting for a specified delay period between calls */
|
---|
721 | public void run()
|
---|
722 | {
|
---|
723 | try {
|
---|
724 |
|
---|
725 | System.err.println("Running display thread");
|
---|
726 |
|
---|
727 | Thread curr_thread = Thread.currentThread();
|
---|
728 |
|
---|
729 | //long tm = System.currentTimeMillis();
|
---|
730 |
|
---|
731 | while (curr_thread == this) {
|
---|
732 | next_frame();
|
---|
733 | //tm += app_.refreshDelay();
|
---|
734 | //Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
|
---|
735 | Thread.sleep(app_.refreshDelay());
|
---|
736 | //Thread.sleep(2);
|
---|
737 | curr_thread = Thread.currentThread();
|
---|
738 | }
|
---|
739 |
|
---|
740 | System.err.println("Display thread finished");
|
---|
741 |
|
---|
742 | } catch (Exception e) {
|
---|
743 | e.printStackTrace();
|
---|
744 | }
|
---|
745 | }
|
---|
746 | }
|
---|