Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Microsoft.VisualBasic;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Data;
- using System.Diagnostics;
- public class Form1
- {
- Image[] SpriteArray;
- private void Form1_Load(System.Object sender, System.EventArgs e)
- {
- string FileName = Constants.vbNullString;
- MessageBox.Show("Please locate and open your Tibia.spr file", ".spr Reader");
- var _with1 = OpenFileDialog1;
- _with1.Filter = "Spr file (*.spr)|*.spr|" + "All files|*.*";
- if (_with1.ShowDialog == System.Windows.Forms.DialogResult.OK) {
- FileName = _with1.FileName;
- } else {
- Application.Exit();
- }
- using (System.IO.BinaryReader reader = new System.IO.BinaryReader(System.IO.File.OpenRead(FileName))) {
- int SpriteVersion = reader.ReadUInt32();
- int NumberOfSprites = reader.ReadUInt16();
- SpriteArray = Array.CreateInstance(typeof(Image), NumberOfSprites);
- //even though sprite IDs start at 2, I started the loop at 0 for the array
- for (int i = 0; i <= NumberOfSprites - 1; i++) {
- Bitmap Sprite = new Bitmap(32, 32);
- //this is the bitmap we'll be storing the sprite in, notice it's 32x32 pixels
- System.Drawing.Imaging.BitmapData SpriteData = Sprite.LockBits(new Rectangle(0, 0, 32, 32), Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb);
- //here is where we lock the bits of the bitmap, since sprites are ARGB-based we have to make sure the format is the same
- byte[] ByteArray = new byte[4097];
- //this is the array we'll store the pixel data in, even though a 32x32 pixel sprite has 1024 pixels we have to store 4 bits for each pixel (alpha, red, green blue)
- ushort currentPixel = 0;
- long targetOffset = 0;
- //to begin, we have to seek to the sprite to get it's offset
- //since I started the loop at 0 I have to add 1 because the sprites aren't 0-based (however, keep in mind sprite IDs begin at 2, not 1)
- //each sprite is offset by 4 because the offset is stored as an integer (4 bytes)
- //and the +6 is to skip past the SpriteVersion and NumberOfSprites
- reader.BaseStream.Seek(6 + (i + 1) * 4, System.IO.SeekOrigin.Begin);
- //now that we're at our desired sprite we have to read it's offset address (reader.ReadUInt32()), then we seek the returned value +3
- //the +3 is to skip the transparent pixels' color, since we don't need it
- reader.BaseStream.Seek(reader.ReadUInt32() + 3, System.IO.SeekOrigin.Begin);
- //it seems as though sprite file for clients 7.40 and lower return a out-of-bounds position on the last sprite
- //I didn't take the time to figure out why, but you can easily counter this problem with this line of code making sure the position
- //of the stream is not beyond the file's size
- if (reader.BaseStream.Position >= reader.BaseStream.Length)
- continue;
- targetOffset = reader.BaseStream.Position + reader.ReadUInt16();
- //the ReadUInt16() returns the size of the sprite
- if (reader.BaseStream.Position < 9)
- continue;
- //if we encounter a blank sprite it actually sets the position of the stream at byte-5 and that's actually the beginning of the NumberOfSprites value, so we use Continue For to skip this sprite
- while (reader.BaseStream.Position < targetOffset) {
- ushort transparentPixels = reader.ReadUInt16();
- ushort coloredPixels = reader.ReadUInt16();
- if ((transparentPixels > 1024) || (coloredPixels > 1024))
- break; // TODO: might not be correct. Was : Exit While
- //as an extra padding of protection, I make sure the number of transparent and/or colored pixels doesn't exceed the size of a sprite
- currentPixel += transparentPixels;
- for (int x = 0; x <= coloredPixels - 1; x++) {
- //here's where we get different from TibiaAPI's SetPixel()
- //remember what I said about us storing all four pixel colors? here's where we use it
- int CurrentOffset = (currentPixel * 4);
- //this goes to the offset in ByteArray where the current pixel we're reading is going to be located
- //pixel data is actually stored in reverse in bitmaps, so we write the Alpha value first (255) at the end of the pixel data, followed by Red before it, then Green before Red, and finally Blue at the beginning of the pixel data.
- ByteArray[CurrentOffset + 3] = 255;
- ByteArray[CurrentOffset + 2] = reader.ReadByte();
- ByteArray[CurrentOffset + 1] = reader.ReadByte();
- ByteArray[CurrentOffset] = reader.ReadByte();
- currentPixel += 1;
- }
- }
- System.Runtime.InteropServices.Marshal.Copy(ByteArray, 0, SpriteData.Scan0, 4096);
- //here is where we copy the data in the byte array (where we stored the pixel data for the sprite) into our BitmapData
- Sprite.UnlockBits(SpriteData);
- //then we unlock the sprite so that we can use it
- SpriteArray[i] = Sprite;
- //here I store the sprite in an Image array
- }
- }
- }
- public Form1()
- {
- Load += Form1_Load;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement