Notifications
Clear all

[Closed] Biped Preview image as TGA included in .bip files

Hi

Just found out that the Biped preview image(s) are included in the .bip files.
They are encrypted as TGA’s and have DATA-TYPE 10 format ending with TRUEVISION-XFILE
So whoever (like me) wants to use this information to create previews without opening the Biped in the scene can just extract the data out of the file and safe it as a TGA to show it.

Here is a short code example:

From here:

To here:

Cheers

15 Replies

Hi maT-Star,

How are you taking this data and saving out a TGA from it?

You could open the file binary (openFile <filename_string> mode:“rb”), read the file with readDelimitedString <filestream> “TRUEVISION-XFILE” to read until the end tag of TGA and just define the starting position, as it is different in Biped files. Then just format it out to a different file (create a file with createFile, name it .tga and I would use openFile <filename_string> mode:“wb” afterwards to open the new file binary).

I did not test this, but I think it might work

Ok, I got it now working.

What it does:

  1. Reads the file and gets the end point of the TGA part
  2. Writes the TGA out to a seperate file which can then be loaded in an rollout (btw. the bitmap control can load TGA too)
function extractBipedTGA bipPath =
 (
 	
 		--// open the file to read binary
 	binFile = fopen bipPath "rb"
 	
 		--// create saveTo file if not available
 	if (getFiles "C:\	est_tga.tga").count == 0 then
 		createFile "C:\	est_tga.tga"
 	
 		--// open saveTo file binary
 	binSaveFile = fopen "C:\	est_tga2.tga" "wb"
 	
 		--// retrieve the end of file
 	fseek binFile 0 #seek_end
 	endFile = ftell binFile
 	
 		--// TGA header start
 	fseek binFile 24 #seek_set
 	
 		--// indication of TGA
 	tempString = "TRUEVISION-XFILE"
 	
 	TGAEnd = 0	
 	foundTill = 1
 	
 	
 		--// going through the file and getting position of the TRUEVISION-XFILE
 	while ftell binFile < endFile - 1 do
 	(
 				--// checks, if the last indicator is found
 		if foundTill <= tempString.count then
 		(
 				--// comapres the indexed indicator with the current readed char
 			if tempString[foundTill] == bit.intAsChar (readByte binFile #unsigned) then
 				--// increase indicator to the next char
 				foundTill += 1
 				--// otherwise reset, to start from the beginning
 			else
 				foundTill = 1
 		)
 		else
 		(
 				--// set the TGA ending
 			TGAEnd = ftell binFile
 			exit
 		)
 	)
 	
 		--// TGA file end
 	TGAEnd += 2
 	
 		--// TGA header start
 	fseek binFile 24 #seek_set
 	
 	
 	while ftell binFile < TGAEnd do
 		writeByte binSaveFile (readByte binFile #unsigned) #unsigned
 	
 
 	fclose binFile
 	fclose binSaveFile
 )

Mathias, you’re my hero

This works only for the first preview image of the Biped file.
If you want to access the rest of them (max. 5 I think) then you need to the same steps according to the start point of the TGA).

(.max files have the preview image as bitmap format at the end of the file btw. ^^)

Here is the function to extract the bitmap from the max file.
Is quite fast too

I hope Autodesk does not change their format now

function extractMaxBMP maxPath =
(
		--// open the file to read binary
	binFile = fopen maxPath "rb"
	
		--// create saveTo file if not available
	if (getFiles "C:\	est_preview.bmp").count == 0 then
		createFile "C:\	est_preview.bmp"
	
		--// open saveTo file binary
	binSaveFile = fopen "C:\	est_preview.bmp" "wb"
	
		--// retrieve the end of file
	fseek binFile 0 #seek_end
	endFile = ftell binFile
	
		--// rough guess where to start the search for the BMP header
	fseek binFile (endFile - 70000) #seek_set
	
		--// indication of BMP start
	startIndicator = #(255, 255,255,255,3,0,0,0,1,0,128)  --// FF FF FF FF 03 00 00 00 01 00 80 as integer
	
	BMPStart = 0	
	foundTill = 1
	
	
		--// going through the file and getting position of the BMP start indicator
	while ftell binFile < endFile - 1 do
	(
				--// checks, if the last indicator is found
		if foundTill <= startIndicator.count then
		(
				--// comapres the indexed indicator with the current readed char
			if startIndicator[foundTill] == (readByte binFile #unsigned) then
				--// increase indicator to the next char
				foundTill += 1
				--// otherwise reset, to start from the beginning
			else
				foundTill = 1
		)
		else
		(
				--// set the BMP Start
			BMPStart = ftell binFile
			exit
		)
	)
	
		--// BMP file start
	BMPStart += 37
	
		--// BMP header start
	fseek binFile BMPStart #seek_set
	
	
		--// writing the BMP part to a new file
	while ftell binFile < endFile do
		writeByte binSaveFile (readByte binFile #unsigned) #unsigned
	
		--// moving to the start of the BMP file
	fseek binSaveFile 0 #seek_set
	
		--// new header as the max file had funny stuff in it
	local addedValues = #(66,77,0,0,0,0,0,0,0,0,54)
	
		--// writing new header
	for i = 1 to addedValues.count do
		writeByte binSaveFile addedValues[i] #unsigned
	
	
		--// closing binStreams
	fclose binFile
	fclose binSaveFile
)

Hi Mathias,

That is great stuff, brilliant. I wish you had been here before I tried to do this with DotNet! In your comments you have a part where you take a rough guess to the start of the file. I assume that is because the size of the thumb can vary?

Do you think this method could be converted to a DotNet language like c# or VB? I would love to be able to take this method and embed it into a class library, as my method involved installing a COM class to retrieve the file from IpropertyStorage. I’m not sure, but I would have thought that the method could be converted. any thoughts?
Seriously, good work my friend. thankyou.:applause::bowdown:

Here we go, a VB.net conversion – only useful if you are wanting to extract max thumbs for class libraries. This function should be pasted into a visualstudio.net project and called with the maxfile path as a string

What i’d like to look into is to to be able to extract straight to an image object, but it works. thanks again Mathias, you are a binary god.

 
         Public Sub GetMaxThumb(ByVal file As String)

		Dim SaveFileStream As New FileStream("C:\\_MThumb.bmp", FileMode.Create, FileAccess.Write)
		Dim MaxFileStream = New FileStream(file, FileMode.Open, FileAccess.Read)
		Dim binfile As New StreamReader(MaxFileStream)
		Dim endfile As Long = binfile.BaseStream.Seek(0, SeekOrigin.End)
		binfile.BaseStream.Position = endfile - 70000
		Dim startIndicator As Byte() = {255, 255, 255, 255, 3, 0, 0, 0, 1, 0, 128}
		Dim BMPStart As Long = 0
		Dim foundTill As Long = 1

		While binfile.BaseStream.Position < endfile - 1

			If foundTill <= startIndicator.Length - 1 Then

				If startIndicator.GetValue(foundTill) = binfile.BaseStream.ReadByte() Then
					foundTill += 1
				Else
					foundTill = 0
				End If

			Else
				BMPStart = binfile.BaseStream.Position
				Exit While
			End If

		End While

		BMPStart += 37
		binfile.BaseStream.Position = BMPStart

		Dim BinWriter As New StreamWriter(SaveFileStream)

		While binfile.BaseStream.Position < endfile
			BinWriter.BaseStream.WriteByte(binfile.BaseStream.ReadByte())
		End While

		BinWriter.BaseStream.Seek(0, SeekOrigin.Begin)
		Dim addedValues As Byte() = {66, 77, 0, 0, 0, 0, 0, 0, 0, 0, 54}
	  
		'For Each addval In addedValues
		'	BinWriter.BaseStream.WriteByte(addval)
		'Next

		' this seems to be better

		BinWriter.BaseStream.Write(addedValues, 0, addedValues.Length)


		binfile.Close()
		BinWriter.Close()
		SaveFileStream.Close()
		MaxFileStream.Close()

	End Sub

    
    	End Sub
    

there’s possibly a few methods with the streamwriter class that may well do things a bit more directly, but i haven’t been able to suss them out yet. if anyone who is good with this thing could take a look and see if it’s the most efficient way, please let me know.

a ha, in vb.net i can get a bitmap from a filestream like so –

Dim newbmp As New System.Drawing.Bitmap(BinWriter.BaseStream)

I’m getting a few access issues with running my code in a loop to find all the maxthumbs from a folder of files – it seems that the previous image hasn’t finished saving before the next read is attempted. Is that a disk limitation or do i have to code it to wait until the save is performed? I’m working a bit in the dark with these methods so any pointers welcome.

p.s. whoo hoo, getting close to 4 figure post count, better think of something good to say…

Page 1 / 2