Updates: October 8, 2016 (New format)
This is a fairly big update, first before I mention the updates. I had to change the encoding format Galkon originally had to support hd sprites. So if you use this version to read your past archives it won't work but I'll show you how to convert it takes 2 seconds.
- Support for HD sprites
- Pixels are now packed instead of the entire sprite data
- Better compression
- The program now ignores the color rgb (255, 0, 255) or hexadecimal 0xFF00FF which is the Pink color and makes it transparent by default.
Next update or so I'll let you pick your own transparency colors.
- The program now creates only 1 image archive (it used to create a .dat and .idx file, but I merged the two for convenience so you don't have all of these files)
- All image formats are supported (PNG, JPG, GIF, Tiff, Bmp, Webp, Bpg, Enif) They all get converted to PNG for transparency reasons when you dump the sprites.
- You can now change the offsets of a sprite (x or y)
- You don't even have to use this for RSPS anymore, if you wanted you can use this to create sprite archives for other games well or for general image compression.
Archives made pre version 1.45 will not work with this update follow these instructions to convert over.
To convert pre-1.45 archives
Use version 1.44 which can be found
here, load up your archives and dump your sprites as images into a directory. Then use version 1.45 found
here to load up the sprites then you can create new archives (you can now delete the sprites.idx since its no longer used)
To make the new format work with your client
Go to your SpriteLoader class and replace it with this.
Code:
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
/**
* The class that loads sprites from a custom sprites archive.
*
* @author Vult-R
*/
public final class SpriteLoader {
private static final Logger logger = Logger.getLogger(SpriteLoader.class.getName());
public static SpriteLoader[] cache;
public static Sprite[] sprites;
public static int totalSprites;
private int id = -1;
private String name = "name";
private int offsetX = 0;
private int offsetY = 0;
private int width;
private int height;
private int[] pixels;
public static void load() {
Buffer data = new Buffer(FileUtility.readFile(SignLink.findcachedir() + "sprites.dat"));
try(DataInputStream dataFile = new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(data.buffer)))) {
int totalSprites = dataFile.readInt();
logger.info("Sprites Loaded: " + totalSprites);
if (cache == null) {
cache = new SpriteLoader[totalSprites];
sprites = new Sprite[totalSprites];
}
for (int index = 0; index < totalSprites; index++) {
SpriteLoader loader = cache[index] = SpriteLoader.decode(dataFile);
sprites[index] = new Sprite(loader);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static SpriteLoader decode(DataInputStream dat) throws IOException {
SpriteLoader loader = new SpriteLoader();
while (true) {
byte opcode = dat.readByte();
if (opcode == 0) {
return loader;
} else if (opcode == 1) {
loader.id = dat.readShort();
} else if (opcode == 2) {
loader.name = dat.readUTF();
} else if (opcode == 3) {
loader.width = dat.readShort();
} else if (opcode == 4) {
loader.height = dat.readShort();
} else if (opcode == 5) {
loader.offsetX = dat.readShort();
} else if (opcode == 6) {
loader.offsetY = dat.readShort();
} else if (opcode == 7) {
int indexLength = dat.readInt();
int[] pixels = new int[indexLength];
for (int i = 0; i < pixels.length; i++) {
pixels[i] = dat.readInt();
}
loader.pixels = pixels;
}
}
}
public static BufferedImage convert(BufferedImage src, int bufImgType) {
BufferedImage img= new BufferedImage(src.getWidth(), src.getHeight(), bufImgType);
Graphics2D g2d= img.createGraphics();
g2d.drawImage(src, 0, 0, null);
g2d.dispose();
return img;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getOffsetX() {
return offsetX;
}
public void setOffsetX(int offsetX) {
this.offsetX = offsetX;
}
public int getOffsetY() {
return offsetY;
}
public void setOffsetY(int offsetY) {
this.offsetY = offsetY;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int[] getPixels() {
return pixels;
}
public void setPixels(int[] pixels) {
this.pixels = pixels;
}
}
Go to your sprite class add this
Code:
public Sprite(SpriteLoader loader) {
this.width = loader.getWidth();
this.height = loader.getHeight();
this.drawOffsetX = loader.getOffsetX();
this.drawOffsetY = loader.getOffsetY();
this.raster = loader.getPixels();
this.setTransparency(255, 0, 255);
}
Change the variables to your naming if you have errors. For transparency to work make sure you did the HD Sprites tutorial in your client which can be found here.
https://www.rune-server.org/runescape-development/rs2-client/tutorials/316016-client-hd-sprites-support.html (most clients have this nowadays)
I did test this a 100 times, before I released.
nothing to special to show but most of the sprites used in this screenshot have pink backgrounds.
Download
version 1.45 (newer format)
bsp_1.45
version 1.44 (old format works with galkons format)
bsp_1.44