Manipulação binária de arquivos/memória (Game Maker)

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qua 04 Jan 2012, 23:04



Manipulação binária de arquivos/memória

No nosso tutorial anterior sobre operadores bitwise (clique aqui) nós aprendemos quais são as operações usadas para trabalhar com bits. Também vimos que essas operações partem da lógica de comparação entre dois bits e que os operadores são AND, OR, XOR ou NOT. A partir dessa aula nós vamos dividir o conteúdo da matéria para cada linguagem, pois cada uma tem seus pormenores e precisam de uma explicação mais detalhada antes de prosseguirmos. Nessa aula, usaremos o Game Maker. Boa sorte, bons estudos e use o tópico pra perguntar alguma coisa se precisar.

Nós já sabemos que tudo em nosso computador é feito por bits. Uma foto em Jpeg é feita de bits tanto quanto uma música em Mp3, no entanto, o que faz a diferenciação entre seus conteúdos é o software usado para abrir cada um desses arquivos. O leitor de fotos está preparado para decodificar o formato Jpeg e o player de áudio decodificar para o formato Mp3. Porém, alguns arquivos podem ter suas extensões trocadas e ser abertos por programas para os quais eles não foram escritos. É claro que essa experiência será inútil, pois não resultará em nada além de bagunça na interpretação dos dados. Como exemplo, tente abrir uma foto Jpeg em um editor de textos e o resultado será um texto indecifrável!


Isso se deve ao fato de que o computador não se importa com o que significa aquele monte de bits! O que importa de fato é como eles são interpretados pra nós, seres humanos. Aí é que entra o papel do software, que vai decodificar o conteúdo da forma correta e mostrar pra gente nos periféricos, seja monitor, caixa de som, impressora, etc.. Então, para manipularmos esses dados binários nós precisamos saber exatamente o que significam esses valores representados por cada bit ou byte, obedecendo a ordem e estrutura do arquivo que estamos lidando. Precisamos conhecer como o arquivo é montado e onde estão as informações que precisamos.

A maioria dos tipos de arquivos mais conhecidos (bitmap, jpeg, mp3, png, gif, wav...) segue uma ordem predefinida para que os dados sejam gravados em seu conteúdo. Isso é muito bom pois evita erros tanto na escrita quanto na leitura dos dados. Na maioria das vezes, essa ordem é dita por uma espécie de tabela que fica no início do arquivo, partindo do primeiro byte até algum tamanho predefinido (dependendo do tipo do arquivo), que chamamos de cabeçalho. E quase todo tipo de arquivo tem seu próprio cabeçalho. Ele contém várias informações importantes, referentes ao conteúdo e como ele deve ser interpretado pelo software.

Como exemplo, vamos ver como é o cabeçalho de um arquivo Bitmap genérico, sem compressão... É o formato de imagem mais comum que existe e é de fácil manipulação. Foi adotado pela Microsoft até para uso em memória do próprio Windows, por ser simples e depender de muito pouco pré-processamento. Também existem outros formatos de Bitmap que usam um método de compactação chamado de RLE. Inclusive, é a mesma compactação usada em vários outros tipos de arquivos conhecidos que usamos diariamente! Mas, por hora, vamos deixar o RLE um pouco de lado... Ainda teremos matérias especiais sobre compactação em outras ocasiões! Todavia, quando o Bitmap usa RLE, é somente em casos onde o arquivo tem, no máximo, 256 cores (bitmap indexado). No nosso exemplo, o Bitmap usará o padrão True Colors, que é excessivamente grande, mas de fácil compreensão.

O cabeçalho do formato Bitmap possui 54 bytes, sendo que:
2 Os dois primeiros bytes são marcados com os caracteres ASCII “B” e “M”, para identificar o arquivo como sendo um Bitmap.
4 Bytes para identificar o tamanho do arquivo (em bytes).
4 Bytes reservados para futuras implementações no formato. No momento devem ser todos marcados como zero (0).
4 Bytes que indicam onde começam os dados da imagem (dentro do conteúdo binário). No nosso caso será, obviamente, o tamanho do cabeçalho (54, decimal), pois é ele que se deve “saltar” para começarmos a ler/escrever a imagem.
4 Bytes que indicam uma espécie de “sub-cabeçalho”, o valor deve ser 40 (decimal).
4 Bytes que indicam a largura da imagem em pixels
4 Bytes que indicam a altura da imagem em pixels
2 Bytes que indicam o número de camadas da imagem. Marque como “1”
2 Bytes que indicam a quantidade de bits por pixel, no nosso exemplo, deve ser o valor 24
4 Bytes que indicam o tipo de compactação do arquivo. Esse valor pode ser 0 (sem compressão), 1 (RLE 8 bits) ou 2 (RLE 4 bits).
4 Bytes que indicam o tamanho da imagem (exceto o cabeçalho) em bytes. Esse cálculo é igual a (largura x altura x bytes por pixel)
4 Resolução horizontal da imagem
4 Resolução vertical da imagem
4 Bytes para representar o número de cores que a imagem usa. Deixe sempre como 0 para que esse valor corresponda ao máximo permitido, dentro das limitações especificadas no próprio arquivo.
4 Bytes para representar o número de cores importantes. Isso é mais usado quando o arquivo é Bitmap de 8 ou 4 bits. Marque esse campo como zero (0).


