Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

mmb

Criar função para ler arquivo binário

Recommended Posts

Galera estou tentando criar uma função no PHP que consiga ler um arquivo binário e tranformar em uma imagem. Existe já essa função pronta em uma outra linguagem(http://code.google.com/p/tibiaapi/source/b...SpriteReader.cs)

 

Gostaria de saber se tem como tranformar isso para o php?

 

Aqui tem um comentario de um cara que explica como funciona esse arquivo:

 

The first 4 bytes contain information for the sprite version(?), like in the .dat file I'm not sure what this information is used for, maybe so the client can make sure you're using the right sprite file(?). The next 2 bytes are the number of sprites in the file. Then starts each sprites information.

 

Each sprite is offset by 4 and the sprites start 6 bytes from the beginning of the file, because of the sprite version and number of sprites. Also, the first sprite has an ID of 2 so you have to subtract 1 from each sprite ID to get to its offset. The equation used for this is (6 + (spriteID - 1) * 4). Now that we know this let's get back to the sprite information.

 

From what I understand the first 3 bytes of each sprite is unnecessary when getting the sprite's pixel information, so just skip the first 3 bytes. The next 2 bytes are the size of the sprite, ie. if this returned 36 then the sprite would be 6x6 pixels. The next 2 bytes are the amount of transparent pixels until a colored pixel. Then the next 2 bytes are the amount of colored pixels until a transparent pixel. The next 3 bytes are the RGB value of the colored pixels and the amount depends on how many colored pixels were found. (ie. If 1 colored pixel was found then there would just be 3 bytes [r][g], if there were 2 colored pixels found then there would be 2 sets of 3 bytes [r][g][r][g].) The transparent/colored pixel information is read from left to right (starts at the top-left of the sprite and ends at the bottom-right).

 

Here's the structure of the first sprite including the header information (spr version and number of sprites). [x] = number of bytes:

 

[4] - spr version = 1228754556
[2] - number of sprites = 28729
[3] - ?
[2] - sprite size = 512
[2] - transparent pixels = 397
[2] - colored pixels = 4
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 27
[2] - colored pixels = 5
[3] - RGB value = [0][0][0]
[3] - RGB value = [12][84][17]
[3] - RGB value = [18][145][21]
[3] - RGB value = [8][88][12]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 3
[2] - colored pixels = 1
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 22
[2] - colored pixels = 6
[3] - RGB value = [0][0][0]
[3] - RGB value = [16][98][28]
[3] - RGB value = [17][199][21]
[3] - RGB value = [21][169][28]
[3] - RGB value = [9][104][15]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 2
[2] - colored pixels = 4
[3] - RGB value = [0][0][0]
[3] - RGB value = [115][180][44]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 19
[2] - colored pixels = 8
[3] - RGB value = [0][0][0]
[3] - RGB value = [157][8][13]
[3] - RGB value = [235][30][31]
[3] - RGB value = [8][174][17]
[3] - RGB value = [13][105][26]
[3] - RGB value = [157][8][13]
[3] - RGB value = [237][27][35]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 1
[2] - colored pixels = 4
[3] - RGB value = [0][0][0]
[3] - RGB value = [4][57][8]
[3] - RGB value = [115][180][44]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 19
[2] - colored pixels = 12
[3] - RGB value = [0][0][0]
[3] - RGB value = [6][62][10]
[3] - RGB value = [6][60][10]
[3] - RGB value = [12][152][17]
[3] - RGB value = [13][97][26]
[3] - RGB value = [6][62][10]
[3] - RGB value = [6][62][10]
[3] - RGB value = [1][40][5]
[3] - RGB value = [0][0][0]
[3] - RGB value = [4][69][9]
[3] - RGB value = [33][169][45]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 21
[2] - colored pixels = 11
[3] - RGB value = [0][1][0]
[3] - RGB value = [5][61][10]
[3] - RGB value = [13][174][18]
[3] - RGB value = [26][189][35]
[3] - RGB value = [12][84][25]
[3] - RGB value = [1][40][5]
[3] - RGB value = [8][95][13]
[3] - RGB value = [16][169][21]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 20
[2] - colored pixels = 9
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][1][0]
[3] - RGB value = [7][55][12]
[3] - RGB value = [25][188][32]
[3] - RGB value = [19][234][23]
[3] - RGB value = [22][132][29]
[3] - RGB value = [7][61][10]
[3] - RGB value = [6][61][10]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 1
[2] - colored pixels = 5
[3] - RGB value = [0][0][0]
[3] - RGB value = [119][187][45]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 17
[2] - colored pixels = 8
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [6][42][8]
[3] - RGB value = [15][148][20]
[3] - RGB value = [18][231][23]
[3] - RGB value = [19][184][23]
[3] - RGB value = [16][86][22]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 1
[2] - colored pixels = 6
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [1][35][4]
[3] - RGB value = [5][82][9]
[3] - RGB value = [131][205][49]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 17
[2] - colored pixels = 14
[3] - RGB value = [0][0][0]
[3] - RGB value = [115][180][44]
[3] - RGB value = [1][9][3]
[3] - RGB value = [15][103][20]
[3] - RGB value = [17][224][22]
[3] - RGB value = [30][192][38]
[3] - RGB value = [20][105][27]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [1][22][4]
[3] - RGB value = [15][145][19]
[3] - RGB value = [0][0][0]
[3] - RGB value = [1][37][4]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 18
[2] - colored pixels = 14
[3] - RGB value = [0][0][0]
[3] - RGB value = [6][85][10]
[3] - RGB value = [0][0][0]
[3] - RGB value = [13][104][18]
[3] - RGB value = [18][155][27]
[3] - RGB value = [21][225][27]
[3] - RGB value = [23][179][30]
[3] - RGB value = [22][153][31]
[3] - RGB value = [0][0][0]
[3] - RGB value = [13][178][16]
[3] - RGB value = [15][194][19]
[3] - RGB value = [13][178][19]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 19
[2] - colored pixels = 13
[3] - RGB value = [0][0][0]
[3] - RGB value = [4][63][9]
[3] - RGB value = [0][0][0]
[3] - RGB value = [13][82][18]
[3] - RGB value = [19][205][26]
[3] - RGB value = [19][206][26]
[3] - RGB value = [14][190][20]
[3] - RGB value = [18][151][24]
[3] - RGB value = [17][143][22]
[3] - RGB value = [8][101][12]
[3] - RGB value = [14][197][21]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 20
[2] - colored pixels = 12
[3] - RGB value = [0][0][0]
[3] - RGB value = [4][63][8]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [22][134][31]
[3] - RGB value = [24][137][33]
[3] - RGB value = [0][0][0]
[3] - RGB value = [11][84][15]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [6][78][10]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 21
[2] - colored pixels = 2
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 1
[2] - colored pixels = 2
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[2] - transparent pixels = 1
[2] - colored pixels = 4
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]
[3] - RGB value = [0][0][0]

