Path: blob/master/SLICK_HOME/src/org/newdawn/slick/Image.java
1456 views
package org.newdawn.slick;12import java.io.IOException;3import java.io.InputStream;45import org.lwjgl.opengl.EXTSecondaryColor;6import org.lwjgl.opengl.EXTTextureMirrorClamp;7import org.lwjgl.opengl.GL11;8import org.lwjgl.opengl.GLContext;9import org.newdawn.slick.opengl.ImageData;10import org.newdawn.slick.opengl.InternalTextureLoader;11import org.newdawn.slick.opengl.Texture;12import org.newdawn.slick.opengl.TextureImpl;13import org.newdawn.slick.opengl.pbuffer.GraphicsFactory;14import org.newdawn.slick.opengl.renderer.Renderer;15import org.newdawn.slick.opengl.renderer.SGL;16import org.newdawn.slick.util.Log;1718/**19* An image loaded from a file and renderable to the canvas20*21* @author kevin22*/23public class Image implements Renderable {24/** The top left corner identifier */25public static final int TOP_LEFT = 0;26/** The top right corner identifier */27public static final int TOP_RIGHT = 1;28/** The bottom right corner identifier */29public static final int BOTTOM_RIGHT = 2;30/** The bottom left corner identifier */31public static final int BOTTOM_LEFT = 3;3233/** The renderer to use for all GL operations */34protected static SGL GL = Renderer.get();3536/** The sprite sheet currently in use */37protected static Image inUse;38/** Use Linear Filtering */39public static final int FILTER_LINEAR = 1;40/** Use Nearest Filtering */41public static final int FILTER_NEAREST = 2;4243/** The OpenGL texture for this image */44protected Texture texture;45/** The width of the image */46protected int width;47/** The height of the image */48protected int height;49/** The texture coordinate width to use to find our image */50protected float textureWidth;51/** The texture coordinate height to use to find our image */52protected float textureHeight;53/** The x texture offset to use to find our image */54protected float textureOffsetX;55/** The y texture offset to use to find our image */56protected float textureOffsetY;57/** Angle to rotate the image to. */58protected float angle;59/** The alpha to draw the image at */60protected float alpha = 1.0f;61/** The name given for the image */62protected String ref;63/** True if this image's state has been initialised */64protected boolean inited = false;65/** A pixelData holding the pixel data if it's been read for this texture */66protected byte[] pixelData;67/** True if the image has been destroyed */68protected boolean destroyed;6970/** The x coordinate of the centre of rotation */71protected float centerX;72/** The y coordinate of the centre of rotation */73protected float centerY;7475/** A meaningful name provided by the user of the image to tag it */76protected String name;7778/** The colours for each of the corners */79protected Color[] corners;80/** The OpenGL max filter */81private int filter = SGL.GL_LINEAR;8283/** True if the image should be flipped vertically */84private boolean flipped;85/** The transparent colour set if any */86private Color transparent;8788/**89* Create a texture as a copy of another90*91* @param other The other texture to copy92*/93protected Image(Image other) {94this.width = other.getWidth();95this.height = other.getHeight();96this.texture = other.texture;97this.textureWidth = other.textureWidth;98this.textureHeight = other.textureHeight;99this.ref = other.ref;100this.textureOffsetX = other.textureOffsetX;101this.textureOffsetY = other.textureOffsetY;102103centerX = width / 2;104centerY = height / 2;105inited = true;106}107108/**109* Cloning constructor - only used internally.110*/111protected Image() {112}113114/**115* Creates an image using the specified texture116*117* @param texture118* The texture to use119*/120public Image(Texture texture) {121this.texture = texture;122ref = texture.toString();123clampTexture();124}125126/**127* Create an image based on a file at the specified location128*129* @param ref130* The location of the image file to load131* @throws SlickException132* Indicates a failure to load the image133*/134public Image(String ref) throws SlickException {135this(ref, false);136}137138/**139* Create an image based on a file at the specified location140*141* @param ref The location of the image file to load142* @param trans The color to be treated as transparent143* @throws SlickException Indicates a failure to load the image144*/145public Image(String ref, Color trans) throws SlickException {146this(ref, false, FILTER_LINEAR, trans);147}148149/**150* Create an image based on a file at the specified location151*152* @param ref The location of the image file to load153* @param flipped True if the image should be flipped on the y-axis on load154* @throws SlickException Indicates a failure to load the image155*/156public Image(String ref, boolean flipped) throws SlickException {157this(ref, flipped, FILTER_LINEAR);158}159160/**161* Create an image based on a file at the specified location162*163* @param ref The location of the image file to load164* @param flipped True if the image should be flipped on the y-axis on load165* @param filter The filtering method to use when scaling this image166* @throws SlickException Indicates a failure to load the image167*/168public Image(String ref, boolean flipped, int filter) throws SlickException {169this(ref, flipped, filter, null);170}171172/**173* Create an image based on a file at the specified location174*175* @param ref The location of the image file to load176* @param flipped True if the image should be flipped on the y-axis on load177* @param f The filtering method to use when scaling this image178* @param transparent The color to treat as transparent179* @throws SlickException Indicates a failure to load the image180*/181public Image(String ref, boolean flipped, int f, Color transparent) throws SlickException {182this.filter = f == FILTER_LINEAR ? SGL.GL_LINEAR : SGL.GL_NEAREST;183this.transparent = transparent;184this.flipped = flipped;185186try {187this.ref = ref;188int[] trans = null;189if (transparent != null) {190trans = new int[3];191trans[0] = (int) (transparent.r * 255);192trans[1] = (int) (transparent.g * 255);193trans[2] = (int) (transparent.b * 255);194}195texture = InternalTextureLoader.get().getTexture(ref, flipped, filter, trans);196} catch (IOException e) {197Log.error(e);198throw new SlickException("Failed to load image from: "+ref, e);199}200}201202/**203* Set the image filtering to be used. This will cause the image204* to be reloaded.205*206* @param f The filtering mode to use207* @throws SlickException Indicates a failure to revalidate the image source208*/209public void setFilter(int f) throws SlickException {210this.filter = f == FILTER_LINEAR ? SGL.GL_LINEAR : SGL.GL_NEAREST;211212try {213int[] trans = null;214if (transparent != null) {215trans = new int[3];216trans[0] = (int) (transparent.r * 255);217trans[1] = (int) (transparent.g * 255);218trans[2] = (int) (transparent.b * 255);219}220texture = InternalTextureLoader.get().getTexture(ref, flipped, filter, trans);221} catch (IOException e) {222Log.error(e);223throw new SlickException("Failed to load image from: "+ref, e);224}225}226/**227* Create an empty image228*229* @param width The width of the image230* @param height The height of the image231* @throws SlickException Indicates a failure to create the underlying resource232*/233public Image(int width, int height) throws SlickException {234ref = super.toString();235236try {237texture = InternalTextureLoader.get().createTexture(width, height);238} catch (IOException e) {239Log.error(e);240throw new SlickException("Failed to create empty image "+width+"x"+height);241}242243init();244}245246/**247* Create an image based on a file at the specified location248*249* @param in The input stream to read the image from250* @param ref The name that should be assigned to the image251* @param flipped True if the image should be flipped on the y-axis on load252* @throws SlickException Indicates a failure to load the image253*/254public Image(InputStream in, String ref, boolean flipped) throws SlickException {255this(in, ref, flipped, FILTER_LINEAR);256}257258/**259* Create an image based on a file at the specified location260*261* @param in The input stream to read the image from262* @param ref The name that should be assigned to the image263* @param flipped True if the image should be flipped on the y-axis on load264* @param filter The filter to use when scaling this image265* @throws SlickException Indicates a failure to load the image266*/267public Image(InputStream in, String ref, boolean flipped,int filter) throws SlickException {268load(in, ref, flipped, filter, null);269}270271/**272* Create an image from a pixelData of pixels273*274* @param buffer The pixelData to use to create the image275*/276Image(ImageBuffer buffer) {277this(buffer, FILTER_LINEAR);278TextureImpl.bindNone();279}280281/**282* Create an image from a pixelData of pixels283*284* @param buffer The pixelData to use to create the image285* @param filter The filter to use when scaling this image286*/287Image(ImageBuffer buffer, int filter) {288this((ImageData) buffer, filter);289TextureImpl.bindNone();290}291292/**293* Create an image from a image data source294*295* @param data The pixelData to use to create the image296*/297public Image(ImageData data) {298this(data, FILTER_LINEAR);299}300301/**302* Create an image from a image data source. Note that this method uses303*304* @param data The pixelData to use to create the image305* @param f The filter to use when scaling this image306*/307public Image(ImageData data, int f) {308try {309this.filter = f == FILTER_LINEAR ? SGL.GL_LINEAR : SGL.GL_NEAREST;310texture = InternalTextureLoader.get().getTexture(data, this.filter);311ref = texture.toString();312} catch (IOException e) {313Log.error(e);314}315}316317/**318* Get the OpenGL image filter in use319*320* @return The filter for magnification321*/322public int getFilter() {323return filter;324}325326/**327* Get the reference to the resource this image was loaded from, if any. Note that328* this can be null in the cases where an image was programatically generated.329*330* @return The reference to the resource the reference was loaded from331*/332public String getResourceReference() {333return ref;334}335336/**337* Set the color of the given corner when this image is rendered. This is338* useful lots of visual effect but especially light maps339*340* @param corner The corner identifier for the corner to be set341* @param r The red component value to set (between 0 and 1)342* @param g The green component value to set (between 0 and 1)343* @param b The blue component value to set (between 0 and 1)344* @param a The alpha component value to set (between 0 and 1)345*/346public void setColor(int corner, float r, float g, float b, float a) {347if (corners == null) {348corners = new Color[] {new Color(1,1,1,1f),new Color(1,1,1,1f), new Color(1,1,1,1f), new Color(1,1,1,1f)};349}350351corners[corner].r = r;352corners[corner].g = g;353corners[corner].b = b;354corners[corner].a = a;355}356357/**358* Clamp the loaded texture to it's edges359*/360public void clampTexture() {361if (GLContext.getCapabilities().GL_EXT_texture_mirror_clamp) {362GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, EXTTextureMirrorClamp.GL_MIRROR_CLAMP_TO_EDGE_EXT);363GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, EXTTextureMirrorClamp.GL_MIRROR_CLAMP_TO_EDGE_EXT);364} else {365GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);366GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);367}368}369370/**371* Give this image a meaningful tagging name. Can be used as user data/identifier372* for the image.373*374* @param name The name to assign the image375*/376public void setName(String name) {377this.name = name;378}379380/**381* Return a meaningful tagging name that has been assigned to this image.382*383* @return A name or null if the name hasn't been set384*/385public String getName() {386return name;387}388389/**390* Get a graphics context that can be used to draw to this image391*392* @return The graphics context used to render to this image393* @throws SlickException Indicates a failure to create a graphics context394*/395public Graphics getGraphics() throws SlickException {396return GraphicsFactory.getGraphicsForImage(this);397}398399/**400* Load the image401*402* @param in The input stream to read the image from403* @param ref The name that should be assigned to the image404* @param flipped True if the image should be flipped on the y-axis on load405* @param f The filter to use when scaling this image406* @param transparent The color to treat as transparent407* @throws SlickException Indicates a failure to load the image408*/409private void load(InputStream in, String ref, boolean flipped, int f, Color transparent) throws SlickException {410this.filter = f == FILTER_LINEAR ? SGL.GL_LINEAR : SGL.GL_NEAREST;411412try {413this.ref = ref;414int[] trans = null;415if (transparent != null) {416trans = new int[3];417trans[0] = (int) (transparent.r * 255);418trans[1] = (int) (transparent.g * 255);419trans[2] = (int) (transparent.b * 255);420}421texture = InternalTextureLoader.get().getTexture(in, ref, flipped, filter, trans);422} catch (IOException e) {423Log.error(e);424throw new SlickException("Failed to load image from: "+ref, e);425}426}427428/**429* Bind to the texture of this image430*/431public void bind() {432texture.bind();433}434435/**436* Reinitialise internal data437*/438protected void reinit() {439inited = false;440init();441}442443/**444* Initialise internal data445*/446protected final void init() {447if (inited) {448return;449}450451inited = true;452if (texture != null) {453width = texture.getImageWidth();454height = texture.getImageHeight();455textureOffsetX = 0;456textureOffsetY = 0;457textureWidth = texture.getWidth();458textureHeight = texture.getHeight();459}460461initImpl();462463centerX = width / 2;464centerY = height / 2;465}466467/**468* Hook for subclasses to perform initialisation469*/470protected void initImpl() {471472}473474/**475* Draw this image at the current location476*/477public void draw() {478draw(0,0);479}480481/**482* Draw the image based on it's center483*484* @param x The x coordinate to place the image's center at485* @param y The y coordinate to place the image's center at486*/487public void drawCentered(float x, float y) {488draw(x-(getWidth()/2),y-(getHeight()/2));489}490491/**492* Draw this image at the specified location493*494* @param x The x location to draw the image at495* @param y The y location to draw the image at496*/497public void draw(float x, float y) {498init();499draw(x,y,width,height);500}501502/**503* Draw this image at the specified location504*505* @param x The x location to draw the image at506* @param y The y location to draw the image at507* @param filter The color to filter with when drawing508*/509public void draw(float x, float y, Color filter) {510init();511draw(x,y,width,height, filter);512}513514/**515* Draw this image as part of a collection of images516*517* @param x The x location to draw the image at518* @param y The y location to draw the image at519* @param width The width to render the image at520* @param height The height to render the image at521*/522public void drawEmbedded(float x,float y,float width,float height) {523init();524525if (corners == null) {526GL.glTexCoord2f(textureOffsetX, textureOffsetY);527GL.glVertex3f(x, y, 0);528GL.glTexCoord2f(textureOffsetX, textureOffsetY + textureHeight);529GL.glVertex3f(x, y + height, 0);530GL.glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY531+ textureHeight);532GL.glVertex3f(x + width, y + height, 0);533GL.glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY);534GL.glVertex3f(x + width, y, 0);535} else {536corners[TOP_LEFT].bind();537GL.glTexCoord2f(textureOffsetX, textureOffsetY);538GL.glVertex3f(x, y, 0);539corners[BOTTOM_LEFT].bind();540GL.glTexCoord2f(textureOffsetX, textureOffsetY + textureHeight);541GL.glVertex3f(x, y + height, 0);542corners[BOTTOM_RIGHT].bind();543GL.glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY544+ textureHeight);545GL.glVertex3f(x + width, y + height, 0);546corners[TOP_RIGHT].bind();547GL.glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY);548GL.glVertex3f(x + width, y, 0);549}550}551552/**553* Get the x offset in texels into the source texture554*555* @return The x offset556*/557public float getTextureOffsetX() {558init();559560return textureOffsetX;561}562563/**564* Get the y offset in texels into the source texture565*566* @return The y offset567*/568public float getTextureOffsetY() {569init();570571return textureOffsetY;572}573574/**575* Get the width in texels into the source texture576*577* @return The width578*/579public float getTextureWidth() {580init();581582return textureWidth;583}584585/**586* Get the height in texels into the source texture587*588* @return The height589*/590public float getTextureHeight() {591init();592593return textureHeight;594}595596/**597* Draw the image with a given scale598*599* @param x The x position to draw the image at600* @param y The y position to draw the image at601* @param scale The scaling to apply602*/603public void draw(float x,float y,float scale) {604init();605draw(x,y,width*scale,height*scale,Color.white);606}607608/**609* Draw the image with a given scale610*611* @param x The x position to draw the image at612* @param y The y position to draw the image at613* @param scale The scaling to apply614* @param filter The colour filter to adapt the image with615*/616public void draw(float x,float y,float scale,Color filter) {617init();618draw(x,y,width*scale,height*scale,filter);619}620621/**622* Draw this image at a specified location and size623*624* @param x625* The x location to draw the image at626* @param y627* The y location to draw the image at628* @param width629* The width to render the image at630* @param height631* The height to render the image at632*/633public void draw(float x,float y,float width,float height) {634init();635draw(x,y,width,height,Color.white);636}637638/**639* Draw this image at a specified location and size640*641* @param x The x location to draw the image at642* @param y The y location to draw the image at643* @param hshear The amount to shear the bottom points by horizontally644* @param vshear The amount to shear the right points by vertically645*/646public void drawSheared(float x,float y, float hshear, float vshear) {647Color.white.bind();648texture.bind();649650GL.glTranslatef(x, y, 0);651if (angle != 0) {652GL.glTranslatef(centerX, centerY, 0.0f);653GL.glRotatef(angle, 0.0f, 0.0f, 1.0f);654GL.glTranslatef(-centerX, -centerY, 0.0f);655}656657GL.glBegin(SGL.GL_QUADS);658init();659660GL.glTexCoord2f(textureOffsetX, textureOffsetY);661GL.glVertex3f(0, 0, 0);662GL.glTexCoord2f(textureOffsetX, textureOffsetY + textureHeight);663GL.glVertex3f(hshear, height, 0);664GL.glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY665+ textureHeight);666GL.glVertex3f(width + hshear, height + vshear, 0);667GL.glTexCoord2f(textureOffsetX + textureWidth, textureOffsetY);668GL.glVertex3f(width, vshear, 0);669GL.glEnd();670671if (angle != 0) {672GL.glTranslatef(centerX, centerY, 0.0f);673GL.glRotatef(-angle, 0.0f, 0.0f, 1.0f);674GL.glTranslatef(-centerX, -centerY, 0.0f);675}676GL.glTranslatef(-x, -y, 0);677}678679/**680* Draw this image at a specified location and size681*682* @param x The x location to draw the image at683* @param y The y location to draw the image at684* @param width The width to render the image at685* @param height The height to render the image at686* @param filter The color to filter with while drawing687*/688public void draw(float x,float y,float width,float height,Color filter) {689if (alpha != 1) {690if (filter == null) {691filter = Color.white;692}693694filter = new Color(filter);695filter.a *= alpha;696}697if (filter != null) {698filter.bind();699}700701texture.bind();702703GL.glTranslatef(x, y, 0);704if (angle != 0) {705GL.glTranslatef(centerX, centerY, 0.0f);706GL.glRotatef(angle, 0.0f, 0.0f, 1.0f);707GL.glTranslatef(-centerX, -centerY, 0.0f);708}709710GL.glBegin(SGL.GL_QUADS);711drawEmbedded(0,0,width,height);712GL.glEnd();713714if (angle != 0) {715GL.glTranslatef(centerX, centerY, 0.0f);716GL.glRotatef(-angle, 0.0f, 0.0f, 1.0f);717GL.glTranslatef(-centerX, -centerY, 0.0f);718}719GL.glTranslatef(-x, -y, 0);720}721722/**723* Draw this image at a specified location and size as a silohette724*725* @param x The x location to draw the image at726* @param y The y location to draw the image at727* @param width The width to render the image at728* @param height The height to render the image at729*/730public void drawFlash(float x,float y,float width,float height) {731drawFlash(x,y,width,height,Color.white);732}733734/**735* Set the centre of the rotation when applied to this image736*737* @param x The x coordinate of center of rotation relative to the top left corner of the image738* @param y The y coordinate of center of rotation relative to the top left corner of the image739*/740public void setCenterOfRotation(float x, float y) {741centerX = x;742centerY = y;743}744745/**746* Get the x component of the center of rotation of this image747*748* @return The x component of the center of rotation749*/750public float getCenterOfRotationX() {751init();752753return centerX;754}755756/**757* Get the y component of the center of rotation of this image758*759* @return The y component of the center of rotation760*/761public float getCenterOfRotationY() {762init();763764return centerY;765}766767/**768* Draw this image at a specified location and size as a silohette769*770* @param x The x location to draw the image at771* @param y The y location to draw the image at772* @param width The width to render the image at773* @param height The height to render the image at774* @param col The color for the sillohette775*/776public void drawFlash(float x,float y,float width,float height, Color col) {777init();778779col.bind();780texture.bind();781782if (GLContext.getCapabilities().GL_EXT_secondary_color) {783GL.glEnable(EXTSecondaryColor.GL_COLOR_SUM_EXT);784EXTSecondaryColor.glSecondaryColor3ubEXT((byte)(col.r * 255),785(byte)(col.g * 255),786(byte)(col.b * 255));787}788789GL.glTexEnvi(SGL.GL_TEXTURE_ENV, SGL.GL_TEXTURE_ENV_MODE, SGL.GL_MODULATE);790791GL.glTranslatef(x, y, 0);792if (angle != 0) {793GL.glTranslatef(centerX, centerY, 0.0f);794GL.glRotatef(angle, 0.0f, 0.0f, 1.0f);795GL.glTranslatef(-centerX, -centerY, 0.0f);796}797798GL.glBegin(SGL.GL_QUADS);799drawEmbedded(0,0,width,height);800GL.glEnd();801802if (angle != 0) {803GL.glTranslatef(centerX, centerY, 0.0f);804GL.glRotatef(-angle, 0.0f, 0.0f, 1.0f);805GL.glTranslatef(-centerX, -centerY, 0.0f);806}807GL.glTranslatef(-x, -y, 0);808809if (GLContext.getCapabilities().GL_EXT_secondary_color) {810GL.glDisable(EXTSecondaryColor.GL_COLOR_SUM_EXT);811}812}813814/**815* Draw this image at a specified location and size in a white silohette816*817* @param x The x location to draw the image at818* @param y The y location to draw the image at819*/820public void drawFlash(float x,float y) {821drawFlash(x,y,getWidth(),getHeight());822}823824/**825* Set the angle to rotate this image to. The angle will be normalized to826* be 0 <= angle < 360. The image will be rotated around its center.827*828* @param angle The angle to be set829*/830public void setRotation(float angle) {831this.angle = angle % 360.0f;832}833834/**835* Get the current angle of rotation for this image.836* The image will be rotated around its center.837*838* @return The current angle.839*/840public float getRotation() {841return angle;842}843844/**845* Get the alpha value to use when rendering this image846*847* @return The alpha value to use when rendering this image848*/849public float getAlpha() {850return alpha;851}852853/**854* Set the alpha value to use when rendering this image855*856* @param alpha The alpha value to use when rendering this image857*/858public void setAlpha(float alpha) {859this.alpha = alpha;860}861862/**863* Add the angle provided to the current rotation. The angle will be normalized to864* be 0 <= angle < 360. The image will be rotated around its center.865*866* @param angle The angle to add.867*/868public void rotate(float angle) {869this.angle += angle;870this.angle = this.angle % 360;871}872873/**874* Get a sub-part of this image. Note that the create image retains a reference to the875* image data so should anything change it will affect sub-images too.876*877* @param x The x coordinate of the sub-image878* @param y The y coordinate of the sub-image879* @param width The width of the sub-image880* @param height The height of the sub-image881* @return The image represent the sub-part of this image882*/883public Image getSubImage(int x,int y,int width,int height) {884init();885886float newTextureOffsetX = ((x / (float) this.width) * textureWidth) + textureOffsetX;887float newTextureOffsetY = ((y / (float) this.height) * textureHeight) + textureOffsetY;888float newTextureWidth = ((width / (float) this.width) * textureWidth);889float newTextureHeight = ((height / (float) this.height) * textureHeight);890891Image sub = new Image();892sub.inited = true;893sub.texture = this.texture;894sub.textureOffsetX = newTextureOffsetX;895sub.textureOffsetY = newTextureOffsetY;896sub.textureWidth = newTextureWidth;897sub.textureHeight = newTextureHeight;898899sub.width = width;900sub.height = height;901sub.ref = ref;902sub.centerX = width / 2;903sub.centerY = height / 2;904905return sub;906}907908/**909* Draw a section of this image at a particular location and scale on the screen910*911* @param x The x position to draw the image912* @param y The y position to draw the image913* @param srcx The x position of the rectangle to draw from this image (i.e. relative to this image)914* @param srcy The y position of the rectangle to draw from this image (i.e. relative to this image)915* @param srcx2 The x position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)916* @param srcy2 The t position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)917*/918public void draw(float x, float y, float srcx, float srcy, float srcx2, float srcy2) {919draw(x,y,x+width,y+height,srcx,srcy,srcx2,srcy2);920}921922/**923* Draw a section of this image at a particular location and scale on the screen924*925* @param x The x position to draw the image926* @param y The y position to draw the image927* @param x2 The x position of the bottom right corner of the drawn image928* @param y2 The y position of the bottom right corner of the drawn image929* @param srcx The x position of the rectangle to draw from this image (i.e. relative to this image)930* @param srcy The y position of the rectangle to draw from this image (i.e. relative to this image)931* @param srcx2 The x position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)932* @param srcy2 The t position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)933*/934public void draw(float x, float y, float x2, float y2, float srcx, float srcy, float srcx2, float srcy2) {935draw(x,y,x2,y2,srcx,srcy,srcx2,srcy2,Color.white);936}937938/**939* Draw a section of this image at a particular location and scale on the screen940*941* @param x The x position to draw the image942* @param y The y position to draw the image943* @param x2 The x position of the bottom right corner of the drawn image944* @param y2 The y position of the bottom right corner of the drawn image945* @param srcx The x position of the rectangle to draw from this image (i.e. relative to this image)946* @param srcy The y position of the rectangle to draw from this image (i.e. relative to this image)947* @param srcx2 The x position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)948* @param srcy2 The t position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)949* @param filter The colour filter to apply when drawing950*/951public void draw(float x, float y, float x2, float y2, float srcx, float srcy, float srcx2, float srcy2, Color filter) {952init();953954if (alpha != 1) {955if (filter == null) {956filter = Color.white;957}958959filter = new Color(filter);960filter.a *= alpha;961}962filter.bind();963texture.bind();964965GL.glTranslatef(x, y, 0);966if (angle != 0) {967GL.glTranslatef(centerX, centerY, 0.0f);968GL.glRotatef(angle, 0.0f, 0.0f, 1.0f);969GL.glTranslatef(-centerX, -centerY, 0.0f);970}971972GL.glBegin(SGL.GL_QUADS);973drawEmbedded(0,0,x2-x,y2-y,srcx,srcy,srcx2,srcy2);974GL.glEnd();975976if (angle != 0) {977GL.glTranslatef(centerX, centerY, 0.0f);978GL.glRotatef(-angle, 0.0f, 0.0f, 1.0f);979GL.glTranslatef(-centerX, -centerY, 0.0f);980}981GL.glTranslatef(-x, -y, 0);982983// GL.glBegin(SGL.GL_QUADS);984// drawEmbedded(x,y,x2,y2,srcx,srcy,srcx2,srcy2);985// GL.glEnd();986}987988/**989* Draw a section of this image at a particular location and scale on the screen, while this990* is image is "in use", i.e. between calls to startUse and endUse.991*992* @param x The x position to draw the image993* @param y The y position to draw the image994* @param x2 The x position of the bottom right corner of the drawn image995* @param y2 The y position of the bottom right corner of the drawn image996* @param srcx The x position of the rectangle to draw from this image (i.e. relative to this image)997* @param srcy The y position of the rectangle to draw from this image (i.e. relative to this image)998* @param srcx2 The x position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)999* @param srcy2 The t position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)1000*/1001public void drawEmbedded(float x, float y, float x2, float y2, float srcx, float srcy, float srcx2, float srcy2) {1002drawEmbedded(x,y,x2,y2,srcx,srcy,srcx2,srcy2,null);1003}10041005/**1006* Draw a section of this image at a particular location and scale on the screen, while this1007* is image is "in use", i.e. between calls to startUse and endUse.1008*1009* @param x The x position to draw the image1010* @param y The y position to draw the image1011* @param x2 The x position of the bottom right corner of the drawn image1012* @param y2 The y position of the bottom right corner of the drawn image1013* @param srcx The x position of the rectangle to draw from this image (i.e. relative to this image)1014* @param srcy The y position of the rectangle to draw from this image (i.e. relative to this image)1015* @param srcx2 The x position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)1016* @param srcy2 The t position of the bottom right cornder of rectangle to draw from this image (i.e. relative to this image)1017* @param filter The colour filter to apply when drawing1018*/1019public void drawEmbedded(float x, float y, float x2, float y2, float srcx, float srcy, float srcx2, float srcy2, Color filter) {1020if (filter != null) {1021filter.bind();1022}10231024float mywidth = x2 - x;1025float myheight = y2 - y;1026float texwidth = srcx2 - srcx;1027float texheight = srcy2 - srcy;10281029float newTextureOffsetX = (((srcx) / (width)) * textureWidth)1030+ textureOffsetX;1031float newTextureOffsetY = (((srcy) / (height)) * textureHeight)1032+ textureOffsetY;1033float newTextureWidth = ((texwidth) / (width))1034* textureWidth;1035float newTextureHeight = ((texheight) / (height))1036* textureHeight;10371038GL.glTexCoord2f(newTextureOffsetX, newTextureOffsetY);1039GL.glVertex3f(x,y, 0.0f);1040GL.glTexCoord2f(newTextureOffsetX, newTextureOffsetY1041+ newTextureHeight);1042GL.glVertex3f(x,(y + myheight), 0.0f);1043GL.glTexCoord2f(newTextureOffsetX + newTextureWidth,1044newTextureOffsetY + newTextureHeight);1045GL.glVertex3f((x + mywidth),(y + myheight), 0.0f);1046GL.glTexCoord2f(newTextureOffsetX + newTextureWidth,1047newTextureOffsetY);1048GL.glVertex3f((x + mywidth),y, 0.0f);1049}10501051/**1052* Get the width of this image1053*1054* @return The width of this image1055*/1056public int getWidth() {1057init();1058return width;1059}10601061/**1062* Get the height of this image1063*1064* @return The height of this image1065*/1066public int getHeight() {1067init();1068return height;1069}10701071/**1072* Get a copy of this image. This is a shallow copy and does not1073* duplicate image adata.1074*1075* @return The copy of this image1076*/1077public Image copy() {1078init();1079return getSubImage(0,0,width,height);1080}10811082/**1083* Get a scaled copy of this image with a uniform scale1084*1085* @param scale The scale to apply1086* @return The new scaled image1087*/1088public Image getScaledCopy(float scale) {1089init();1090return getScaledCopy((int) (width*scale),(int) (height*scale));1091}10921093/**1094* Get a scaled copy of this image1095*1096* @param width The width of the copy1097* @param height The height of the copy1098* @return The new scaled image1099*/1100public Image getScaledCopy(int width, int height) {1101init();1102Image image = copy();1103image.width = width;1104image.height = height;1105image.centerX = width / 2;1106image.centerY = height / 2;1107return image;1108}11091110/**1111* Make sure the texture cordinates are inverse on the y axis1112*/1113public void ensureInverted() {1114if (textureHeight > 0) {1115textureOffsetY = textureOffsetY + textureHeight;1116textureHeight = -textureHeight;1117}1118}11191120/**1121* Get a copy image flipped on potentially two axis1122*1123* @param flipHorizontal True if we want to flip the image horizontally1124* @param flipVertical True if we want to flip the image vertically1125* @return The flipped image instance1126*/1127public Image getFlippedCopy(boolean flipHorizontal, boolean flipVertical) {1128init();1129Image image = copy();11301131if (flipHorizontal) {1132image.textureOffsetX = textureOffsetX + textureWidth;1133image.textureWidth = -textureWidth;1134}1135if (flipVertical) {1136image.textureOffsetY = textureOffsetY + textureHeight;1137image.textureHeight = -textureHeight;1138}11391140return image;1141}11421143/**1144* End the use of this sprite sheet and release the lock.1145*1146* @see #startUse1147*/1148public void endUse() {1149if (inUse != this) {1150throw new RuntimeException("The sprite sheet is not currently in use");1151}1152inUse = null;1153GL.glEnd();1154}11551156/**1157* Start using this sheet. This method can be used for optimal rendering of a collection1158* of sprites from a single sprite sheet. First, startUse(). Then render each sprite by1159* calling renderInUse(). Finally, endUse(). Between start and end there can be no rendering1160* of other sprites since the rendering is locked for this sprite sheet.1161*/1162public void startUse() {1163if (inUse != null) {1164throw new RuntimeException("Attempt to start use of a sprite sheet before ending use with another - see endUse()");1165}1166inUse = this;1167init();11681169Color.white.bind();1170texture.bind();1171GL.glBegin(SGL.GL_QUADS);1172}11731174/**1175* @see java.lang.Object#toString()1176*/1177public String toString() {1178init();11791180return "[Image "+ref+" "+width+"x"+height+" "+textureOffsetX+","+textureOffsetY+","+textureWidth+","+textureHeight+"]";1181}11821183/**1184* Get the OpenGL texture holding this image1185*1186* @return The OpenGL texture holding this image1187*/1188public Texture getTexture() {1189return texture;1190}11911192/**1193* Set the texture used by this image1194*1195* @param texture The texture used by this image1196*/1197public void setTexture(Texture texture) {1198this.texture = texture;1199reinit();1200}12011202/**1203* Translate an unsigned int into a signed integer1204*1205* @param b The byte to convert1206* @return The integer value represented by the byte1207*/1208private int translate(byte b) {1209if (b < 0) {1210return 256 + b;1211}12121213return b;1214}12151216/**1217* Get the colour of a pixel at a specified location in this image1218*1219* @param x The x coordinate of the pixel1220* @param y The y coordinate of the pixel1221* @return The Color of the pixel at the specified location1222*/1223public Color getColor(int x, int y) {1224if (pixelData == null) {1225pixelData = texture.getTextureData();1226}12271228int xo = (int) (textureOffsetX * texture.getTextureWidth());1229int yo = (int) (textureOffsetY * texture.getTextureHeight());12301231if (textureWidth < 0) {1232x = xo - x;1233} else {1234x = xo + x;1235}12361237if (textureHeight < 0) {1238y = yo - y;1239} else {1240y = yo + y;1241}12421243int offset = x + (y * texture.getTextureWidth());1244offset *= texture.hasAlpha() ? 4 : 3;12451246if (texture.hasAlpha()) {1247return new Color(translate(pixelData[offset]),translate(pixelData[offset+1]),1248translate(pixelData[offset+2]),translate(pixelData[offset+3]));1249} else {1250return new Color(translate(pixelData[offset]),translate(pixelData[offset+1]),1251translate(pixelData[offset+2]));1252}1253}12541255/**1256* Check if this image has been destroyed1257*1258* @return True if this image has been destroyed1259*/1260public boolean isDestroyed() {1261return destroyed;1262}12631264/**1265* Destroy the image and release any native resources.1266* Calls on a destroyed image have undefined results1267*1268* @throws SlickException Indicates a failure to release resources on the graphics card1269*/1270public void destroy() throws SlickException {1271if (isDestroyed()) {1272return;1273}12741275destroyed = true;1276texture.release();1277GraphicsFactory.releaseGraphicsForImage(this);1278}12791280/**1281* Flush the current pixel data to force a re-read next update1282*/1283public void flushPixelData() {1284pixelData = null;1285}1286}128712881289