WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Graphics Help (https://www.wowinterface.com/forums/forumdisplay.php?f=14)
-   -   Converting multiple BLPs (or PNGs) into a single BLP (or PNG) (https://www.wowinterface.com/forums/showthread.php?t=43624)

Ketho 07-01-12 01:48 PM

Converting multiple BLPs (or PNGs) into a single BLP (or PNG)
 
1 Attachment(s)
In the WoW artwork files, it seems common to see a bunch of BLP files, that actually form a single art file when glued together
  • Are there any scripts, or specific tools available to convert them to a single BLP? So we don't have to use Photoshop/Gimp/etc?
  • If an executable/script is required, is it possible to do this with Lua, or is this better done in "real" programming languages?
  • It would also be great if instead of BLP files, it could work with PNG files instead, since most people would want to convert it to PNG anyway

  • I found this post from Xinhuan, but the reference only exists in the Google Cache now, but it was focusing more about the MPQ's Minimap files in particular

  • WorldMapFrame_Update and CreditsFrame_SetArtTextures seem to have the Lua logic for it, but I don't quite understand it, and it's only for making them appear pasted together ..
  • I'm also wondering how Wowhead and MMO-Champion manage to do this

Here is an example:
Quote:

http://imgur.com/a/e7K3d
  • Interface\WorldMap\Pandaria\Pandaria1.blp
  • Interface\WorldMap\Pandaria\Pandaria2.blp
  • Interface\WorldMap\Pandaria\Pandaria3.blp
  • Interface\WorldMap\Pandaria\Pandaria4.blp
  • Interface\WorldMap\Pandaria\Pandaria5.blp
  • Interface\WorldMap\Pandaria\Pandaria6.blp
  • Interface\WorldMap\Pandaria\Pandaria7.blp
  • Interface\WorldMap\Pandaria\Pandaria8.blp
  • Interface\WorldMap\Pandaria\Pandaria9.blp
  • Interface\WorldMap\Pandaria\Pandaria10.blp
  • Interface\WorldMap\Pandaria\Pandaria11.blp
  • Interface\WorldMap\Pandaria\Pandaria12.blp
(10 images per post restriction)
Quote:


--


Ketho 07-01-12 01:49 PM

Quote:


----------

Seerah 07-01-12 04:55 PM

As far as I know, the game just pieces them together in the correct locations.

Ketho 07-01-12 05:00 PM

but I want to have them pieced together out of the game :P

Seerah 07-01-12 05:01 PM

Then you'll have to use Photoshop. :p :)

Haleth 07-01-12 06:50 PM

Perhaps slightly unrelated, but is there a reason why the maps are stored in separate pieces? I can't think of any.

Rilgamon 07-01-12 09:29 PM

Quote:

Originally Posted by Haleth (Post 257459)
Perhaps slightly unrelated, but is there a reason why the maps are stored in separate pieces? I can't think of any.

Webgraphics are sliced to speed up loading time because you can download them at the same time.
Perhaps the same is true for disc access.

Cybeloras 07-01-12 11:58 PM

My best guess is that because maps are not square (at least I don't think they are), and that all images displayed by WoW must have their dimensions be powers of 2, there is less wasted space when many small images are used rather than one large image.

Othgar 07-02-12 05:54 AM

1 Attachment(s)
I couldn't wait.. I had to assemble it :o

Attachment 7015

Ketho 07-02-12 01:47 PM

Quote:

Originally Posted by Othgar (Post 257479)
I couldn't wait.. I had to assemble it :o

Attachment 7015

Thanks for assembling it Othgar, but I'm really looking for a script or tool to automate this ..

It would be of a great help for contributing to this MoP Artwork Changes thread at least

Othgar 07-02-12 02:25 PM

Quote:

Originally Posted by Ketho (Post 257506)
Thanks for assembling it Othgar, but I'm really looking for a script or tool to automate this ..

It would be of a great help for contributing to this MoP Artwork Changes thread at least

Yeah I don't know of any scripts or anything that could do this out of game. In this case the images went together in order from top to bottom left to right, so at least in this case the logic for assembling them would be easy but there's no way to know if all the bigger images like this are broken up that way. If they are then no worries if not then it could make a huge mess out of it. It is possible that since wowhead and MMO champion are both news sites with press credentials that they got the complete images straight from blizz. Although they have enough of a staff that it wouldn't be a big deal to have a few people just throwing the images together like I did either.

Also the image I posted was double the size of the actual assembled map.

Digital_Utopia 04-20-14 07:54 AM

Well, if you're talking specifically about the WorldMaps, WoW doesn't really put them together, per se. It's just the world map frame has several sections for its own piece of the full map.

Now, if you're talking about the exploration areas that show up when you discover them, then it gets a little more complicated.

WoW uses a bunch of database files that are stored in the MPQs, which provide all sorts of information for - well, all sorts of things. One of those files are for the placement of those parts of the world map.

As far as an out of game script that generates all these images as a single one, I made a php script that does exactly that. Unfortunately, I lost my webhost, and had a recent hard drive failure, so the database table that held this information, which I parsed from the WoW database file, is currently missing.

Actually...wow.

Apparently I also made a db file parser in php for the map data, to insert it into a database.

I know this is a pretty old thread, but in case someone wants it, I'll edit this to provide a link in a little bit

Digital_Utopia 04-21-14 07:35 AM

Here's the PHP script that uses information from WorldMapOverlay.dbc and WorldMapArea.dbc, to generate a single map from tiles and overlays.

Code:

<?
header("Content-Type: image/png");
$name=$_GET['n'];

$mysqli = new mysqli("localhost", "root", "password", "WoWMapStuff");
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

$query1="SELECT ID,MapID FROM worldmaparea WHERE AreaName='$name'";
$res=$mysqli->query($query1);
$row=$res->fetch_assoc();
$id=$row['ID'];
$mapID=$row['MapID'];
$mapData = Array();
$query2 = "SELECT DISTINCT Name,Width,Height,X,Y FROM worldmapoverlay WHERE WorldMapAreaID='$id' AND Name <> '' AND Width > 0 AND Height >0";
$res=$mysqli->query($query2);
while ($row = $res->fetch_assoc()) {
    $mapData[]=Array($row['Name'],$row['Width'],$row['Height'],$row['X'],$row['Y']);
   
}


if(file_exists("WorldMap/$name/".$name."1.png"))
{
        $phase="";
}else{
        $phase="1_";
}

$im = imagecreatetruecolor(1002,668);
$im1 = imagecreatefrompng("WorldMap/$name/".$name.$phase."1.png");
$im2 = imagecreatefrompng("WorldMap/$name/".$name.$phase."2.png");
$im3 = imagecreatefrompng("WorldMap/$name/".$name.$phase."3.png");
$im4 = imagecreatefrompng("WorldMap/$name/".$name.$phase."4.png");
$im5 = imagecreatefrompng("WorldMap/$name/".$name.$phase."5.png");
$im6 = imagecreatefrompng("WorldMap/$name/".$name.$phase."6.png");
$im7 = imagecreatefrompng("WorldMap/$name/".$name.$phase."7.png");
$im8 = imagecreatefrompng("WorldMap/$name/".$name.$phase."8.png");
$im9 = imagecreatefrompng("WorldMap/$name/".$name.$phase."9.png");
$im10 = imagecreatefrompng("WorldMap/$name/".$name.$phase."10.png");
$im11 = imagecreatefrompng("WorldMap/$name/".$name.$phase."11.png");
$im12 = imagecreatefrompng("WorldMap/$name/".$name.$phase."12.png");

imagecopy($im,$im1,0,0,0,0,256,256);
imagecopy($im,$im2,256,0,0,0,256,256);
imagecopy($im,$im3,512,0,0,0,256,256);
imagecopy($im,$im4,768,0,0,0,234,256);
imagecopy($im,$im5,0,256,0,0,256,256);
imagecopy($im,$im6,256,256,0,0,256,256);
imagecopy($im,$im7,512,256,0,0,256,256);
imagecopy($im,$im8,768,256,0,0,234,256);
imagecopy($im,$im9,0,512,0,0,256,156);
imagecopy($im,$im10,256,512,0,0,256,156);
imagecopy($im,$im11,512,512,0,0,256,156);
imagecopy($im,$im12,768,512,0,0,234,156);
$index=1;
$ix=0;
$iy=0;

function mapChunk($width,$height,$name,$zone)
{
        $im=imagecreatetruecolor($width,$height);
        $black = imagecolorallocate($im, 0, 0, 0);
        imagecolortransparent($im, $black);
        imagefill($im,0,0,$black);
        imagealphablending($im, false);
        imagesavealpha($im, true);
        $tw=ceil($width/256);
        $th=ceil($height/256);
        $index=1;
       
        for($y=0;$y < $th;$y++)
        {
                for($x=0;$x < $tw;$x++)
                {
                        $cwidth = ((($x+1)*256) > $width ? $width - $x*256 :256);
                        $cheight = ((($y+1)*256) > $height ? $height - $y*256 :256);
                        $imx=imagecreatefrompng("Worldmap/$zone/".$name.$index.".png");
                        imagecopy($im,$imx,($x*256),($y*256),0,0,$cwidth,$cheight);
                        $index++;
                }
        }
        return $im;
}

for($i=0;$i< count($mapData);$i++)
{
        imagecopy($im,mapChunk($mapData[$i][1],$mapData[$i][2],$mapData[$i][0],$name),$mapData[$i][3],$mapData[$i][4],0,0,$mapData[$i][1],$mapData[$i][2]);
       
}
imagepng($im);
imagedestroy($im);
?>

Finally, this is the script used to parse the dbc files and insert it into the database

Code:

<?
function sUnpack($format,$data)
{
        $temp=unpack($format,$data);
        return $temp[1];
       
}

function prepStrings($stringTable)
{
        $offsets=Array();
        $strings=Array();
        for($x=0;$x< strlen($stringTable);$x++)
        {
                if($stringTable[$x]=="\0")
                {
                        $offsets[]=$x+1;
                }
        }
        for($x=0;$x < count($offsets)-1;$x++)
        {
                $strings[$offsets[$x]]=substr($stringTable,$offsets[$x],$offsets[$x+1]-$offsets[$x]-1);
        }
        return $strings;
}

function makeTable($data,$fields,$rowSize)
{
        $dataTable=Array();
        $rows=str_split($data,$rowSize);
        for($x=0;$x<count($rows);$x++)
        {
                $dataTable[]=str_split($rows[$x],4);
        }
        return $dataTable;
       
       
}

function formatTable($dataTable,$stringCols,$floatCols,$strings)
{
        for($x=0;$x < count($dataTable[0]);$x++)
        {
                for($y=0;$y < count($dataTable);$y++)
                {
                        if(in_array($x,$stringCols)){
                               
                                        @$dataTable[$y][$x]=$strings[sUnpack("l",$dataTable[$y][$x])];
                               
                        }elseif(in_array($x,$floatCols))
                        {
                                $dataTable[$y][$x] = sUnpack("f",$dataTable[$y][$x]);
                        }
                        else
                        {
                                $dataTable[$y][$x] = sUnpack("l",$dataTable[$y][$x]);
                        }
                }
        }
        return $dataTable;
}

/* DBC files don't contain any type information or field names,
so this info needs to be artificially provided to the function via
arrays containing 0-indexed column maps. For instance, if column 0
and column 3 are string type, $stringCols would equal Array(0,3)

field names/types courtesy of the WoWDev wiki*/

function readDBC($filename,$stringCols,$floatCols)
{
        $handle = fopen($filename,"rb");
        $test = fread($handle,4);
        $records = sUnpack("L",fread($handle,4));
        $fields = sUnpack("L",fread($handle,4));
        $rowSize= sUnpack("L",fread($handle,4));
        $stringSize= sUnpack("L",fread($handle,4));
        if($test=="WDB2")
        {
                fseek($handle,28,SEEK_CUR);
        }
        $data=fread($handle,$records*$rowSize);
        fseek($handle,-$stringSize,SEEK_END);
        $stringTable=fread($handle,$stringSize);
        $strings=prepStrings($stringTable);
        $dataTable=makeTable($data,$fields,$rowSize);
        $dataTable=formatTable($dataTable,$stringCols,$floatCols,$strings);
        return $dataTable;
}
$overlay = readDBC("WorldMapOverlay.dbc",Array(6),Array());
$area = readDBC("WorldMapArea.dbc",Array(3),Array(4,5,6,7));


$mysqli = new mysqli("localhost", "root", "password", "WoWMapStuff");
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
for($y=0;$y < count($area);$y++)
{
        $valstring="";
        for($x=0;$x < count($area[$y]);$x++)
        {
                $valstring.="'".$area[$y][$x]."'";
                if($x < count($area[$y])-1)$valstring.=",";
        }
        $query1 = "INSERT INTO worldmaparea (ID,MapID,AreaTableID,AreaName,Y1,Y2,X1,X2,Flag,Flag2,Flag3,UNK1,UNK2,UNK3) VALUES($valstring)";
        if(!$mysqli->query($query1))
        {
                echo $mysqli->error;
        }
}

for($y=0;$y < count($overlay);$y++)
{
        $valstring="";
        for($x=0;$x < count($overlay[$y]);$x++)
        {
                $valstring.="'".$overlay[$y][$x]."'";
                if($x < count($overlay[$y])-1)$valstring.=",";
        }
        $query1 = "INSERT INTO worldmapoverlay (ID,WorldMapAreaID,AreaTableID1,AreaTableID2,AreaTableID3,AreaTableID4,Name,Width,Height,X,Y,Y1,X1,Y2,X2,UNK) VALUES($valstring)";
        if(!$mysqli->query($query1))
        {
                echo $mysqli->error;
        }
}


?>



All times are GMT -6. The time now is 06:28 PM.

vBulletin © 2019, Jelsoft Enterprises Ltd
© 2004 - 2019 MMOUI