Eae alguém vai encarar?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Se você conseguir posta no www.phpclasses.org provavelmente você vá ganhar um reconhecimento de inovação =D

 

Boa sorte ai, eu não encaro não =X;

Procure esta funcão em C, já deve existir assim para converter para PHP é facil.

 

sucesso pra ti

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom é só utilizar:

 

fopen('arquivo','rb');

Ele irá ler o arquivo em binário.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não é tão simples assim, andei brincando e ja cheguei nisso:

 

function getSpriteImage($spriteId) {
	
	$fp = fopen('C:\Arquivos de Programas\Tibia 8.41\Tibia.spr', 'rb');
	
	$im = imagecreatetruecolor(32, 32);
	
	
	fseek($fp, 6 + ($spriteId - 1) * 4);
	$address = unpack('I', fread($fp, 4));
	$address = $address[1];
	

	fseek($fp, $address+3);
	
	$size = unpack('s', fread($fp, 2));
	$size = $size[1];
	
	$counter = 0;
	$read = 0;
	
	while($read < $size) {
		$transparent_pixels = unpack('s', fread($fp, 2));
		$transparent_pixels = $transparent_pixels[1];

		$colored_pixels = unpack('s', fread($fp, 2));
		$colored_pixels = $colored_pixels[1];

		
		$read += 4;
		$counter += $transparent_pixels;		
		

		for($i = 0; $i < $colored_pixels; $i++) {
			$rgb = unpack('@', fread($fp, 3));
			echo var_dump($rgb);
			imagesetpixel($im, $counter % $size, $counter / $size, $rgb);
			$counter++;					
		}
		
		
		$read = $read + $colored_pixels * 3;
		
	}
	//echo var_dump($rgb);
	//return imagegif($im);
	fclose($fp);		
}

Mas to impacado no trecho "$rgb = unpack('@', fread($fp, 3));", pois preciso armazenar em 3 arrays....

 

Eae to indo pelo caminho certo?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom meu amigo ele criou uma extensão de imagem em PHP, veja o codigo dele e vê se ajuda:

 

<?PHP // BPF.PHP v1.1.2b - Desenvolvido por Rafael Perrella

class BPF {
	// Lê um arquivo
	function	readPFile ($Path)	{
	$Stream = FOpen ($Path, "r+b");
	$PicString = "";
	While (! FEOF ($Stream)) $PicString .= FGets ($Stream, 4096);

	FClose ($Stream);
	Return $PicString;
	}

	// Transforma uma string BPF em imagem
	function	loadBPF ($Pic)	{

	# Cria nova imagem
	$width = $this->getBPFWidth ($Pic);
	$height = $this->getBPFHeight ($Pic);
	$init = $this->getBPFInit ($Pic);
	$trans = $this->BPFAcceptsTransparency ($Pic);
	$img = ImageCreateTrueColor ($width, $height);

	# Verifica se PODE ser BPF
	if (! $this->canBeBPF ($Pic)) Return FALSE;
	$len = StrLen ($Pic);

	# Permite transparência na imagem
	If ($trans) {
		ImageAlphaBlending ($img, FALSE);
		ImageSaveAlpha ($img, TRUE);
	}

	For ($c = 0, $h = 0, $t = 0, $a = ($trans ? 4 : 3); $h < $height; $h ++)
		For ($w = 0; $w < $width; $w ++, $c += $a) {
			$p = $init +$c;
			If ($p >= $len) Return $img;
			If ($Pic[$p] == "-") {
				If (! $t) $t = $trans *Ord ($Pic[$p +1]) *65536 + Ord ($Pic[$p +1 +$trans]) *256 + Ord ($Pic[$p +2 +$trans]); Else $t -= 1;
				If ($t) $p = $init +($c -= $a); Else $p = $init +($c += $a);
			}
			If ($p == $len) Return $img;
			$pixel = ImageColorAllocateAlpha ($img, Ord ($Pic[$p]), Ord ($Pic[$p +1]), Ord ($Pic[$p +2]), $trans *Ord ($Pic[$p +3]));
			ImageSetPixel ($img, $w, $h, $pixel);
		}
	Return $img;
	}

	// Verifica se é BPF
	function	canBeBPF ($Pic)	{

	If (StrLen ($Pic) < 10) Return FALSE;
	If (SubStr ($Pic, 0, 3) != "BPF") Return FALSE;
	Return TRUE;
	}

	// Retorna a posição do primeiro caractere de pixel
	function	getBPFInit ($Pic)	{

	$len = StrLen ($Pic);
	For ($i = 0; $i < $len && $Pic[$i] != "!"; $i ++);
	Return $i +1;
	}

	// Largura e altura de uma imagem BPF
	function	getBPFWidth ($Pic)	{

	$w = "";
	$len = StrLen ($Pic);
	For ($i = ($Pic[3] == Chr (1)) ? 4 : 3; $i < $len && $Pic[$i] != "."; $i ++)
		$w .= $Pic[$i];
	Return $w;
	}

	function	getBPFHeight ($Pic)	{

	$h = "";
	$len = StrLen ($Pic);
	For ($i = 3; $i < $len && $Pic[$i] != "."; $i ++);
	For (++ $i; $i < $len && $Pic[$i] != "!"; $i ++)
		$h .= $Pic[$i];
	Return $h;
	}

	// Transparência em um BPF
	function	BPFAcceptsTransparency ($Pic)	{

	If (! $this->canBeBPF ($Pic)) Return FALSE;
	If ($Pic[3] == Chr (1)) Return TRUE;
	Return FALSE;
	}
}

If (IsSet ($_GET['img'])) {
	$BPF = new BPF;
	Header ("Content-Type: image/png"); 
	ImagePNG ($BPF->loadBPF ($BPF->readPFile ($_GET['img'])));
}

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que não ajuda muito não http://forum.imasters.com.br/public/style_emoticons/default/cry.gif

 

To precisando que alguem mi ajude naquele ultimo unpack...

 

[Edit]

 

Brincando mais um pouco e descobri que estou no caminho certo...

 

Utilizando este código obtenho "1228754556" que são os exatos "[4] - spr version = 1228754556" que o cara mostrou.

$fp = fopen('C:\Arquivos de Programas\Tibia 8.4\Tibia.spr', 'rb');

echo var_dump(unpack('i', fread($fp, 2)));


fclose($fp);

 

Utilizando este código obtenho "28729" que tambem é igual a "[2] - number of sprites = 28729"

$fp = fopen('C:\Arquivos de Programas\Tibia 8.4\Tibia.spr', 'rb');

fseek($fp, 4);
echo var_dump(unpack('s', fread($fp, 2)));


fclose($fp);

 

Porem ao utilizar este código não consigo chegar a nenhum resultado igual a "[2] - sprite size = 512", ja tentei utilizar todos os parâmetros dessa lista(unpack) e nenhum chegou perto do resultado esperado.

$fp = fopen('C:\Arquivos de Programas\Tibia 8.4\Tibia.spr', 'rb');

fseek($fp, 9);
echo var_dump(unpack('s', fread($fp, 2)));


fclose($fp);

E agora qual o mistério?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu recomendo que você faça um loop verificando caractere por caractere, sendo assim utilizando no unpack. E de preferencia use fgets.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Após alguns dias quase cheguei ao resultado esperado, o código é esse:

 

header("Content-type: image/gif");

function getSpriteImage($spriteId) {
	
	$fp = fopen('C:\Arquivos de Programas\Tibia 8.42\Tibia.spr', 'rb');
	
	fseek($fp, (6 + ($spriteId - 1) * 4));
	$address = unpack('I', fread($fp, 4));
	$address = $address[1];
	
	fseek($fp, $address+3);
	
	$size = unpack('S', fread($fp, 2));
	$size = $size[1];
	
	$im = imagecreatetruecolor(32, 32);

	$counter = 0;
	$read = 0;

	while($read < $size) {
		$transparent_pixels = unpack('S', fread($fp, 2));
		$transparent_pixels = $transparent_pixels[1];

		$colored_pixels = unpack('S', fread($fp, 2));
		$colored_pixels = $colored_pixels[1];

		$read += 4;
		$counter += $transparent_pixels;			

		for($i = 0; $i < $colored_pixels; $i++) {
			$rgb = unpack('Cr/Cg/Cb', fread($fp, 3));

			if($rgb['r'] == 0 && $rgb['g'] == 0 && $rgb['b'] == 0) {
				$rgb = array('r' => 255, 'g' => 0, 'b' => 255);
			}
			imagesetpixel($im, intval($counter % 32), intval($counter / 32), imagecolorallocate($im, $rgb['r'], $rgb['g'], $rgb['b']));

			$counter++;	
			
		}
		
		
		$read += 3*$colored_pixels;
	}

	fclose($fp);

	$in = imagecolorallocate($im, 0, 0, 0);
	imagecolortransparent($im, $in);
	
	/*while($x != 32 && $y != 32) {
		if($x == 32) {
			$x = 0;
			$y++;
		}
		
		if(imagecolorat($im, $x, $y) == 16711935) {
			imagesetpixel($im, $x, $y, imagecolorallocate($im, 0, 0, 0));
		}
		$x++;
	}*/
		
	$img = imagegif($im);
	imagedestroy($im);
	return $img;
			
}

getSpriteImage(3);
Utilizando este código eu obtenho esse resultado:

Imagem Postada

 

O problema agora é voltar o rosa(RGB 255, 0, 255) para o preto, visto que ao usar a função createtruecolor o fundo fica em preto. Ja tentei dar um loop verificando pixel por pixel mas o resultado é o mesmo, ja utilizei imagecolorexact e imagecolorset e o resultado continua igual...

 

Se trocar o imagecretetruecolor para imagecreate obtenho isso:

Imagem Postada

 

A imagem sai quase perfeita, mas não sei por qual motivo que só sai pela metade, se for uma imagem que não ocupa tantos pixels sai perfeitamente como desejo...

 

 

E agora o que fazer?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Este rosa não seria para dar transparencia dentro do jogo? Ao menos em Ragnarok esse rosa é pra isso.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Seria sim, tanto que no imagecreate eu seto o bg como rosa e no final apenas coloco como transparente, mas como visto algumas imagem ficam pela metade(??). Então sou obrigado a utilizar a imagecreatruecolor e que tem a cor preta como fundo, ae eu troco na imagem tudo que for preto pra rosa, no final coloco como transparente o preto e trocaria o rosa para o preto novamente, mas não estou conseguindo nesta última etapa...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olha me desculpe, mas não irei poder lhe ajudar, é muito raro eu mexer com Imagens, vou ler essas funções no Manual do PHP, depois se não tiver resolvido eu ajudo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá pessoal;

 

Pelo que percebo, estão com problema na apresentação da imagem.

Dica: Olhem o tamanho maximo de leitura de imagem e arquivos binários dentro do PHP.ini.

 

espero ter ajudado.

 

Abraço a todos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.