Advertisement
Guest User

Untitled

a guest
Jun 29th, 2013
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.90 KB | None | 0 0
  1. using Microsoft.VisualBasic;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Data;
  6. using System.Diagnostics;
  7. public class Form1
  8. {
  9.  
  10. Image[] SpriteArray;
  11. private void Form1_Load(System.Object sender, System.EventArgs e)
  12. {
  13. string FileName = Constants.vbNullString;
  14. MessageBox.Show("Please locate and open your Tibia.spr file", ".spr Reader");
  15. var _with1 = OpenFileDialog1;
  16. _with1.Filter = "Spr file (*.spr)|*.spr|" + "All files|*.*";
  17. if (_with1.ShowDialog == System.Windows.Forms.DialogResult.OK) {
  18. FileName = _with1.FileName;
  19. } else {
  20. Application.Exit();
  21. }
  22.  
  23. using (System.IO.BinaryReader reader = new System.IO.BinaryReader(System.IO.File.OpenRead(FileName))) {
  24. int SpriteVersion = reader.ReadUInt32();
  25. int NumberOfSprites = reader.ReadUInt16();
  26. SpriteArray = Array.CreateInstance(typeof(Image), NumberOfSprites);
  27.  
  28. //even though sprite IDs start at 2, I started the loop at 0 for the array
  29. for (int i = 0; i <= NumberOfSprites - 1; i++) {
  30. Bitmap Sprite = new Bitmap(32, 32);
  31. //this is the bitmap we'll be storing the sprite in, notice it's 32x32 pixels
  32. System.Drawing.Imaging.BitmapData SpriteData = Sprite.LockBits(new Rectangle(0, 0, 32, 32), Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppArgb);
  33. //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
  34. byte[] ByteArray = new byte[4097];
  35. //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)
  36. ushort currentPixel = 0;
  37. long targetOffset = 0;
  38.  
  39. //to begin, we have to seek to the sprite to get it's offset
  40. //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)
  41. //each sprite is offset by 4 because the offset is stored as an integer (4 bytes)
  42. //and the +6 is to skip past the SpriteVersion and NumberOfSprites
  43. reader.BaseStream.Seek(6 + (i + 1) * 4, System.IO.SeekOrigin.Begin);
  44.  
  45. //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
  46. //the +3 is to skip the transparent pixels' color, since we don't need it
  47. reader.BaseStream.Seek(reader.ReadUInt32() + 3, System.IO.SeekOrigin.Begin);
  48.  
  49. //it seems as though sprite file for clients 7.40 and lower return a out-of-bounds position on the last sprite
  50. //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
  51. //of the stream is not beyond the file's size
  52. if (reader.BaseStream.Position >= reader.BaseStream.Length)
  53. continue;
  54.  
  55. targetOffset = reader.BaseStream.Position + reader.ReadUInt16();
  56. //the ReadUInt16() returns the size of the sprite
  57. if (reader.BaseStream.Position < 9)
  58. continue;
  59. //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
  60.  
  61. while (reader.BaseStream.Position < targetOffset) {
  62. ushort transparentPixels = reader.ReadUInt16();
  63. ushort coloredPixels = reader.ReadUInt16();
  64. if ((transparentPixels > 1024) || (coloredPixels > 1024))
  65. break; // TODO: might not be correct. Was : Exit While
  66. //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
  67. currentPixel += transparentPixels;
  68. for (int x = 0; x <= coloredPixels - 1; x++) {
  69. //here's where we get different from TibiaAPI's SetPixel()
  70. //remember what I said about us storing all four pixel colors? here's where we use it
  71. int CurrentOffset = (currentPixel * 4);
  72. //this goes to the offset in ByteArray where the current pixel we're reading is going to be located
  73. //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.
  74. ByteArray[CurrentOffset + 3] = 255;
  75. ByteArray[CurrentOffset + 2] = reader.ReadByte();
  76. ByteArray[CurrentOffset + 1] = reader.ReadByte();
  77. ByteArray[CurrentOffset] = reader.ReadByte();
  78. currentPixel += 1;
  79. }
  80. }
  81.  
  82. System.Runtime.InteropServices.Marshal.Copy(ByteArray, 0, SpriteData.Scan0, 4096);
  83. //here is where we copy the data in the byte array (where we stored the pixel data for the sprite) into our BitmapData
  84. Sprite.UnlockBits(SpriteData);
  85. //then we unlock the sprite so that we can use it
  86. SpriteArray[i] = Sprite;
  87. //here I store the sprite in an Image array
  88. }
  89. }
  90. }
  91. public Form1()
  92. {
  93. Load += Form1_Load;
  94. }
  95. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement