Author Topic: View TIM files with PHP? ...done it, see how  (Read 2613 times)

scmark15

  • *
  • Posts: 9
    • View Profile
View TIM files with PHP? ...done it, see how
« on: 2010-06-01 13:34:27 »
Okay for those who read my "TIM files for those starting out" (http://forums.qhimm.com/index.php?topic=9754.0)
thread my last post had a sample code to use PHP to read 8 bit TIM files. I decided this should have its own thread because
this thread isn't about how TIM files store there data but how to view them using PHP.

What you need to begin:
  -IIS or Apache Server running PHP 5
  -A copy of the script below (Just copy & paste it to notepad and save it as TIMViewer.php)
  -A few TIM files (must be copied to the same directory as the TIMViewer.php script)

Code: [Select]
<html>
<head>
  <title>TIM Viewer</title>
  <style>
    <!--
      body, table, tr, td{
        font-family: courier new;
        font-size:   11px;
      }
    -->
  </style>
</head>
<body>
<?php
if(isset($_GET[&#39;file&#39;])){
  
$infile $_GET[&#39;file&#39;];
}else{
  die(
"Error: no file selected");
}

$curCLUT 1;
if(isset(
$_GET[&#39;clut&#39;])){
  
$curCLUT $_GET[&#39;clut&#39;];
}
$handle fopen($infile, &#39;rb&#39;);

//
// HEX => CONVERT => BINARY
//
function hexbin($strHex) {
  
$strBin = &#39;&#39;;
  
for($i 0$i strlen($strHex); $i++){
    
$strBin .= sprintf("%04s"decbin(hexdec($strHex[$i])));
  }
  return 
$strBin;
}

//
// ABGR[1555] => CONVERT => RGB[888]
//
function getRGB($color){
  
$colorBin hexbin(str_repeat("0"strlen(dechex($color))) . dechex($color));

  
$a1 substr($colorBin01);
  
$b5 substr($colorBin15);
  
$g5 substr($colorBin65);
  
$r5 substr($colorBin115);

  
$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"strlen(dechex($r8))) . dechex($r8));
  
$RGBGreen strtoupper(str_repeat("0"strlen(dechex($g8))) . dechex($g8));
  
$RGBBlue  strtoupper(str_repeat("0"strlen(dechex($b8))) . dechex($b8));
  
$RGB $RGBRed $RGBGreen $RGBBlue;
  return 
$RGB;
}

//
// FILE HEADER
//
$data unpack("V2"fread($handle8));
$timMagic = &#39;0x&#39; . dechex($data[1]);
$timType = &#39;0x0&#39; . $data[2];
unset($data);

if(
$timType == 0x08 || $timType == 0x09){
  
//
  // CLUT HEADER
  //
  
$data unpack(&#39;Vlong/v4short&#39;, fread($handle, 12));
  
$clutLength $data[&#39;long&#39;];
  
$clutX      $data[&#39;short1&#39;];
  
$clutY      $data[&#39;short2&#39;];
  
$colorNum   $data[&#39;short3&#39;];
  
$clutCount  $data[&#39;short4&#39;];
  
unset($data);

  
//
  // CLUT DATA
  //
  
for($x 1$x <= $clutCount$x++){
    for(
$i 1$i <= $colorNum$i++){
      
$data unpack(&#39;v&#39;, fread($handle, 2));
      
$clutData[$x][$i] = getRGB($data[1]);
    }
  }
  unset(
$data);
}

//
// IMAGE HEADER
//
$data unpack(&#39;Vlong/v4short&#39;, fread($handle, 12));
$imgLength $data[&#39;long&#39;];
$imgX      $data[&#39;short1&#39;];
$imgY      $data[&#39;short2&#39;];
$imgPitch  $data[&#39;short3&#39;];
$imgHeight $data[&#39;short4&#39;];
unset($data);

//
// IMAGE WIDTH FIX
//
if($timType == 0x08){
  
$imgWidth $imgPitch 4;
  
$imgArea = ($imgPitch 2) * $imgHeight;
}else if(
$timType == 0x09){
  
$imgWidth $imgPitch 2;
  
$imgArea $imgWidth $imgHeight;
}else if(
$timType == 0x02){
  
$imgWidth $imgPitch;
  
$imgArea $imgWidth $imgHeight;
}else if(
$timType == 0x03){
  
$imgWidth $imgPitch 1.5;
  
$imgArea $imgWidth $imgHeight;
}

//
// File Info
//
echo &#39;<h3>File Info</h3>&#39; . "\n";
echo &#39;TIM Header: &#39; . $timMagic . &#39;<br/>&#39; . "\n";
if($timType == 0x08){
  
$bpp = &#39;4bpp&#39;;
}else if($timType == 0x09){
  
$bpp = &#39;8bpp&#39;;
}else if($timType == 0x02){
  
$bpp = &#39;16bpp&#39;;
}else if($timType == 0x03){
  
$bpp = &#39;24bpp&#39;;
}
echo &
#39;TIM Type: &nbsp;&nbsp;&#39; . $timType . &#39; => &#39; . $bpp . &#39;<br/>&#39; . "\n";

echo &#39;<br/>&#39;;
if($timType == 0x08 || $timType == 0x09){
  echo &
#39;<b>CLUT Header</b><br />&#39; . "\n";
  
echo &#39;CLUT Size: &nbsp;&nbsp;&#39; . $clutLength . &#39; Bytes<br/>&#39; . "\n";
  
echo &#39;H. Res: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39; . $clutX . &#39;<br/>&#39; . "\n";
  
echo &#39;V. Res: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39; . $clutY . &#39;<br/>&#39; . "\n";
  
echo &#39;# of Colors: &#39; . $colorNum . &#39;<br/>&#39; . "\n";
  
echo &#39;# of CLUTS: &nbsp;&#39; . $clutCount . &#39;<br/>&#39; . "\n";

  
echo &#39;<br/>&#39; . "\n";

  
echo &#39;<b>CLUT (Color Look-Up Table)</b><br />&#39; . "\n";
  
echo &#39;<table border="0" cellpadding="0" cellspacing="2"><tr>&#39; . "\n";
  
$count 0;
  for(
$i 1$i <= $colorNum$i++){
    
$color $clutData[$curCLUT][$i];
    echo &
#39;<td style="border: #000000 1px solid; background-color: #&#39; . $color . &#39;; height: 16px; text-align: center; width: 16px;">&nbsp;</td>&#39; . "\n";
    
$count++;
    if(
$count == && $colorNum == 16){
      echo &
#39;</tr><tr>&#39; . "\n";
      
$count 0;
    }else if(
$count == 16 && $colorNum == 256){
      echo &
#39;</tr><tr>&#39; . "\n";
      
$count 0;
    }
  }
  echo &
#39;</tr></table>&#39; . "\n";

  
echo &#39;<br/>&#39; . "\n";
}

echo &
#39;<b>Image Header</b><br />&#39; . "\n";
echo &#39;Image Size: &#39; . $imgLength . &#39; Bytes<br/>&#39; . "\n";
echo &#39;Org. X: &nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgX . &#39;<br/>&#39; . "\n";
echo &#39;Org. Y: &nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgY . &#39;<br/>&#39; . "\n";
echo &#39;Width: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgWidth . &#39;px<br/>&#39; . "\n";
echo &#39;Height: &nbsp;&nbsp;&nbsp;&nbsp;&#39; . $imgHeight . &#39;px<br/>&#39; . "\n";

echo &#39;<br/>&#39; . "\n";
echo &#39;<h3>Output</h3>&#39; . "\n";
echo &#39;<table border="0" cellpadding="0" cellspacing="0" height="&#39; . $imgHeight . &#39;" width="&#39; . $imgWidth . &#39;"><tr>&#39; . "\n";
if($timType == 0x08 || $timType == 0x09){
  
$count 0;
  for(
$i 1$i <= $imgArea$i++){
    if(
$timType == 0x08){
      
$buff fread($handle1);

      
$data unpack(&#39;h&#39;, $buff);
      
$highNibble hexdec($data[1]) + 1;
      unset(
$data);

      
$data unpack(&#39;H&#39;, $buff);
      
$lowNibble hexdec($data[1]) + 1;
      unset(
$data);

      
$count++;
      echo &
#39;<td style="background-color: #&#39; . $clutData[$curCLUT][$highNibble] .&#39;"></td>&#39; . "\n";

      
$count++;
      echo &
#39;<td style="background-color: #&#39; . $clutData[$curCLUT][$lowNibble] .&#39;"></td>&#39; . "\n";
    
}else if($timType == 0x09){
      
$buff fread($handle1);

      
$data unpack(&#39;C&#39;, $buff);
      
$picked $data[1] + 1;
      unset(
$data);

      
$count++;
      echo &
#39;<td style="background-color: #&#39; . $clutData[$curCLUT][$picked] .&#39;"></td>&#39; . "\n";
    
}
    if(
$count == $imgWidth){
      
$count 0;
      echo &
#39;</tr><tr>&#39; . "\n";
    
}
  }
  echo &
#39;</tr></table>&#39; . "\n";
}else if($timType == 0x02){
  
$count 0;
  for(
$i 1$i <= $imgArea$i++){
    
$data unpack(&#39;v&#39;, fread($handle, 2));
    
$rawData getRGB($data[1]);
    unset(
$data);

    
$count++;
    echo &
#39;<td style="background-color: #&#39; . $rawData . &#39;"></td>&#39; . "\n";

    
if($count == $imgWidth){
      
$count 0;
      echo &
#39;</tr><tr>&#39; . "\n";
    
}
  }
}else if(
$timType == 0x03){
  
$count 0;
  for(
$i 1$i <= $imgArea$i++){
    
$data unpack(&#39;C3&#39;, fread($handle, 3));
    
$rawData strtoupper(str_repeat("0"strlen(dechex($data[1]))) . dechex($data[1])) .
               
strtoupper(str_repeat("0"strlen(dechex($data[2]))) . dechex($data[2])) .
               
strtoupper(str_repeat("0"strlen(dechex($data[3]))) . dechex($data[3]));
    unset(
$data);

    
$count++;
    echo &
#39;<td style="background-color: #&#39; . $rawData . &#39;"></td>&#39; . "\n";
    
$rawData = &#39;&#39;;

    
if($count == $imgWidth){
      
$count 0;
      echo &
#39;</tr><tr>&#39; . "\n";
    
}
  }
}else{
  die(
"Error: Invalid TIM file");
}
echo &
#39;</tr></table>&#39; . "\n";
fclose($handle);
?>

</body>
</html>

Usage:
  Open your browser and type in the address of the script ie. "localhost/TIMViewer.php?file=tim.tim"
     Where "tim.tim" is change it to the file name of your TIM file.
     If the file is a 4 bit or an 8 bit TIM add "&clut=x" (x is which clut you wish to use to view the image, default is 1)
        => "localhost/TIMViewer.php?file=mytim.tim&clut=1" (this would view the image with the 1st clut from the mytim.tim file)

Notes:
  -This is not the most efficient coding or fastest loading but it does work.
  -Big TIM files might take a long time to load.
  -This script is writen purely by me and can be edited freely (Please post your updated code if you modify)
  -Script does not show image as any graphic file (it's actually a table <= maybe why it's slow loading)

Tested with:
  - Works with FF6 character faces (4bpp)
  - Works with FF7 character faces (8bpp)
  - Works with FF9 game over screen (16bpp)
  - Works with adobe TIM plugin for all bpp (used to test 24bpp)

----------------------------------------------------------------------------------------------------------

-Enjoy
SCMark15
« Last Edit: 2010-06-02 12:25:03 by scmark15 »