setRGB [RESOLVIDO]

Pessoal, como que eu faço para pintar UM determinado pixel de uma imagem com o setRGB?

Tipo, eu crio minha imagem:

BufferedImage imagem = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB); Graphics2D g1 = imagem.createGraphics(); g1.setColor(new Color(255,255,255)); //BRANCO g1.fillRect(0, 0, 800, 600);

Agora tipo, eu quero pintar o pixel 0,0 com a cor 248 248 255 / O pixel 20,20 com otra cor… Mas só 1 pixel… Como fazer com o setRGB e não o fillrect??

BufferedImage imagem = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB); Graphics2D g1 = imagem.createGraphics(); g1.setColor(new Color(255,255,255)); //BRANCO g1.fillRect(0, 0, 800, 600); imagem.setRgb(0,0, new Color(248, 248, 255).getRgb()); imagem.setRgb(20,20, new outraCor.getRgb());

Outra opção:

imagem.setRgb(0,0, (248 << 16 + 248 << 8 + 255));
1 curtida

Viny… Vlw ae, mas agora eu não consigo entender um probleminha:

[code]try {
ImageIO.write(imagem, “jpg”, new File(“Imagens”, “argh.jpg”)); //aki eu gravo a imagem (argh.jpg)
} catch (IOException e) {
e.printStackTrace();
}

	System.out.println("___________________"); //Aki eu imprimo os pixels da imagem, só para saber
	System.out.println(imagem.getRGB(0, 0));
	System.out.println(imagem.getRGB(1, 0));
	System.out.println(imagem.getRGB(2, 0));
	
	try {
		img1gp = ImageIO.read(new File("Imagens", "argh.jpg")); //aki eu leio a mesma imagem gravada (argh.jpg)
	} catch (IOException e) {
		e.printStackTrace();
	}

	System.out.println("___________________"); //Aki eu imprimo os pixels da imagem lida (que deveria ser o mesmo da gravada)
	System.out.println(img1gp.getRGB(0, 0));
	System.out.println(img1gp.getRGB(1, 0));
	System.out.println(img1gp.getRGB(2, 0));[/code]

Só que dá diferença… Porque??

1 curtida

O jpg é um formato com compactação lossy, ou seja, existe perda de dados. O java ainda usa um nível de compactação bastante alto (é possível regular isso, como vc pode ver aqui).

Se você quiser fidelidade, precisa usar um formato com compactação lossless, como png ou sem compactação, como o bmp.

AEEEE
Mudei para png e deu certo mesmo!!

Eu precisava dessa fidelidade pois é uma brincadeira que estou fazendo de “criptografia” de texto…
Então ele transforma uma letra em uma cor, e grava em uma imagem…
Para fazer o reverso ele pega o pixel da imagem e compara o RGB…

Agora deu certinho, vlw dinovo ae =)

Mais legal é fazer esteganografia.

Ao invés de transformar cada letra numa cor, pegue uma imagem já pronta e limpe apenas os dois bits menos significativos de cada componente de cor (incluindo o alfa) e substitua-os pelos bits da letra.
Assim você terá uma imagem praticamente idêntica a original, mas com um texto escondido nela.

