Voltar de valor byte para letra [RESOLVIDO]

Pessoal, tava dando uma olhada na Ascii Table, e tava mandando imprimir os valores de cada letra para teste:

int byteValue = 'B'; System.out.println("Valor Byte" + byteValues);

Depois, eu tento voltar para a letra assim:

String str = Integer.toBinaryString((byte) byteValue); int i = Integer.parseInt(str, 2); System.out.println((char) i);
Para todos os valores da taebla funcionam, mas para caracteres especiais não (do tipo á,à,â,ã,ä,ç).
Dá esse erro: [color=red]Exception in thread “main” java.lang.NumberFormatException: For input string: “11111111111111111111111111000111”[/color]

Se eu faço assim:
char b3 = (char) (byteValue);
Funciona, mas ae ele vai pegar de todos os pixels da imagem, inclusive os que eu não quero… Estou usando ele, mas como que eu faço para parar o algoritimo de varredura da imagem quando terminar a frase??
A imagem que estou falando é essa: http://www.guj.com.br/posts/list/15/221333.java

O problema é que caracteres especiais, caracteres estrangeiros, simbolos, etc, seguem a tabela Unicode, e não a tabela ascii. É por isso que o char, no Java, tem 2 bytes e não 1.

Uma das formas de resolver isso é você parar de lidar com strings, e passar a lidar com o texto byte-a-byte, como se fosse um arquivo binário. E depois fazer o mesmo para recompor. Agora, seu texto ocupará o dobro do espaço, o que exigirá uma imagem duas vezes maior.

Por isso, além de tratar byte-a-byte, recomendo que você use um inputstream com compactação.

String str = Integer.toBinaryString(color=red[/color] byteValue);

Remove esse cast que funciona.

Consegui… deu certo, vlw ae vini

Agora estou com um problema:
Saber quando parar de pegar texto da imagem
Eu fiz o seguinte: No primeiro pixel (0,0) eu do um setRed com o tamanho do texto…
Depois na hora de descriptografar eu volto lá e do um getRed no primeiro pixel…

Funciona certinho… Mas tem 1 problema… Quando o texto tem mais do que 255 caracteres não dá pra dar um setRed com ele…
Pensei em /1000 e depois fazer *1000 mas ele só aceita valor inteiro… Então se tiver 300 caracteres, vai pra 0,3 e volta pra 0…

Transforme o int da cor numa Color, diretamente. Aí grave essa color no primeiro pixel.

Outra opção é fazer como o C faz. Criptografa um 0 no final do texto.
Quando chegar no 0, você sabe que o texto acabou.

Não estou falando de um pixel com a cor 0, mas de colocar 0 em todos os bits que você usa para as esconder as letras.

É isso que tava tentando fazer… Assim:

Color m = new Color(imagem.getRGB(0, 0)); Color newColorr = new Color(text.length(),m.getGreen(),m.getBlue(),m.getAlpha()); imagem.setRGB(0, 0, newColorr.getRGB());
Mas ae da erro quando é mais que 255…

Mas não pode ocorrer coincidentemente de ter um texto com 0 nakeles bits?

Não. O 0 em todas as tabelas representa NUL.

Entendi…
Arranjei uma outra maneira:

imagem.setRGB(0, 0,  -text.length());

E na hora de voltar:

int tamanho = img1gp.getRGB(0, 0); tamanho = -tamanho *2; //* 2 pq é 2 pixels para cada letra
Testei com uns textos grandes aqui e deu certo…
RGB tem limite também? De quanto é?

Se você usar os 3 bytes do R, G e B, você terá 24 bits para guardar o número. Portanto, o limite será de (2^24)-1, ou seja: 16777215.

Axo que dá! rs

Eu colokei para criptografar um texto "grandinho" (de 8940 caracteres):

Ele só conseguiu chegar até o 1370, depois deu isso:
[color=red]Exception in thread "Thread-4" java.lang.StackOverflowError
at sun.nio.cs.SingleByteEncoder.encodeArrayLoop(Unknown Source)
at sun.nio.cs.SingleByteEncoder.encodeLoop(Unknown Source)
at java.nio.charset.CharsetEncoder.encode(Unknown Source)
at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.BufferedWriter.flushBuffer(Unknown Source)
at java.io.PrintStream.write(Unknown Source)
at java.io.PrintStream.print(Unknown Source)
at java.io.PrintStream.println(Unknown Source)[/color]

Meu método chama ele mesmo várias vezes, deve tar estorando…

