TIM files for those starting out

  • Thread starter Thread starter scmark15
  • Start date Start date
Status
Not open for further replies.
S

scmark15

Guest
Here is some notes I made using a hex editor and playing around...
Code: [Select]
Code:
Everything below is from this 4x4 pixel image with 4 colors (Red, Green, Blue & White)...+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+--------- 4-Bit TIM (Paletted)--------------- HEADER ---------------------------------  Format:  10 00 00 00  TIM Magic  BPP:     08 00 00 00  4bpp-- CLUT DATA HEADER------------------------  Length:  2C 00 00 00  44 bytes (32 bytes/palette + 12 bytes for this header)  palX:    00 00        0px  palY:    00 00        0px  colr#:   10 00        16 (Always 16)  #CLUT:   01 00        1 CLUT-- CLUT - 2 byte (ABGR[1555] Color) little endian-------   HEX  ->  HEX  -> BINARY              -> COLOR -> COLOR-REF   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -   ->     -  -----------------------------------------------------------  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED   -> 0000  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN -> 0001  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  -> 0010  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE -> 0100  There is only 4 Colors in palette rest is "Black" padding -> 00 00    00 00 -> 0 00000 00000 00000 -> BLACK -> 1000    00 00 -> 0 00000 00000 00000 -> BLACK -> 1001    00 00 -> 0 00000 00000 00000 -> BLACK -> 1010  ...repeat until this CLUT is a total of 32 bytes/16 color entries (last index: 00 00 -> 0 00000 00000 00000 -> BLACK -> 1111)  (Example: We only have 4 colors so there will be 24 bytes of padding or            "00 00" 12 times (PADDING: 00 00 -> 0 00000 00000 00000 -> BLACK --> XXXX)-- IMAGE HEADER ---------------------------  Length:  14 00 00 00  20 bytes (1 byte for each 2 pixel set + 12 bytes for this header)  Hres:    C0 03        960  Vres:    00 00        0  Width:   01 00        4px (multiplied by 4 to get actual)  Height:  04 00        4px-- IMAGE DATA (Like 8-bit TIM, REFERENCED, only 4 bits instead of 8 bits)----------------  HEX -> BINARY    -> PX2Cr | PX1Cr      -> px2  px1  ->   -   |   -  ------------------------------------------------  00  -> 0000 0000 -> RED   | RED  11  -> 0001 0001 -> GREEN | GREEN  00  -> 0000 0000 -> RED   | RED  11  -> 0001 0001 -> GREEN | GREEN  22  -> 0010 0010 -> BLUE  | BLUE  33  -> 0100 0100 -> WHITE | WHITE  22  -> 0010 0010 -> BLUE  | BLUE  33  -> 0100 0100 -> WHITE | WHITE  Read 2 pixels at a time but second pixel is output'd first (ie right to left)    1st byte...       1st 4-bit set -> 2nd pixel      2nd 4-bit set -> 1st pixel    2nd byte...       3rd 4-bit set -> 4th pixel      4th 4-bit set -> 3rd pixel    3rd byte...       5th 4-bit set -> 6th pixel      6th 4-bit set -> 5th pixel    4th byte...       7th 4-bit set -> 8th pixel      8th 4-bit set -> 7th pixel    Visual Example (4 x 2 px image):    +-------+-------+-------+-------+    |  2nd  |  1st  |  4th  |  3rd  |    +-------+-------+-------+-------+    |  6th  |  5th  |  8th  |  7th  |    +-------+-------+-------+-------+  So... 00 -> Output is: RED   | RED        11 -> Output is: GREEN | GREEN        01 -> Output is: GREEN | RED        10 -> Output is: RED   | GREEN         ^-- RED is 0 and GREEN is 1IMAGE (1 CLUT):+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+====================================================================--------- 8-Bit TIM (Paletted)--------------- HEADER ---------------------------------  Format:  10 00 00 00  TIM Magic  BPP:     09 00 00 00  8bpp-- CLUT DATA HEADER------------------------  Length:  0C 02 00 00  524 bytes (512 bytes/palette + 12 bytes for this header)  palX:    00 00        0px  palY:    00 00        0px  colr#:   00 01        256 (Always 256)  #CLUT:   01 00        1 CLUT-- CLUT - 2 byte (ABGR[1555] Color) little endian -------  *Each CLUT or Color LookUp Table is 256 colors or 512 bytes     HEX  ->  HEX  -> BINARY              -> COLOR -> COLOR-REF   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -   ->     -  ------------------------------------------------------------  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED   -> color00  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN -> color01  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  -> color02  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE -> color03  There is only 4 Colors in palette rest is "Black" padding -> 00 00 ...    00 00 -> 0 00000 00000 00000 -> BLACK -> color04    00 00 -> 0 00000 00000 00000 -> BLACK -> color05  ...repeat until this CLUT is a total of 512 bytes/256 color entries  (Example: We only have 4 colors so there will be 504 bytes of padding or            "00 00" 252 times (PADDING: 00 00 -> 0 00000 00000 00000 -> BLACK -> colorXX)-- IMAGE HEADER ---------------------------  Length:  1C 00 00 00  28 bytes (1 byte for each pixel + 12 bytes for this header)  Hres:    C0 03        960  Vres:    00 00        0  Width:   02 00        4px (multiplied by 2 to get actual)  Height:  04 00        4px-- IMAGE DATA (Just like paletted BMP, REFERENCE each color from CLUT) -- HEX -> REF     -> COLOR -----------------------  00 -> color00 -> RED  00 -> color00 -> RED  01 -> color01 -> GREEN  01 -> color01 -> GREEN  00 -> color00 -> RED  00 -> color00 -> RED  01 -> color01 -> GREEN  01 -> color01 -> GREEN  02 -> color02 -> BLUE   02 -> color02 -> BLUE  03 -> color03 -> WHITE  03 -> color03 -> WHITE  02 -> color02 -> BLUE  02 -> color02 -> BLUE  03 -> color03 -> WHITE  03 -> color03 -> WHITEIMAGE (1 CLUT):+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+====================================================================------- 16-Bit TIM (NO CLUT DATA)------------ HEADER ---------------------------------  Format:  10 00 00 00  TIM Magic  BPP:     02 00 00 00  16bpp-- IMAGE DATA HEADER-----------------------  Length:  2C 00 00 00  44 bytes (2 bytes for each pixel + 12 bytes for this header)  Hres:    C0 03        960  Vres:    00 00        0  Width:   04 00        4px  Height:  04 00        4px-- RAW IMAGE DATA - 2 byte (ABGR[1555] Color) little endian-------   HEX  ->  HEX  -> BINARY              -> COLOR   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -  -----------------------------------------------  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITEIMAGE:+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+====================================================================  -------- 24-Bit TIM (NO CLUT DATA)--------- NOTE: Some TIM programs don't support 24-bit TIMs       Example...Yu_Ri doesn't but TIM viewer does-- HEADER ---------------------------------  Format:  10 00 00 00  TIM Magic  BPP:     03 00 00 00  24bpp-- IMAGE DATA HEADER ----------------------  Length:  3C 00 00 00  60 bytes (3 bytes for each pixel + 12 bytes for this header)  Hres:    C0 03        960  Vres:    00 00        0  Width:   06 00        4px (Divided by 1.5 to get actual)  Height:  04 00        4px-- RAW IMAGE DATA - 3 byte RGB[888] big endian ----  HEX      -> COLOR  RR GG BB ->   -  -----------------  FF 00 00 -> Red  FF 00 00 -> Red  00 FF 00 -> Green  00 FF 00 -> Green  FF 00 00 -> Red  FF 00 00 -> Red  00 FF 00 -> Green  00 FF 00 -> Green  00 00 FF -> Blue  00 00 FF -> Blue  FF FF FF -> White  FF FF FF -> White  00 00 FF -> Blue  00 00 FF -> Blue  FF FF FF -> White  FF FF FF -> WhiteIMAGE:+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Red  |  Red  | Green | Green |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+|  Blue |  Blue | White | White |+-------+-------+-------+-------+
Updated: for those who just wanna copy and paste to have a copy (see my next post to see what was fixed)
 
