ui/src/main/java/ucar/nc2/ui/image/SourcePicture.java
public void loadPicture() {
		Tools.log("SourcePicture.loadPicture: " + imageUrl.toString() + " loaded into SourcePicture object: " + Integer.toString(this.hashCode()) );
		//Tools.freeMem();
						
		setStatus( LOADING, "Loading: " + imageUrl.toString() );
		abortFlag = false;

		try {
			
			// Java 1.4 way with a Listener
			ImageInputStream iis = ImageIO.createImageInputStream( imageUrl.openStream() );
			Iterator i = ImageIO.getImageReaders( iis );
			if ( ! i.hasNext() ) { throw new IOException ("No Readers Available!"); }
			reader = (ImageReader) i.next();  // grab the first one
			
			reader.addIIOReadProgressListener( imageProgressListener );
			reader.setInput( iis );
			sourcePictureBufferedImage = null;
			// try {
				sourcePictureBufferedImage = reader.read( 0 ); // just get the first image
			/* } catch ( OutOfMemoryError e ) {
				Tools.log("SourcePicture caught an OutOfMemoryError while loading an image." );

				iis.close();
				reader.removeIIOReadProgressListener( imageProgressListener );
				reader.dispose();

				setStatus(ERROR, "Out of Memory Error while reading " + imageUrl.toString());
				sourcePictureBufferedImage = null; 
				// PictureCache.clear();

				JOptionPane.showMessageDialog( null,  //deliberately null or it swaps the window
					"outOfMemoryError",
					"genericError",
					JOptionPane.ERROR_MESSAGE);

				System.gc();
				System.runFinalization();

				Tools.log("JPO has now run a garbage collection and finalization.");
				return;
			} */

			iis.close();
			reader.removeIIOReadProgressListener( imageProgressListener );
			//Tools.log("!!dispose being called!!");
			reader.dispose();

			if ( ! abortFlag ) {
			
				if ( rotation != 0 ) {
					setStatus( ROTATING, "Rotating: " + imageUrl.toString() );
					int xRot = sourcePictureBufferedImage.getWidth() / 2;
					int yRot = sourcePictureBufferedImage.getHeight() / 2;
					AffineTransform rotateAf = AffineTransform.getRotateInstance( Math.toRadians( rotation ), xRot, yRot );
					AffineTransformOp op = new AffineTransformOp( rotateAf, AffineTransformOp.TYPE_BILINEAR );
					Rectangle2D newBounds = op.getBounds2D( sourcePictureBufferedImage );
					// a simple AffineTransform would give negative top left coordinates -->
					// do another transform to get 0,0 as top coordinates again.
					double minX = newBounds.getMinX();
					double minY = newBounds.getMinY();
					
					AffineTransform translateAf = AffineTransform.getTranslateInstance( minX * (-1), minY * (-1) );
					rotateAf.preConcatenate( translateAf );
					op = new AffineTransformOp( rotateAf, AffineTransformOp.TYPE_BILINEAR );
					newBounds = op.getBounds2D( sourcePictureBufferedImage );

					// this piece of code is so essential!!! Otherwise the internal image format
					// is totally altered and either the AffineTransformOp decides it doesn't
					// want to rotate the image or web browsers can't read the resulting image.
					BufferedImage targetImage = new BufferedImage(
						(int) newBounds.getWidth(),
						(int) newBounds.getHeight(),
						BufferedImage.TYPE_3BYTE_BGR );
					
					sourcePictureBufferedImage = op.filter( sourcePictureBufferedImage, targetImage );
				}

				setStatus( READY, "Loaded: " + imageUrl.toString() );
				PictureCache.add( imageUrl, (SourcePicture) this.clone() );
			} else {
				setStatus( ERROR, "Aborted: " + imageUrl.toString() );
				sourcePictureBufferedImage = null; 
			}
		} catch ( IOException e ) {
			setStatus(ERROR, "Error while reading " + imageUrl.toString());
			sourcePictureBufferedImage = null; 
		}

	}