Vamos recaptular uma coisa importante agora! Como vimos anteriormente na nossa aula sobre RGB em games (clique aqui), cada pixel do formato True Colors é representado por 3 bytes, um para cada componente de cor. Embora a cor seja dada por Red, Green e Blue (pois segue a ordem real de cores do espectro luminoso), não é necessariamente essa a ordem em que os bytes são dispostos na memória. A ordem correta para trabalhar com eles é Blue, Green e Red (BGR). Portanto, a partir do ponto onde termina esse cabeçalho até o final do arquivo, cada conjunto de 3 bytes será um pixel da imagem.

Até aqui tudo bem, mas nem tudo são flores... No caso do Bitmap, há uma restrição na forma como esses bytes são escritos! Cada linha do Bitmap tem que ser um número de bytes múltiplo de 4. Caso não seja, você deve arredondar o número para o múltiplo mais próximo e preencher esses bytes extras com zero (0). Por exemplo, se a nossa imagem tivesse 295 pixels de largura, escreveríamos 888 bytes (296 x 3) ao invés de 885 bytes (295 x 3), sendo que os 3 últimos bytes dessa linha (888 – 885) serão nulos (0) e não farão diferença na imagem.

Além disso, os pixels da imagem são escritos de baixo para cima. O primeiro pixel corresponderá ao do canto inferior esquerdo e o último pixel será o do canto superior direito. Apesar de parecer complicado, essa forma de escrita torna o processo de manipulação muito mais simples, pois corresponde ao sistema natural de um plano cartesiano.

Sabendo tudo isso agora fica fácil criar um arquivo Bitmap até em scripts Batch. Quem freqüenta a nossa categoria do fórum sobre linha de comando possivelmente já deve ter em mente que bastaria criar um cabeçalho padrão, usar duas variáveis para os valores de largura e altura e escrever um Bitmap em branco. Taí um exemplo que eu fiz pra vocês de um arquivo batch para criar um Bitmap com tamanho preestabelecido. Ele só vai funcionar em sistemas que dão suporte ao Debug para processadores de 32 bits. Infelizmente no Windows 7 ele não funcionará.

Código:

@echo off
rem Script: Cria um bitmap em branco
rem Author: BrendanLS (bl8086)

if "%~1"=="" goto usage
goto initfile

:gethex
   set ntype=0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
   set char=%~1

   for %%a in (%ntype%) do for %%b in (%ntype%) do (
      set /a n=0x%%a%%b
      if !n! equ %char% (
         set hchar=%%a%%b
         goto quit
         )
      )

:hexnumb
   set /a nval=%~2

   for /l %%n in (0,1,3) do (
      set /a "ncalc = (nval >> (%%n * 8)) & 0xff"
      call :gethex !ncalc!
      set %~1%%%n=!hchar!
      )

   goto quit

:initfile
   if "%~2"=="" goto usage
   if "%~3"=="" goto usage

   set /a isreal=%~1
   if %isreal% equ 0 goto usage

   set /a isreal=%~2
   if %isreal% equ 0 goto usage

   set fname=%~3
   setlocal enabledelayedexpansion
   call :hexnumb w %~1
   call :hexnumb h %~2

   (
   echo n %fname:~0,8%.bmp
   echo e 100 42 4D EA 7C 0E 00 00 00 00 00 36 00 00 00 28 00
   echo e 110 00 00 %w0% %w1% %w2% %w3% %h0% %h1% %h2% %h3% 01 00 18 00 00 00
   echo e 120 00 00 B4 7C 0E 00 00 00 00 00 00 00 00 00 00 00
   echo e 130 00 00 00 00 00 00
   echo rcx
   echo 87
   echo w
   echo q
   )|debug > nul 2>&1

   goto quit

:usage
   echo.
   echo Sintaxe:
   echo criabmp [largura] [altura] [arquivo.bmp]


:quit
endlocal