Por exemplo, vamos supor que você tenha a letra A, que representa o código 65, isso em binário é:
01[color=red"]00[/color][color=“green”]00[/color][color=“blue”]01[/color]

E sua primeira cor é 248, 248, 255, 255, ou seja, em binário:

11111000 11111000 11111111 11111111

Limpe os dois bits menos significativos:
11111000 11111000 11111100 11111100

E substitua pelos da letra:
11111001 111110[color=“red”]00[/color] 111111[color=“green”]00[/color] 111111[color=“blue”]01[/color]

Assim cada pixel “esconde” uma letra.

Se quiser gerar com mais fidelidade, você pode usar 2 pixels (8 bytes) para representar uma única letra (1 byte), apenas aproveitando o último bit de cada canal de cor.

NICE IDEAAAA

Amanhã vou fazer isso!!!
Me empolguei agora! xD

Tou tentando aki, mas não to conseguindo =X

Para fazer o programa, você não converte nada em Strings. Você precisa trabalhar com operadores bitwise. E tratar as variáveis inteiras como se fossem bits.

Por exemplo, imagine que você tem uma cor, lida da imagem original, definida por:

int r = 248;
int g = 248;
int b = 255;
int a = 255;

Cada número desses tem uma representação binária (use a calculadora do Windows para descobri-la, se quiser):
248 = 1111 1000
255 = 1111 1111

Agora, você pode usar aqueles operadores. Vamos usar o afastamento de bits, por exemplo, para zerar os dois últimos dígitos:

b = (b >> 2); //Afasta 2 bits para direita. b agora fica com 0011 1111 b = (b << 2); //Volta pro lugar. b fica com 1111 1100

Agora, considere a letra K. O valor dela é 75, em binário, pela calculadora, dá: 01001001
Vamos supor que você queira colocar os dois bits descatados em negrito em B. Você faria:

int bits = 'K'; //01001001 bits >> 2; //00010010 bits = bits & 3;

veja a última operação em detalhes (o & é um "e" bit a bit):
00010010 &
00000011

00000010

Agora. Falta combinar bits com B:

int novoB = b | bits;

Isso é um ou bit-a-bit. Veja em detalhes:
1111 1100 |
0000 0010

1111 1110

Entendeu? E por aí você vai trabalhando. :slight_smile:

Dúvida 2)
Como que eu leio a cor de determinado pixel da imagem assim: “248, 248, 255, 255” ??
Com o getRGB(l, c) vem o número… Como que eu faço para sair “248,248, …” ?

E qual operação que eu uso pra descubrir que ‘K’ = 01001001 ?

[quote=pedroroxd]Como que eu leio a cor de determinado pixel da imagem assim: “248, 248, 255, 255” ??
Com o getRGB(l, c) vem o número… Como que eu faço para sair “248,248, …” ?
[/quote]

O getRGB vai te retornar os 4 bytes juntos, num único int. Essa cor irá retornar um número assim:

1111 1000 1111 1000 1111 1111 1111 1111
Sei lá que valor int é isso, mas provavelmente é um número negativo. Você pode passar esse valor para um color e usar os método getRed(), getGreen(), getBlue() e getAlpha() para le-los separadamente. Ou pode fazer ginásticas com operadores de bits.

Para descobrir você faz o seguinte:

  1. Olhe o valor do caracter na tabela ascii. Você vai ver que o valor decimal dele é 75.
  2. Abra a calculadora do windows e tecle 75.
  3. No menu exibir, troque para o modo científico (ou programador, se for windows 7) e clique em “Bin”. Isso te retornará a representação binária do número.

Você pode fazer o oposto também, para converter para decimal. Ou converter para hexa, se for conveniente.

[quote=ViniGodoy]Mais legal é fazer estenografia.

Ao invés de transformar cada letra numa cor, pegue uma imagem já pronta e limpe apenas os dois bits menos significativos de cada componente de cor (incluindo o alfa) e substitua-os pelos bits da letra.
Assim você terá uma imagem praticamente idêntica a original, mas com um texto escondido nela.

Por exemplo, vamos supor que você tenha a letra A, que representa o código 65, isso em binário é:
01[color=red"]00[/color][color=“green”]00[/color][color=“blue”]01[/color]

E o sua primeira cor é 248, 248, 255, 255, ou seja, em binário:

11111000 11111000 11111111 11111111

Limpe os dois bits menos significativos:
11111000 11111000 11111100 11111100

E substitua pelos da letra:
11111001 111110[color=“red”]00[/color] 111111[color=“green”]00[/color] 111111[color=“blue”]01[/color]

Assim cada pixel “esconde” uma letra.

Se quiser gerar com mais fidelidade, você pode usar 2 pixels (8 bytes) para representar uma única letra (1 byte), apenas aproveitando o último bit de cada canal de cor.[/quote]

Cara… gostei disso ai…

[quote=pedroroxd]Dúvida 2)
Como que eu leio a cor de determinado pixel da imagem assim: “248, 248, 255, 255” ??
Com o getRGB(l, c) vem o número… Como que eu faço para sair “248,248, …” ?

E qual operação que eu uso pra descubrir que ‘K’ = 01001001 ?[/quote]