Last edited:
:o I forgot to note that you have to change the hex in the CLUT/Raw Image Data (4, 8 & 16 bit palettes)  to Big Endian before converting it to binary to get A BBBBB GGGGG RRRRR
because its stored in Little Endian as GGG RRRRR A BBBBB GG. :-D

Code: [Select]
Code:
For example... Little Endian 1F 00 (Binary: 000 11111 0 00000 00) -> Big Endian: 00 1F  (Binary: 0 00000 00000 11111)this will output pure red.
Code: [Select]
Code:
    HEX  ->  HEX  -> BINARY              -> COLOR -> COLOR-REF   LE   ->  BE   -> A BBBBB GGGGG RRRRR ->   -   ->     -  -----------------------------------------------------------  1F 00 -> 00 1F -> 0 00000 00000 11111 -> RED   -> 0000  E0 03 -> 03 E0 -> 0 00000 11111 00000 -> GREEN -> 0001  00 7C -> 7C 00 -> 0 11111 00000 00000 -> BLUE  -> 0010  FF 7F -> 7F FF -> 0 11111 11111 11111 -> WHITE -> 0011
I just thought people who didn't know anything or not enough about TIM files might enjoy this so I thought I'd share.
I only used a 4x4 image with 4 colors because it was easier to figure out then a smaller image and a bigger image had
too much to sort through. As for odd pixeled images I think I tried once and I couldn't get it to display, maybe because of
the CLUT data, or BPP I tried... I can't remember, I'll have to look into that ^_^