Mas por que o script consegue criar um bitmap grande sem escrever o conteúdo de imagem dele? Embora saibamos que a memória do Debug é limitada a 64KB (portanto não há como escrever o arquivo todo), o que acontece é que o Paint abre esse arquivo lendo somente o cabeçalho (que gasta apenas 54 bytes). E como não há conteúdo da imagem, ele coloca o conteúdo como nulo, ou “tela em branco”. Também teríamos a opção de “sujar” esse bitmap pegando valores que estão na memória Ram no momento em que executamos o debug. Esses valores são aleatórios, podendo criar um Bitmap com conteúdo diferente a cada vez. Nada muito útil, mas não deixa de ser interessante para criar efeitos diferentes! Lembre-se que temos que explorar ao máximo os recursos que temos à mão.

Game Maker - Brincando com conteúdo binário:

Depois de toda aquela chatice sobre lógica e teoria, finalmente chegou a hora de botar a mão na massa! Agora vamos aprender a ler e escrever dados em arquivos usando bits. As operações de escrita e leitura são muito simples e não são diferentes do que você já está acostumado. São funções diretas que procuram um determinado valor de byte em alguma posição no arquivo. No exemplo que criei para o Game Maker, fiz um script que carrega um arquivo bitmap direto para dentro de uma surface, lendo cada pixel individualmente:

Hospedado no 4Shared, 1,1 MB:

Bom, alguns poderão pensar que "lidar com bitmaps no Game Maker usando um script que nós mesmos criamos (e ainda por cima usando surfaces)" será uma tremenda perda de tempo. Afinal, nele temos funções nativas e outras alternativas melhores de arquivos, como o PNG por exemplo. O que eu quero ressaltar aqui é que o interessante pra nós é o aprendizado. Não fique restrito ao script pois ele é só um exemplo básico do que você poderá fazer quando aprender a usar esses recursos. Você poderá criar (por que não?) seus próprios tipos de arquivo onde só o seu software será capaz de decodificar. Ou quem sabe, criar patchs para seus jogos apenas adicionando ou retirando dados binários do executável original. São muitas possibilidades, basta usar a criatividade!

Durante os nossos bate-papos lá no fórum da GMBR, rolou uma ideia de pegar um bitmap de 24 bits e transformar em um de 12 bits! Acabamos criando um arquivo de imagem personalizado de brincadeira. Nesse caso, cada componente de cor usaria um nibble (4 bits) ao invés de um byte (8 bits). A conversão ainda é bem simples, não é nenhum algoritmo robusto mas pelo menos dá pra ter uma noção do ganho de compactação do arquivo. Tudo já está no exemplo que fiz pra vocês. Taí o resultado da brincadeira nas imagens. O arquivo ficou menor e mais leve! O impacto da conversão das cores é o mesmo se usarmos o recurso de Posterizar a imagem no Photoshop usando 16 níveis de cor:


Imagem original: ela é um Bitmap de 24 bits, sem compactação:



Nossa imagem personalizada: ela usa 12 bits por pixel, reduzimos o tamanho do arquivo pela metade!



As funções que utilizaremos:


file_bin_open(fname, mod) - Abre um arquivo para manipulação binária. Fname é o nome do arquivo e seu caminho. Mod é o tipo de tratamento onde os valores podem ser: 0 para apenas leitura, 1 para apenas escrita e 2 para ambos. Essa função retornará um número id que utilizaremos para identificar esse arquivo nas demais funções binárias (como qualquer função que lida com arquivos). Isso é necessário, pois podemos trabalhar com até 32 arquivos simultaneamente. Também é bom lembrar que se o arquivo não existir, ele será criado pela função.

file_bin_close(fileid) - Termina as operações e fecha o arquivo. O id, como disse antes, deve ser especificado. Essa função é muito importante. Lembre-se se que - se tratando de manipulação binária - quando um arquivo está sendo usado no Windows, ele fica restrito para os demais aplicativos até que seja liberado pelo aplicativo que o está manipulando. Apesar de não ser obrigatório, é sempre bom fechar o arquivo para evitar erros.

A partir do momento em que abrimos um arquivo através de file_bin_open(), nós vamos navegar pelo conteúdo dele através de um indicador de posição que chamamos de ponteiro (não confunda com ponteiros de memória em variáveis). Antes de ler ou escrever algum byte no arquivo nós temos que mover o ponteiro para a posição que queremos e então operar com o valor que está lá. As funções a seguir lidam especificamente com isso:

file_bin_position(fileid) - Retorna a posição atual do ponteiro, em bytes. A posição 0 (zero) se refere ao início do arquivo.

file_bin_seek(fileid, pos) - Move o ponteiro para uma posição qualquer, em bytes. Há um fator importante a ser exclarecido aqui. Quando movemos o ponteiro para uma posição maior que o tamanho do arquivo e escrevemos alguma coisa ali, o tamanho do arquivo também será mudado para essa posição, ou seja, aumentará. Por exemplo, se você tiver um arquivo de 1 mb, mover o ponteiro para 700 mb e escrever um dado qualquer, o novo tamanho do arquivo será de 700 mb.

