缩放并加载非常大的TIFF文件

时间:2013-05-02 16:22:23

标签: java image loading large-files rescale

我有一个非常大的高分辨率地图,我想在一个应用程序中使用(图像大小约为80 MB)。

我想知道以下内容:

  • 如何以最佳方式加载此图像?我知道加载图像需要几秒钟(这没关系),但我想通知用户进度。我想使用一种确定的模式,并以某种JProgressBar向用户显示此模式。这应该反映已加载的字节数或类似的数字。是否有任何可以提供此功能的图像加载方法(如ImageIO.read())?
  • 由于地图的分辨率非常高,我想让用户滚动放大和缩小。我怎么能以最好的方式做到这一点?我知道一个事实是,重新标记BufferedImage标准方式对于这么大的文件需要花费很长时间。有没有有效的方法呢?

感谢您的投入!

亲切的问候,
Héctorvanden Boorn

P.S。图像将在JPanel的画布上绘制。


你好安德鲁,非常感谢你的帮助;一切都很完美,加载速度很快。 如果没有你的专业知识和解释,我仍然会在这方面努力,所以你已经获得了公平和广泛的赏金。

我做的是以下几点;使用imagemagick我创建了不同分辨率的多个图像,并且在执行开始时我只加载最小的res。图片。其余部分以单独的线程加载,因此执行不会停止。使用您提供给我的信息,然后在放大或缩小时使用适当的图像。我对使用瓷砖有点怀疑,因为我需要在地图上绘制我自己的图像,而且我无法在你告诉我使用的外部jar中找到绘图功能,所以我最终使用了一些简单的东西;当缩放或平移时,重新缩放模式设置为快速,当您不进行缩放或平移时,重新缩放设置为平滑的像素完美图像(就像您建议的那样),但结果证明速度足够快我不喜欢需要瓷砖(尽管我看到更大的图像,这将是必要的,我理解你给我的信息)。

再次感谢,一切都完美无缺:)

1 个答案:

答案 0 :(得分:2)

您应该(同时)采取两种方法:

  1. 缩小您的图片为各种尺寸。您应该以一系列较低分辨率(1 / 2,1 / 4,1 / 8等)缩小图像尺寸,直到图像达到最大可能的屏幕分辨率。当用户首次打开图像时,您将显示较低分辨率的图像。这将加载快速并允许用户平移。当用户放大时,您使用更高分辨率的图像。您可以使用ImageMagick:http://www.imagemagick.org/Usage/resize/
  2. 平铺您的较大图片。这将单个大图像分解为网格图案中的大量小图像。当用户放大某个区域时,您可以计算用户正在查看哪些图块,并且只渲染它们,而不是图像的其他区域。您可以使用ImageMagick将图像拆分为图块,例如ImageMagick. What is the correct way to dice an image into sub-tiles。文档为http://www.imagemagick.org/Usage/crop/#crop_tile
  3. (提供适当大小和平铺图像的缓存是允许GoogleEarth和无数其他地图应用程序渲染如此之快,然后以极高的分辨率放大地图)

    获得瓷砖后,可以使用Java中的几种引擎之一:

    也可能有其他人。

    您可以在此框架内实现任意缩放(适用于缩放或类似缩放)。在您允许的缩放限制内,您的算法将类似于:

    1. 对于用户选择的缩放级别,请选择最接近的更高分辨率缓存。例如,如果您有100%,50%,25%和12.5%的图块,并且用户选择33%缩放,请选择50%图块
    2. 设置切片的布局,使切片方块具有所选缩放的正确大小(这可能是最低缩放级别的单个切片)。例如,使用50%图块进行33%缩放,图块为100像素正方形,网格将为67像素正方形
    3. 单独加载和缩放平铺图像以适应屏幕(这可以是多线程,适用于现代CPU架构)
    4. 有几点需要注意:

      1. 当您达到最高分辨率时,scaling algorithm会发生变化。
        1. 最多100%缩放图像,使用双线性或双三次缩放。这为具有少量锯齿的照片提供了出色的外观
        2. 高于100%,您可能想要显示像素,因此最近邻居可能是一个不错的选择
      2. 为了获得更高的保真度,请使用更高比例的平铺和缩小> 50%。例如,假设您准备了100%,50%,25%和12.5%的瓷砖。要显示40%的缩放比例,请不要缩小50%的图块;而是使用100%瓷砖并将其缩小至40%。这很有用:
        1. 如果您的图像是文本或图表(即包含许多直线的光栅图像)。如果不进行过采样,缩放这些类型的图像通常会产生令人讨厌的假象
        2. 如果你需要非常高的照片风格图像保真度
      3. 如果您需要渲染缩放的预览(例如,当用户仍在捏合和缩放时),请在手势开始时抓取屏幕截图并缩放。更重要的是,动画是平滑的,而缩放预览是像素完美的。
      4. 选择正确尺寸的瓷砖非常重要。非常大的图块(每个屏幕<1)渲染很慢。太小的磁贴会产生其他开销,并且经常会产生令人讨厌的渲染假象,您会看到屏幕随意填满。性能和复杂性之间的良好折衷是使磁贴大约占全屏尺寸的四分之一。

      5. 使用这些技术时,图像的加载速度要快得多,因此进度条不那么重要。如果是,则需要在ImageReader上注册IIOReadProgressListener:

        来自JavaDoc:

          

        ImageReader实现用于通知调用者其图像和缩略图读取进度方法的接口。

             

        此接口接收解码进度的一般指示(通过imageProgress和thumbnailProgress方法),以及指示整个图像何时更新的事件(通过imageStarted,imageComplete,thumbnailStarted和thumbnailComplete方法)。希望在发生像素更新时(例如,在逐行解码期间)获得通知的应用程序应提供IIOReadUpdateListener。