Please note: that these are my notes and may not be 100% correct...so if anyone could or wants to add/update
these notes please do so and share with the community, especially me... could always use some more info & feedback.

Oh, and if they want to add some of these notes to the wiki I have no problem with that at all.

Peace,
scmark15
<[email protected]>
 
Last edited:
I'm always forgetting to mention something ^_^

If anyone wants a copy of Yu_Ri 0.99e in english drop me an email at <[email protected]>
just make sure to add "NEED YU_RI" as the Subject or I won't read it.

Yu_Ri is a TIM, BMP extractor... it searches through big and small files for images.
It will take a multi CLUT TIM and open an image for each CLUT to view as well as save/multi-save
to BMP or TIFF. Version 0.99e includes GIF and JPEG ripping plugins.

Yu_Ri 0.99e is the last version of yu_ri released and is hard to find most websites only
have version 0.99c. I translated 90% of it to english for personal use but I'm willing to share ^_^

-later
 
Last edited:
I wanted to see if this could be done....

I made a TIM reader using PHP. It only works for 8bpp images with only 1 CLUT...for now anyway. I got it to work with the FF7 character faces in the psx versions "MENU" folder.

Test Requirements:
-PHP 5 (this is what I used)
-IIS or Apache Server running PHP
-A copy of FF7 for PSX
-A 1x1 GIF image thats completely transparent (must be named "spacer.gif")
            - place it in the same folder as the php script.
            - (its for drawing a table to display the TIM)
 -A copy of the script below
            - Copy it to notepad and save it as TIMReader.php
