Advertisement
TizzyT

GVD2PNG -TizzyT

Jun 9th, 2015
455
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 9.94 KB | None | 0 0
  1. Imports System.IO
  2. Imports System.Drawing
  3.  
  4. Module Module1
  5.     Sub Main()
  6.         Console.WriteLine(vbTab & "GVD2PNG v1.2 - TizzyT")
  7.         If My.Application.CommandLineArgs.Count = 0 Then Console.ReadKey()
  8.         For Each arg As String In My.Application.CommandLineArgs
  9.             Try
  10.                 Dim File As String = System.IO.Path.GetFileNameWithoutExtension(arg)
  11.                 Dim path As String = System.IO.Path.GetDirectoryName(arg).Trim("\")
  12.                 Dim CrntGVD As New GVD(arg)
  13.                 CrntGVD.SavePNGs(path & "\" & File)
  14.             Catch ex As Exception
  15.                 Console.WriteLine("Failed to process " & vbCrLf & arg & vbCrLf & ex.Message)
  16.                 Console.ReadKey()
  17.             End Try
  18.         Next
  19.     End Sub
  20. End Module
  21.  
  22. Public Class GVD
  23.     ' Static magic
  24.     Private Shared ReadOnly GVEW0100JPEG0100() As Byte = _
  25.         New Byte() {71, 86, 69, 87, 48, 49, 48, 48, 74, 80, 69, 71, 48, 49, 48, 48}
  26.     Private GVD_Width As Integer
  27.     Private GVD_Height As Integer
  28.     ' Static BLK_
  29.     Private Shared ReadOnly BLK_() As Byte = New Byte() {66, 76, 75, 95}
  30.     Private DataBaseCount As Integer
  31.     ' Static value 1
  32.     Private Shared ReadOnly Static1() As Byte = New Byte() {0, 0, 0, 1, 0, 0, 0, 0}
  33.     Private DataBase As New List(Of Entries)
  34.     Private LengthOfEntries As Integer
  35.     Private GVDreader As FileStream
  36.     ' Structure for Each GVD image Entry
  37.     Private Structure Entries
  38.         Dim PosX As Integer
  39.         Dim PosY As Integer
  40.         Dim Level As Integer
  41.         Dim ImageLength As Integer
  42.         Dim PadLength As Integer
  43.         Dim Width As Integer
  44.         Dim Height As Integer
  45.         Dim Image As Bitmap
  46.         Public Sub New(ByVal OldEntry As Entries, ByVal Image As Bitmap)
  47.             PosX = OldEntry.PosX
  48.             PosY = OldEntry.PosY
  49.             Level = OldEntry.Level
  50.             ImageLength = OldEntry.ImageLength
  51.             PadLength = OldEntry.PadLength
  52.             Width = OldEntry.Width
  53.             Height = OldEntry.Height
  54.             Me.Image = Image
  55.         End Sub
  56.     End Structure
  57.     ' Contructor
  58.     Public Sub New(ByVal SrcGVD As String)
  59.         If IO.File.Exists(SrcGVD) Then 'Checks to see if file actually exists
  60.             GVDreader = New FileStream(SrcGVD, FileMode.Open, FileAccess.Read)
  61.             Dim Magic(15) As Byte
  62.             GVDreader.Read(Magic, 0, 16)
  63.             'Checks for expected Magic
  64.             If Magic.SequenceEqual(GVEW0100JPEG0100) Then
  65.                 'Gets GVD header info
  66.                 If ProcessHeader() Then
  67.                     GVDreader.Seek(16, SeekOrigin.Current)
  68.                     ' Process and populate Entries into Entries List
  69.                     For i = 1 To DataBaseCount
  70.                         ProcessEntry(i)
  71.                     Next
  72.                     ' Check for second occurence of BLK bytes
  73.                     Dim BLKcheck(3) As Byte
  74.                     GVDreader.Read(BLKcheck, 0, 4)
  75.                     If BLKcheck.SequenceEqual(BLK_) Then
  76.                         ' Skip Length of embedded images and static value
  77.                         GVDreader.Seek(12, SeekOrigin.Current)
  78.                         ' Redo all processed Entries by adding their respective image (fix this)
  79.                         For i = 0 To DataBase.Count - 1
  80.                             Dim Data(DataBase(i).ImageLength - 1) As Byte
  81.                             GVDreader.Read(Data, 0, DataBase(i).ImageLength)
  82.                             Using meh As New MemoryStream(Data)
  83.                                 Dim sup As New Bitmap(meh)
  84.                                 DataBase(i) = New Entries(DataBase(i), sup)
  85.                                 meh.Close()
  86.                                 meh.Dispose()
  87.                             End Using
  88.                             'Skip the length of the image pad to beginning of next image
  89.                             GVDreader.Seek(DataBase(i).PadLength, SeekOrigin.Current)
  90.                         Next
  91.                     Else
  92.                         Throw New Exception("Expect BLK_ not found")
  93.                     End If
  94.                     Erase BLKcheck
  95.                 Else
  96.                     Throw New Exception("Unknow error trying to read GVD Header" & vbCrLf & _
  97.                                         "Possible BLK bytes not present where expected")
  98.                 End If
  99.             Else
  100.                 Throw New Exception("Invalid GVD file (Magic mismatch)")
  101.             End If
  102.         Else
  103.             Throw New Exception("GVD file at location doesn't exist")
  104.         End If
  105.     End Sub
  106.     ' Used to verify and grab information from GVD
  107.     Private Function ProcessHeader() As Boolean
  108.         Try
  109.             ' Get GVD width
  110.             Dim Width(3) As Byte
  111.             GVDreader.Read(Width, 0, 4)
  112.             Array.Reverse(Width)
  113.             GVD_Width = BitConverter.ToInt32(Width, 0)
  114.             Erase Width
  115.             ' Get GVD height
  116.             Dim Height(3) As Byte
  117.             GVDreader.Read(Height, 0, 4)
  118.             Array.Reverse(Height)
  119.             GVD_Height = BitConverter.ToInt32(Height, 0)
  120.             Erase Height
  121.             ' Check for expected BLK bytes
  122.             Dim BLKcheck(3) As Byte
  123.             GVDreader.Read(BLKcheck, 0, 4)
  124.             ' Check if expected BLK bytes are present
  125.             If Not BLKcheck.SequenceEqual(BLK_) Then Return False
  126.             Erase BLKcheck
  127.             ' Get number of DataBase Entries
  128.             Dim DBcount(3) As Byte
  129.             GVDreader.Read(DBcount, 0, 4)
  130.             Array.Reverse(DBcount)
  131.             DataBaseCount = (BitConverter.ToInt32(DBcount, 0) - 8) / 32
  132.             Erase DBcount
  133.         Catch ex As Exception
  134.             Return False ' Something went wrong
  135.         End Try
  136.         Return True
  137.     End Function
  138.     ' Used to read from file and process an Entry
  139.     Private Sub ProcessEntry(ByVal Entry As Integer)
  140.         Dim Temp As New Entries ' Working Entry
  141.         ' Get Horizontal Position
  142.         Dim PosX(3) As Byte
  143.         GVDreader.Read(PosX, 0, 4)
  144.         Array.Reverse(PosX)
  145.         Temp.PosX = BitConverter.ToInt32(PosX, 0)
  146.         Erase PosX
  147.         ' Get Vertical Posoition
  148.         Dim PosY(3) As Byte
  149.         GVDreader.Read(PosY, 0, 4)
  150.         Array.Reverse(PosY)
  151.         Temp.PosY = BitConverter.ToInt32(PosY, 0)
  152.         Erase PosY
  153.         ' Get Layer Level
  154.         Dim LvL(3) As Byte
  155.         GVDreader.Read(LvL, 0, 4)
  156.         Array.Reverse(LvL)
  157.         Temp.Level = BitConverter.ToInt32(LvL, 0)
  158.         Erase LvL
  159.         ' Get length of image (in bytes)
  160.         Dim ImgLen(3) As Byte
  161.         GVDreader.Read(ImgLen, 0, 4)
  162.         Array.Reverse(ImgLen)
  163.         Temp.ImageLength = BitConverter.ToInt32(ImgLen, 0)
  164.         Erase ImgLen
  165.         ' Get length of padding (in bytes)
  166.         Dim PadLen(3) As Byte
  167.         GVDreader.Read(PadLen, 0, 4)
  168.         Array.Reverse(PadLen)
  169.         Temp.PadLength = BitConverter.ToInt32(PadLen, 0)
  170.         Erase PadLen
  171.         ' Skip "Not Used" (4 bytes)
  172.         GVDreader.Seek(4, SeekOrigin.Current)
  173.         ' Get Width of image
  174.         Dim Width(3) As Byte
  175.         GVDreader.Read(Width, 0, 4)
  176.         Array.Reverse(Width)
  177.         Temp.Width = BitConverter.ToInt32(Width, 0)
  178.         Erase Width
  179.         ' Get height of image
  180.         Dim Height(3) As Byte
  181.         GVDreader.Read(Height, 0, 4)
  182.         Array.Reverse(Height)
  183.         Temp.Height = BitConverter.ToInt32(Height, 0)
  184.         Erase Height
  185.         ' Add working Entry to Entries List
  186.         DataBase.Add(Temp)
  187.     End Sub
  188.     ' Returns byte array as a bitmap
  189.     Private Function Bytes2Bitmap(ByVal ArrayData() As Byte) As Bitmap
  190.         Dim bm As Bitmap
  191.         Using ms As New MemoryStream(ArrayData)
  192.             bm = New Bitmap(ms)
  193.             ms.Close()
  194.             ms.Dispose()
  195.         End Using
  196.         Return bm
  197.     End Function
  198.     ' Saves the PNGs for each layer
  199.     Public Sub SavePNGs(ByVal Location As String)
  200.         Dim LayerRes() As Size = CalcRes(GVD_Width, GVD_Height)
  201.         Dim Layers(LayerRes.Length - 1) As EditableBitmap
  202.         For i = 0 To Layers.Length - 1
  203.             Layers(i) = New EditableBitmap(LayerRes(i).Width, LayerRes(i).Height)
  204.         Next
  205.         For Each GVD As Entries In DataBase
  206.             Layers(GVD.Level).Draw(GVD.Image, GVD.PosX * 256, GVD.PosY * 256, GVD.Width, GVD.Height)
  207.         Next
  208.         For i = 0 To Layers.Length - 1
  209.             Layers(i).Save(Location & "_Layer" & i & ".png", Imaging.ImageFormat.Png)
  210.         Next
  211.     End Sub
  212.     ' Calculate the multiple resolutions for the GVD
  213.     Private Function CalcRes(ByVal X As Integer, ByVal Y As Integer) As Size()
  214.         Dim Res(CalcLevel(X, Y)) As Size
  215.         For i = 0 To Res.Length - 1
  216.             Res(i) = New Size(X, Y)
  217.             X = Math.Round(X / 2)
  218.             Y = Math.Round(Y / 2)
  219.         Next
  220.         Return Res
  221.     End Function
  222.     ' Given a resolution return how many levels are needed
  223.     Private Function CalcLevel(ByVal X As Integer, Y As Integer) As Integer
  224.         CalcLevel = 0
  225.         While X > 256 OrElse Y > 256
  226.             X = Math.Round(X / 2)
  227.             Y = Math.Round(Y / 2)
  228.             CalcLevel += 1
  229.         End While
  230.     End Function
  231.     ' Bitmap class with embedded graphics object for editing
  232.     Public Class EditableBitmap
  233.         Private BM As Bitmap
  234.         Private G As Graphics
  235.         Sub New(ByVal ResX As Integer, ByVal ResY As Integer)
  236.             BM = New Bitmap(ResX, ResY)
  237.             G = Graphics.FromImage(BM)
  238.         End Sub
  239.         Public Sub Draw(ByVal Image As Bitmap, _
  240.                         ByVal PosX As Integer, _
  241.                         ByVal PosY As Integer, _
  242.                         ByVal SizeX As Integer, _
  243.                         ByVal SizeY As Integer)
  244.             G.DrawImage(Image, PosX, PosY, SizeX, SizeY)
  245.         End Sub
  246.         Public Sub Save(ByVal Location As String, ByVal Format As Imaging.ImageFormat)
  247.             BM.Save(Location, Format)
  248.         End Sub
  249.     End Class
  250. End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement