/*
* Copyright (c) 2005 Thomas Weise
*
* E-Mail : tweise@gmx.de
* Creation Date : 2005-06-17 20:01:54
* Original Filename: org.sfc.io.Images.java
* Version : 1.0.1
* Last modification: 2006-03-07
* by: Thomas Weise
*
* License : GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
* You should have received a copy of this license along
* with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307, USA or download the license under
* http://www.gnu.org/copyleft/lesser.html.
*
* Warranty : This software is provided "as is" without any
* warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose.
* See the Gnu Lesser General Public License for more
* details.
*/
package org.sfc.io;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.ImageObserver;
import java.io.InputStream;
import org.sfc.io.IO;
import org.sfc.io.StreamLoader;
/**
* This class implements basic image support.
*
* pattern: Singleton
* lifetime: static
*
* @author Thomas Weise
*/
public final class Images
{
/**
* Keep anybody from instantiating this class.
*/
private Images()
{
super();
}
/**
* Load an image fully so it can be displayed.
*
* @param p_image The image to be tracked.
* @return true if everything went ok.
*/
public static final boolean track_image (final Image p_image)
{
Tracker l_t;
l_t = new Tracker(p_image);
return l_t.run();
}
/**
* Load an image froman InputStream
.
*
* @param p_source The InputStream
to load from. This stream
* will be loaded fully and the closed.
*
* @return An Image
-object or null, if the wanted image could
* not be created.
*/
public static final Image load_stream_image (final InputStream p_source)
{
StreamLoader l_sl;
Image l_im;
if(p_source != null)
{
try
{
l_sl = new StreamLoader(0);
l_sl.load_stream(p_source);
l_im = Toolkit.getDefaultToolkit()
.createImage(l_sl.get_data(), 0, l_sl.get_length());
if(l_im != null)
{
if(track_image(l_im)) return l_im;
}
}
finally
{
try
{
p_source.close();
}
catch(Throwable l_t)
{
//
}
}
}
return null;
}
/**
* Load an image from a resource.
*
* @param p_source The source to load from. This object describes where
* the image resides.
*
* @return An Image
-object or null, if the wanted image could
* not be created.
*/
public static final Image load_resource_image (final Object p_source)
{
return load_stream_image(
IO.get_resource_input_stream(p_source, 1));
}
/**
* Load an image from the file system or the internet.
*
* @param p_source The source to load from. This object describes where
* the image resides.
*
* @return An Image
-object or null, if the wanted image could
* not be created.
*/
public static final Image load_image (final Object p_source)
{
return load_stream_image(IO.get_input_stream(p_source));
}
/**
* This class will be used to track images down.
* It is a descendant of Task
to allow dynamic image tracking
* from multiple threads.
*
* @author Thomas Weise
*/
private static final class Tracker implements ImageObserver
{
/**
* The image to track.
*/
private final Image m_image;
/**
* Tells if everything went ok.
*/
private int m_flags;
/**
* Create a new image tracker.
*
* @param p_image The image to track.
*/
public Tracker (final Image p_image)
{
super();
this.m_image = p_image;
this.m_flags = 0;
}
/**
* This method is called when information about an image which was
* previously requested using an asynchronous interface becomes
* available. Asynchronous interfaces are method calls such as
* getWidth(ImageObserver) and drawImage(img, x, y, ImageObserver)
* which take an ImageObserver object as an argument. Those methods
* register the caller as interested either in information about
* the overall image itself (in the case of getWidth(ImageObserver))
* or about an output version of an image (in the case of the
* drawImage(img, x, y, [w, h,] ImageObserver) call).
*
* This method should return true if further updates are needed or false
* if the required information has been acquired. The image which was
* being tracked is passed in using the img argument. Various constants
* are combined to form the infoflags argument which indicates what
* information about the image is now available. The interpretation
* of the x, y, width, and height arguments depends on the contents
* of the infoflags argument.
*
* The p_infoflags argument should be the bitwise inclusive
* OR of the following flags: WIDTH, HEIGHT, PROPERTIES, SOMEBITS,
* FRAMEBITS, ALLBITS, ERROR, ABORT.
*
* @param p_img the image being observed.
* @param p_infoflags the bitwise inclusive OR of the following
* flags: WIDTH, HEIGHT,
* PROPERTIES, SOMEBITS,
* FRAMEBITS, ALLBITS,
* ERROR, ABORT.
* @param p_x the x coordinate.
* @param p_y the y coordinate.
* @param p_width the width.
* @param p_height the height.
* @return false if the infoflags indicate that the
* image is completely loaded; true otherwise.
*/
public final boolean imageUpdate(Image p_img,
int p_infoflags,
int p_x,
int p_y,
int p_width,
int p_height)
{
if((p_infoflags & ABORT) != 0) p_infoflags |= ERROR;
this.m_flags |= p_infoflags ;
if(((this.m_flags & (ALLBITS | FRAMEBITS)) != 0) ||
((this.m_flags & ERROR) != 0))
{
this.notifyAll();
return false;
}
return true;
}
/**
* Executes the tracking.
* @return true if everything went ok, false othwise.
*/
public final boolean run ()
{
Toolkit l_t;
l_t = Toolkit.getDefaultToolkit();
if(!imageUpdate(this.m_image,
l_t.checkImage(this.m_image, -1, -1, null), 0, 0, 0, 0))
{
return ((this.m_flags & ERROR) == 0);
}
l_t.prepareImage(this.m_image, -1, -1, this);
for(;;)
{
try
{
this.wait();
break;
}
catch(InterruptedException l_ie)
{
//
}
catch(Throwable l_th)
{
this.m_flags = ERROR;
break;
}
}
return ((this.m_flags & ERROR) == 0);
}
}
}