I can't seem to figure out what I did wrong

Answered I can't seem to figure out what I did wrong

  • Friday, August 17, 2012 5:48 PM
     
      Has Code

    Hello again!

    I'm currently creating an application based on ideas from the game Minecraft; an application that lets you store step-by-step building instructions for a certain construction (trees (by this I mean those you find in forests)) to a file on your computer, so you can pick it back up later.

    Here's the clue - the file I'm saving ranges from 197,179 bytes to 211,714 bytes (depending on the amount of steps ("layers") on the blueprint.

    This file can be divided into 6 fundamental pieces:

    • The first is the name of the project and ranges from byte 0 to 255 in the file.
    • The second is the project's author name and ranges from byte 256 to 511.
    • The third is a picture preview of the project and ranges from byte 512 to 197,119.
    • The fourth is a "flag" byte determining the type of tree the we're talking about. 0 = Oak tree, 1 = Spruce tree, 2 = Birch tree and 3 = Jungle tree. This is a single byte located at 197,120.
    • The fifth is a byte telling how many layers the tree consists of. This value ranges from 0 to 255 and is a single byte located at index 197,121.
    • The sixth are the building layers, each representing 57 bytes. There can be up to 256 layers. Ranges from 197,122 and on to the end of the file.

    The application saves and opens the file in this format using the following code:

    Open:

            If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
                TextBox1.Text = OpenFileDialog1.FileName
    
                Dim treeData As New TreeInfo(My.Computer.FileSystem.ReadAllBytes(OpenFileDialog1.FileName))
    
                Dim treeName As String = treeData.BytesToString(treeData.GetBytesFromIndex(0, 256))
                TextBox2.Text = treeName
                Dim treeAuth As String = treeData.BytesToString(treeData.GetBytesFromIndex(256, 256))
                TextBox3.Text = treeAuth
                Dim treePrev As Bitmap = treeData.BytesToBitmap(treeData.GetBytesFromIndex(512, 196608), New Size(256, 256))
                treePrev.RotateFlip(RotateFlipType.Rotate90FlipNone)
                PictureBox1.Image = treePrev
                Dim treeType As TreeType = CType(treeData.GetBytesFromIndex(197120, 1)(0), TreeType)
                Application.DoEvents()
                Dim treeStpi As Byte = treeData.GetBytesFromIndex(197121, 1)(0)
    
                Dim TMP_treestep As Integer = 197122
    
                Dim treeSteps(treeStpi - 1) As TreeBlueprint
                For i = 0 To treeStpi - 1
                    'If entry 29 is 255 and all others 0, this is part of the trunk with no leaves.
                    'If entry 35 is 4 and all others 0, something went horribly wrong when saving.
                    treeSteps(i) = New TreeBlueprint(treeData.GetBytesFromIndex(TMP_treestep, 57), treeType)
                    TMP_treestep += 57
                Next
    
                mTreeSteps = treeSteps
    
                PictureBox2.Image = treeSteps(0).ToBitmap()
    
                If mTreeSteps.Count > 1 Then Button2.Enabled = True
            End If

    Save (TrBps is an array of TreeBlueprint (see below)):

            If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim saveArray(197121) As Byte
                Dim lbt As Integer = 512
    
                Dim newName As String = TextBox2.Text.PadRight(256, " "c)
                Dim newAuth As String = TextBox3.Text.PadRight(256, " "c)
    
                For i = 0 To 255
                    saveArray(i) = Convert.ToByte(newName(i))
                Next
                For i = 0 To 255
                    saveArray(i + 256) = Convert.ToByte(newAuth(i))
                Next
    
                Dim pbbitmap As New Bitmap(PictureBox1.Image)
                For i = 0 To 255
                    For j = 0 To 255
                        saveArray(lbt) = pbbitmap.GetPixel(i, j).R
                        lbt += 1
                        saveArray(lbt) = pbbitmap.GetPixel(i, j).G
                        lbt += 1
                        saveArray(lbt) = pbbitmap.GetPixel(i, j).B
                        lbt += 1
                    Next
                Next
    
                saveArray(197120) = CByte(curTreetype)
                lbt += 1
    
                saveArray(197121) = CByte(Label5.Text)
                lbt += 1
    
                For i = 0 To TrBps.Count - 1
                    ReDim Preserve saveArray(saveArray.Count + 56)
                    For Each SaveByte As Byte In TrBps(i).GetBytesForSaving()
                        saveArray(lbt) = SaveByte
                        lbt += 1
                    Next
                Next
    
                My.Computer.FileSystem.WriteAllBytes(SaveFileDialog1.FileName, saveArray, False)
    
            End If

    How tree block data is converted to bytes (saving):

            Dim nState(56) As Byte
            Dim curByte As Byte = 0
            For i = 0 To 55
                nState(i) = 0
    
                nState(i) += CByte(64 * State(curByte))
                curByte += 1
                nState(i) += CByte(16 * State(curByte))
                curByte += 1
                nState(i) += CByte(4 * State(curByte))
                curByte += 1
                nState(i) += State(curByte)
                curByte += 1
            Next
    
            nState(56) += CByte(64 * State(curByte))
    
            ReDim Preserve TrBps(TrBps.Count)
            TrBps(TrBps.Count - 1) = New TreeBlueprint(nState, curTreetype)
            Label5.Text = (CInt(Label5.Text) + 1).ToString()
            If Label5.Text = "256" Then Button2.Enabled = False

    As you can see from this code I'm using several custom classes. I'm not bothering to post them out here in this topic, but you can download the project at the bottom of this post. They're located at the bottom of the Form1.vb file.

    On to the actual problem:

    I've been struggling with, either, how the file is saved, how it's loaded or how a blueprint layer is rendered into a picture (TreeBlueprint.ToBitmap()).

    I'm saving a tree that looks like this:

    And when I load it up again it looks like this:

    Notice the big difference in the tree blueprint grid to the right - many of the cells are shifted.

    I'm wondering what I've overseen in my code. It could be anything that has to do with saving, loading or rendering. I would really appreciate if anyone was willing to take a look at it, for I'm completely stuck.

    Here is the project download link:
    http://mol.b2910.ftp.sh:8080/24396Hidden/VisualBasicNet/McTreeSched.zip

    To make this work you also need the following file:
    http://mol.b2910.ftp.sh:8080/24396Hidden/VisualBasicNet/tree.png

    Click in the box saying Tree preview when you make a tree and open this file.

    INFO: The file host was down for updates from 6:31 PM to 6:38 PM GMT on Aug 17, if you tried to download then, try again now. Sorry for this, but just noticed crucial updates to the host was neccessary D:

    Thank you a lot for your help, even if you just try to figure it out.

    Ask me if you have any questions.

    Thank you,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

    • Edited by bilde2910 Friday, August 17, 2012 6:48 PM
    •  

All Replies

  • Sunday, August 19, 2012 7:38 PM
     
     

    Any chance I could get a helping hand on this?
    No one replied in 2 days :(

    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

  • Sunday, August 19, 2012 7:42 PM
    Moderator
     
     

    Without a deep investigation into your problem, you say the problem is that many of the cells are shifted, and this may because you are storing whatever values that pertain to those cell in an array, and when accessing that array you may have somewhere in your code forgotten that the first index in a list/array is zero, which means the highest index in the array/list is the .count property minus one.

    btw, impressive topic ;-)

    Notice how the "misdrawn cells" are all shifted down one extra cooridinate?


    If you want something you've never had, you need to do something you've never done.



  • Sunday, August 19, 2012 7:56 PM
    Moderator
     
     
    I also want to suggest, if your problem persists to be difficult to find, comment each line of your source explaining what you intended to do(and post it here), it may help to easier reveal the problem.

    If you want something you've never had, you need to do something you've never done.

  • Sunday, August 19, 2012 8:45 PM
     
     
    In your save routine, you have these lines of code that lead me to believe lbt is expected to be in sync with the values 197120 and 197121, as the next lines after these update bytes using lbt.
     
    saveArray(197120) = CByte(curTreetype)
    lbt += 1
     
    saveArray(197121) = CByte(Label5.Text)
    lbt += 1
     
    Are you sure about the value of "lbt" before the loop in the save code (For i = 0 to TrBps.Count - 1)?  If I look at your code correctly, the value at this point should be 66048.

    --
    Mike
  • Sunday, August 19, 2012 9:51 PM
     
     
    Are you sure about the value of "lbt" before the loop in the save code (For i = 0 to TrBps.Count - 1)?  If I look at your code correctly, the value at this point should be 66048.

    This line is in the Load
         Dim TMP_treestep As Integer = 197122
    but there is no equivalent in the save.

  • Monday, August 20, 2012 5:47 AM
    Moderator
     
     
    Just out of curiosity, what is the format for the "mct" file format, is it your own, or is there a binary specification somewhere that I can look at?

    If you want something you've never had, you need to do something you've never done.


  • Monday, August 20, 2012 5:48 AM
     
     

    Thank you all for the replies :)

    @Paul Ishak:

    I don't think I've forgotten that .Count is first index 0, as the picture part works all fine, as with the other parts. The only thing that's going wrong are the blueprint layers (the grid). And yes, I noticed that the cells are also shifted down.

    I will comment each of the lines and reupload the project, but I'll first do that in some 6 hours because I'm going to school soon. Do you want me to comment on every line in the whole project, or just in spesific ones? Also, thanks (@impressive topic)!

    @Family Tree Mike:

    Yes indeed, lbt is a value indicating which byte index to next save at. But you're wrong in that the value is 66048:

    Screenshot (value is 197120)

    @Acamar:

    The equivalent in saving is lbt.

    Thanks all for the replies (again), will look more into this after school!

    Sincerely yours,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

    • Edited by bilde2910 Monday, August 20, 2012 5:49 AM Typo
    •  
  • Monday, August 20, 2012 5:53 AM
    Moderator
     
     
     Do you want me to comment on every line in the whole project, or just in spesific ones?
    I would say comment in the areas that are most likely related to your error, most likely being the areas of save file/ load file. But if you feel so inclined to comment all of your code, it may help you gain a perspective to what you have so far, and some insight to optimize your code as well. Sometimes I find that if I have an error, and I go back and comment my code, the error will reveal itself to me(this is of course totally backwards to 'planning a project')

    If you want something you've never had, you need to do something you've never done.


  • Monday, August 20, 2012 9:47 AM
    Moderator
     
      Has Code

    Try this file format for your file:

    Example Usage:

    Option Strict On
    Imports System.IO
    Public Class Form2
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            'Make sure your form has a background image!
            '
            '
            '
            '
            'Generate some dummy Layer Data
            Dim LayerCount As Integer = 22
            'Create a byte array for holding 22 layers of data at 57 bytes per layer
            Dim Layers22((LayerCount * 57) - 1) As Byte
            'randomize the timer
            Randomize()
            'Create a random number generator
            Dim R As New Random
            'Iterate through each byte in the layers22 array
            For I = 0 To (LayerCount * 57) - 1
                'assign each element in the array a random bye
                Layers22(I) = CByte(R.Next(0, 256))
                'Next
            Next
            'Create a new MCTFile
            Dim A As New MCTFile("Test Project22", "Paul Ishak", Me.BackgroundImage, MCTFile.TreeType.Birch, Layers22)
            'Save the file to the desktop
            A.SaveFile(My.Computer.FileSystem.SpecialDirectories.Desktop & "\test.MCT")
            'verify the properties of the file
            'Unicode byte length of the project name string
            MsgBox(A.File.LengthOfProjectName)
            'project name
            MsgBox(A.File.ProjectName)
            'Unicode byte length of the project author name
            MsgBox(A.File.LengthOfAuthorName)
            'project author name
            MsgBox(A.File.ProjectAuthorname)
            'byte length of the preview picture
            MsgBox(A.File.LegnthOfPreviewPicture)
            'test the picture
            PictureBox1.BackgroundImage = Image.FromStream(New MemoryStream(A.File.PreviewPicture))
            PictureBox1.BackgroundImageLayout = ImageLayout.Stretch
            'tree type
            MsgBox(A.File.TreeType)
            'layer count
            MsgBox(A.File.LayerCount)
            'Total bytes in the layerdata array
            MsgBox(A.File.LayerData.Count)
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            'Make sure your form has a background image!
            '
            '
            '
            '
            'Generate some dummy data, different than the data we saved in button1
            Dim nineLayers((9 * 57)) As Byte
            Randomize()
            Dim R As New Random
            For I = 0 To (9 * 57) - 1
                nineLayers(I) = CByte(R.Next(0, 256))
            Next
            'create a new MCTFile
            Dim A As New MCTFile("Test Project9", "Some Dude", Me.BackgroundImage, MCTFile.TreeType.Birch, nineLayers)
            'Overwrite all the data we just created by opening a file
            A.OpenFile(My.Computer.FileSystem.SpecialDirectories.Desktop & "\test.MCT")
            'verify the properties of the file
            'Unicode byte length of the project name string
            MsgBox(A.File.LengthOfProjectName)
            'project name
            MsgBox(A.File.ProjectName)
            'Unicode byte length of the project author name
            MsgBox(A.File.LengthOfAuthorName)
            'project author name
            MsgBox(A.File.ProjectAuthorname)
            'byte length of the preview picture
            MsgBox(A.File.LegnthOfPreviewPicture)
            'test the picture
            PictureBox1.BackgroundImage = Image.FromStream(New MemoryStream(A.File.PreviewPicture))
            PictureBox1.BackgroundImageLayout = ImageLayout.Stretch
            'tree type
            MsgBox(A.File.TreeType)
            'layer count
            MsgBox(A.File.LayerCount)
            'Total bytes in the layerdata array
            MsgBox(A.File.LayerData.Count)
        End Sub
    End Class

    Class

    Option Strict On
    Imports System.Text
    Imports System.IO
    Public Class MCTFile
        Public File As New MCTStruct
        Class MCTStruct
    #Region "Private Properties"
            'Property Name                                      Data Length                             Offset to Data Formula
            '
            '
            '
            Public Property _LengthOfProjectName As UInt32 '   4 Bytes                                 0
            Public Property _ProjectName As String '           _LengthOfProjectName                    4
            Public Property _LengthOfAuthorName As UInt32 '    4 Bytes                                 4 + _LengthOfProjectName
            Public Property _ProjectAuthorname As String '     _LengthOfAuthorName                     4 + _LengthOfProjectName + 4 
            Public Property _LegnthOfPreviewPicture As UInt64 '8 Bytes                                 4 + _LengthOfProjectName + 4 + _LengthOfAuthorName
            Public Property _PreviewPicture As Byte() '        _LegnthOfPreviewPicture                 4 + _LengthOfProjectName + 4 + _LengthOfAuthorName + 8
            Public Property _TreeType As TreeType '            1 Byte                                  4 + _LengthOfProjectName + 4 + _LengthOfAuthorName + 8 + PicturePreview.Count
            Public Property _LayerCount As UInt32 '            4 Bytes                                 4 + _LengthOfProjectName + 4 + _LengthOfAuthorName + 8 + PicturePreview.Count + 1
            Public Property _LayerData As Byte() '             LayerCount * 57                         4 + _LengthOfProjectName + 4 + _LengthOfAuthorName + 8 + PicturePreview.Count + 1 + 4
    #End Region
    #Region "Public Properties"
            Public ReadOnly Property LengthOfProjectName As UInt32 'Dword
                Get
                    Return _LengthOfProjectName
                End Get
            End Property
            Public Property ProjectName As String
                Get
                    Return _ProjectName
                End Get
                Set(ByVal value As String)
                    'Set ProjectName, Calculate and set LengthOfProjectName
                    _ProjectName = value
                    _LengthOfProjectName = Convert.ToUInt32(Encoding.Unicode.GetBytes(value.ToCharArray).Count)
                End Set
            End Property
            Public ReadOnly Property LengthOfAuthorName As UInt32 'Dword
                Get
                    Return _LengthOfAuthorName
                End Get
            End Property
            Public Property ProjectAuthorname As String
                Get
                    Return _ProjectAuthorname
                End Get
                Set(ByVal value As String)
                    'Set Project Author Name, Calculate and set LengthOfauthorname
                    _ProjectAuthorname = value
                    _LengthOfAuthorName = Convert.ToUInt32(Encoding.Unicode.GetBytes(value.ToCharArray).Count)
                End Set
            End Property
            Public ReadOnly Property LegnthOfPreviewPicture As UInt64 'Qword
                Get
                    Return _LegnthOfPreviewPicture
                End Get
            End Property
            Public Property PreviewPicture As Byte()
                Get
                    Return _PreviewPicture
                End Get
                Set(ByVal value As Byte())
                    'Set bytes, set length of bytes
                    _PreviewPicture = value
                    _LegnthOfPreviewPicture = CULng(value.Count)
                End Set
            End Property
            Public Property TreeType As TreeType
                Get
                    Return _TreeType
                End Get
                Set(ByVal value As TreeType)
                    'set treetype(converts to predefined integer)
                    _TreeType = value
                End Set
            End Property
            Public ReadOnly Property LayerCount As UInt32 'Dword
                Get
                    Return _LayerCount
                End Get
            End Property
            Public Property LayerData As Byte()
                Get
                    Return _LayerData
                End Get
                Set(ByVal value As Byte())
                    'Set layer data, and count of layer data
                    _LayerData = value
                    _LayerCount = Convert.ToUInt32(value.Count \ 57)
                End Set
            End Property
    #End Region
        End Class
        Sub OpenFile(ByVal FileName As String)
            'Read all the bytes of the file
            Dim RawBytes As Byte() = My.Computer.FileSystem.ReadAllBytes(FileName)
            'calculate offsets, convert and set values
            Dim Offset1 As UInt32 = 0
            Me.File._LengthOfProjectName = BitConverter.ToUInt32(GetByteRange(RawBytes, Offset1, 4), 0)
            Dim Offset2 As UInt32 = 4
            Me.File._ProjectName = Encoding.Unicode.GetString(GetByteRange(RawBytes, Offset2, Me.File.LengthOfProjectName))
            Dim Offset3 As UInt32 = Convert.ToUInt32(Offset2 + Me.File.LengthOfProjectName)
            Me.File._LengthOfAuthorName = BitConverter.ToUInt32(GetByteRange(RawBytes, Offset3, 4), 0)
            Dim Offset4 As UInt32 = Convert.ToUInt32(Offset3 + 4)
            Me.File._ProjectAuthorname = Encoding.Unicode.GetString(GetByteRange(RawBytes, Offset4, Me.File.LengthOfAuthorName))
            Dim Offset5 As UInt32 = Convert.ToUInt32(Offset4 + Me.File.LengthOfAuthorName)
            Me.File._LegnthOfPreviewPicture = BitConverter.ToUInt64(GetByteRange(RawBytes, Offset5, 8), 0)
            Dim Offset6 As UInt32 = Convert.ToUInt32(Offset5 + 8)
            Me.File._PreviewPicture = GetByteRange(RawBytes, Offset6, Convert.ToUInt32(Me.File.LegnthOfPreviewPicture))
            Dim Offset7 As UInt32 = Convert.ToUInt32(Offset6 + Me.File.PreviewPicture.Count)
            Me.File._TreeType = CType(GetByteRange(RawBytes, Offset7, 1)(0), TreeType)
            Dim Offset8 As UInt32 = Convert.ToUInt32(Offset7 + 1)
            Dim LayerCountBytes As Byte() = GetByteRange(RawBytes, Offset8, 4)
            Me.File._LayerCount = BitConverter.ToUInt32(ReverseByteOrder(LayerCountBytes), 0)
            Dim Offset9 As UInt32 = Convert.ToUInt32(Offset8 + 4)
            Me.File._LayerData = GetByteRange(RawBytes, Offset9, CUInt((Me.File.LayerCount * 57)))
        End Sub
        Function ReverseByteOrder(ByVal Bytes() As Byte) As Byte()
            Dim Result(Bytes.Count - 1) As Byte
            Dim Counter As Integer = -1
            For I = Bytes.Count - 1 To 0 Step -1
                Counter = Counter + 1
                Result(Counter) = Bytes(I)
            Next
            Return Result
        End Function
        Sub SaveFile(ByVal FileName As String)
            My.Computer.FileSystem.WriteAllBytes(FileName, Me.GetBytes, False)
        End Sub
        Sub New(ByVal ProjectName As String, ByVal AuthorName As String, ByVal PreviewPicture As Image, ByVal TreeType As TreeType, ByVal LayerData As Byte())
            Me.File.ProjectName = ProjectName
            Me.File.ProjectAuthorname = AuthorName
            Me.File.PreviewPicture = ImageToByte(PreviewPicture)
            Me.File.TreeType = TreeType
            Me.File.LayerData = LayerData
        End Sub
        Function GetBytes() As Byte()
            Dim RawData As Byte() = BitConverter.GetBytes(File.LengthOfProjectName)
            RawData = CombineArrays(RawData, Encoding.Unicode.GetBytes(File.ProjectName.ToCharArray))
            RawData = CombineArrays(RawData, BitConverter.GetBytes(File.LengthOfAuthorName))
            RawData = CombineArrays(RawData, Encoding.Unicode.GetBytes(File.ProjectAuthorname.ToCharArray))
            RawData = CombineArrays(RawData, BitConverter.GetBytes(File.LegnthOfPreviewPicture))
            RawData = CombineArrays(RawData, File.PreviewPicture)
            RawData = CombineArrays(RawData, BitConverter.GetBytes(File.TreeType))
            RawData = CombineArrays(RawData, BitConverter.GetBytes(File.LayerCount))
            RawData = CombineArrays(RawData, File.LayerData)
            Return RawData
        End Function
        Function CombineArrays(ByVal Array1 As Byte(), ByVal Array2 As Byte()) As Byte()
            Dim Merged((Array1.Length + Array2.Length) - 1) As Byte
            Array1.CopyTo(Merged, 0)
            Array2.CopyTo(Merged, Array1.Length)
            Return Merged
        End Function
        Function GetByteRange(ByVal Bytes As Byte(), ByVal Offset As UInt32, ByVal Length As UInt32) As Byte()
            Dim Results As New List(Of Byte)
            For I As UInt32 = Offset To CUInt((Offset + Length) - 1)
                Results.Add(Bytes(CInt(I)))
            Next
            Return Results.ToArray
        End Function
        Public Shared Function ImageToByte(ByVal img As Image) As Byte()
            Dim imgStream As MemoryStream = New MemoryStream()
            img.Save(imgStream, System.Drawing.Imaging.ImageFormat.Jpeg)
            imgStream.Close()
            Dim byteArray As Byte() = imgStream.ToArray()
            imgStream.Dispose()
            Return byteArray
        End Function
        Enum TreeType
            Oak = 0
            Spruce = 1
            Birch = 2
            Jungle = 3
        End Enum
    End Class
    


    If you want something you've never had, you need to do something you've never done.



  • Monday, August 20, 2012 3:29 PM
     
     

    Updating the project with comments is now done.

    Here is the download link:
    http://mol.b2910.ftp.sh:8080/24396Hidden/VisualBasicNet/McTreeSched.zip

    @Paul Ishak:

    The version of the code you provided yielded the same results, but the cells were even more shifted. Might not be as obvious since you made a completely random blueprint, but when setting the blueprint to something organized it failed. But that might just as well be an error on my part.

    Sincerely yours,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

  • Monday, August 20, 2012 8:06 PM
    Moderator
     
     

    Please answer this:

    Is there a standard format that the "MCT" file must conform to? or are you using your own proposed format? Please let me know... I have been unable to locate the cause of your error as of yet, still looking(downloaded your commented source)

    took me a little while to realize that although when you create a new tree, you can edit the grid, that no first layer will exist until you add one. so I was stuck getting an error for that:

    Suggestion: add the first layer automatically when the user clicks "new tree".


    If you want something you've never had, you need to do something you've never done.




  • Tuesday, August 21, 2012 5:51 AM
     
     

    @Paul Ishak:

    Hmm.. somehow I've forgotten to say that. Let's clear things up :)

    1. The MCT format is a random file format I came up with, and I confirmed on fileinfo.com that no such format was being popularly used. This means it can be in any way I prefer.
    2. Yes, you have to add a layer first, thought that would be obvious (who creates a blueprint with no papers?), but I'll add in a warning dialogue. This will also ask you to get a picture for your blueprint.
    3. Your suggestion sounds good, but I don't really like the idea, because if the user wants the first layer changed (jungle trees spesifically have a trunk size of 2x2 logs instead of everything else with 1x1), that can't be done.

    I must though really say that I am a fan of your file format, since it opens up for a lot of possibilities (including being able to select any picture instead of it having to be 256x256), I'm sure I can add that in on my own. Also I like how you can have a file name nearly infinite (from a regular user's perspective, that is) but the name hardly exceeds 256 characters anyway. Same applies with author.

    I also noticed, if you take a look at the pictures above, the original holds 21 tiles, but the shifted one holds just 17. This is a loss of four.

    Also, if you shift the tiles back in place, this number increases to 5. The missing tiles after shifting are highlighted in blue.

    Missing tiles

    Thank you for willing to spend time on this! It's really encouraging me to work!

    Sincerely yours,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

    • Edited by bilde2910 Tuesday, August 21, 2012 5:53 AM
    •  
  • Tuesday, August 21, 2012 6:11 AM
    Moderator
     
     
    1. Yes, you have to add a layer first, thought that would be obvious (who creates a blueprint with no papers?), but I'll add in a warning dialogue. This will also ask you to get a picture for your blueprint.

    The main reason I bring this up, is because of 2 things:

    1.) You have not handled the error.

    2.) You still allow the user to edit a layer that has not been added.

    I am glad that you have seen some of the advantages to coming up with a planned file specification, and I think you should consider writing a class to hold and implement your specification, the main advantage being that once you have your class written right, you could easily port it to future versions of your program. As far as the 2x2 log issue goes, I would think that would be a matter of brush size in your designer(an not file format), seeing as trunk being 2x2 cells wide would still constitute a total of 4 cells.


    If you want something you've never had, you need to do something you've never done.

  • Tuesday, August 21, 2012 4:21 PM
     
     Answered Has Code

    I actually figured out what went wrong.

    Have a look at this. This code is for rendering the blueprint. See what I did wrong?

                    'Get what the fourth block is
                    'If the value is >= to 3
                    If tempbyte - 3 >= 0 Then
                        'Subtract this from the byte, and...
                        tempbyte = CByte(tempbyte - 3)
                        '... set the FOURTH block to be 3 ("nothing").
                        block(3) = 3
                    ElseIf tempbyte - 2 >= 0 Then
                        'If it's not >= 3, is it >= 2?
                        'If it is, subtract this from the byte and...
                        tempbyte = CByte(tempbyte - 2)
                        '... set the fourth block to be 2 (leaves).
                        block(2) = 2
                    ElseIf tempbyte - 1 >= 0 Then
                        'If it's not >= 2, is it >= 1?
                        'If it is, subtract this from the byte and...
                        tempbyte = CByte(tempbyte - 1)
                        '... set the fourth block to be 1 (log).
                        block(1) = 1
                    End If
                    'If it's not >= 1 at all, the fourth block should be 0 (a blank tile).
                    'This value was preset from the initialization of block, so do nothing.

    Somehow I had managed to try to update block number three and two instead of number four, depending on whether it was a leaf or log block.

    What's weird is that when I went about commenting every line, I didn't notice this. Perhaps I thought it was how it was supposed to be, without further insight?

    I would, though, like to thank you for your great help - I've taken your tips into consideration, have made an own class holding everything. You can have a look at it here:

    http://mol.b2910.ftp.sh:8080/24396Hidden/VisualBasicNet/MCT.vb

    I fixed the code and now it works great!

    Loading the file:

            'Get a file.
            If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim mctF As New MCT.MCTFile(OpenFileDialog1.FileName)
                TextBox2.Text = mctF.ProjectName
                TextBox3.Text = mctF.ProjectAuthor
                PictureBox1.Image = mctF.PreviewImage
                PictureBox2.Image = mctF.TreeLayers(0).ToBitmap()
            End If

    Saving the file:

            'Get where to save the file.
            If SaveFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
    'Will add in dialogs here (like "you must select a screenshot!") later.
    'PS. TrBps was changed from TreeBlueprint to MCT.MCTLayerBlueprint, if you were to wonder :) Dim mctF As New MCT.MCTFile(TextBox2.Text, TextBox3.Text, CType(DomainUpDown1.SelectedIndex, TreeType), PictureBox1.Image, TrBps) mctF.Save(SaveFileDialog1.FileName) End If

    I also thought about what you said - having a layer ready for the user. I initially misunderstood what you ment - but now I will now proceed in letting the user work on the first layer and if they need an additional one, they just press the "Add" button which I've renamed to "Add new layer".

    Thank you a LOT for your help!

    Sincerely yours,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

    • Marked As Answer by bilde2910 Tuesday, August 21, 2012 4:21 PM
    • Edited by bilde2910 Tuesday, August 21, 2012 4:28 PM
    •  
  • Tuesday, August 21, 2012 4:55 PM
    Moderator
     
     
    You're welcome, am glad you found your error!" You should update us on new downloads as this project advances. I find it very interesting.

    If you want something you've never had, you need to do something you've never done.

  • Tuesday, August 21, 2012 7:01 PM
     
     
    You're welcome, am glad you found your error!" You should update us on new downloads as this project advances. I find it very interesting.

    If you want something you've never had, you need to do something you've never done.

    Of course, I can put up downloads of this if you want!

    Are you gonna have any use of it, or just in matter of code?

    Sincerely yours,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

  • Tuesday, August 21, 2012 7:23 PM
    Moderator
     
     

    You're welcome, am glad you found your error!" You should update us on new downloads as this project advances. I find it very interesting.


    If you want something you've never had, you need to do something you've never done.

    Of course, I can put up downloads of this if you want!

    Are you gonna have any use of it, or just in matter of code?

    Sincerely yours,
    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!


    Well, I just find certain things to be interesting, and I'm interested to see where you go with it, as far as are you going to have a 3d rotatable preview? I just think its neat basically... ;)

    If you want something you've never had, you need to do something you've never done.

  • Wednesday, August 22, 2012 5:57 AM
     
     

    Well, I just find certain things to be interesting, and I'm interested to see where you go with it, as far as are you going to have a 3d rotatable preview? I just think its neat basically... ;)


    If you want something you've never had, you need to do something you've never done.

    Sure, I can see what I get :)

    But when it comes as far as to a 3D preview (that can be rotated), I don't think I would add that in. Well, if I could figure out how, that would be great, but I don't even have an idea where to begin. I'm sure I can google around, but how complex this code will be I'm not sure (probably very complicated).

    At any rate, I can add other functions, like I'm also considering a new file format (*.tbx), capable of holding 256 block types instead of 4.

    I'll see what I can reach :D

    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

  • Wednesday, August 22, 2012 6:07 AM
    Moderator
     
     
    You mean for creating things other than trees? nice, and you never know where it may lead you if you keep working on it. "mindcraft"

    If you want something you've never had, you need to do something you've never done.

  • Wednesday, August 22, 2012 1:16 PM
     
     
    You mean for creating things other than trees? nice, and you never know where it may lead you if you keep working on it. "mindcraft"

    If you want something you've never had, you need to do something you've never done.

    Nope, but seeing a lot of things being added to Minecraft trees nowadays...

    Minecraft 1.3.2
    + Added sideways logs in trees

    Minecraft 1.3.1
    + Added cocoa beans to jungles

    This causes me having to add in compability for sideways logs and cocoa beans, but there is not enough capacity in the code for more than 4 block types (because it saves 4 blocks per byte), but if I can reduce that to 1 block per byte (that's easy!) I can have 256 block types, which makes me more prepared for things to come in the future.

    Compability is a nice thing, but I openly forgot that there were more than logs and leaves on trees in Minecraft these days...

    But making things other than trees is also a tempting idea! Interesting if you want to make 3D pixel arts and similar stuff!

    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

    • Edited by bilde2910 Wednesday, August 22, 2012 1:18 PM
    •  
  • Wednesday, August 22, 2012 3:33 PM
    Moderator
     
      Has Code

    Take a look at this, I know its insane, but it could provide much room for forward compatibility, or give you further ideas at the least.

            Field Name             Data Type             Data Size                                Offset Formula
    
    MCTFileStructure_
    	LengthOfProjectName    UInt32                DWORD                                    Offset1  = 0
    	ProjectName            String                Byte(LengthOfProjectName-1)              Offset2  = Offset1  + 4
    	LengthOfAuthorName     UInt32                DWORD                                    Offset3  = Offset2  + LengthOfProjectName
    	AuthorName             String                Byte(LengthOfAuthorName-1)               Offset4  = Offset3  + 4 
    	LengthOfPicturePreview UInt64                QWORD                                    Offset5  = Offset4  + LengthOfAuthorName
    	PreviewPicture         Byte()                Byte(LengthOfPicturePreview-1)           Offset6  = Offset5  + 8  
    	TreeType               Byte                  1 Byte                                   Offset7  = Offset6  + LengthOfPicturePreview
    	LengthOfLayerData      UInt32                DWORD                                    Offset8  = Offset7  + 1
            LayerCollection        LayerCollection       Byte(LengthOfLayerData-1)                Offset9  = Offset8  + 4
            'You can change this to a collection of images...(similar to the layer collection and cell collection layout)
            LengthLogImage         UInt64                QWORD                                    Offset10 = Offset9  + LengthOfLayerData
            LogImage               Byte()                Byte(LengthLogImage-1)                   Offset11 = Offest10 + 8
            LengthOfLeavesImage    UInt64                QWORD                                    Offset12 = Offset11 + LengthLogImage
            LeavesImage            Byte()                Byte(LengthOfLeavesImage-1)              Offset13 = Offset12 + 8
    Structure
    LayerCollectionStructure
            LayerCount             UInt32                DWORD                                    Offset1 = 0
    	Layer1DataLength       UInt32                DWORD                                    Offset2 = Offset1 + 4
            Layer1Data             LayerData             Bytes(Layer1DataLength)                  Offset3 = Offset2 + 4
    	Layer2DataLength       UInt32                DWORD                                    Offset4 = Offset3 + Layer1DataLength
            Layer2Data             LayerData             Bytes(Layer2DataLength)                  Offset5 = Offset3 + 4
    	Layer2DataLength       UInt32                DWORD                                    Offset4 = Offset3 + Layer1DataLength
            Layer2Data             LayerData             Bytes(Layer2DataLength)                  Offset5 = Offset3 + 4
    	Layer2DataLength       UInt32                DWORD                                    Offset4 = Offset3 + Layer1DataLength
            Layer2Data             LayerData             Bytes(Layer2DataLength)                  Offset5 = Offset3 + 4
            etc...                                                                                etc...
    Structure
    LayerDataStructure
    	LayerNumber            UInt16                WORD                                     Offset1 = 0
            CellCollectionLength   UIint32               DWORD                                    Offset2 = Offset1 + 2
            CellCollectionData     CellCollectionData    Byte(CellCollectionLength)               Offset3 = Offset2 + CellCollectionLength
    Structure
    CellCollectionStructure
            CellCount              UInt32                DWORD                                    Offset1 = 0 
            Cell1DataLength        UInt32                DWORD                                    Offset2 = Offset1 + 4
            Cell1Data              Cell                  Byte(Cell1DataLength)                    Offset3 = Offset2 + 4 
            Cell2DataLength        UInt32                DWORD                                    Offset4 = Offset3 + Cell1DataLength
            Cell2Data              Cell                  Byte(Cell2DataLength)                    Offset5 = Offset4 + 4
            etc...                                                                                ect...
    Structure
    CellDataStructure
    	X                      UInt16                WORD                                     Offset1 = 0
            Y                      UInt16                WORD                                     Offset2 = Offset1 + 2
            TreeImageType          TreeImageType         1 Byte                                   Offset3 = Offset2 + 2
    Structure
    EnumTreeImageType
            1 = Log                Byte                  1 Byte                                   N/A
            2 = Leaves             Byte                  1 Byte                                   N/A
            'Forward Compatible up to 256 "image types"
    Enum
    EnumTreeType
    	1 = Oak                Byte                  1 Byte                                   N/A
            2 = Spruce             Byte                  1 Byte                                   N/A
            3 = Birch              Byte                  1 Byte                                   N/A
            4 = Jungle             Byte                  1 Byte                                   N/A
            'Forward Compatible up to 256 "image types"
    Enum


    If you want something you've never had, you need to do something you've never done.

  • Thursday, August 23, 2012 6:39 PM
     
     

    Took some time to consider what you've said above here...

    What you've written does allow for much better compability. But it's gonna take long to implement. Also a few questions - what are WORD, DWORD and QWORD?

    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

  • Thursday, August 23, 2012 6:46 PM
    Moderator
     
     

    Took some time to consider what you've said above here...

    What you've written does allow for much better compability. But it's gonna take long to implement. Also a few questions - what are WORD, DWORD and QWORD?

    - bilde2910


    If a post is helpful to you or solves a problem, remember to mark it as answer, propose it as answer or vote up.
    Check out my development so far!

    Those are terminology that refers to the a given datalength

    A byte is 8 bits, A word is 2 bytes, a double word (dword) is 4 bytes, a quadruple word(qword) is 8 bytes. and there also exists such thing as a nibble which is half a byte

    In hex a byte looks like this

    &hFF for instance

    but in binary, that would look like this:

    11111111b

    The reason different byte lengths are assigned to the fields is depending on the potential data size.

    If you use a single byte to describe the length of a field, you will top off at 256 characters.


    If you want something you've never had, you need to do something you've never done.


  • Thursday, August 23, 2012 6:49 PM
    Moderator
     
      Has Code

    I wrote the following class for the listed format, but I have not had an ability to test it due to not writing the rest of the program. but if you can figure out how to implement it, its yours ;)

    Option Strict On
    Imports System.Text
    Imports System.IO
    Public Class MCTClass
    #Region "Class Properties"
        Public File As FileData
    #End Region
        Sub New(ByVal Options As MCTData)
            'Will skip if called fromfile
            If Not CType(Options.InteralParameter, String) = "Skip Load" Then
                If Options.ProjectName = Nothing Then Throw New Exception("Project must have a Name.")
                If Options.AuthorName = Nothing Then Throw New Exception("Project must have an Author.")
                If Options.PreviewPicture Is Nothing Then Throw New Exception("Project must have a Preview Image.")
                If Options.TreeType = Nothing Then Throw New Exception("Project must have a Tree Image Family Type.")
                If Options.LayersCollection Is Nothing Then Throw New Exception("Project must have a Layer Collection.")
                If Options.LogImage Is Nothing Then Throw New Exception("Project must have a Log Image.")
                If Options.LeavesImage Is Nothing Then Throw New Exception("Project must have a Leaves Image.")
                If Options.ImageFormat Is Nothing Then Options.ImageFormat = Imaging.ImageFormat.Png
                Me.File.ProjectName = Options.ProjectName
                Me.File.Author = Options.AuthorName
                Me.File.PreviewPicture = Options.PreviewPicture
                Me.File.TreeType = Options.TreeType
                Me.File.LayerCollection = Options.LayersCollection
                Me.File.LogImage = Options.LogImage
                Me.File.LeavesImage = Options.LeavesImage
                Me.File.ImageFormat = Options.ImageFormat
            End If
        End Sub
        Public Shared Function FromFile(ByVal FileName As String) As MCTClass
            Dim BlankOptions As New MCTData
            BlankOptions.InteralParameter = CType("Skip Load", Object)
            Dim LoadedFile As New MCTClass(BlankOptions)
            Dim RawBytes As Byte() = My.Computer.FileSystem.ReadAllBytes(FileName)
    
            Dim Offset1 As UInt32 = 0 'Offset1  = 0
            Dim LengthOfProjectName As UInt32 = BitConverter.ToUInt32(GetByteRange(RawBytes, Offset1, DWORD), 0)
    
            Dim Offset2 As UInt32 = Offset1 + Convert.ToUInt32(DWORD) 'Offset2  = Offset1  + 4
            LoadedFile.File.ProjectName = Encoding.Unicode.GetString(GetByteRange(RawBytes, Offset2, LengthOfProjectName))
    
            Dim Offset3 As UInt32 = Offset2 + LoadedFile.File.LengthOfProjectName    'Offset3  = Offset2  + LengthOfProjectName
            Dim LengthOfAuthorName As UInt32 = BitConverter.ToUInt32(GetByteRange(RawBytes, Offset3, DWORD), 0)
    
            Dim Offset4 As UInt32 = Offset3 + Convert.ToUInt32(DWORD)  'Offset4  = Offset3  + 4 
            LoadedFile.File.Author = Encoding.Unicode.GetString(GetByteRange(RawBytes, Offset4, LengthOfAuthorName))
    
            Dim Offset5 As UInt32 = Offset4 + LengthOfAuthorName 'Offset5  = Offset4  + LengthOfAuthorName
            Dim LengthOfPicturePreview As UInt32 = BitConverter.ToUInt32(GetByteRange(RawBytes, Offset5, QWORD), 0)
    
            Dim Offset6 As UInt32 = Offset5 + Convert.ToUInt32(QWORD) 'Offset6  = Offset5  + 8 
            LoadedFile.File.PreviewPicture = Image.FromStream(New MemoryStream(GetByteRange(RawBytes, Offset6, LengthOfPicturePreview)))
    
            Dim Offset7 As UInt32 = Offset6 + LengthOfPicturePreview 'Offset7  = Offset6  + LengthOfPicturePreview
            LoadedFile.File.TreeType = CType(CInt(GetByteRange(RawBytes, Offset7, 1)(0)), TreeImageFamily)
    
            Dim Offset8 As UInt32 = Offset7 + Convert.ToUInt32(1) 'Offset8  = Offset7  + 1
            Dim LengthOfLayerData As UInt32 = BitConverter.ToUInt32(GetByteRange(RawBytes, Offset8, DWORD), 0)
    
            Dim Offset9 As UInt32 = Offset8 + Convert.ToUInt32(DWORD) 'Offset9  = Offset8  + 4
            Dim LayerCollection As Byte() = GetByteRange(RawBytes, Offset9, LengthOfLayerData)
            LoadedFile.File.LayerCollection = LayerCollection
    
            Dim Offset10 As UInt32 = Offset9 + LengthOfLayerData   'Offset10 = Offset9  + LengthOfLayerData
            Dim LengthOfLogImage As UInt64 = BitConverter.ToUInt64(GetByteRange(RawBytes, Offset10, QWORD), 0)
    
            Dim Offset11 As UInt32 = Offset10 + Convert.ToUInt32(QWORD) 'Offset11 = Offest10 + 8
            LoadedFile.File.LogImage = Image.FromStream(New MemoryStream(GetByteRange(RawBytes, Offset11, Convert.ToUInt32(LengthOfLogImage))))
    
            Dim Offset12 As UInt32 = Offset11 + Convert.ToUInt32(LengthOfLogImage) 'Offset12 = Offset11 + LengthLogImage
            Dim LengthOfLeavesImage As UInt64 = BitConverter.ToUInt64(GetByteRange(RawBytes, Offset12, QWORD), 0)
    
            Dim Offset13 As UInt32 = Offset12 + Convert.ToUInt32(QWORD) 'Offset13 = Offset12 + 8
            LoadedFile.File.LeavesImage = Image.FromStream(New MemoryStream(GetByteRange(RawBytes, Offset13, Convert.ToUInt32(LengthOfLeavesImage))))
    
    
    
            Return LoadedFile
        End Function
        Sub Save(ByVal FileName As String)
            My.Computer.FileSystem.WriteAllBytes(FileName, GetBytes, False)
        End Sub
        Public Function GetBytes() As Byte()
            Dim RawBytes As Byte() = BitConverter.GetBytes(Me.File.LengthOfProjectName)
            RawBytes = CombineArrays(RawBytes, Encoding.Unicode.GetBytes(Me.File.ProjectName))
            RawBytes = CombineArrays(RawBytes, BitConverter.GetBytes(Me.File.LengthOfAuthorName))
            RawBytes = CombineArrays(RawBytes, Encoding.Unicode.GetBytes(Me.File.Author))
            RawBytes = CombineArrays(RawBytes, BitConverter.GetBytes(Me.File.LengthOfPicturePreview))
            RawBytes = CombineArrays(RawBytes, ImageBytes(Me.File.PreviewPicture, Me.File.ImageFormat))
            RawBytes = CombineArrays(RawBytes, {CByte(Me.File.TreeType)})
            RawBytes = CombineArrays(RawBytes, BitConverter.GetBytes(Me.File.LengthOfLayerCollection))
            RawBytes = CombineArrays(RawBytes, Me.File.LayerCollection)
            RawBytes = CombineArrays(RawBytes, BitConverter.GetBytes(Me.File.LengthOfLogImage))
            RawBytes = CombineArrays(RawBytes, ImageBytes(Me.File.LogImage, Me.File.ImageFormat))
            RawBytes = CombineArrays(RawBytes, BitConverter.GetBytes(Me.File.LengthOfLeavesImage))
            RawBytes = CombineArrays(RawBytes, ImageBytes(Me.File.LeavesImage, Me.File.ImageFormat))
            Return RawBytes
        End Function
    #Region "File Data Structure(Main structure)"
        'Field Name                Data Type             Data Size                                Offset Formula
        '
        Class FileData
            '	LengthOfProjectName    UInt32                DWORD                                    Offset1  = 0
            '	ProjectName            String                Byte(LengthOfProjectName-1)              Offset2  = Offset1  + 4
            '	LengthOfAuthorName     UInt32                DWORD                                    Offset3  = Offset2  + LengthOfProjectName
            '	AuthorName             String                Byte(LengthOfAuthorName-1)               Offset4  = Offset3  + 4 
            '	LengthOfPicturePreview UInt64                QWORD                                    Offset5  = Offset4  + LengthOfAuthorName
            '	PreviewPicture         Byte()                Byte(LengthOfPicturePreview-1)           Offset6  = Offset5  + 8  
            '	TreeType               Byte                  1 Byte                                   Offset7  = Offset6  + LengthOfPicturePreview
            '	LengthOfLayerData      UInt32                DWORD                                    Offset8  = Offset7  + 1
            '   LayerCollection        LayerCollection       Byte(LengthOfLayerData-1)                Offset9  = Offset8  + 4
            '   LengthLogImage         UInt64                QWORD                                    Offset10 = Offset9  + LengthOfLayerData
            '   LogImage               Byte()                Byte(LengthLogImage-1)                   Offset11 = Offest10 + 8
            '   LengthOfLeavesImage    UInt64                QWORD                                    Offset12 = Offset11 + LengthLogImage
            '   LeavesImage            Byte()                Byte(LengthOfLeavesImage-1)              Offset13 = Offset12 + 8
            'Structure
            Public ImageFormat As Imaging.ImageFormat
            Private Property _LengthOfProjectName As UInt32
            Private Property _ProjectName As String
            Private Property _LengthOfAuthorName As UInt32
            Private Property _Author As String
            Private Property _LengthOfPicturePreview As UInt64
            Private Property _PreviewPicture As Image
            Private Property _TreeType As TreeImageFamily
            Private Property _LengthOfLayerCollection As UInt32
            Private Property _LayerCollection As Byte()
            Private Property _LengthOfLogImage As UInt64
            Private Property _LogImage As Image
            Private Property _LengthOfLeavesImage As UInt64
            Private Property _LeavesImage As Image
            Public ReadOnly Property LengthOfProjectName As UInt32
                Get
                    Return _LengthOfProjectName
                End Get
            End Property
            Public Property ProjectName As String
                Get
                    Return _ProjectName
                End Get
                Set(ByVal value As String)
                    Dim Bytes As Byte() = Encoding.Unicode.GetBytes(value)
                    _ProjectName = value
                    _LengthOfProjectName = Convert.ToUInt32(Bytes.Count)
                End Set
            End Property
            Public ReadOnly Property LengthOfAuthorName As UInt32
                Get
                    Return _LengthOfAuthorName
                End Get
            End Property
            Public Property Author As String
                Get
                    Return _Author
                End Get
                Set(ByVal value As String)
                    Dim Bytes As Byte() = Encoding.Unicode.GetBytes(value)
                    _Author = value
                    _LengthOfAuthorName = Convert.ToUInt32(Bytes.Count)
                End Set
            End Property
            Public ReadOnly Property LengthOfPicturePreview As UInt64
                Get
                    Return _LengthOfPicturePreview
                End Get
            End Property
            Public Property PreviewPicture As Image
                Get
                    Return _PreviewPicture
                End Get
                Set(ByVal value As Image)
                    Dim Bytes As Byte() = ImageBytes(value, Me.ImageFormat)
                    _PreviewPicture = value
                    _LengthOfPicturePreview = Convert.ToUInt64(Bytes.Count)
                End Set
            End Property
            Public Property TreeType As TreeImageFamily
                Get
                    Return _TreeType
                End Get
                Set(ByVal value As TreeImageFamily)
                    _TreeType = value
                End Set
            End Property
            Public ReadOnly Property LengthOfLayerCollection As UInt32
                Get
                    Return _LengthOfLayerCollection
                End Get
            End Property
            Public Property LayerCollection As Byte()
                Get
                    Return _LayerCollection
                End Get
                Set(ByVal value As Byte())
                    _LayerCollection = value
                    _LengthOfLayerCollection = Convert.ToUInt32(value.Count)
                End Set
            End Property
            Public ReadOnly Property LengthOfLogImage As UInt64
                Get
                    Return _LengthOfLogImage
                End Get
            End Property
            Public Property LogImage As Image
                Get
                    Return _LogImage
                End Get
                Set(ByVal value As Image)
                    _LogImage = value
                    Dim Bytes As Byte() = ImageBytes(value, Me.ImageFormat)
                    _LengthOfLogImage = Convert.ToUInt64(Bytes.Count)
                End Set
            End Property
            Public ReadOnly Property LengthOfLeavesImage As UInt64
                Get
                    Return _LengthOfLeavesImage
                End Get
            End Property
            Public Property LeavesImage As Image
                Get
                    Return _LeavesImage
                End Get
                Set(ByVal value As Image)
                    _LeavesImage = value
                    Dim Bytes As Byte() = ImageBytes(value, Me.ImageFormat)
                    _LengthOfLeavesImage = Convert.ToUInt64(Bytes.Count)
                End Set
            End Property
        End Class
    #End Region
    #Region "Layer Collection Strucutre"
    
        Public Class LayerCollectionStructure
            '   LayerCount             UInt32                DWORD                                    Offset1 = 0
            '   Layer1DataLength       UInt32                DWORD                                    Offset2 = Offset1 + 4
            '   Layer1Data             LayerData             Bytes(Layer1DataLength)                  Offset3 = Offset2 + 4
            '	Layer2DataLength       UInt32                DWORD                                    Offset4 = Offset3 + Layer1DataLength
            '   Layer2Data             LayerData             Bytes(Layer2DataLength)                  Offset5 = Offset3 + 4
            '   etc... 
            Public Property Layers As List(Of LayerDataStructure)
            Public Bytes As Byte()
            Sub New(ByVal Options As LayerCollectionStructureOptions)
                If Not CType(Options.InteralParameter, String) = "Skip Load" Then
                    Me.Layers = Options.Layers
                    Dim LayerCount As UInt32 = Convert.ToUInt32(Options.Layers.Count)
                    Dim RawBytes As Byte() = BitConverter.GetBytes(LayerCount)
                    For Each Layer As LayerDataStructure In Options.Layers
                        Dim LayerDataLength As Byte() = BitConverter.GetBytes(Convert.ToUInt16(Layer.Bytes.Count))
                        Dim LayerData As Byte() = Layer.Bytes
                        RawBytes = CombineArrays(RawBytes, LayerDataLength)
                        RawBytes = CombineArrays(RawBytes, LayerData)
                    Next
                    Bytes = RawBytes
                End If
            End Sub
            Public Shared Function FromBytes(ByVal Bytes As Byte()) As LayerCollectionStructure
                Dim BlankOptions As New LayerCollectionStructureOptions
                BlankOptions.InteralParameter = CType("Skip Load", Object)
                Dim LayerCollectionData As Byte() = GetByteRange(Bytes, 4, Convert.ToUInt32(Bytes.Count) - Convert.ToUInt32(4))
                Dim LoadedLayerCollectionStructure As New LayerCollectionStructure(BlankOptions)
                Dim TMPLayers As New List(Of LayerDataStructure)
                Dim LayerCount As UInt32 = BitConverter.ToUInt32(GetByteRange(Bytes, 0, DWORD), 0)
                Dim Count As Integer = 0
                Dim Offset As UInt32 = 0
                Do
                    Count = Count + 1
                    Dim DataLength As UInt32 = BitConverter.ToUInt32(GetByteRange(LayerCollectionData, Offset, DWORD), 0)
                    Dim Data As Byte() = GetByteRange(LayerCollectionData, Offset + DWORD, DataLength)
                    TMPLayers.Add(LayerDataStructure.FromBytes(Data))
                    Offset = Offset + DWORD + DataLength
                Loop Until Count = LayerCount
                LoadedLayerCollectionStructure.Layers = TMPLayers
                LoadedLayerCollectionStructure.Bytes = Bytes
                Return LoadedLayerCollectionStructure
            End Function
        End Class
    #End Region
    #Region "Layer Data Strucutre"
        Public Class LayerDataStructure
            '	LayerNumber            UInt16                WORD                                     Offset1 = 0
            '   CellCollectionLength   UIint32               DWORD                                    Offset2 = Offset1 + 2
            '   CellCollectionData     CellCollectionData    Byte(CellCollectionLength)               Offset3 = Offset2 + CellCollectionLength
            Public Property Bytes As Byte()
            Public Property LayerNumber As UInt16
            Public Property CellCollectionLength As UInt32
            Public CellCollectionData As Byte()
            Public LayerCell As CellCollectionStructure
            Sub New(ByVal Options As LayerDataStructureOptions)
                If Not CType(Options.InteralParameter, String) = "Skip Load" Then
                    Me.LayerNumber = Options.LayerNumber
                    Me.LayerCell = Options.LayerCells
                    Me.CellCollectionLength = Convert.ToUInt32(Options.LayerCells.Bytes.Count)
                    Me.CellCollectionData = Options.LayerCells.Bytes
                    Dim RawBytes As Byte()
                    'Append Layer Number
                    RawBytes = BitConverter.GetBytes(Options.LayerNumber)
                    'Append Cell Collection Length
                    RawBytes = CombineArrays(RawBytes, BitConverter.GetBytes(Me.CellCollectionLength))
                    'Append Cell Collection Data
                    RawBytes = CombineArrays(RawBytes, Me.CellCollectionData)
                    Bytes = RawBytes
                End If
            End Sub
            Public Shared Function FromBytes(ByVal Bytes As Byte()) As LayerDataStructure
                Dim Options As New LayerDataStructureOptions
                Options.InteralParameter = CType("Skip Load", Object)
                Dim LoadedLayerDataStructure As New LayerDataStructure(Options)
                '	LayerNumber            UInt16                WORD                                     Offset1 = 0
                '   CellCollectionLength   UIint32               DWORD                                    Offset2 = Offset1 + 2
                '   CellCollectionData     CellCollectionData    Byte(CellCollectionLength)               Offset3 = Offset2 + CellCollectionLength
                Dim Offset1 As UInt32 = 0
                LoadedLayerDataStructure.LayerNumber = BitConverter.ToUInt16(GetByteRange(Bytes, Offset1, WORD), 0)
                Dim Offset2 As UInt32 = Offset1 + WORD
                LoadedLayerDataStructure.CellCollectionLength = BitConverter.ToUInt32(GetByteRange(Bytes, Offset2, DWORD), 0)
                Dim Offset3 As UInt32 = Offset2 + LoadedLayerDataStructure.CellCollectionLength
                LoadedLayerDataStructure.CellCollectionData = GetByteRange(Bytes, Offset3, LoadedLayerDataStructure.CellCollectionLength)
                LoadedLayerDataStructure.LayerCell = CellCollectionStructure.FromBytes(LoadedLayerDataStructure.CellCollectionData)
                LoadedLayerDataStructure.Bytes = Bytes
                Return LoadedLayerDataStructure
            End Function
        End Class
    #End Region
    #Region "Cell Collection Structure"
        Public Class CellCollectionStructure
            Public Cell As List(Of CellDataStructure)
            Public Property Bytes As Byte()
            Sub New(ByVal Options As CellCollectionStructureOptions)
                If Not CType(Options.InteralParameter, String) = "Skip Load" Then
                    Me.Cell = Options.Cells
                    Dim RawBytes As Byte() = Nothing
                    '   CellCount              UInt32                DWORD                                    Offset1 = 0 
                    Dim CellCount As UInt32 = Convert.ToUInt32(Options.Cells.Count)
                    For Each Cell As CellDataStructure In Options.Cells
                        Dim Tmp2 As Byte() = BitConverter.GetBytes(Cell.X)
                        Dim Tmp3 As Byte() = BitConverter.GetBytes(Cell.Y)
                        Dim Tmp4(0) As Byte
                        'Generate CellData
                        Tmp4(0) = CByte(Cell.TreeImageType)
                        RawBytes = CombineArrays(RawBytes, Tmp2)
                        RawBytes = CombineArrays(RawBytes, Tmp3)
                        RawBytes = CombineArrays(RawBytes, Tmp4)
                        'Get Cell Data Length, append to front of collection
                        Dim Tmp1 As Byte() = BitConverter.GetBytes(Convert.ToUInt32(RawBytes.Count))
                        RawBytes = CombineArrays(Tmp1, RawBytes)
                        'Append cellcount to front of array
                        RawBytes = CombineArrays(BitConverter.GetBytes(CellCount), RawBytes)
                        Bytes = RawBytes
                    Next
                End If
            End Sub
            Public Shared Function FromBytes(ByVal Bytes As Byte()) As CellCollectionStructure
                Dim Options As New CellCollectionStructureOptions
                Options.InteralParameter = CType("Skip Load", Object)
                Dim LoadedCellCollectionStructure As New CellCollectionStructure(Options)
                LoadedCellCollectionStructure.Bytes = Bytes
                Dim TMPCells As New List(Of CellDataStructure)
                Dim CellOptions As New CellDataStructureOptions
                CellOptions.InteralParameter = CType("Skip Load", Object)
                For I = 0 To Bytes.Count Step 5
                    Dim TMPCell As New CellDataStructure(CellOptions)
                    Dim CurrentBytes As Byte() = GetByteRange(Bytes, Convert.ToUInt32(I), 5)
                    TMPCell.X = BitConverter.ToUInt16(GetByteRange(CurrentBytes, 0, WORD), 0)
                    TMPCell.Y = BitConverter.ToUInt16(GetByteRange(CurrentBytes, 2, WORD), 0)
                    TMPCell.TreeImageType = CType(GetByteRange(CurrentBytes, 4, 1)(0), CellTreeImageType)
                    TMPCells.Add(TMPCell)
                Next
                LoadedCellCollectionStructure.Cell = TMPCells
                Return LoadedCellCollectionStructure
            End Function
        End Class
    #End Region
    #Region "Cell Data Strucure"
        Public Class CellDataStructure
            Public X As UInt16
            Public Y As UInt16
            Public TreeImageType As CellTreeImageType
            Sub New(ByVal Options As CellDataStructureOptions)
                If Not CType(Options.InteralParameter, String) = "Skip Load" Then
                    '	X                      UInt16                WORD                                     Offset1 = 0
                    Me.X = Options.X
                    '   Y                      UInt16                WORD                                     Offset2 = Offset1 + 2
                    Me.Y = Options.Y
                    '   TreeImageType          TreeImageType         1 Byte                                   Offset3 = Offset2 + 2
                    Me.TreeImageType = Options.TreeImageType
                End If
            End Sub
            Shared Function FromBytes(ByVal Bytes() As Byte) As CellDataStructure
                Dim BlankOptions As New CellDataStructureOptions
                BlankOptions.InteralParameter = CType("Skip Load", Object)
                Dim LoadedCellDataStructure As New CellDataStructure(BlankOptions)
                LoadedCellDataStructure.X = BitConverter.ToUInt16(GetByteRange(Bytes, 0, WORD), 0)
                LoadedCellDataStructure.Y = BitConverter.ToUInt16(GetByteRange(Bytes, 2, WORD), 0)
                LoadedCellDataStructure.TreeImageType = CType(BitConverter.ToUInt16(GetByteRange(Bytes, 4, 1), 0), CellTreeImageType)
                Return LoadedCellDataStructure
            End Function
        End Class
    #End Region
    #Region "Enumerations"
        Public Enum CellTreeImageType
            '   0 = Blank
            Blank = 0
            '   1 = Log                Byte                  1 Byte                                   N/A
            Log = 1
            '   2 = Leaves             Byte                  1 Byte                                   N/A
            Leaves = 2
        End Enum
        Public Enum TreeImageFamily
            Oak = 0
            Spruce = 1
            Birch = 2
            Jungle = 3
        End Enum
    #End Region
    #Region "Shared Functions"
        Public Shared Function CombineArrays(ByVal Array1 As Byte(), ByVal Array2 As Byte()) As Byte()
            Dim Merged((Array1.Length + Array2.Length) - 1) As Byte
            Array1.CopyTo(Merged, 0)
            Array2.CopyTo(Merged, Array1.Length)
            Return Merged
        End Function
        Public Shared Function ReverseByteOrder(ByVal Bytes() As Byte) As Byte()
            Dim Result(Bytes.Count - 1) As Byte
            Dim Counter As Integer = -1
            For I = Bytes.Count - 1 To 0 Step -1
                Counter = Counter + 1
                Result(Counter) = Bytes(I)
            Next
            Return Result
        End Function
        Public Shared Function ImageBytes(ByVal Image As Image, ByVal Format As Imaging.ImageFormat) As Byte()
            Dim Stream As MemoryStream = New MemoryStream()
            Image.Save(Stream, Format)
            Stream.Close()
            Dim byteArray As Byte() = Stream.ToArray()
            Stream.Dispose()
            Return byteArray
        End Function
        Public Shared Function GetByteRange(ByVal Bytes As Byte(), ByVal Offset As UInt32, ByVal Length As UInt32) As Byte()
            Dim Results As New List(Of Byte)
            For I As UInt32 = Offset To (Offset + Length) - Convert.ToUInt32(1)
                Results.Add(Bytes(CInt(I)))
            Next
            Return Results.ToArray
        End Function
    #End Region
    #Region "Structure Options"
        Public Const WORD As UInt32 = 2
        Public Const DWORD As UInt32 = 4
        Public Const QWORD As UInt32 = 8
        Public Structure LayerCollectionStructureOptions
            Public Layers As List(Of LayerDataStructure)
            Public InteralParameter As Object
        End Structure
        Public Structure LayerDataStructureOptions
            Public LayerNumber As UInt16
            Public LayerCells As CellCollectionStructure
            Public InteralParameter As Object
        End Structure
        Public Structure CellCollectionStructureOptions
            Public Cells As List(Of CellDataStructure)
            Public InteralParameter As Object
        End Structure
        Public Structure CellDataStructureOptions
            Public X As UInt16
            Public Y As UInt16
            Public TreeImageType As CellTreeImageType
            Public InteralParameter As Object
        End Structure
        Public Structure MCTData
            Public ProjectName As String
            Public AuthorName As String
            Public PreviewPicture As Image
            Public TreeType As TreeImageFamily
            Public LayersCollection As Byte()
            Public LogImage As Image
            Public LeavesImage As Image
            Public ImageFormat As Imaging.ImageFormat
            'Using this paramater(InternalParameter) may cause errors. Do not delete this parameter.
            Public InteralParameter As Object
        End Structure
    #End Region
    End Class
    
    


    If you want something you've never had, you need to do something you've never done.

  • Thursday, August 23, 2012 7:10 PM
    Moderator
     
     

    Did you notice I used things such as Uint16,Uint32,uint64... Etc

    This is what they mean:

    U-nsigned(non-negative) int-eger 16-bits(2 bytes) or 1 WORD

    U-nsigned(non-negative) int-eger 32-bits(4 bytes) or 1 DWORD

    U-nsigned(non-negative) int-eger 64-bits(8 bytes) or 1 QWORD

    Look at wiki, they have a great article about data types:

    http://en.wikipedia.org/wiki/Integer_%28computer_science%29

    You will see −2,147,483,648 to 2,147,483,647 the values(this is a 32 bit signed integer) if you notice, it can go one number more negative that it can go positive, this is because of the binary calculation is that when going positive, the final bit will reset every bit in every column, but the carry will not be processed, making it go to zero... but the carry makes it overflow. but when going negative, this does not happen, this is for any singed data type so you know.... not too important, just interesting.


    If you want something you've never had, you need to do something you've never done.

  • Thursday, August 23, 2012 7:37 PM
     
     

    if you know how to do xml you can write to collada format some of your values for your picture of a tree in 3d and display with xna. Hmm, seem to remember an xna viewer on codeplex with code heres one viewer i found on codeplex out of many with code for viewing 3d models:

    http://modelviewer.codeplex.com/SourceControl/list/changesets

    I can help with conversion from c# to vb.net manually when im available as i have started learning how to do basic xna things manually in code but still trying to learn somethings. Im sure theirs code to help also with the creation of an collada file (*. dae)  in vb.net code. you ca use collada.org as reference though if needed.

    Edit: found this nice piece of code libraries that does the loading and saving of collada files with code but look into the model viewer above also:

    http://code4k.blogspot.com/2010/08/import-and-export-3d-collada-files-with.html#!/2010/08/import-and-export-3d-collada-files-with.html


    Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth. - "Sherlock holmes" "speak softly and carry a big stick" - theodore roosevelt. Fear leads to anger, anger leads to hate, hate leads to suffering - Yoda. Blog - http://www.computerprofessions.co.nr


    • Edited by The Thinker Thursday, August 23, 2012 7:37 PM
    •