É por isso que não existe a função "append" como há nos arquivos de texto, pois ela é desnecessária. Para fazer um append no arquivo, basta mover o ponteiro até o final dele. Para saber o tamanho do arquivo, há a função file_bin_size(fileid), que retorna o tamanho em bytes.

file_bin_read_byte(fileid) - Lê o valor do byte na posição onde o ponteiro se encontrar.
file_bin_write_byte(fileid, byte) - Escreve um byte na posição onde o ponteiro se encontrar.

Por questão de comodidade, no Game Maker só temos leitura e escrita para bytes e não para bits. Para manipularmos bits, vamos usar a lógica binária que aprendemos no tutorial anterior. Através dela poderemos usar quantos bits quisermos, não importando a quantidade. Poderemos tratar cada bit individualmente ou usar nibbles. Nibble é o nome dado à um conjunto de 4 bits, ou seja, a metade de um byte.

À primeira vista, pode parecer inútil usar nibbles, mas é muito bom racionar de forma inteligente os recursos que temos! Vários hacks de roms de consoles 16bits se baseiam em valores de RGB simplificados, usando 5 bits ao invés de 8 para cada componente de cor. No sistema de cores do Super Nintendo, por exemplo, essa é a forma de armazenar cores: cada componente RGB usa 5 bits, o que abrange um valor de 0 a 31 possibilidades para cada um. Nesse caso, com apenas dois bytes (16 bits) temos um sistema de cores simples, mas eficiente!


Paleta de cores do Snes: 32 x 32 x 32 = 32768 cores

Você pode capturar um snapshot pelo emulador, olhar o valor RGB real da cor que gostaria de alterar, converter para esse sistema de 16bits, localizar o valor binário dentro da rom e modificá-la até mesmo através do Game Maker! É claro que existem outros detalhes, mas falaremos disso em outro tópico!

Até aí tudo bem, mas... Como eu faço pra trabalhar com valores maiores que 1 byte? Bom, é aí que entra o nosso operador bit shift em conjunto com os operadores lógicos, que estudamos no tutorial anterior (clique aqui). Vamos supor que você tenha um número inteiro que está entre 0 e 35.535, ou seja, um valor do tipo Word. Sabendo que ele gasta 2 bytes na memória para ser armazenado, o que vamos fazer é armazenar esses 2 bytes separadamente em um arquivo qualquer. Por exemplo:

Código:
valor := 19822; // Número que desejamos armazenar em arquivo
file_bin_write_byte(arquivo, valor >> 8); // Grava o primeiro byte do valor (77)
file_bin_write_byte(arquivo, valor & $ff); // Grava o segundo byte do valor (110)

Para ler o valor é ainda mais fácil:

Código:
valor := 0;
repeat (2) // Faz um loop com o número de bytes que a variável usa
begin
   valor := valor << 8;
   valor := valor | file_bin_read_byte(arquivo);
end;

A mesma regra vale para qualquer outro tipo de variável, mesmo que seja um valor negativo ou fracionado. Basta organizar bem onde você guarda esses dados no arquivo, e claro, o tamanho correto de cada um. Crie esquemas de tabelas para seus arquivos (como o exemplo do bitmap) para facilitar seu trabalho. Faça rascunhos ou anotações de como a estrutura binária do seu arquivo vai funcionar. Organização é essencial nessas horas! Enfim, acho que por enquanto é só! Se eu puder ajudar a eliminar alguma dúvida, é só perguntar aqui no tópico, vou ficar feliz em responder! Abraços e bons estudos!




Última edição por Borderline em Sex 14 Dez 2012, 15:06, editado 4 vez(es)

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por thundercats em Qua 04 Jan 2012, 23:57

Ninja8086

CARAMBA !!!
aula incrivel !!
aposto que ta cheio de salas secretas esse forum Cool

Editado por Joton
Evite post sem conteúdos na próximo você pode perde warning

thundercats

Número de Mensagens : 161
Idade : 21
Data de inscrição : 20/09/2011
Reputação : 1
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://gamemakerhtml5.blogspot.com/p/jogos.html

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 00:08

Acho que ficou meio grande rsss, tomara que não tenha ficado cansativo! Smile Qualquer dúvida, estamos aí... Valeu!

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Qui 05 Jan 2012, 10:39

Eu li o tutorial inteiro.
Ficou bem interessante.
Foi muito bom você colocar a tabela da estrutura bitmap.
Vou procurar mais tabelas do tipo, para ver como são outros arquivos.
Eu acho que 256^3 cores é muita coisa. Acho que se usassem a metade disso seria o suficiente e as imagens seriam mais leves.
Vou tentar fazer algo aqui e quando surgir alguma dúvida eu posto aqui.

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por Convidad em Qui 05 Jan 2012, 10:51

Realmente,este tutorial merece todo o mérito.Você soube usar bem o código de criar bitmaps,com binário e tals.Me interesso muito por batch e inclusive acho que sou melhor com batch do que com qualquer coisa xD
Este tutorial ficou tão bom que até li ele 2 vezes.

Meus parabéns,e sempre que quiseres postar tutoriais assim,poste,pois aprendo muito contigo Happy

Convidad
Convidado


Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 13:14



@Pedro

256^3 é muita coisa mesmo! O arquivo vai ficar grande. Como eu tinha comentado antes, dá pra reduzir pra outros esquemas mais leves. Aquele sisteminha de 2 bytes que eu comentei, usa 5 bits pra cada cor (0 a 32), e deixaria o arquivo 1/3 menor em tamanho.

Faz as contas, 32 x 32 x 32 = 32768 cores. É um número muito bom e pra sprites pequenos, fica bem compacto. Essa paleta aqui é a variação de todas as 32768 cores (paleta do Snes):



Mesmo assim ainda dá pra reduzir pra apenas 1 byte, só que o número de cores seria só 256, e a gente teria que ter uma tabela dessas cores. Mas se o camarada fizer uma conversão boa, fica excelente. Essa por exemplo é da Micro$oft:



Aqui é uma imagem com essa paleta da dita cuja:



O Gif usa esse esquema: reduz pra 256 cores e usa compactação LZW. Daí fica pequeno, mas é osso esse algoritmo do LZW... Enfim, jeito tem vários, o lance aí é você saber aproveitar o espaço que vc tem pra guardar o que quer.



@TRFN

Obrigado! Opa, legal saber que vc curte batch script! Também gosto demais! Já participei de um monte de comunidade, um fórum que eu acho excelente é o Batch-Satti. Esse Batch-Satti tem o Boss-Head, é um dos melhores programadores que eu já vi! Fica a dica aí, já que vc gosta! Happy

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Qui 05 Jan 2012, 14:27

Houve um problema quando eu testei o exemplo:


Na imagem apareceram algumas linhas brancas verticais.
Parece que isso ocorreu onde o brilho era maior...
O que pode ser?

Até mais!

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 14:40

Vou dar uma olhada. Aparece só quando carrega o canal vermelho? Ou com os outros também? E só com essa imagem ou com as outras também? Valeu!

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Qui 05 Jan 2012, 16:19

Em todos os canais.
Não testei com as outras imagens.

Valeu!

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 16:28

Tenta abrir as outras e vê se dá isso também. Preciso ver se é algo relacionado com o tamanho dessa imagem do Uncharted. O estranho é que aqui todas abrem sem isso. Tenta aí e me diz. E qual é o seu Gm? Valeu!

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Qui 05 Jan 2012, 16:42

É o Game Maker 8.0.

Eu coloquei a imagem do 640kb world, não tinha outra aqui, o resultado foi o mesmo. Só que agora as linhas apareceram em cima do 'kb' e no final também.

Outra dúvida: se eu usar 5 bits para cada componente da cor, teria o mesmo tamanho (as imagens teriam o mesmo tamanho) que usar 4 bits? De qualquer jeito seria 2 bytes. A menos que poupando alguns bits desse para juntá-los e formar outra cor.

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 18:22

Pedro, eu tentei olhar aqui de várias formas, tá estranho! Tentei no Gm6, no 7, no 8, todos abriram normal, tentei mudar resolução também e nada. Eu penso que se fosse algum "pulo de pixel" no script, ele seria uniforme pela imagem toda... eu comparei essa imagem com a gerada aqui no meu pc, são iguais, daí não pode ser saltos scratch

Tudo me faz pensar que pode ser algum problema com surface! Mas tá difícil dizer o que é, não tenho ideia do que pode tá causando isso. Eu tentaria diminuir bastante a surface nesse caso pra ver o que aconteceria. Pessoal, se alguém mais tiver testado e puder nos dar um retorno, por favor postem aí o que houve pra gente tentar ajudar!

Outra dúvida: se eu usar 5 bits para cada componente da cor, teria o mesmo tamanho (as imagens teriam o mesmo tamanho) que usar 4 bits? De qualquer jeito seria 2 bytes. A menos que poupando alguns bits desse para juntá-los e formar outra cor.

Usando 5 x 3 = 15 ainda sobra 1 bit dos 16 totais. Esse 1 bit vc tem duas alternativas: ou deixa ele lá sem mexer (pra facilitar a programação) ou aproveita ele juntando com os outros bits que sobrarem. A cada 16 bytes vc então economizaria 16 bits, aí é só usar essa sobra se fossem 2 bytes comuns e distribuir o valor entre esses bits.

