Changeset 11691
- Timestamp:
- 2006-04-26T09:16:01+12:00 (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gsdl/src/java/org/nzdl/gsdl/GsdlCollageApplet/DisplayImages.java
r11648 r11691 12 12 * 13 13 * Retrieves images from the download thread, determines an appropriate position 14 * for thes eimages onscreen ensuring maximum whitespace coverage and minimal overlap14 * for thes images onscreen ensuring maximum whitespace coverage and minimal overlap 15 15 * when possible. Draws images using advanced image processing techniques when applicable, 16 16 * such as fading the edges of an image and discolouring backgrounds. Also re-uses images … … 19 19 public class DisplayImages extends Thread { 20 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 processing24 * 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 collage28 * simultaneously it is difficult to distinguish their edges<br>29 * Only used when java2 parameter is true and advanced image processing30 * techniques may be applied */31 static final int NO_OF_COLORS = 7;32 21 33 22 /** Will fire a removal operation when 4 images in the collage overlap a single area */ … … 60 49 protected boolean is_java2_ = false; 61 50 62 /** Holds images currently on display in the applet */ 63 protected Vector inuse_ready_ = null; 64 51 65 52 /** Holds images currently on display in the applet */ 66 53 protected Vector inuse_ = null; 67 54 55 /** Holds images ready to be used */ 56 protected Vector inuse_ready_ = null; 57 68 58 /** Holds previously displayed images for re-use */ 69 59 protected Vector notinuse_ = null; … … 87 77 public static int [] [] used_space = null; 88 78 89 /** Defines the shades of white used to colour the backgrounds of white images <br> 90 * These colours are used because when several white images appear in the collage 91 * simultaneously it is difficult to distinguish their edges<br> 92 * Only used when java2 parameter is true and advanced image processing 93 * techniques may be applied */ 94 int colorMask [] = {0xF8FFFF, 0xFFF8FF, 0xFFFFF8, 0xF8F8FF, 0xFFF8F8, 0xF8FFF8, 0xFAFAFA}; 95 79 96 80 /** 97 81 * Starts the display images thread. Initialises variables using parameters and … … 114 98 115 99 inuse_ = new Vector(); 116 inuse_ready_ = new Vector();117 notinuse_ = new Vector();100 notinuse_ = new Vector(); 101 inuse_ready_ = new Vector(); 118 102 download_images_ = download_images; 119 103 // sets width and height … … 151 135 while (curr_thread == next_frame_) { 152 136 try { 153 next_frame(); 154 Thread.sleep(app_. refreshDelay_); 155 curr_thread = Thread.currentThread(); 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(); 156 146 } catch (Exception e) { 147 e.printStackTrace(); 157 148 break; 158 149 } … … 165 156 }); 166 157 167 158 next_frame_.start(); 168 159 169 160 … … 210 201 public void display_collage() 211 202 { 212 213 // get the number of images currently in the collage 214 final int no_images = inuse_.size(); 215 216 203 217 204 // if there is nothing new to add 218 if (no_images==0) return; 219 205 if (inuse_.size()==0) return; 220 206 221 207 // otherwise need to re-generate images 222 208 if (app_.verbosity() >= 2) 223 {224 System.err.println("Regenerating images: " +no_images);225 }209 { 210 //system.err.println("Regenerating images"); 211 } 226 212 227 213 // get each image currently onscreen inturn 228 for (int i=0; i<inuse_.size(); i++) 229 { 230 CollageImage collage_image = (CollageImage)inuse_.elementAt(i); 231 232 Image image = collage_image.image_; 233 // images x and y dimensions 234 int image_x_dim = image.getWidth(app_); 235 int image_y_dim = image.getHeight(app_); 236 237 //int status = app_.checkImage(image,app_); 238 239 if ((image_x_dim>0) && (image_y_dim>0)) 214 for (int i=0; i<inuse_.size();) 240 215 { 216 CollageImage collage_image = (CollageImage)inuse_.elementAt(i); 217 218 if (!collage_image.isValid()){ 219 continue; 220 } 221 222 int[] pixels = null; 241 223 // the first time the image is painted, determine its position and size 242 224 if (collage_image.fresh == true) 243 225 { 244 // first time => randomly place doc 245 collage_image.setDimensions(image_x_dim,image_y_dim); 246 247 // places and sizes the image 248 MyAffineTransform af = new MyAffineTransform(image_x_dim,image_y_dim); 249 250 // sets location & size of collage image 251 collage_image.setAffineTransform(af, is_java2_); 252 253 if (is_java2_) { 254 collage_image.image_ 255 = restoreAlpha(collage_image.image_, 0, 0, 256 collage_image.image_x_dim_, collage_image.image_y_dim_); 257 258 } 259 260 226 collage_image.process(); 261 227 } 262 228 263 229 // advanced image processing may be used 264 230 if (is_java2_) 265 { 266 267 // conducts fading and colouring of image 268 Image img = handlepixels(collage_image.image_, 0, 0, collage_image.image_x_dim_, 269 collage_image.image_y_dim_, i, collage_image.fresh ); 270 collage_image.image_ = img; 231 { 232 // conducts fading and colouring of image 233 pixels = collage_image.handlepixels(inuse_.size()-i); 234 } 271 235 272 273 }274 275 236 if (collage_image.fresh) { 276 237 collage_image.fresh = false; 277 238 } 278 279 } 280 else { 281 if (app_.verbosity()>=3) { 282 System.err.println(" Image ["+i+"] not ready yet!"); 283 } 284 } 285 //finished_graphic_.drawImage(screen_buffer_,0,0,app_); 286 287 } 288 289 // draws the finished image onscreen 290 finished_graphic_.drawImage(screen_buffer_,0,0,app_); 291 remove_old_images(); 292 } 293 294 295 /** loops through removing oldest images and reduces number of images if excessive overlap is occuring */ 296 void remove_old_images() { 297 298 // loops through removing oldest images that have almost faded completely 299 // and restricting the size of a simple collage to 25 images 300 int i=0; 301 while (i<inuse_.size()) 302 { 303 CollageImage collage_image = (CollageImage)inuse_.elementAt(i); 304 305 // if we remove when images have faded too much 306 if (is_java2_) { 307 if (checkFaded(collage_image.image_, 0, 0, collage_image.image_x_dim_, collage_image.image_y_dim_) || overlap) 308 { 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) { 309 269 overlap = false; 310 270 311 271 CollageImage removed_image = (CollageImage)inuse_.elementAt(i); 312 272 inuse_.remove(i); 313 314 // restores alpha channel to represent a solid image315 Image img = restoreAlpha(removed_image.image_, 0, 0, removed_image.image_x_dim_, removed_image.image_y_dim_);316 273 317 274 // indicates space for this image is no longer used … … 320 277 if(used_space[n][m] != 0) { 321 278 used_space[n][m]--; 322 323 279 if (used_space[n][m] > NO_IMAGES_OF_OVERLAP) 280 overlap = true; 324 281 } 325 282 326 283 // sets the image as fresh and adds it to the vector of images previously seen 327 removed_image.image_ = img;328 284 removed_image.fresh = true; 329 285 notinuse_.addElement(removed_image); 330 286 } 331 else { 332 i++; 333 } 334 } 335 // if we remove to prevent too many images being displayed simultaneously 336 else { 337 if (inuse_.size() > 25 || overlap) { 338 overlap = false; 339 340 CollageImage removed_image = (CollageImage)inuse_.elementAt(i); 341 inuse_.remove(i); 342 343 // indicates space for this image is no longer used 344 for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++) 345 for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++) 346 if(used_space[n][m] != 0) { 347 used_space[n][m]--; 348 if (used_space[n][m] > NO_IMAGES_OF_OVERLAP) 349 overlap = true; 350 } 351 352 // sets the image as fresh and adds it to the vector of images previously seen 353 removed_image.fresh = true; 354 notinuse_.addElement(removed_image); 355 } 356 else { 357 i++; 358 } 359 } 360 } 361 362 363 } 364 287 else{ 288 i++; 289 } 290 291 } 292 } 293 365 294 366 295 /** Alters the images currently on display in the applet <br> … … 377 306 { 378 307 double random = Math.random(); 379 380 381 if (inuse_ready_.size() > 0){308 309 310 if (inuse_ready_.size() > 0){ 382 311 int pos = (int) ((inuse_ready_.size() - 1) * random); 383 inuse_.addElement(inuse_ready_.remove(pos));384 }385 else if (notinuse_.size()>0)386 {387 int position = (int) ((notinuse_.size() - 1) * random);388 Image image;389 390 CollageImage collage_image = (CollageImage)notinuse_.elementAt(position);391 notinuse_.remove(position);392 inuse_.addElement(collage_image);393 394 if (app_.verbosity()>3)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) 395 324 { 396 325 System.err.println("Re-using an image not on screen"); 397 326 } 398 } 399 // otherwise repaint the first image as the last image 400 // else if (inuse_.size() > 0){ 401 // CollageImage removed_image = (CollageImage)inuse_.elementAt(0); 402 403 // // empty the picture from the grid 404 // for (int n = removed_image.xl_; n < (removed_image.xl_ + removed_image.image_x_dim_); n++) 405 // for (int m = removed_image.yt_; m < (removed_image.yt_ + removed_image.image_y_dim_); m++) 406 // used_space[n][m]--; 407 408 // // reset the alpha and add it 409 // removed_image.fresh = true; 410 411 // if (is_java2_) { 412 // removed_image.image_ = restoreAlpha(removed_image.image_, 0, 0, 413 // removed_image.image_x_dim_, removed_image.image_y_dim_); 414 // } 415 416 // notinuse_.addElement(removed_image); 417 // inuse_.remove(0); 418 // if (app_.verbosity()>=4){ 419 // System.err.println("Removing oldest image"); 420 // } 421 // } 422 else{ 423 if (app_.verbosity()>=4) 424 System.err.println("No images in download area"); 425 } 426 display_collage(); 427 428 } 429 430 /** Adjusts the colour and alpha value of an individual pixel <br> 431 * If the image is being drawn for the first time, the RGB values are 432 * extracted. If the pixel is close to white (RGB > 250) then an offwhite 433 * colour is applied to this pixel. 434 * This is done because when several white images appear in the collage 435 * simultaneously it is difficult to distinguish their edges. <br> 436 * This function also fades the alpha value of the pixel as the image ages. 437 * The alpha value is more heavily decremented as pixels get closer to the 438 * edge of the image 439 * 440 * @param pixel the pixel to manipulate 441 * @param p the position of the image in collage (representative of age) 442 * @param fresh indicates whether or not the image is being drawn for the first time 443 * @param edge indicates whether or not this pixel is near the edge of the image 444 * @param fade the amount by which to fade this pixel 445 * @return the adjusted pixel as an int */ 446 public int handlesinglepixel(int pixel, int p, boolean fresh, boolean edge, int fade) { 447 448 int newpixel = 0; 449 450 //changes the colour of the picture, only when first drawn 451 //and only if the pixel is close to white 452 if (fresh) { 453 454 int red = (pixel >> 16) & 0xff; 455 int green = (pixel >> 8) & 0xff; 456 int blue = (pixel ) & 0xff; 457 458 if (red >= 250 && green >= 250 && blue >= 250) { 459 460 int c = colorMask[((int) (p%NO_OF_COLORS))]; 461 462 red = (c >> 16) & 0xff; 463 green = (c >> 8) & 0xff; 464 blue = (c) & 0xff; 465 } 466 467 newpixel |= (red << 16) & 0x00ff0000; 468 newpixel |= (green << 8) & 0x0000ff00; 469 newpixel |= blue & 0x000000ff; 470 } 471 472 else { 473 newpixel |= pixel & 0x00ffffff; 474 } 475 476 int alpha = (pixel >> 24) & 0xff; 477 478 if (edge) { 479 // fade the edges more... 480 alpha = fade; 481 } 482 else if (alpha > 10 && !fresh) { 483 alpha -= 10; 484 } 485 486 newpixel |= (alpha << 24) & 0xff000000; 487 488 return (newpixel); 489 } 490 491 /** Fades and colours the image on a pixel-by-pixel basis <br> 492 * First it grabs the pixels of the entire image and stores them in a 2D array. 493 * Then a bound is calculated to indicate the point from which edge 494 * fading should occur. The position of the bound will change in proportion 495 * to the age of the image so that older images have a larger faded edge. 496 * The area within the bounds, that forms the center of the image, is processed 497 * first and faded by a standard alpha value. Then each edge of the image 498 * is processed separately, creating a gradient fade from the true edge to the 499 * position of the bound. <br> 500 * The faded pixel array is then turned into a new image a returned. 501 * 502 * @param img the image that requires processing 503 * @param x the x co-ordinate of the image 504 * @param y the y co-ordinate of the image 505 * @param w the width of the image 506 * @param h the height of the image 507 * @param p the position of the image in the applet (indicates age) 508 * @param fresh whether the image is being processed for the first time */ 509 510 public Image handlepixels(Image img, int x, int y, int w, int h, int p, boolean fresh) { 511 512 513 // declare an array to hold the pixels 514 int[] pixels = new int[w * h]; 515 516 // get the pixels of the image into the pixels array 517 PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w); 518 try { 519 pg.grabPixels(); 520 521 } catch (InterruptedException e) { 522 System.err.println("interrupted waiting for pixels!"); 523 return img; 524 } 525 // check for any failures 526 if ((pg.getStatus() & ImageObserver.ABORT) != 0) { 527 System.err.println("image fetch aborted or errored"); 528 return img; 529 } 530 531 // calculates the bound from which fading should begin 532 double bound = (inuse_.size() - p) * 0.01; 533 if (w > h) 534 bound *= w; 535 else 536 bound *= h; 537 538 int upperboundheight = h - (int) bound; 539 int upperboundwidth = w - (int) bound; 540 int lowerbound = (int) bound; 541 542 // loop through every pixel in the picture and handle it 543 for (int j = lowerbound; j < upperboundheight; j++) { 544 for (int i = lowerbound; i < upperboundwidth; i++) { 545 // width and height: x+i y+j 546 pixels[j * w + i] = handlesinglepixel(pixels[j * w + i], p, fresh, false, 255); 547 } 548 } 549 550 int fade = 0; 551 int fader = 0; 552 int corealpha = (pixels[(h/2) * w + (w/2)] >> 24) & 0xff; 553 554 // top edge 555 for (int n = lowerbound; n >= 0; n--) { 556 fader = corealpha - fade; 557 if (fader < 0) 558 fader = 0; 559 560 for (int m = 0; m < w; m++){ 561 int index = n* w + m; 562 if (index <pixels.length){ 563 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader); 564 565 } 566 } 567 568 569 570 fade+= FADEVALUE; 571 } 572 573 // bottom edge 574 fade = 0; 575 for (int n = upperboundheight; n < h; n++) { 576 fader = corealpha - fade; 577 if (fader < 0) 578 fader = 0; 579 for (int m = 0; m < w; m++){ 580 int index = n * w + m; 581 if (index <pixels.length){ 582 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader); 583 584 } 585 } 586 587 fade += FADEVALUE; 588 } 589 590 // left edge 591 fade = 0; 592 for (int n = lowerbound; n >= 0; n--) { 593 fader = corealpha - fade; 594 if (fader < 0) 595 fader = 0; 596 for (int m = 0; m < h; m++) { 597 if ( m < lowerbound && n > m); 598 else if ( m > upperboundheight && n > (h - m)); 599 else { 600 int index = m * w + n; 601 if (index <pixels.length){ 602 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader); 603 604 } 605 } 606 607 } 608 fade += FADEVALUE; 609 } 610 611 // right edge 612 fade = 0; 613 for (int n = upperboundwidth; n < w; n++) { 614 fader = corealpha - fade; 615 if (fader < 0) 616 fader = 0; 617 for (int m = 0; m < h; m++) { 618 if ( m < lowerbound && (w - n) > m); 619 else if ( m > upperboundheight && (w - n) > (h - m)); 620 else { 621 int index = m * w + n; 622 if (index <pixels.length){ 623 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader); 624 625 } 626 } 627 628 } 629 630 fade += FADEVALUE; 631 } 632 633 // set the pixels of the whole picture to the pixels array 634 pg.setPixels(0, 0, w, h, pg.getColorModel(), pixels, 0, w); 635 636 // create the new image and return it 637 return( app_.createImage(new MemoryImageSource(w, h, pixels, 0, w)) ); 638 639 } 640 641 /** Resets the alpha channel of an image so that it appears solid 642 * 643 * @param img the image to restore 644 * @param x the x co-ordinate of the image 645 * @param y the y co-ordinate of the image 646 * @param w the width of the image 647 * @param h the height of the image */ 648 public Image restoreAlpha(Image img, int x, int y, int w, int h) { 649 650 // declare an array to hold the pixels 651 int[] pixels = new int[w * h]; 652 653 // get the pixels of the image into the pixels array 654 PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w); 655 656 try { 657 658 pg.grabPixels(); 659 660 } catch (InterruptedException e) { 661 System.err.println("interrupted waiting for pixels!"); 662 return img; 663 } 664 665 666 // check for any failures 667 if ((pg.getStatus() & ImageObserver.ABORT) != 0) { 668 System.err.println("image fetch aborted or errored"); 669 return img; 670 } 671 672 // loop through every pixel in the picture and handle it 673 for (int j = 0; j < h; j++) { 674 for (int i = 0; i < w; i++) { 675 pixels[j * w + i] |= (255 << 24) & 0xff000000; 676 } 677 } 678 679 // set the pixels of the whole picture to the pixels array 680 pg.setPixels(0, 0, w, h, pg.getColorModel(), pixels, 0, w); 681 682 // create the new image and return it 683 return( app_.createImage(new MemoryImageSource(w, h, pixels, 0, w)) ); 684 685 } 686 687 /** Checks whether an image has faded to the point where it must be removed 688 * from the collage. 689 * 690 * @param img the image to restore 691 * @param x the x co-ordinate of the image 692 * @param y the y co-ordinate of the image 693 * @param w the width of the image 694 * @param h the height of the image */ 695 public boolean checkFaded (Image img, int x, int y, int w, int h) { 696 if (w == 0 || h == 0) 697 return false; 698 699 // declare an array to hold the pixels 700 int[] pixels = new int[w * h]; 701 702 // get the pixels of the image into the pixels array 703 PixelGrabber pg = new PixelGrabber(img, x, y, w, h, pixels, 0, w); 704 try { 705 pg.grabPixels(); 706 707 } catch (InterruptedException e) { 708 System.err.println("interrupted waiting for pixels!"); 709 return false; 710 } 711 // check for any failures 712 if ((pg.getStatus() & ImageObserver.ABORT) != 0) { 713 System.err.println("image fetch aborted or errored"); 714 return false; 715 } 716 717 // get the alpha value of the middle pixel of the image 718 int corealpha = (pixels[(h/2) * w + (w/2)] >> 24) & 0xff; 719 720 if (corealpha < 10) 721 return true; 722 723 return false; 724 725 } 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 726 338 727 339 /** Paints the applet on the screen */ … … 749 361 if (collage_image.fresh) { 750 362 if (app_.verbosity()>=1) { 751 System.err.println("doing nothing... images in useis fresh.");363 System.err.println("doing nothing... "+ collage_image.name_ +" is fresh."); 752 364 } 753 365 } … … 766 378 // simple image collage 767 379 else 768 { 769 // add the image to the collage 380 { // add the image to the collage 770 381 771 382 screen_graphic_.drawImage(collage_image.image_, … … 803 414 804 415 while (curr_thread == this) { 805 CollageImage collage_image = download_images_.getCollageImage();806 if (collage_image !=null){807 inuse_ready_.addElement(collage_image);808 }809 else{810 break; 811 }812 curr_thread = Thread.currentThread();813 814 815 816 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 817 428 } catch (Exception e) { 818 429 e.printStackTrace();
Note:
See TracChangeset
for help on using the changeset viewer.