se não quiser ficar fazendo operações com bitwise para pegar pixels da imagem vc pode fazer isto atravez de um WritableRaster

	WritableRaster raster = bufferedimagem.getRaster();
		int[] pixels = new int[3];

		for (int x = 0; x < bufferedimagem.getWidth(); x++) {
			for (int y = 0; y < bufferedimagem.getHeight(); y++) {
				raster.getPixel(x, y, pixels);
				pixels[0] //r
                                pixels[1] //g
                                pixels[2] //b
			}
		}

entendeu…

[EDIT]
Esqueça!! Agora q entendi… Eu não preciso saber o binário… ele precisa apenas existir! =)

Boiei no comentário…

Fiz assim:

[code]
Color m = new Color(imagem.getRGB(line, colum));
int a = m.getRed(); //A
a = a>>2;
a = a<<2;
int b = m.getGreen(); //B
b = b>>2;
b = b<<2;
int c = m.getBlue(); //C
c = c>>2;
c = c<<2;
int d = m.getAlpha(); //D
d = d>>2;
d = d<<2;

		      //a  b  c  d

int bits = letras[x]; //01 00 10 01

int novoD = d | bits;

bits = bits >> 2;
bits = bits & 3;
int novoC = c | bits;

bits = letras[x];
bits = bits >>4;
bits = bits & 3;
int novoB = b | bits;

bits = letras[x];
bits = bits >>6;
bits = bits & 3;
int novoA = a | bits;[/code]

Se isso estiver certo, eu consegui criptografar… Eu comparo os RGB das imagens e os que eu troquei realmente dão diferença…
Agora para descriptografar que é o foda!

Para eu fazer o inverso estou com dificuldade…

				int what = img1gp.getRGB(x, c);
				Color m = new Color(what);
				int A = m.getRed();
				int B = m.getGreen();
				int C = m.getBlue();
				int D = m.getAlpha();

Agora como eu pego os ultimos 2 bits de cada?

[code]int R = m.getRed();
int G = m.getGreen();
int B = m.getBlue();
int A = m.getAlpha();

int byteValue = ((R & 3) << 6) | ((G & 3) << 4) | ((B & 3) << 2) | (A&3);

[/code]

Deu tudo certo o negosso da Criptografia lá… Mas mais uma vez os dados gravados não estão batendo totalmente com os dados lidos… Mais precisamente: Somente o getAlpha() não está dando certo… E eu preciso dessa fidelidade de informação para ler os bits…

[code]Color newColorr = new Color(novoA,novoB,novoC,novoD);
System.out.println(novoA+ " " + novoB+ " " +novoC+ " " +novoD);
imagem.setRGB(line, colum, newColorr.getRGB());

//GRAVADO, AGORA EU VOU LER OS DADOS GRAVADOS NO MESMO PIXEL, PARA VER SE TEM FIDELIDADE NO GRAVADO E NO LIDO.

Color kkk = new Color(imagem.getRGB(line, colum));
System.out.println(kkk.getRed()+ " " + kkk.getGreen() + " " + kkk.getBlue() + " " + kkk.getAlpha());[/code]

Olha só a saída (em cima é o novoA, novoB, novoC, novoD e em baixo são os lidos):
33 24 48 253
33 24 48 255

33 29 52 255
33 29 52 255

33 29 52 255
33 29 52 255

29 28 48 253
29 28 48 255

20 26 44 252
20 26 44 255

O getAlpha() sempre está retornando 255… Estou trabalhando com imagens .png… Onde será que estou falhando?

Todos estão dando certo, menos o Alpha… A primeira letra é um E. Com o meu método, ele retorna 01000011 sendo que era para os 2 ultimos dígitos serem 01. Ele sempre está retornando 11, por causa do 255 (ele pega os 2 ultimos bits de cada cor).

Só uma dúvida, o valor convertido para inteiro:

newColorr.getRGB()

É diferente do valor convertido para inteiro lido?

E como vc fez para criar o PNG de saída? Você fez:

BufferedImage novaImagem = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 

Pq se o tipo for só RGB, aí vai desprezar o alfa mesmo.

Fiz assim:
o filetxt.getParent() é pq eu criptografo um documento de texto, ae eu gravo no mesmo local…

try { ImageIO.write(imagem, "png", new File(filetxt.getParent(), "Imagem Criptografada.png")); } catch (IOException e) { e.printStackTrace(); }

E sim, são diferentes
A letra que é ‘criptografada’ é o E (69) = 01000101
A saída é G (71) = 01000111