public void loadPicture() {
		Tools.log("SourcePicture.loadPicture: " + imageUrl.toString() + " loaded into SourcePicture object: " + Integer.toString(this.hashCode()) );
		//Tools.freeMem();
						
		setStatus( LOADING, "Loading: " + imageUrl.toString() );
		abortFlag = false;

		try {
			
			// Java 1.4 way with a Listener
			ImageInputStream iis = ImageIO.createImageInputStream( imageUrl.openStream() );
			Iterator i = ImageIO.getImageReaders( iis );
			if ( ! i.hasNext() ) { throw new IOException ("No Readers Available!"); }
			reader = (ImageReader) i.next();  // grab the first one
			
			reader.addIIOReadProgressListener( imageProgressListener );
			reader.setInput( iis );
			sourcePictureBufferedImage = null;
			// try {
				sourcePictureBufferedImage = reader.read( 0 ); // just get the first image
			/* } catch ( OutOfMemoryError e ) {
				Tools.log("SourcePicture caught an OutOfMemoryError while loading an image." );

				iis.close();
				reader.removeIIOReadProgressListener( imageProgressListener );
				reader.dispose();

				setStatus(ERROR, "Out of Memory Error while reading " + imageUrl.toString());
				sourcePictureBufferedImage = null; 
				// PictureCache.clear();

				JOptionPane.showMessageDialog( null,  //deliberately null or it swaps the window
					"outOfMemoryError",
					"genericError",
					JOptionPane.ERROR_MESSAGE);

				System.gc();
				System.runFinalization();

				Tools.log("JPO has now run a garbage collection and finalization.");
				return;
			} */

			iis.close();
			reader.removeIIOReadProgressListener( imageProgressListener );
			//Tools.log("!!dispose being called!!");
			reader.dispose();

			if ( ! abortFlag ) {
			
				if ( rotation != 0 ) {
					setStatus( ROTATING, "Rotating: " + imageUrl.toString() );
					int xRot = sourcePictureBufferedImage.getWidth() / 2;
					int yRot = sourcePictureBufferedImage.getHeight() / 2;
					AffineTransform rotateAf = AffineTransform.getRotateInstance( Math.toRadians( rotation ), xRot, yRot );
					AffineTransformOp op = new AffineTransformOp( rotateAf, AffineTransformOp.TYPE_BILINEAR );
					Rectangle2D newBounds = op.getBounds2D( sourcePictureBufferedImage );
					// a simple AffineTransform would give negative top left coordinates -->
					// do another transform to get 0,0 as top coordinates again.
					double minX = newBounds.getMinX();
					double minY = newBounds.getMinY();
					
					AffineTransform translateAf = AffineTransform.getTranslateInstance( minX * (-1), minY * (-1) );
					rotateAf.preConcatenate( translateAf );
					op = new AffineTransformOp( rotateAf, AffineTransformOp.TYPE_BILINEAR );
					newBounds = op.getBounds2D( sourcePictureBufferedImage );

					// this piece of code is so essential!!! Otherwise the internal image format
					// is totally altered and either the AffineTransformOp decides it doesn't
					// want to rotate the image or web browsers can't read the resulting image.
					BufferedImage targetImage = new BufferedImage(
						(int) newBounds.getWidth(),
						(int) newBounds.getHeight(),
						BufferedImage.TYPE_3BYTE_BGR );
					
					sourcePictureBufferedImage = op.filter( sourcePictureBufferedImage, targetImage );
				}

				setStatus( READY, "Loaded: " + imageUrl.toString() );
				PictureCache.add( imageUrl, (SourcePicture) this.clone() );
			} else {
				setStatus( ERROR, "Aborted: " + imageUrl.toString() );
				sourcePictureBufferedImage = null; 
			}
		} catch ( IOException e ) {
			setStatus(ERROR, "Error while reading " + imageUrl.toString());
			sourcePictureBufferedImage = null; 
		}

	}
loads a picture from the URL in the imageUrl object into the sourcePictureBufferedImage
object and updates the status when done or failed.