评论中已经进行了广泛的讨论,但总结一下我认为重要的几点:
您需要在几个标准之间进行权衡:
您可以通过高图像压缩来减少网络流量。但这会增加CPU负载并可能降低图像质量。
是否降低图像质量取决于压缩类型:对于JPG,您可以将图像任意小,但是图像的质量将......好吧,任意差。对于 PNG,图像质量将保持不变(因为它是无损压缩),但 CPU 负载和生成的图像大小可能会更大。
还提到了压缩图像数据的选项。确实,压缩图像的 JPG 或 PNG 数据几乎不会减少数据量(因为数据已经is压缩)。但压缩raw图像数据是一种可行的选择,可以替代 JPG 或 PNG。
哪种压缩技术(JPG、PNG 或 ZIP)合适还取决于图像content:JPG 更适合“自然”图像,例如照片或渲染图像。它们可以承受高压缩而不会造成伪影。对于人造图像(如线条图),它很快就会产生不良的伪影,特别是在锐利边缘或图像包含文本时。与此相反:当图像包含单一颜色的大区域时,由于这些压缩方法的“运行长度压缩”性质,像 PNG(或 ZIP)这样的压缩可以减小图像大小。
我很早之前就已经对这种图像传输进行了一些实验,并以一种可以轻松调整这些参数并在不同方法之间切换以及比较不同应用案例的速度的方式实现它。但从我的头脑中,我无法对结果进行深刻的总结。
顺便说一句:取决于what如果您确实想要传输,您可以考虑使用与以下技术不同的技术来获取图像数据:Robot#createScreenCapture(Rectangle)
。众所周知,这种方法速度慢得令人痛苦。例如,当您想要传输 Swing 应用程序时,您可以让您的应用程序直接绘制到图像中。大致有这样的模式
BufferedImage image = new BufferedImage(w,h,type);
Graphics g = image.getGraphics();
myMainFrame.paint(g);
g.dispose();
(这是only草图,展示基本想法!)
此外,您可以考虑其他选项来提高此类图像传输的“感知速度”。例如,您可以将图像分为tiles,然后将这些瓷砖依次转移。如果图像尽快至少部分可见,接收者可能会感激。这个想法可以进一步延伸。例如,通过检测两帧之间哪些图块确实发生了变化,并且仅传输这些变化的图块。 (这种方法可以通过检测必须转移的“最小区域”以相当复杂的方式扩展和实施)
但是,对于您首先想要使用最明显的调整参数的情况:以下是一种允许将质量值在 0.0 到 1.0 之间的 JPG 图像写入输出流的方法:
public static void writeJPG(
BufferedImage bufferedImage,
OutputStream outputStream,
float quality) throws IOException
{
Iterator<ImageWriter> iterator =
ImageIO.getImageWritersByFormatName("jpg");
ImageWriter imageWriter = iterator.next();
ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();
imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
imageWriteParam.setCompressionQuality(quality);
ImageOutputStream imageOutputStream =
new MemoryCacheImageOutputStream(outputStream);
imageWriter.setOutput(imageOutputStream);
IIOImage iioimage = new IIOImage(bufferedImage, null, null);
imageWriter.write(null, iioimage, imageWriteParam);
imageOutputStream.flush();
}