Code: [Select]
Code:
<html><head>  <title></title>  <style>    <!--      body {       margin:      10px;       padding:     0px;       font-family: courier new;       font-size:   11px;      }    -->  </style></head><body><?php$file = "test.tim";// Dummy out file$fileHex = '';$handle = fopen($file, "rb") or die("Error: Check your permissions");while(!feof($handle)){  foreach(unpack("C*", fgets($handle)) as $dec){    $tmp = dechex($dec);    $fileHex .= strtoupper(str_repeat("0", 2-strlen($tmp)) . $tmp);  }}fclose($handle);function hexbin($str_hex) {  $str_bin = FALSE;  for ($i=0; $i < strlen($str_hex); $i++) {    $str_bin .= sprintf("%04s", decbin(hexdec($str_hex[$i])));  }  return $str_bin;}// FILE HEADER//                          file, offset, numchar$timMagic = wordwrap(substr($fileHex, 0, 8), 2, " ", true);$timType  = wordwrap(substr($fileHex, 8, 8), 2, " ", true);// CLUT HEADER$CLUTLength = wordwrap(substr($fileHex, 16, 8), 2, " ", true);$PalX       = wordwrap(substr($fileHex, 24, 4), 2, " ", true);$PalY       = wordwrap(substr($fileHex, 28, 4), 2, " ", true);$NumColors  = wordwrap(substr($fileHex, 32, 4), 2, " ", true);$NumCLUTs   = wordwrap(substr($fileHex, 36, 4), 2, " ", true);// CLUT DATA ~~~~ offsex starts at 40$offset = 40;//for($i = 0; $i < $NumCLUTs; $i++){  for($i = 0; $i < 256; $i++){    $colorArray[] = wordwrap(substr($fileHex, $offset, 4), 2, " ", true);    $offset += 4;  }//}// IMAGE HEADER$IMGLength = wordwrap(substr($fileHex, $offset, 8), 2, " ", true);$IMGX      = wordwrap(substr($fileHex, $offset + 8, 4), 2, " ", true);$IMGY      = wordwrap(substr($fileHex, $offset + 12, 4), 2, " ", true);$Pitch     = wordwrap(substr($fileHex, $offset + 16, 4), 2, " ", true);$Height    = wordwrap(substr($fileHex, $offset + 20, 4), 2, " ", true);// Fix Offset for the next block;$offset += 24;// OUTPUTecho "TIM Header: " . $timMagic . "<br />" . "\n";echo "TIM Type: " . $timType . "<br />" . "\n";echo "<br />" ."\n";echo "CLUT Length: " . $CLUTLength . "<br />" . "\n";echo "PalX: " . $PalX . "<br />" . "\n";echo "PalY: " . $PalY . "<br />" . "\n";echo "# of Colors: " . $NumColors . "<br />" . "\n";echo "# of CLUTs: " . $NumCLUTs . "<br />" . "\n";echo "<br />" ."\n";$x = 0;// BGR[1555] to RGB[888]function getRGB($colorBin, $int){  global $Palette;  $a1 = substr($colorBin, 0, 1);  $b5 = substr($colorBin, 1, 5);  $g5 = substr($colorBin, 6, 5);  $r5 = substr($colorBin, 11, 5);  $alphadec = bindec($a1);  $bluedec = bindec($b5);  $greendec = bindec($g5);  $reddec = bindec($r5);  $a8 = $alphadec * 8;  // Older BGR[1555] to RGB[888] Conversion  // (Output is slightly darker)  // $r8 = $reddec * 8;  // $g8 = $greendec * 8;  // $b8 = $bluedec * 8;  // New BGR[1555] to RGB[888] Conversion  // (Output is slightly brighter)  $r8 = round(($reddec * 8) + ($reddec / 31 * 7));  $g8 = round(($greendec * 8) + ($greendec / 31 * 7));  $b8 = round(($bluedec * 8) + ($bluedec / 31 * 7));  // Alpha is ignored  // $RGBAlpha = strtoupper(str_repeat("0", 2-strlen(dechex($a8))) . dechex($a8));  $RGBRed   = strtoupper(str_repeat("0", 2-strlen(dechex($r8))) . dechex($r8));  $RGBGreen = strtoupper(str_repeat("0", 2-strlen(dechex($g8))) . dechex($g8));  $RGBBlue  = strtoupper(str_repeat("0", 2-strlen(dechex($b8))) . dechex($b8));  $RGB = '#' . $RGBRed . $RGBGreen . $RGBBlue;  $Palette[$int] = $RGB;  return $RGB;}foreach($colorArray as $color){  $tmp = explode(" ", $color);  $colorLE = $tmp[1] . $tmp[0];  unset($tmp);  echo "Color " . strtoupper(str_repeat("0", 2-strlen(dechex($x))) . dechex($x)) . ": " . $color . "\n";  echo ' -> ' . "\n";  $colorBin = hexbin($colorLE);  echo $colorBin;  echo ' -> ' . "\n";  echo getRGB($colorBin, $x);  echo '<br />' . "\n";  $x++;}echo "<br />" ."\n";echo "IMG Length: " . $IMGLength . "<br />" . "\n";echo "IMGX: " . $IMGX . "<br />" . "\n";echo "IMGY: " . $IMGY . "<br />" . "\n";echo "Pitch: " . $Pitch . "<br />" . "\n";echo "Height: " . $Height . "<br />" . "\n";echo "<br />" ."\n";$tmp = explode(" ", $Pitch);$Pitch = $tmp[1] . $tmp[0];$Width = hexdec($Pitch) * 2;unset($tmp);$tmp = explode(" ", $Height);$tHeight = $tmp[1] . $tmp[0];$High = hexdec($tHeight);$RawLength = $High * $Width;echo '<table border="0" cellpadding="0" cellspacing="0"><tr>' ."\n";$count = 0;for($i = 0; $i < $RawLength; $i++){  $IMGRaw = substr($fileHex, $offset, 2);  $offset += 2;  $picked = hexdec($IMGRaw);  echo '<td style="background-color: ' . $Palette[$picked] . ';><img src="spacer.gif" border="0" height="1" width="1" /></td>' . "\n";  $count++;  if($count == $Width){    echo '</tr></tr>' ."\n";    $count = 0;  }}echo '</tr></table>';?></body></html>
To use: copy the TIM file to the same folder as the script and rename it to "test.tim"
Run the script to see if it worked.

This is only a work in progress, so I appologize for my messy code (I wasn't trying to impress ^_^)
I hope to add functionality to work with Multi-CLUT tims as well as 4, 16 & 24 bpp also.

SCMark15

P.S.
Any feedback or comments are welcome anytime. I need to know if this worked for you, or what
other files you tried it out on. I'll update this when I have more time to play around with it.

-later
 
Last edited:
Status
Not open for further replies.
Back
Top