[RESOLVIDO] Tamanho, qualidade e profundidade de cor de uma JPEG

Bom dia a todos.

Tenho um problema com gravação de imagem JPG que ainda não consegui resolver. Eu tiro uma screen da tela e envio da máquina cliente até a máquina servidor pela Internet, porém, notei que está meio lento para atualizar as telas, e descobri que as imagens geradas estão muito grandes (em kb).

Uma imagem JPG, de 1024x768, em 256 cores com 70% de qualidade está girando em torno de 100KB (inviável).

Mesmo com o programa enviando telas apenas quando a screen tirada pelo robot for diferente da screen anteriormente enviada, ainda fica lento.

Tenho o seguinte código:

Rectangle screenSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); BufferedImage screen = robot.createScreenCapture(screenSize); BufferedImage bimage = new BufferedImage(screenSize.width, screenSize.height, preferencias.getQualidadeCor());

Onde qualidade cor pode ser

byte qualidadeCor = BufferedImage.TYPE_BYTE_INDEXED //256 Cores byte qualidadeCor = BufferedImage.TYPE_BYTE_GRAY //Tons de Cinza

Após obter esta BufferedImage, eu crio ela com a qualidade desejada assim

[code]
public static void createJPG(BufferedImage image, OutputStream out, float quality) throws IOException {

 Iterator jpgWriter = ImageIO.getImageWritersBySuffix("jpeg");
 ImageWriter imageWriter = (ImageWriter) jpgWriter.next();
 ImageOutputStream ios = ImageIO.createImageOutputStream(out);
 jpgWriter.setOutput(ios);
 ImageWriteParam imgParam = jpgWriter.getDefaultWriteParam();

 imgParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
 imgParam.setCompressionQuality(quality);

 jpgWriter.write(null, new IIOImage(image, null, null), imgParam);

}[/code]

onde quality é

Float quality = new Float(7 / 10.0f)

Depois, envio esta imagem, que é um byte[], em um byte[] comprimido em ZIP. Mesmo com compressão máxima, a imagem não muda muito de tamanho. Consigo uma compressão de no máximo 10%.

Minha pergunta é:

  • Existe a possibilidade de gravar uma imagem JPG entre 60-70% de qualidade, com 256 cores (pode até ser menos, só preciso mesmo é “ver” a tela do computador monitorado) e que fique com um tamanho mais “aceitável”?

Pensei em redimensionar para enviar, mas a imagem fica muito pequena.

A imagem precisa ser pequena (em kb) e não precisa ter qualidade, portanto, não há necessidade de trabalhar com Antialiasing, Blur, etc, etc.

Tentei até mesmo usar o depreciado JPEGEncoder, mas é lento que chega a dar dó.

Alguma dica?

Ja pensasse em salvar a imagem em PNG? JPEG eh mais adequado pra fotos reais

Salvei meu desktop aqui (1440x900), converti pra preto e branco e PNG de 256 cores no GIMP e deu 60kb. O melhor eh que PNG nao perde qualidade nenhuma. Voce pode ate tentar salvar a imagem em tamanhos menores pra diminuir mais ainda o tamanho

So evite wallpapers no desktop e etc, pq ai PNG nao se da muito bem, a especialidade dele eh imagems sem muita variacao de cores, tipo uma imagem com quadrados cada um com uma unica cor. Se tiver fotos, degradês, ai vai ter q diminuir o numero de cores pra algo bem baixo tipo 4-16 pra ficar um tamanho aceitavel

Obrigado pela resposta victorcosta, mas o Java parece gravar as PNGs com tamanho maior que a JPEG.

Basicamente, este programa é um VNC, onde o dono do estabelecimento poderia, a qualquer momento, interagir no PC do funcionário.

Fiz um código bem enxuto para isto. Meus eventos de mouse, por exemplo, só enviam cliques. mousePressed em XY e mouseReleased em X+10Y-90 seria um drag. Nem mesmo a movimentação da seta eu envio.

Pensei ser este o culpado, mas vi que a imagem é que está me passando a perna.

Mas enfim, tive uma idéia e gostaria de pedir outra dica agora:

  • Pensei em dividir a tela decorrente do screenshot em 6 setores, calculados pelo tamanho do desktop do PC monitorado.
  • Ao mudar a tela, eu iria apenas enviar o setor que sofreu modificações nos seus pixels, e “colar” este setor enviado na tela do visualizador por cima do setor alterado.
  • Não pode ser transmissão síncrona, por isso corro o risco de não ter um setor atualizado caso o pacote se perca

Pergunta: Graphics2D seria a melhor maneira de gerar os setores e fazer a comparação?

Imagino que deva ficar meio lento esta comparação.

  • Tira screen A
  • Tira screen B
  • Sccreen B é diferente de A
  • Percorre os (digamos) 6 setores de A e os compara com os 6 setores de B
  • Avalia qual sofreu modificação
  • Envia setor modificado

Seria uma boa saída ou não?!?!?!

Abraço

http://www.tightvnc.com/doc/java/README.txt - no seu caso, provavelmente você teria de habilitar um túnel ssh para usar o protocolo vnc de forma segura.

Vou dar uma lida neste Readme, mas eu já posso te adiantar que a conexão estabelecida entre as máquinas é feita usando SSH.

Malditas imagens que não cooperam :stuck_out_tongue:

Se não conseguir um encode com tamanho menor, vou tentar usar a idéia dos setores.

Respondendo para não deixar o tópico sem uma “finalização”.

O tamanho final da imagem não tem como ficar menor.

A tela inteira em PNG fica menor que do que em JPG, mas mesmo assim, com tamanho não aceitável.

Acabei dividindo a imagem da screenshot em 8 subImages e enviando apenas a subImage modificada. Escolhi o formato JPG, pois as subImages em JPG ficaram menores do que em PNG, e como 95% do tráfego vai ser de subImages, optei por este formato.

Era isto.

Obrigado aos que despenderam seu tempo dando dicas.

Abraço