package com.opticalcobra.storybear.res; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.sql.SQLException; import java.util.HashMap; import java.util.Random; import javax.imageio.ImageIO; import com.opticalcobra.storybear.db.Database; import com.opticalcobra.storybear.db.ImageResult; import com.opticalcobra.storybear.exceptions.ImageNotFoundException; import com.opticalcobra.storybear.exceptions.QueryTypeNotFoundException; /** * * @author Tobias * */ public class Imagelib { private static Imagelib instance; /* * Hashmap prefixes: * map- All map elements * img- Internal graphics (eg cluster graphics) * hero- Image of a hero * cha- Character Object * menu- Images for Menu * col- Collectable * ils- Illustration Small (Animals, things) * ilb- Illustration Big (Vehicle, building) */ private HashMap<String,BufferedImage> images; //Hashmap f�r alle Bilder private Database db; //Datenbankverbindung private StoryBearRandom rand = StoryBearRandom.getInstance(); //Zufall mit seed private Random realRand = new Random(); //Constants public static final char QUERY_FOREGROUND = 'f'; public static final char QUERY_MIDDLEGROUND = 'm'; public static final char QUERY_BACKGROUND = 'b'; public static final char QUERY_CLOUDS = 'c'; public static final char QUERY_FOREGROUNDTWO = 'v'; public static final int MENU_SHELF = 246; public static final int MENU_SCROLL_UP = 247; public static final int MENU_SCROLL_DOWN = 248; public static final int MENU_SCROLL_THUMB_TOP = 249; public static final int MENU_SCROLL_THUMB_BOTTOM = 250; public static final int MENU_SCROLL_THUMB_MIDDLE = 251; public static final int MENU_BOOK_1 = 261; public static final int MENU_BOOK_2 = 262; public static final int MENU_BOOK_3 = 263; public static final int MENU_BOOK_4 = 264; public static final int GAME_BUTTON_MENU_BLACK = 252; public static final int GAME_BUTTON_MENU_WHITE = 255; public static final int GAME_BUTTON_MENU_GREY = 258; public static final int GAME_BUTTON_BREAK_BLACK = 253; public static final int GAME_BUTTON_BREAK_WHITE = 256; public static final int GAME_BUTTON_BREAK_GREY = 259; public static final int GAME_BUTTON_EXIT_BLACK = 254; public static final int GAME_BUTTON_EXIT_WHITE = 257; public static final int GAME_BUTTON_EXIT_GREY = 260; private Imagelib(){ db = new Database(); images = new HashMap<String,BufferedImage>(); } /** * * loads the requested image if necessary and returns it as {@link BufferedImage} * * @param queryType dertermines the DB table to select on..represents a layer * @param type type id for requested tile * @return the requested image loaded in RAM * @author Tobias * @exception ImageNotFoundException will be raised if the image was not found in the database */ public BufferedImage loadLandscapeTile(int type, char queryType, String settingNameForFG) throws ImageNotFoundException{ BufferedImage result; BufferedImage full; ImageResult image = getRandomID(type, queryType, settingNameForFG); //Request can be handled with internal Hash map result = images.get("map-"+image.getId()); if(result != null){ return result; } //Request must be handled via database request //cut images to fit full=loadRessourcesImage(image.getUrl()); // result=full.getSubimage((int)(image.getX()/Ressources.SCALE),(int) (image.getY()/Ressources.SCALE),(int) (image.getWidth()/Ressources.SCALE),(int) (image.getHeight()/Ressources.SCALE)); result = cutAndScaleImage(full, image); images.put("map-"+image.getId(), result); return result; } /** * @param rundirection of the hero pic where he is looking at (front, right, left) * @param type of the hero, e.g. a bear, ... * @return Loaded Image requested image * @exception ImageNotFoundException will be raised if the image was not found in the database * @author Miriam * @throws SQLException */ public BufferedImage loadHeroPic(String rundirection, char type) throws ImageNotFoundException, SQLException{ BufferedImage result; BufferedImage full; String sql = "SELECT IMAGEID FROM HEROS WHERE RUNDIRECTION = '" + rundirection + "' AND TYPE = '" + type + "'"; Integer[] ids = db.queryNumberResultOnly(sql); if(ids.length > 0){ ImageResult image = db.queryImagedata(ids[0]); result = images.get("hero-"+image.getId()); if(result != null){ return result; } //cut images to fit full=loadRessourcesImage(image.getUrl()); // result=full.getSubimage((int)(image.getX()/Ressources.SCALE),(int) (image.getY()/Ressources.SCALE),(int) (image.getWidth()/Ressources.SCALE),(int) (image.getHeight()/Ressources.SCALE)); result = cutAndScaleImage(full, image); images.put("hero-"+image.getId(), result); return result; } return null; } /** * Loads a full Sprite Image eather from local cache or from file system * @param graphicName Name of the requested File * @return Loaded Image from the requested sprite * @throws ImageNotFoundException The sprite was not on the file System * @author Tobias */ private BufferedImage loadRessourcesImage(String graphicName) throws ImageNotFoundException{ BufferedImage result; //Check whether image is already cached result = images.get("img-"+graphicName); if(result != null){ return result; } try { //load images from file system BufferedImage temp = ImageIO.read(new File(Ressources.RESPATH+graphicName)); // result = new BufferedImage((int)(temp.getWidth()/Ressources.SCALE),(int)(temp.getHeight()/Ressources.SCALE),BufferedImage.TYPE_INT_ARGB); // result.getGraphics().drawImage(temp, 0, 0, (int)(temp.getWidth()/Ressources.SCALE),(int)(temp.getHeight()/Ressources.SCALE),null); // images.put("img-"+graphicName, result); // return result; // result = getScaledImage(temp,(int)(temp.getWidth()/Ressources.SCALE),(int)(temp.getHeight()/Ressources.SCALE)); images.put("img-"+graphicName, temp); return temp; } catch (IOException e) { //images nicht gefunden throw new ImageNotFoundException("Could not find an Image for:'"+graphicName+"' on file System", e); } } /** * @author Martika * @param image_id * @param prefix * @return */ public BufferedImage loadObjectPic(int image_id, String prefix){ BufferedImage result; BufferedImage full; //Check whether image is already cached result = images.get(prefix+"-"+image_id); if(result != null){ return result; } //Request must be handled via database request ImageResult image; try { image = db.queryImagedata(image_id); full=loadRessourcesImage(image.getUrl()); // result=full.getSubimage((int)(image.getX()/Ressources.SCALE),(int) (image.getY()/Ressources.SCALE),(int) (image.getWidth()/Ressources.SCALE),(int) (image.getHeight()/Ressources.SCALE)); result = cutAndScaleImage(full, image); images.put(prefix+"-"+image_id, result); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } //cut images to fit return result; } /** * load images for design * @param name name as identifier for image * @return need image * @throws ImageNotFoundException * @author Nicolas */ public BufferedImage loadDesignImage(String name) throws ImageNotFoundException { BufferedImage result; BufferedImage full; try { ImageResult image = db.queryImagedata(db.queryNumberResultOnly("SELECT IMAGES_ID FROM DESIGNELEMENTS WHERE NAME = '" + name + "';")[0]); result = images.get("design-"+image.getId()); if(result != null){ return result; } //cut images to fit full = loadRessourcesImage(image.getUrl()); // result = getScaledImage(full.g/etSubimage(image.getX(),image.getY(),image.getWidth(), image.getHeight()), (int) (image.getWidth()/Ressources.SCALE),(int)(image.getHeight()/Ressources.SCALE)); result = cutAndScaleImage(full, image); images.put("design-"+image.getId(), result); return result; } catch (SQLException e) { throw new ImageNotFoundException("No entry for " + name + " in database", e); } } /** * Singleton implementation * @return Instance of {@link Imagelib} */ public static Imagelib getInstance(){ if(instance == null){ instance = new Imagelib(); } return instance; } /** * Return a list of possible tiles to come after the current one * @param type type number of tile to be tested for following tiles * @param queryType Constancy from {@link Imagelib} to identify the layer for witch the query is * @return list of possible following tiles * @author Tobias */ public Integer[] getFollowingTiles(int type, char queryType){ String query; switch (queryType) {// determine which tbles to select on case QUERY_BACKGROUND: query="SELECT DISTINCT f.following_type_id FROM BACKGROUND b JOIN IMAGES i ON i.id = b.images_id JOIN BACKGROUND_FOLLOWING f ON b.type_id = f.type_id WHERE f.type_id = "+type+";"; break; case QUERY_FOREGROUND: query="SELECT DISTINCT f.following_type_id FROM FOREGROUND_ONE b JOIN IMAGES i ON i.id = b.images_id JOIN FOREGROUND_FOLLOWING f ON b.type_id = f.type_id WHERE f.type_id = "+type+";"; break; case QUERY_MIDDLEGROUND: query="SELECT DISTINCT f.following_type_id FROM MIDDLEGROUND b JOIN IMAGES i ON i.id = b.images_id JOIN MIDDLEGROUND_FOLLOWING f ON b.type_id = f.type_id WHERE f.type_id = "+type+";"; break; case QUERY_FOREGROUNDTWO: query="SELECT DISTINCT f.following_type_id FROM FOREGROUND_TWO b JOIN IMAGES i ON i.id = b.images_id JOIN FOREGROUND_FOLLOWING f ON b.type_id = f.type_id WHERE f.type_id = "+type+";"; break; default: throw new QueryTypeNotFoundException("Your Querytype was not valid. Type: "+queryType); } try { return db.queryNumberResultOnly(query); // run Query on DB } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } /** * Returns a Random ID of an Image suitable for the requested slice type from the database * @param type The type a Image ID should be returned from * @param queryType Constancy from {@link Imagelib} to identify the layer for witch the query is * @return Image ID * @author Tobias */ private ImageResult getRandomID(int type, char queryType, String settingNameForFG){ String dbName; switch (queryType) {//determine which database to query on case QUERY_BACKGROUND: dbName="BACKGROUND"; break; case QUERY_FOREGROUND: dbName="FOREGROUND_ONE"; break; case QUERY_MIDDLEGROUND: dbName="MIDDLEGROUND"; break; case QUERY_CLOUDS: dbName=""; break; case QUERY_FOREGROUNDTWO: dbName = "FOREGROUND_TWO"; break; default: throw new QueryTypeNotFoundException("Your Querytype was not valid. Type: "+queryType); } try { Integer[] ids; if(queryType != QUERY_CLOUDS && queryType != QUERY_FOREGROUNDTWO){ ids = db.queryNumberResultOnly("SELECT i.id from images i JOIN "+dbName+" b ON i.id = b.images_id WHERE b.type_id = "+type+";"); return db.queryImagedata(ids[rand.nextInt(ids.length)]); } else{ if (queryType == QUERY_CLOUDS){ ids = db.queryNumberResultOnly("SELECT id from images where url = 'images\\layer_slice_clouds.png'"); return db.queryImagedata(ids[realRand.nextInt(ids.length)]); } else { ids = db.queryNumberResultOnly("SELECT i.id from images i JOIN "+dbName+" b ON i.id = b.images_id WHERE b.type_id = "+type+" and b.setting_name = '"+ settingNameForFG +"';"); return db.queryImagedata(ids[rand.nextInt(ids.length)]); } } } catch (SQLException e) { e.printStackTrace(); return null; //TODO richtiges fehlerhandlich einbauen } } /** * * @param type */ public BufferedImage menuImage (int type){ BufferedImage result; BufferedImage full; //Check whether image is already cached result = images.get("menu-"+type); if(result != null){ return result; } //Request must be handled via database request ImageResult image; try { image = db.queryImagedata(type); full=loadRessourcesImage(image.getUrl()); // result=full.getSubimage((int)(image.getX()/Ressources.SCALE),(int) (image.getY()/Ressources.SCALE),(int) (image.getWidth()/Ressources.SCALE),(int) (image.getHeight()/Ressources.SCALE)); result = cutAndScaleImage(full, image); images.put("menu-"+type, result); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return result; } private BufferedImage cutAndScaleImage(BufferedImage img, ImageResult image){ BufferedImage result = getScaledImage(img.getSubimage(image.getX(),image.getY(),image.getWidth(), image.getHeight()), (int) (image.getWidth()/Ressources.SCALE),(int)(image.getHeight()/Ressources.SCALE)); return result; } /** * scale image * @param image * @param width * @param height * @return * @throws IOException */ public static BufferedImage getScaledImage(BufferedImage image, int width, int height){ int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); double scaleX = (double)width/imageWidth; double scaleY = (double)height/imageHeight; AffineTransform scaleTransform = AffineTransform.getScaleInstance(scaleX, scaleY); AffineTransformOp bilinearScaleOp = new AffineTransformOp(scaleTransform, AffineTransformOp.TYPE_BILINEAR); return bilinearScaleOp.filter( image, new BufferedImage(width, height, image.getType())); } }