[code]private static void start(BufferedImage imagem) {
for (int x = 0; x < size; x++) {
String qual = text.substring(y, y + 1);

		if (qual.equals(String.valueOf(letras[x]))) {				
			System.out.println(letras[x]);
			int xd = line + 1;
			
			Color pixel1 = new Color(imagem.getRGB(line, colum));  
			int r1 = pixel1.getRed() & 0xFC;    //Limpa os dois ultimos bit. FC=1111 1100  
			int g1 = pixel1.getGreen() & 0xFE; //Limpa o ultimo bit. FE=1111 1110  
			int b1 = pixel1.getBlue() & 0xFE;  
			
			Color pixel2 = new Color(imagem.getRGB(xd, colum));  
			int r2 = pixel2.getRed() & 0xFC;
			int g2 = pixel2.getGreen() & 0xFE;
			int b2 = pixel2.getBlue() & 0xFE;  


			/////
			int bits = letras[x];
			bits = bits & 3;  
			int novoRED1 = r1 | bits; 
						 
							 
			bits = letras[x];
			bits = bits >>2;
			bits = bits & 1;
			int novoGREEN1 = g1 | bits;
						     
			bits = letras[x];
			bits = bits >>3;
			bits = bits & 1;
			int novoBLUE1 = b1 | bits;
						     
						     
			/////////////////////
			bits = letras[x];
			bits = bits >>4; //5
			bits = bits & 3;
			int novoRED2 = r2 | bits;
						     
			bits = letras[x];
			bits = bits >>6;
			bits = bits & 1;
			int novoGREEN2 = g2|bits;
						     
			bits = letras[x];
			bits = bits >>7;
			bits = bits & 1;
			int novoBLUE2 = b2 |bits;
				

			Color newColorr = new Color(novoRED1,novoGREEN1,novoBLUE1,pixel1.getAlpha()); //pixel1.getAlpha()
			Color newColorr2 = new Color(novoRED2,novoGREEN2,novoBLUE2,pixel2.getAlpha());	//pixel2.getAlpha()

			
			imagem.setRGB(line, colum, newColorr.getRGB());
			imagem.setRGB(xd, colum, newColorr2.getRGB());

			line = line + 2;
			if (line == imagem.getWidth()) {
				colum++;
				line = 0;
			}

			y++;

			if (y < text.length()) {
				start(imagem); //AKI.. Ele se chama
			}
			break;
		}
	}
}[/code]

Ali no (y<text.lenght) ele vai chamar dinovo, até completar o texto…>

Por que seu método chama a si mesmo várias vezes?

Porque ele recebe como parâmetro a imagem…
Depois ele edita 1 pixel da imagem, e passa a nova imagem para si mesmo…

Vou ver se faço pra editar todos os pixels em vez de ficar chamando a si mesmo…

Ae! Consegui!
Realmente não precisava ficar se chamando várias vezes…

Mandei criptografar um texto de 20.000 caracteres e deu certinho…
O unico caractere que não sai é o um abre aspas, que quando eu coloko aki no guj vira interrogação… O " sai…

Realmente, não percebesse nenhuma variação na imagem, só no primeiro pixel que é o RGB da quantidade de caracteres… no mais é tudo igualzinho…

Vlws ae vinigodoy, que me ajudou pra caramba mesmo, malz ae por ter enchido tanto o saco! kkkk
=]

Ultima pergunta…
Agora que li com atenção seu post…
O que vc queria dizer com a compactação no texto?

Bom, acabei me empolgando e escrevi também meu algoritmo de esteganografia.

Em anexo, está o jar que faz o algoritmo rodar. E uma imagem, com a logo do GUJ.

Para esteganografar:
java -jar Esteganografia.jar -e NomeDaImagem.png NomeDoArquivo1 NomeDoArquivo2 …

Para reverter
java -jar Esteganografia.jar -r NomeDaImagem.png

Experimente rodar o programa para reverter os textos secretos que estão nessa logo.
Os textos saem na forma de arquivos. Então, não tentem só procurar uma frasezinha escrita no console.

Para quem perdeu, a explicação de como o processo funciona está aqui: http://www.guj.com.br/posts/list/221333.java#1132889

Entretanto, esse programa não usa o canal alfa. Uma otimização no PNG as vezes pré-multiplica o canal, o que o inviabiliza para o processo.
No lugar, uso 2 bits do canal vermelho, 1 do verde e 1 do azul para guardar meio byte, o que torna necessário usar 2 pixels para armazenar cada byte do que quero esconder.

1 curtida

Legal!!
Ele funciona para outros tipos de documentos também? ou só txt?

[quote=pedroroxd]Legal!!
Ele funciona para outros tipos de documentos também? ou só txt?[/quote]

Pra qualquer tipo de arquivo.

A única limitação é que a imagem original precisa ser lossless, ou seja, .png ou bmp.
O arquivo de saída sempre chama-se output.png.

tentei com 1 documento .doc, ele gera a imagem, mas na volta ele não gera o texto…

Mas com o logo do guj deu certo…
Bem bacana… Tem bastante coisa que não entendi, mas beleza… Devo ver isso quando entrar na faculdade ! rs
Por enquanto sou apenas um vestibulando rs…

Mas enfim, meu exemplo beeeem mais simples tá nesse site (não coube aki no guj):
http://www.easy-share.com/1912655629/ProjetoPronto.jar

dá 1 olhada ae! dei 1 enfeitada nele… rs

Não faz o menor sentido. O programa nem sequer olha pro formato do arquivo. Ele lê um arquivo byte-a-byte e esconde. Pode ser qualquer coisa.
Você tem certeza que mandou reverter a imagem certa?

Em todo caso, está aqui uma demonstração. Essa imagem contém o doc dos fontes do programa.