Você pode usar do jeito que quiser. Dá um pouco de trabalho, mas faz as contas: se a cada 16 bytes você ganha 2 extras, proporcionalmente você tá ganhando 12,5 % de espaço em disco. Um arquivo de 1MB passaria a ter 896KB. A mesma coisa vale pra 4 bits só que nesse caso vai ser bem mais fácil pq vc tá mexendo com 1 byte e 1 nibble, que são valores pares.

Um esquema que facilita pra mexer com número ímpar de bits é você achar um múltiplo do valor. Por exemplo, o 5 bits. O múltiplo que cabe pra esse caso é usar 40 bits (8 bits x 5), portanto, 5 bytes. Daí você divide ele dessa forma:



É mais fácil de programar porque essa separação você faz só uma vez, o resto fica por conta de loops usando esse esquema.

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Qui 05 Jan 2012, 18:49

Você poderia fazer um exemplo, se não for pedir muito, de um sistema de Nibbles mesmo (12 bits)? 'Sistema' que eu digo é uma imagem onde cada pixel possui 12 bits de tamanho.

Até mais!

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 19:29

Ok! Vamos pra um exemplo na prática. Cada cor usa 12 bits, portanto BGR ficaria B = 1 nibble, G = 1 nibble, R = 1 nibble. Essa função faz um loop desde o início do arquivo até o final do arquivo, dessa forma:

-> Uma variável controla qual nibble será usado, se o da esquerda (quando a var for 0) ou o da direita (quando a var for 1). Se for o da esquerda, obviamente nós vamos ler um novo byte no arquivo usando file_bin_read_byte(), se for o da direita, nós vamos esperar.

-> Uma variável controla qual o componente BGR vai receber o nibble. 1 = B, 2 = G, 3 = R. A cada loop ela tem um incremento e toda vez que ela for maior que 3, significa que a cor está pronta e vamos reiniciar o processo.

-> O valor máximo de um componente de cor é 256. Portanto 256/nibble = 16. Simplificando, estamos reduzindo o sistema de cores de 24 bits para 12 bits de forma proporcional. Esse é o nosso valor de proporção! Vamos multiplicar o nibble que lemos do arquivo sempre por 16 (para gerar a cor mais próxima possível do sistema original de 24 bits).

Código:

qual_componente := 0; // 0 = blue, 1 = green, 2 = red
nibble_a_ou_b := 0; // 0 = [bits 1 a 4], 1 = [bits 5 a 8]
cor_real := 0; // Usaremos os nibbles pra formar esta cor

do
begin
   
    if nibble_a_ou_b = 0 then
    begin
        byte_lido := file_bin_read_byte(arquivo);
        valor_do_componente := byte_lido >> 4; // Arrasta 4 bits pra direita
    end else valor_do_componente := byte_lido & $F; // $F = 00001111 (bits 5 a 8)
   
    nibble_a_ou_b += 1; // Altera entre os nibbles
    if nibble_a_ou_b > 1 then nibble_a_ou_b := 0;
   
    // Criando a cor pelos valores dos nibbles:
    switch (qual_componente)
    begin
        case (0): cor_real := (valor_do_componente * 16) << 16; break; // Arrasta para o byte blue
        case (1): cor_real := cor_real | ((valor_do_componente * 16) << 8); break; // Arrasta para o byte green e junta os valores
        case (2): cor_real := cor_real | (valor_do_componente * 16); break; // Junta com o byte Red
    end;
   
    qual_componente += 1; // Altera para o próximo componente
    if qual_componente > 2 then // Se terminar o processo de criar a cor
    begin
        /*
        ---------------------------------------------
        Aqui nós vamos usar a cor para qualquer coisa
        ---------------------------------------------     
        */
        qual_componente := 0; // Volta o loop para criar uma nova cor
    end;

end until file_bin_position(arquivo) = file_bin_size(arquivo);

Ok, agora vamos fazer isso na prática mesmo, usando o Game Maker e um arquivo bmp de 24 bits. O que eu fiz aqui nesse exemplo é converter os valores de 24 bits pra 12 bits, dividindo o valor do byte 256 por 16 onde o resultado será 16, ou seja, um nibble de informação. Até aí tudo bem, só não repare porque isso não é nenhum algoritmo espetacular do Photoshop, então a conversão das cores é bem simplória! Laughing

[Download do exemplo]

Depois que você carrega o bitmap, ele lê cada byte e vai transformando em nibble fazendo essa divisão, e depois va1 gravando no arquivo novo. Ou seja, agora a gente tem um bitmap de 12 bits! Como dá pra ver, o arquivo fica bem menor (na proporção que eu tinha dito antes). O segredo aqui é a gente tentar criar um algoritmo de conversão de cores melhor. Só que isso eu não sei fazer, acho que deve ser bem mais complicado.

Ou então, uma alternativa que eu tô imaginando aqui poderia ser usar um bitmap com as cores já otimizadas no Photoshop. Daí a divisão do byte pra nibble fica mais coerente com o que a gente quer. Falou!


Última edição por Ninja8086 em Sex 06 Jan 2012, 12:39, editado 2 vez(es)

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Qui 05 Jan 2012, 22:44

Muito bom.
Continua com as linhas brancas, mas pouco me importa, já que meu objetivo é aprender como fazer, talvez seja bem útil mais para frente.
Obrigado pelo exemplo.

Até mais!

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Qui 05 Jan 2012, 23:29

Essa questão das linhas brancas eu realmente não entendi. Ainda acho que é alguma treta de surfaces... Em todos as vezes aqui abriu normal.

A questão do exemplo.... Eu tava falando "bitmap de 12 bits" só pra especificar qual é qual, mas na família do bitmap mesmo não existem "bitmaps de 12 bits" Laughing , no fim a gente acabou criando nosso próprio arquivo de imagem, mesmo que tenha ficado meio tosco, mas não deixa de ser interessante... Very Happy

Aquele último exemplo que eu postei, pode jogar ele fora! Eu errei em um cálculo lá, mas já arrumei e fiz upload de novo. Agora sim a conversão tá nota 10! Um negócio legal é que reduzir pra 12 bits por pixel dá o mesmo resultado de posterizar a imagem no Photoshop usando 16 níveis! Nesse caso da posterização, o arquivo não vai reduzir o tamanho, mas o impacto de conversão das cores é exatamente igual ao esquema que a gente criou!

Agora a redução de cores tá ótima, olha só:

Nosso arquivo com 12 bits por pixel:


Arquivo bitmap real de 24 bits:


Nem dá pra notar diferença nas cores agora! Valeu!

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Sex 06 Jan 2012, 11:56

Caramba, ficou muito igual.
Nem dá para perceber diferenças.
Muito bom. Você criou um novo formato de imagem super leve (metade do peso).
Eu também vou tentar algo para resolver o problema das linhas brancas, o ideal seria outra pessoa baixar (de preferência com um pc não muito bom) e falar se acontece ou nao.

Até mais!

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Sex 06 Jan 2012, 12:47

Vamos ver se a gente consegue resolver esse problema das linhas. Very Happy

Bom, se caso a imagem ficar distorcida, é só mudar essa linha do código:

Código:
extrabyte := min(incup - bmpw, bmpw - incdown); // Múltiplo mais próximo

por essa:

Código:
extrabyte := max(incup - bmpw, bmpw - incdown); // Múltiplo mais próximo

(já refiz o upload com a correção)

Realmente a imagem fica mais leve, não é tão leve ainda, mas a gente tá manipulando um bitmap... Se a imagem usasse menos cores ainda daria pra reduzir cada pixel pra 3 bits ou até 2 bits. Valeu!

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Sex 06 Jan 2012, 15:39

Na hora que caiu a ficha eu percebi que o tamanho do arquivo externo é menor, mas a memória ram ocupada no jogo/programa é a mesma.

Será que, se for usado 9 bits / pixel, a qualidade vai ficar muito menor?

Meu pc tá demorando uns 2~3 segundos para carregar a imagem. Tá bem lento mesmo. O seu carrega em quanto tempo?

Até mais!


Última edição por Pedrø em Dom 29 Jul 2012, 13:10, editado 1 vez(es)

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Sex 06 Jan 2012, 16:41

A memória que é usada é sempre a mesma, independente de tipo de arquivo, porque quando a imagem tá na memória, ela não tem "formato" (já foi decodificada), ela é só um mapa de bits.

A questão da demora para abrir é porque estamos usando o Game Maker, surface e lendo o arquivo byte a byte, por isso que demora mesmo. No meu PC leva uns 2 segundos.

A perda de qualidade é muito variada, porque depende muito do número de cores que a imagem usa:


Sem perda (24) e com pouca perda (12)
12 bits = 2^12 = 4096 cores

24 bits por pixel:


12 Bits por pixel:


As que sofrem perdas mais bruscas, e redução de tamanho (usando o nosso sistema do script, dividindo a o valor da cor, ficaria assim):
9 bits (3 bits por canal) = 2^9 = 512 cores
6 bits (2 bits por canal) = 2^6 = 64 cores
3 bits (1 bit por canal) - 2^3 = 8 cores

9 bits por pixel:


6 bits por pixel:


3 bits por pixel:

surpreso

Essas aqui são as mesmas condições, porém com dithering ( http://pt.wikipedia.org/wiki/Dither ) feito no Photoshop. As que sofreram dither tem o mesmo tamanho de arquivo que as que não sofreram. É um algoritmo pra otimizar a redução de cores:

9 bits por pixel com dither:


6 bits por pixel com dither:


3 bits por pixel com dither:


Pra fazer o cálculo de quanto espaço cada uma ocupa é só fazer:
([altura] * [largura] * [bits por pixel])/8 = número de bytes que a imagem usa

Uma imagem 320x240, por exemplo...
24 bits = 230400 bytes = 225 KB
12 bits = 115200 bytes = 112 KB
9 bits = 86400 bytes = 84 KB
6 bits = 57600 bytes = 56 KB
3 bits = 28800 bytes = 28 KB

Esse dither eu não tenho ideia de como fazer em programação. Nunca peguei um algoritmo pra ver como é... Essas imagens aí eu fiz no Photoshop. Dá pra reduzir o número de cores no Photoshop como eu fiz e depois usar aquele esquema nosso em GML, aí funciona também. Mas o dithering programado no braço com certeza deve ser bem mais complicado!
Falou!




GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por theguitarmester em Sab 15 Dez 2012, 15:33

sei que o Tópico já tem um Tempo, mas o Usuário entrou ontem mesmo no Fórum, mostrando ainda estar ativo.

As Imagens que são feitas por seu Programa Simplesmente não funcionam, mas não é só isso, queria saber se você me saberia dizer porque se eu abrir uma Imagem 'digamos no Bloco de notas' e salvá-la, ela não irá abrir! não sei se é só no Meu computador, já tentei fazer um programa no GM que soltava arquivos, mas devido a esse problema de você abrir o arquivo e salvar e ele não abrir mais, parei com o Projeto.

Você tem idéia do que seja?

theguitarmester

Ranking : Sem avaliações
Número de Mensagens : 1908
Idade : 20
Data de inscrição : 28/02/2012
Notas recebidas : B
Reputação : 80
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 1
Prêmios
   : 2
   : 2
   : 1

http://guitarmester.no.comunidades.net/index.php?pagina=19362978

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por PedroX em Sab 15 Dez 2012, 15:53

As Imagens que são feitas por seu Programa Simplesmente não funcionam
Aqui funcionam.

mas não é só isso, queria saber se você me saberia dizer porque se eu abrir uma Imagem 'digamos no Bloco de notas' e salvá-la, ela não irá abrir! não sei se é só no Meu computador, já tentei fazer um programa no GM que soltava arquivos, mas devido a esse problema de você abrir o arquivo e salvar e ele não abrir mais, parei com o Projeto.
O problema é que o Bloco de Notas não lê bytes. Se você quiser editar uma imagem modificando seus bytes, você precisa de um editor apropriado. Assim quando você salvar, ele vai escrever todos os bytes corretamente.

Até mais!

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por Pit Bull em Sab 15 Dez 2012, 17:50

PedroX escreveu:
As Imagens que são feitas por seu Programa Simplesmente não funcionam
Aqui funcionam.

mas não é só isso, queria saber se você me saberia dizer porque se eu abrir uma Imagem 'digamos no Bloco de notas' e salvá-la, ela não irá abrir! não sei se é só no Meu computador, já tentei fazer um programa no GM que soltava arquivos, mas devido a esse problema de você abrir o arquivo e salvar e ele não abrir mais, parei com o Projeto.
O problema é que o Bloco de Notas não lê bytes. Se você quiser editar uma imagem modificando seus bytes, você precisa de um editor apropriado. Assim quando você salvar, ele vai escrever todos os bytes corretamente.

Até mais!

O bloco de notas só lê os bytes correspondentes a tabela ASCII, os que ele não reconhece coloca um caractere especial ou um espaço.

Quando você abri uma imagem no bloco de notas e salva, o blocos de notas salva como documento de texto e não mais como imagem.

Pit Bull

Número de Mensagens : 630
Idade : 21
Data de inscrição : 31/08/2010
Reputação : 15
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://leninja.com.br

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por GameMakerTutoriais em Seg 17 Dez 2012, 15:09

Na verdade, sim e não. Dependendo do conteúdo do arquivo, tanto o bloco de notas como qualquer outro editor de texto plano podem salvar o conteúdo binário de um arquivo. O programa não "se importa" com o conteúdo de texto porque ele não tem cabeçalho nem campo apropriado, exceto quando o texto usar Unicode que, se não me engano, o cabeçalho começa com dois bytes predefinidos...

Como o valor do ASCII corresponde a cada valor de byte no arquivo, mesmo que o notepad abra, você ainda vai conseguir salvar o binário. Só que vai depender do conteúdo. Como o amigo falou aí em cima, tem alguns códigos que não são impressos na tela, mas eu não sei se o notepad coloca espaços no lugar.

Aqui o script também funciona. Se você quiser hospedar a imagem gerada aí e colocar o link pra download aqui, eu baixo e tento ver o que aconteceu. Se puder, coloque também a original.

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Re: Manipulação binária de arquivos/memória (Game Maker)

Mensagem por Conteúdo patrocinado Hoje à(s) 20:21


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo

- Tópicos similares

 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum