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

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

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

  • Property svn:keywords set to Author Date Id Revision
File size: 14.8 KB
Line 
1package org.nzdl.gsdl.GsdlCollageApplet;
2
3import java.awt.*;
4import java.awt.geom.*;
5import java.io.*;
6import java.net.*;
7import java.awt.image.*;
8
9
10/**
11 * @author Katrina Edgar
12 * @author David Bainbridge
13 *
14 * Data Structure to store an image once it is displayed in the applet.
15 * This structure remembers the images graphical representation, source url,
16 * name, width, height, position on the screen and whether or not it has
17 * previously been displayed. It provides methods to set the dimensions and
18 * position of the image. It also provides access methods to the translated
19 * x and y co-ordinates of the image */
20public class CollageImage {
21
22 /** Decrements the alpha value between adjacent rows on the edge of an image<br>
23 * Used to fade the edges faster than the rest of the image <br>
24 * Only used when java2 parameter is true and advanced image processing
25 * techniques may be applied */
26 static final int FADEVALUE = 3;
27
28 /** Defines the shades of white used to colour the backgrounds of white images <br>
29 * These colours are used because when several white images appear in the collage
30 * simultaneously it is difficult to distinguish their edges<br>
31 * Only used when java2 parameter is true and advanced image processing
32 * techniques may be applied */
33 int colorMask [] = {0xF8FFFF, 0xFFF8FF, 0xFFFFF8, 0xF8F8FF, 0xFFF8F8, 0xF8FFF8, 0xFAFAFA};
34
35
36 /** Defines the number of shades of white used to colour the backgrounds of white images <br>
37 * These colours are used because when several white images appear in the collage
38 * simultaneously it is difficult to distinguish their edges<br>
39 * Only used when java2 parameter is true and advanced image processing
40 * techniques may be applied */
41 static final int NO_OF_COLORS = 7;
42
43 /** Will fire a removal operation when 4 images in the collage overlap a single area */
44 static final int NO_IMAGES_OF_OVERLAP = 4;
45
46
47 /** Source url of the image */
48 String from_url_ = null;
49 /** Name of the image */
50 String name_ = null;
51 /** Width of the image */
52 int image_x_dim_ = 0;
53 /** Height of the image */
54 int image_y_dim_ = 0;
55 /** Indicates whether or not the image has been drawn on the applet previously */
56 boolean fresh = true;
57
58 URL url_ = null;
59
60 /** Reflects the translation of the image from the origin to its position on the screen */
61 AffineTransform af_ = null;
62 /** Left x co-ordinate */
63 protected int xl_ = 0;
64 /** Top y co-ordinate */
65 protected int yt_ = 0;
66 /** Right x co-ordinate */
67 protected int xr_ = 0;
68 /** Bottom y co-ordinate */
69 protected int yb_ = 0;
70
71 /** Refers to applet */
72 GsdlCollageApplet app_ = null;
73
74 boolean isJava2_;
75
76 Image image_;
77
78 /** Constructs an CollageImage from the three specified parameters
79 *
80 * @param image The graphical representation of the image
81 * @param from_url The source url for the image
82 * @param name The file name of the image */
83 public CollageImage(GsdlCollageApplet app, boolean isJava2, DownloadImages.ImageUrlTriple iutriple)
84 {
85
86 image_ = iutriple.image();
87 from_url_ = iutriple.urlString();
88 name_ = iutriple.name();
89 url_ = iutriple.url();
90
91 isJava2_=isJava2;
92 app_=app;
93
94 process();
95 }
96
97 /** Sets the translation for the image from the origin
98 * And regenerate the image as the scaled version
99 *
100 * @param af The AffineTransform translation that has been calculated */
101 public void setAffineTransform(MyAffineTransform af, boolean is_java2_)
102 {
103 image_x_dim_ = (int) (image_x_dim_ * af.scaleX);
104 image_y_dim_ = (int) (image_y_dim_ * af.scaleY);
105
106 image_ = image_.getScaledInstance(image_x_dim_, image_y_dim_, Image.SCALE_DEFAULT);
107
108 if (is_java2_) {
109 af_ = new AffineTransform();
110 af_.translate(af.translateX, af.translateY);
111 af_.scale(1.0, 1.0);
112
113 calculate_rect();
114 }
115 else {
116 double trans_x = af.translateX;
117 double trans_y = af.translateY;
118
119 xl_ = Math.round((float)trans_x);
120 xr_ = Math.round((float)(trans_x + image_x_dim_)) -1;
121 yt_ = Math.round((float)trans_y);
122 yb_ = Math.round((float)(trans_y + image_y_dim_)) -1;
123 }
124
125 }
126
127 public void expand () {
128
129 // still expands a little too fast... how to fix this?
130 magnify(new Rectangle((int) (xl_ + (image_x_dim_ * 0.000001)),
131 (int) (yt_ + (image_y_dim_ * 0.000001)),
132 (int) (image_x_dim_ * 0.999998),
133 (int) (image_y_dim_ * 0.999998)));
134
135 }
136
137 public void magnify(Rectangle border) {
138
139 double magX = image_x_dim_/(double)border.width;
140 double magY = image_y_dim_/(double)border.height;
141 int x = border.x + border.width/2;
142 int y = border.y + border.height/2;
143 paintImage(x,y,magX, magY);
144 }
145
146 public void paintImage(int magCenterX, int magCenterY, double magX, double magY){
147
148 try {
149 //Point2D mgp = null;
150 //mgp = af_.inverseTransform((new Point(magCenterX, magCenterY)),(Point)mgp);
151 //double x = (mgp.getX()*magX)-mgp.getX();
152 //double y = (mgp.getY()*magY)-mgp.getY();
153 //scale(-x,-y, magX, magY);
154 }catch (Exception e) {System.out.println(e); }
155 }
156
157 public void scale(double magOffsetX, double magOffsetY, double magX, double magY){
158
159 af_.translate(magOffsetX,magOffsetY);
160 af_.scale(magX, magY);
161 }
162
163 /** Calculates the new image co-ordinates after translation has occurred */
164 protected void calculate_rect()
165 {
166 double trans_x = af_.getTranslateX();
167 double trans_y = af_.getTranslateY();
168
169 xl_ = Math.round((float)trans_x);
170 xr_ = Math.round((float)(trans_x + image_x_dim_)) -1;
171 yt_ = Math.round((float)trans_y);
172 yb_ = Math.round((float)(trans_y + image_y_dim_)) -1;
173 }
174
175 /** Determines whether a given co-ordinate is inside this image
176 *
177 * @param x The x co-ordinate
178 * @param y The y co-ordinate */
179 public boolean inside(int x, int y)
180 {
181 return ((x>=xl_) && (x<=xr_)) && ((y>=yt_) && (y<=yb_));
182 }
183
184 /** Gets the width of the translated image */
185 public double getX() {
186 return af_.getTranslateX();
187 }
188
189 /** Gets the height of the translated image */
190 public double getY() {
191 return af_.getTranslateY();
192 }
193
194
195 /** Fades and colours the image on a pixel-by-pixel basis <br>
196 * First it grabs the pixels of the entire image and stores them in a 2D array.
197 * Then a bound is calculated to indicate the point from which edge
198 * fading should occur. The position of the bound will change in proportion
199 * to the age of the image so that older images have a larger faded edge.
200 * The area within the bounds, that forms the center of the image, is processed
201 * first and faded by a standard alpha value. Then each edge of the image
202 * is processed separately, creating a gradient fade from the true edge to the
203 * position of the bound. <br>
204 * The faded pixel array is then turned into a new image a returned.
205 *
206 * @param img the image that requires processing
207 * @param x the x co-ordinate of the image
208 * @param y the y co-ordinate of the image
209 * @param w the width of the image
210 * @param h the height of the image
211 * @param p the position of the image in the applet (indicates age)
212 * @param fresh whether the image is being processed for the first time */
213 public int[] handlepixels(int p) {
214
215 int h = image_y_dim_;
216 int w = image_x_dim_;
217
218 // declare an array to hold the pixels
219 int[] pixels = new int[w * h];
220 // get the pixels of the image into the pixels array
221 PixelGrabber pg = new PixelGrabber(image_, 0, 0, w, h, pixels, 0, w);
222
223 try {
224 pg.grabPixels();
225 } catch (InterruptedException e) {
226 System.err.println("interrupted waiting for pixels!");
227 }
228
229
230 // check for any failures
231 if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
232 System.err.println("image fetch aborted or errored");
233
234 }
235
236
237 // calculates the bound from which fading should begin
238 double bound = p * 0.01;
239 if (w > h)
240 bound *= w;
241 else
242 bound *= h;
243
244 int upperboundheight = h - (int) bound;
245 int upperboundwidth = w - (int) bound;
246 int lowerbound = (int) bound;
247
248 // loop through every pixel in the picture and handle it
249 for (int j = lowerbound; j < upperboundheight; j++) {
250 for (int i = lowerbound; i < upperboundwidth; i++) {
251 // width and height: x+i y+j
252 pixels[j * w + i] = handlesinglepixel(pixels[j * w + i], p, fresh, false, 255);
253 }
254 }
255
256 int fade = 0;
257 int fader = 0;
258 int corealpha = (pixels[(h/2) * w + (w/2)] >> 24) & 0xff;
259
260 // top edge
261 for (int n = lowerbound; n >= 0; n--) {
262 fader = corealpha - fade;
263 if (fader < 0)
264 fader = 0;
265
266 for (int m = 0; m < w; m++){
267 int index = n* w + m;
268 if (index <pixels.length){
269 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader);
270
271 }
272 }
273
274 fade+= FADEVALUE;
275 }
276
277 // bottom edge
278 fade = 0;
279 for (int n = upperboundheight; n < h; n++) {
280 fader = corealpha - fade;
281 if (fader < 0)
282 fader = 0;
283 for (int m = 0; m < w; m++){
284 int index = n * w + m;
285 if (index <pixels.length){
286 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader);
287
288 }
289 }
290
291 fade += FADEVALUE;
292 }
293
294 // left edge
295 fade = 0;
296 for (int n = lowerbound; n >= 0; n--) {
297 fader = corealpha - fade;
298 if (fader < 0)
299 fader = 0;
300 for (int m = 0; m < h; m++) {
301 if ( m < lowerbound && n > m);
302 else if ( m > upperboundheight && n > (h - m));
303 else {
304 int index = m * w + n;
305 if (index <pixels.length){
306 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader);
307
308 }
309 }
310
311 }
312 fade += FADEVALUE;
313 }
314
315 // right edge
316 fade = 0;
317 for (int n = upperboundwidth; n < w; n++) {
318 fader = corealpha - fade;
319 if (fader < 0)
320 fader = 0;
321 for (int m = 0; m < h; m++) {
322 if ( m < lowerbound && (w - n) > m);
323 else if ( m > upperboundheight && (w - n) > (h - m));
324 else {
325 int index = m * w + n;
326 if (index <pixels.length){
327 pixels[index] = handlesinglepixel(pixels[index], p, fresh, true, fader);
328
329 }
330 }
331
332 }
333
334 fade += FADEVALUE;
335 }
336
337 // set the pixels of the whole picture to the pixels array
338 pg.setPixels(0, 0, w, h, pg.getColorModel(), pixels, 0, w);
339
340 image_ = app_.createImage(new MemoryImageSource(w, h, pixels, 0, w));
341
342 return pixels;
343 }
344
345
346 /** Adjusts the colour and alpha value of an individual pixel <br>
347 * If the image is being drawn for the first time, the RGB values are
348 * extracted. If the pixel is close to white (RGB > 250) then an offwhite
349 * colour is applied to this pixel.
350 * This is done because when several white images appear in the collage
351 * simultaneously it is difficult to distinguish their edges. <br>
352 * This function also fades the alpha value of the pixel as the image ages.
353 * The alpha value is more heavily decremented as pixels get closer to the
354 * edge of the image
355 *
356 * @param pixel the pixel to manipulate
357 * @param p the position of the image in collage (representative of age)
358 * @param fresh indicates whether or not the image is being drawn for the first time
359 * @param edge indicates whether or not this pixel is near the edge of the image
360 * @param fade the amount by which to fade this pixel
361 * @return the adjusted pixel as an int */
362 public int handlesinglepixel(int pixel, int p, boolean fresh, boolean edge, int fade) {
363 int newpixel = 0;
364
365 //changes the colour of the picture, only when first drawn
366 //and only if the pixel is close to white
367 if (fresh) {
368
369 int red = (pixel >> 16) & 0xff;
370 int green = (pixel >> 8) & 0xff;
371 int blue = (pixel ) & 0xff;
372
373 if (red >= 250 && green >= 250 && blue >= 250) {
374
375 int c = colorMask[((int) (p%NO_OF_COLORS))];
376
377 red = (c >> 16) & 0xff;
378 green = (c >> 8) & 0xff;
379 blue = (c) & 0xff;
380 }
381
382 newpixel |= (red << 16) & 0x00ff0000;
383 newpixel |= (green << 8) & 0x0000ff00;
384 newpixel |= blue & 0x000000ff;
385 }
386
387 else {
388 newpixel |= pixel & 0x00ffffff;
389 }
390
391 int alpha = (pixel >> 24) & 0xff;
392
393 if (edge) {
394 // fade the edges more...
395 alpha = fade;
396 }
397 else if (alpha > 10 && !fresh) {
398 alpha -= 10;
399 }
400
401 newpixel |= (alpha << 24) & 0xff000000;
402
403 return (newpixel);
404 }
405
406
407
408
409 /** Resets the alpha channel of an image so that it appears solid
410 *
411 * @param img the image to restore
412 * @param x the x co-ordinate of the image
413 * @param y the y co-ordinate of the image
414 * @param w the width of the image
415 * @param h the height of the image */
416 public void restoreAlpha() {
417 int h = image_y_dim_;
418 int w = image_x_dim_;
419
420 // declare an array to hold the pixels
421 int[] pixels = new int[w * h];
422 // get the pixels of the image into the pixels array
423 PixelGrabber pg = new PixelGrabber(image_, 0, 0, w, h, pixels, 0, w);
424 try {
425 pg.grabPixels();
426
427
428 } catch (InterruptedException e) {
429 System.err.println("interrupted waiting for pixels!");
430 }
431
432
433 // check for any failures
434 if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
435 System.err.println("image fetch aborted or errored");
436 }
437
438
439
440 // loop through every pixel in the picture and handle it
441 for (int j = 0; j < h; j++) {
442 for (int i = 0; i < w; i++) {
443 pixels[j * w + i] |= (255 << 24) & 0xff000000;
444 }
445 }
446
447 // set the pixels of the whole picture to the pixels array
448 pg.setPixels(0, 0, w, h, pg.getColorModel(), pixels, 0, w);
449
450 image_ = app_.createImage(new MemoryImageSource(w, h, pixels, 0, w));
451
452 }
453
454 /** Checks whether an image has faded to the point where it must be removed
455 * from the collage.
456 *
457 * @param img the image to restore
458 * @param x the x co-ordinate of the image
459 * @param y the y co-ordinate of the image
460 * @param w the width of the image
461 * @param h the height of the image */
462 public boolean checkFaded (int[] pixels) {
463 int h = image_y_dim_;
464 int w = image_x_dim_;
465
466 // get the alpha value of the middle pixel of the image
467 int corealpha = (pixels[(h/2) * w + (w/2)] >> 24) & 0xff;
468
469 if (corealpha < 50)
470 return true;
471
472 return false;
473
474 }
475
476 public boolean isValid(){
477 image_x_dim_ = image_.getWidth(app_);
478 image_y_dim_ = image_.getHeight(app_);
479
480 return (image_x_dim_) >0 && ( image_x_dim_ >0);
481
482 }
483
484
485 public void process(){
486
487 // images x and y dimensions
488 image_x_dim_ = image_.getWidth(app_);
489 image_y_dim_ = image_.getHeight(app_);
490 if (( image_x_dim_ >0) && ( image_x_dim_ >0))
491 {
492 // places and sizes the image
493 MyAffineTransform af = new MyAffineTransform(image_x_dim_,image_y_dim_);
494
495 // sets location & size of collage image
496 setAffineTransform(af, isJava2_);
497 fresh = false;
498 if (isJava2_ ) {
499 restoreAlpha();
500 }
501
502 }
503
504
505 }
506
507}
508
Note: See TracBrowser for help on using the repository browser.