Thread Tools Display Modes
07-01-12, 01:48 PM   #1
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
Converting multiple BLPs (or PNGs) into a single BLP (or PNG)

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:
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)

--
Attached Files
File Type: zip Pandaria 5.0.1.15799.zip (1.01 MB, 837 views)

Last edited by Ketho : 07-02-12 at 12:12 AM.
  Reply With Quote
07-01-12, 01:49 PM   #2
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
----------

Last edited by Ketho : 07-02-12 at 12:12 AM.
  Reply With Quote
07-01-12, 04:55 PM   #3
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
As far as I know, the game just pieces them together in the correct locations.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-01-12, 05:00 PM   #4
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
but I want to have them pieced together out of the game :P
  Reply With Quote
07-01-12, 05:01 PM   #5
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Then you'll have to use Photoshop.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-01-12, 06:50 PM   #6
Haleth
This Space For Rent
 
Haleth's Avatar
Featured
Join Date: Sep 2008
Posts: 1,173
Perhaps slightly unrelated, but is there a reason why the maps are stored in separate pieces? I can't think of any.
  Reply With Quote
07-01-12, 09:29 PM   #7
Rilgamon
Premium Member
 
Rilgamon's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Sep 2009
Posts: 822
Originally Posted by Haleth View Post
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.
__________________
The cataclysm broke the world ... and the pandas could not fix it!
  Reply With Quote
07-01-12, 11:58 PM   #8
Cybeloras
A Fallenroot Satyr
 
Cybeloras's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 28
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.
  Reply With Quote
07-02-12, 05:54 AM   #9
Othgar
"That" Guy
 
Othgar's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2010
Posts: 228
I couldn't wait.. I had to assemble it

Click image for larger version

Name:	Pandaria.jpg
Views:	837
Size:	302.1 KB
ID:	7015
__________________


  Reply With Quote
07-02-12, 01:47 PM   #10
Ketho
A Pyroguard Emberseer
 
Ketho's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2010
Posts: 1,026
Originally Posted by Othgar View Post
I couldn't wait.. I had to assemble it

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

Last edited by Ketho : 07-02-12 at 01:52 PM.
  Reply With Quote
07-02-12, 02:25 PM   #11
Othgar
"That" Guy
 
Othgar's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2010
Posts: 228
Originally Posted by Ketho View Post
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.
__________________


  Reply With Quote
04-20-14, 07:54 AM   #12
Digital_Utopia
A Flamescale Wyrmkin
 
Digital_Utopia's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2012
Posts: 110
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
__________________
  Reply With Quote
04-21-14, 07:35 AM   #13
Digital_Utopia
A Flamescale Wyrmkin
 
Digital_Utopia's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2012
Posts: 110
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;
	}
}


?>
__________________
  Reply With Quote

WoWInterface » Developer Discussions » Graphics Help » Converting multiple BLPs (or PNGs) into a single BLP (or PNG)

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off