缩放并加载非常大的TIFF文件 [英] Zooming and loading very large TIFF file

查看:156
本文介绍了缩放并加载非常大的TIFF文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a very large hi-res map which I want to use in an application (imagesize is around 80 mb).

我想知道以下内容:


  • 如何以最佳方式加载此图像?我知道加载图像需要几秒钟(这没关系),但我想通知用户进度。我想使用一个确定的模式,并在某种 JProgressBar 中向用户显示。这应该反映已加载的字节数或类似的数字。是否有任何Image加载方法可以提供此功能(如 ImageIO.read())?

  • 因为地图非常好高分辨率我想让用户滚动放大和缩小。我怎样才能做到最好?我知道重新调整 BufferedImage 的事实,标准方法需要花费很长时间来处理这么大的文件。有没有有效的方法呢?

  • How can I load this image the best way possible? I know it will take some seconds to load the image (which is ok) but I would like to notify the user of the progress. I would like to use a determined mode and show this in some sort of JProgressBar to the user. This should reflect the number of bytes that have been loaded or something like that. Is there any Image loading method that can provide this functionality (like ImageIO.read())?
  • Because the map is of very high resolution I would like to offer the user to scroll to zoom in and out. How can I do this the best way? I know for a fact that rescaling a BufferedImage the standard way would take a VERY long time for such a big file. Is there any efficient way of doing this?

感谢您的投入!

亲切的问候,
$ b $bHéctorvanden Boorn

kind regards,
Héctor van den Boorn

ps图像将在JPanel的画布上绘制。

p.s. The image will be drawn on the canvas of a JPanel.

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

Hi Andrew, Thank you so much for your help; everything worked out perfectly and is loading quick. Without your expertise and explanation I would have still been working on this so you've earned the bounty fair and square.

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

What I did was the following; using the imagemagick I created multiple images of different resolution and at the start of execution I load only the smallest res. image. The rest are loaded in seperate threads so execution is not stalled. Using the information you provided me I then use the appropriate images when zooming in or out. I'm a bit sceptical of using the tiles because I need to draw my own images on top of the map and I couldn't find the paint function in the external jar you told me to use, so I ended up using something simple; when zooming or panning the rescale mode is set to fast and when you're not zooming or panning the rescale is set to smooth for pixel-perfect images (just like you suggested), but this turns out to be fast enough and I don't need tiles (altough I do see that with even larger images this would be necesarry and I understand the information you've given me).

所以再次感谢,一切都是完美地工作:)

So thanks again and everything is working perfectly :)

推荐答案

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

There are two approaches you should (simultaneously) take:


  1. 缩小您的图片为各种尺寸。您应该以一系列较低分辨率(1 / 2,1 / 4,1 / 8等)缩小图像尺寸,直到图像达到最大可能的屏幕分辨率。当用户首次打开图像时,您将显示较低分辨率的图像。这将加载快速并允许用户平移。当用户放大时,您使用更高分辨率的图像。您可以使用ImageMagick: http://www.imagemagick.org/Usage/resize/

  2. 平铺您的较大图片。这将单个大图像分解为网格图案中的大量小图像。当用户放大某个区域时,您可以计算用户正在查看哪些切片,并且只渲染它们,而不是渲染图像的其他区域。您可以使用ImageMagick将图像拆分为图块,例如 ImageMagick的。将图像切成子图块的正确方法是什么?文档是 http://www.imagemagick.org/Usage/crop/#crop_tile

  1. Downscaling your image into various sizes. You should downscale your image at a series of lower resolutions (1/2, 1/4, 1/8, etc until the image is about the largest likely screen resolution). When the user first opens the image, you show the lower resolution image. This will load fast and allow the user to pan. When the user zooms in, you use a higher resolution image. You can use ImageMagick for this: http://www.imagemagick.org/Usage/resize/
  2. Tile your larger images. This breaks down the single, large image into a large number of small images in a grid pattern. When a user zooms in on an area, you compute which tiles the user is looking at, and you render only them, not the other areas of the image. You can use ImageMagick to do split an image into tile, eg ImageMagick. What is the correct way to dice an image into sub-tiles. The documentation is http://www.imagemagick.org/Usage/crop/#crop_tile

(提供适当大小和平铺图像的缓存,使GoogleEarth和无数其他地图应用程序能够如此快速地渲染,然后以极高的分辨率放大地图)

(Providing a cache of appropriately sized and tiles images is what allows GoogleEarth and countless other mapping applications, to render so fast, yet zoom into the map at incredibly high resolution)

一旦你有你的瓷砖,你可以使用Java中的几个引擎之一:

Once you have your tiles, you can use one of several engines in Java:

  • https://wiki.openstreetmap.org/wiki/Tirex
  • http://www.slick2d.org/wiki/index.php/Tiled

可能还有其他人。

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

You can implement arbitrary zooming (suitable for pinch-to-zoom or similar) within this framework. Within the zoom limits you allow, your algorithm would be something like:


  1. 对于用户选择的缩放级别,请选择最接近的更高分辨率缓存。例如,如果您有100%,50%,25%和12.5%的图块,并且用户选择33%缩放,请选择50%图块

  2. 设置图块的布局,以便平铺方块具有所选缩放的正确大小(这可能是最低缩放级别的单个平铺)。例如,使用50%图块进行33%缩放,图块为100像素正方形,网格为67像素正方形

  3. 单独加载并缩放图块图像以适合屏幕(这可以是多线程,适用于现代CPU架构)

  1. For the zoom level chosen by the user, choose the closest higher resolution cache. For example, if you have 100%, 50%, 25% and 12.5% tiles, and the user chooses 33% zoom, select the 50% tiles
  2. Set the layout for the tiles so the tile squares have the correct size for the chosen zoom (this might be a single tile at lowest zoom levels). For example, at 33% zoom using 50% tiles, with the tiles being 100 pixels square, the grid will be 67 pixel squares
  3. Individually load and scale the tile images to fit the screen (this can be multi-threaded which works well on modern CPU architectures)

有几点需要注意:


  1. 缩放算法当您达到最大分辨率时更改。

  1. The scaling algorithm changes when you reach the greatest resolution you have tiles for.

  1. 对图像进行高达100%的缩放,使用双线性或双三次缩放。这为具有少量锯齿的照片提供了出色的外观

  2. 高于100%,您可能想要显示像素,因此最近邻居可能是一个不错的选择


  • 为了获得更高的保真度,请使用更高比例的图块并缩小> 50%。例如,假设您准备了100%,50%,25%和12.5%的瓷砖。要显示40%的缩放比例,请不要缩小50%的图块;而是使用100%的瓷砖并将它们缩小到40%。这很有用:

  • For higher fidelity, use a higher scale tile and downscale > 50%. For example, suppose you have tiles prepared at 100%, 50%, 25% and 12.5%. To show 40% zoom, don't scale down the 50% tiles; instead use the 100% tiles and scale them down to 40%. This is useful:


    1. 如果您的图像是文本或图表(即包含许多直线的光栅图像)。如果不进行过度采样,缩放这些类型的图像通常会产生令人讨厌的假象。

    2. 如果您需要非常高保真度的摄影风格图像


  • 如果您需要渲染缩放的预览(例如,当用户仍在捏合和缩放时),请在手势开始时抓取屏幕截图并缩放。更重要的是动画是平滑的,而缩放预览是像素完美的。

  • 选择正确尺寸的瓷砖很重要。非常大的图块(每个屏幕<1)渲染速度很慢。太小的磁贴会产生其他开销,并且经常会产生令人讨厌的渲染伪像,您会看到屏幕随意填满。性能和复杂性之间的良好折衷是使磁贴大约占全屏尺寸的四分之一。






  • 使用这些技术时,图像的加载速度要快得多酒吧不是那么重要。如果是,则需要在 ImageReader

    • ImageReader.addIIOReadProgressListener()

    来自JavaDoc:


    ImageReader实现用于通知呼叫者其图像和缩略图的界面读取进度的方法。

    An interface used by ImageReader implementations to notify callers of their image and thumbnail reading methods of progress.

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

    This interface receives general indications of decoding progress (via the imageProgress and thumbnailProgress methods), and events indicating when an entire image has been updated (via the imageStarted, imageComplete, thumbnailStarted and thumbnailComplete methods). Applications that wish to be informed of pixel updates as they happen (for example, during progressive decoding), should provide an IIOReadUpdateListener.

    这篇关于缩放并加载非常大的TIFF文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