<?php
/**
* GumpReader PHP 1.1.0
* Author: Kinetix <[email protected]>
*
* This has been directly translated from my C program that does the exact same thing. So excuse the messiness.
*
* Use of this is very simple. You navigate to this page with the following parameters:
* index=GRAPHICID, the graphic of the item you want to display the gump of, OR 12/13 for male/female gumps
* female=1/0 (Optional), whether or not to fetch the female version of a gump
* hue=0 to 65535 (Optional), color the gump with X hue. Hues above 8000 result in grayscale-only hueing (mainly for body gumps only)
* isgump=1/0 (Optional), if 1, it will not get the gumpid of an item, but instead INDEX will be the gumpid.
* width/height=1-500 (Optional), if either of these are set, the default settings are overridden.
*
* Using arrays: You can pass arrays by separating each entry with ','.
* Examples:
* [url]http://yourdomain.com/gumpreader.php?index=12,5118,5141&hue=33770,1152,0&isgump=1,0,0&female=0,1,0[/url]
* ^-- The above is the same as the next one, notice the trailing ,0's at the end are removed. You don't NEED them
* if they are the last ones for that parameter.
* [url]http://yourdomain.com/gumpreader.php?index=12,5118,5141&hue=33770,1152&isgump=1&female=0,1[/url]
* ^-- Creates (in the following order) a hued male body, an ice hue katana and a no hue plate breastplate.
*
* IF YOU REDISTRIBUTE THIS FILE WITHIN ANOTHER PACKAGE (such as MyUO), YOU MUST FIRST HAVE MY PERMISSION
* AND MUST GIVE ME CREDIT WHERE IT IS DUE! Do _not_ claim someone else's work for yourself.
*
* Released under The MIT License
Copyright (c) 2004 Kinetix
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
to whom the Software is furnished to do so, subject to the following conditions:
All copyright notices and this permission notice shall be included in all copies or substantial
portions of the Software and must remain unmodified.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ==========================================
* CHANGES:
* It now has $xOffset and $yOffset for telling the script where to align paperdoll images.
* Added a bakground image, change $jpegImage to whatever you want the background to be.
*
*
*/
set_magic_quotes_runtime(0);
$indexA = $_GET['index'];
$femaleA = $_GET['female'];
$hueA = $_GET['hue'];
$isgumpA = $_GET['isgump'];
$width = $_GET['width'];
$height = $_GET['height'];
/* Default Image Settings */
$defaultWidth = 260;
$defaultHeight = 237;
$jpegImage = FALSE;
// $jpegImage = "bg_white.jpg"; // FALSE to disable
$xOffset = ($jpegImage) ? 7 : 0;
$yOffset = ($jpegImage) ? 15 : 0;
$width = (empty($width) || $width > 500) ? 260 : $width;
$height = (empty($height) || $height > 500) ? 237 : $height;
if(strpos($indexA, ","))
{
$indexA = explode(",", $indexA);
$femaleA = explode(",", $femaleA);
$hueA = explode(",", $hueA);
$isgumpA = explode(",", $isgumpA);
}
else
{
$indexA = array($indexA);
$femaleA = array($femaleA);
$hueA = array($hueA);
$isgumpA = array($isgumpA);
}
$hues = FALSE;
$tiledata = FALSE;
$gumpfile = FALSE;
$gumpindex = FALSE;
//printf("Loading hues.mul.\n");
$hues = fopen("c:\Inetpub\wwwroot\client\hues.mul", "rb");
if($hues == FALSE)
{
die("Unable to open hues.mul - ERROR\nDATAEND!");
exit;
}
//printf("Done!\n");
//printf("Loading tiledata.mul.\n");
$tiledata = fopen("c:\Inetpub\wwwroot\client\tiledata.mul", "rb");
if($tiledata == FALSE)
{
fclose($hues);
die("Unable to open tiledata.mul - ERROR\nDATAEND!");
exit;
}
//printf("Done!\n");
//printf("Loading gumpart.mul.\n");
$gumpfile = fopen("c:\Inetpub\wwwroot\client\gumpart.mul", "rb");
if($gumpfile == FALSE)
{
fclose($hues);
fclose($tiledata);
die("Unable to open gumpart.mul - ERROR\nDATAEND!");
exit;
}
//printf("Done!\n");
//printf("Loading gumpidx.mul.\n");
$gumpindex = fopen("c:\Inetpub\wwwroot\client\gumpidx.mul", "rb");
if($gumpindex == FALSE)
{
fclose($hues);
fclose($tiledata);
fclose($gumpfile);
die("Unable to open gumpidx.mul - ERROR\nDATAEND!");
exit;
}
//printf("Done!\n");
InitializeGump($gumprawdata, $width, $height, $jpegImage);
for($i = 0; $i < sizeof($indexA); $i++)
{
$index = intval($indexA[$i]);
$female = intval($femaleA[$i]);
$hue = intval($hueA[$i]);
$isgump = intval($isgumpA[$i]);
if($female >= 1)
$female = 1;
else
$female = 0;
if($hue < 1 || $hue > 65535)
$hue = 0;
if($isgump > 0 || $index == 12 || $index == 13)
$isgump = 1;
else
$isgump = 0;
if($index > 0x3FFF || $index <= 0 || $hue > 65535 || $hue < 0)
{
continue;
}
if($isgump == 1) /* Male/Female Gumps or IsGump Param*/
{
//printf("Files loaded, tiledata not required...\n");
$gumpid = $index;
}
else
{
//printf("Files loaded, parsing tiledata...\n");
$group = intval($index / 32);
$groupidx = $index % 32;
fseek($tiledata, 512 * 836 + 1188 * $group + 4 + $groupidx * 37, SEEK_SET);
if(feof($tiledata))
{
//printf("Error. Invalid gumpid, reached end of tiledata.\nDATAEND!");
continue;
}
/* Read the flags */
$flags = read_big_to_little_endian($tiledata, 4);
if($flags == -1)
{
//printf("Error reading tiledata flags.\nDATAEND!");
continue;
}
if($flags & 0x00400000)
{
fseek($tiledata, 6, SEEK_CUR);
$gumpid = read_big_to_little_endian($tiledata, 2);
$gumpid = ($gumpid & 0xFFFF);
if($gumpid > 65535 || $gumpid <= 0)
{
//printf("Item had an invalid gumpid. - ERROR\nDATAEND!");
continue;
}
if($gumpid < 10000)
{
if($female == 1)
$gumpid += 60000;
else
$gumpid += 50000;
}
}
else
{
//printf("Item is not wearable. - ERROR\nDATAEND!");
continue;
}
}
LoadRawGump($gumpindex, $gumpfile, intval($gumpid), $hue, $hues, $xOffset, $yOffset, $gumprawdata);
}
CreateGump($gumprawdata);
//printf("Done!\n");
fclose($hues);
fclose($tiledata);
fclose($gumpfile);
fclose($gumpindex);
exit;
function LoadRawGump($gumpindex, $gumpfile, $index, $hue, $hues, $xOffset, $yOffset, &$gumprawdata)
{
$send_data = '';
$color32 = array();
fseek($gumpindex, $index * 12, SEEK_SET);
if(feof($gumpindex))
{
//printf("Error. Invalid gumpid, reached end of gumpindex.\nDATAEND!");
return;
}
$lookup = read_big_to_little_endian($gumpindex, 4);
if($lookup == -1)
{
if($index >= 60000)
$index -= 10000;
fseek($gumpindex, $index * 12, SEEK_SET);
if(feof($gumpindex))
{
//printf("Error. Invalid gumpid, reached end of gumpindex.\nDATAEND!");
return;
}
$lookup = read_big_to_little_endian($gumpindex, 4);
if($lookup == -1)
{
//printf("Error. Gumpindex returned invalid lookup.\nDATAEND!");
return;
}
}
$gsize = read_big_to_little_endian($gumpindex, 4);
$gextra = read_big_to_little_endian($gumpindex, 4);
fseek($gumpindex, $index * 12, SEEK_SET);
$gwidth = (($gextra >> 16) & 0xFFFF);
$gheight = ($gextra & 0xFFFF);
$send_data .= sprintf("Lookup: %d\n", $lookup);
$send_data .= sprintf("Size: %d\n", $gsize);
$send_data .= sprintf("Height: %d\n", $gheight);
$send_data .= sprintf("Width: %d\n", $gwidth);
if($gheight <= 0 || $gwidth <= 0)
{
//printf("Error in gumpindex. Gump width or height was less than 0.\nDATAEND!");
return;
}
fseek($gumpfile, $lookup, SEEK_SET);
$heightTable = read_big_to_little_endian($gumpfile, ($gheight * 4));
if(feof($gumpfile))
{
//printf("Error. Invalid gumpid, reached end of gumpfile.\nDATAEND!");
return;
}
$send_data .= sprintf("DATASTART:\n");
if($hue <= 0)
{
for ($y = 0; $y < $gheight; $y++)
{
fseek($gumpfile, $heightTable[$y] * 4 + $lookup, SEEK_SET);
/* Start of row */
$x = 0;
while ($x < $gwidth)
{
$rle = read_big_to_little_endian($gumpfile, 4); /* Read the RLE data */
$length = ($rle >> 16) & 0xFFFF; /* First two bytes - how many pixels does this color cover */
$color = $rle & 0xFFFF; /* Second two bytes - what color do we apply */
/* Begin RGB value decoding */
$r = (($color >> 10)*8);
$g = (($color >> 5) & 0x1F)*8;
$b = ($color & 0x1F)*8;
if($r > 0 || $g > 0 || $b > 0)
$send_data .= sprintf("%d:%d:%d:%d:%d:%d***", $x, $y, $r, $g, $b, $length);
//printf("%d:%d:%d:%d:%d:%d***", $x, $y, $r, $g, $b, $length);
$x = $x + $length;
}
}
}
else /* We are using the hues.mul */
{
$hue = $hue - 1;
$orighue = $hue;
if($hue > 0x8000)
$hue = $hue - 0x8000;
if($hue > 3001) /* Bad hue will cause a crash */
$hue = 1;
$colors = intval($hue / 8) * 4;
$colors = 4 + $hue * 88 + $colors;
fseek($hues, $colors, SEEK_SET);
for ($i = 0; $i < 32; $i++)
{
$color32[$i] = read_big_to_little_endian($hues, 2);
$color32[$i] |= 0x8000;
}
for ($y = 0; $y < $gheight; $y++)
{
fseek($gumpfile, $heightTable[$y] * 4 + $lookup, SEEK_SET);
/* Start of row */
$x = 0;
while ($x < $gwidth)
{
$rle = read_big_to_little_endian($gumpfile, 4); /* Read the RLE data */
$length = ($rle >> 16) & 0xFFFF; /* First two bytes - how many pixels does this color cover */
$color = $rle & 0xFFFF; /* Second two bytes - what color do we apply */
/* Begin RGB value decoding */
$r = (($color >> 10));
$g = (($color >> 5) & 0x1F);
$b = ($color & 0x1F);
/* Check if we're applying a special hue (skin hues), if so, apply only to grays */
if(($orighue > 0x8000) && ($r == $g && $r == $b))
{
$newr = (($color32[$r] >> 10))*8;
$newg = (($color32[$r] >> 5) & 0x1F)*8;
$newb = ($color32[$r] & 0x1F)*8;
}
elseif($orighue > 0x8000)
{
$newr = $r * 8;
$newg = $g * 8;
$newb = $b * 8;
}
else
{
$newr = (($color32[$r] >> 10))*8;
$newg = (($color32[$r] >> 5) & 0x1F)*8;
$newb = ($color32[$r] & 0x1F)*8;
}
if((($r * 8) > 0) || (($g * 8) > 0) || (($b * 8) > 0))
$send_data .= sprintf("%d:%d:%d:%d:%d:%d***", $x , $y, $newr, $newg, $newb, $length);
//printf("%d:%d:%d:%d:%d:%d***", $x , $y, $newr, $newg, $newb, $length);
$x += $length;
}
}
}
$send_data .= sprintf("DATAEND!");
add_gump($send_data, $gumprawdata, $xOffset, $yOffset);
}
function read_big_to_little_endian($file, $length)
{
if(($val = fread($file, $length)) == FALSE)
{
//printf("Error getting file data of length $length.\nDATAEND!");
return -1;
}
switch($length)
{
case 4: $val = unpack('l', $val); break;
case 2: $val = unpack('s', $val); break;
case 1: $val = unpack('c', $val); break;
default: $val = unpack('l*', $val); return $val; break;
}
// echo "<pre>$";
// print_r($val);
// echo "</pre>";
return ($val[1]);
}
function add_gump($read, &$img, $xOffset, $yOffset)
{
if(strpos($read, "ERROR"))
return;
$realheight = intval($realheight);
$realwidth = intval($realwidth);
$data = explode("DATASTART:\n", $read);
$data = $data[1];
$newdata = explode("***", $data);
while(list($key, $val) = @each($newdata))
{
if($val == "DATAEND!")
break;
$val = explode(":", $val);
$x = intval($val[0]) + $xOffset;
$y = intval($val[1]) + $yOffset;
$r = intval($val[2]);
$g = intval($val[3]);
$b = intval($val[4]);
$length = intval($val[5]); // pixel color repeat length
if($r || $g || $b)
{
$col = imagecolorallocate($img, $r, $g, $b);
for($i = 0; $i < $length; $i++)
imagesetpixel($img, $x+$i, $y, $col);
}
}
}
function InitializeGump(&$img, $width, $height, $jpegimg = FALSE)
{
if($jpegimg)
$img = @imagecreatefromjpeg($jpegimg);
else
$img = imagecreatetruecolor($width, $height) or die("couldnt create image");
imagealphablending($img, TRUE);
$alpha = imagecolorallocatealpha($img, 0, 0, 0, 127);
if(imagefilledrectangle($img, 0, 0, $realwidth, $realheight, $alpha) == false)
die("Could not create image alpha layer.");
}
function CreateGump(&$img)
{
Header("Content-type: image/png");
imagepng($img);
imagedestroy($img);
}
?>