Scaling and loading a very large TIFF file

I have a very large hi-Res card that I want to use in the application (the image size is about 80 mb).

I would like to know the following:

  • How can I upload this image in the best way? I know that loading the image will take about a few seconds (this is normal), but I would like to notify the user about the progress. I would like to use a specific mode and show this as a JProgressBar to the user. This should reflect the number of bytes downloaded or something like that. Is there a way to load images that can provide this functionality (e.g. ImageIO.read() )?
  • Since the map has a very high resolution, I would suggest that the user scroll to zoom in and out. How can I do this in the best way? I know that for scaling BufferedImage standard way will take a very long time for such a large file. Is there an effective way to do this?

Thanks for your input!

Yours faithfully,
Hector van den Boorn

ps The image will be drawn on JPanel canvas.


Hi Andrew, Thank you so much for your help; everything works fine and loads quickly. Without your experience and explanation, I would still work on this so that you deserve a reward and a square.

I did the following: using imagemagick, I created several images of different resolutions and at the beginning of execution I downloaded only the smallest res. form. The rest are loaded into separate threads, so the execution does not stop. Using the information you provide, I then use the appropriate images when scaling or exiting. I am a little skeptical about using tiles because I need to draw my own images on top of the map, and I could not find the paint function in the external jar that you told me, so I ended up using something simple; when zooming or panning the zooming mode is set to fast, and when you are not zooming or panning, the zooming scale is set to anti-aliasing for images perfect for the pixel (as you expected), but it turns out to be fast enough, I need tiles (although I see that with even larger images this would be necessary, and I understand the information you gave me).

So thanks again and everything works fine :)

+4
source share
1 answer

There are two approaches (simultaneously):

  • Zoom out your image in various sizes. You need to zoom out using a series of lower resolutions (1/2, 1/4, 1/8, etc., until the image is displayed with the highest possible screen resolution). When the user first opens the image, you display a lower resolution image. This will load quickly and allow the user to pan. When the user zooms in, you are using a higher resolution image. You can use ImageMagick for this: http://www.imagemagick.org/Usage/resize/
  • Tile your large images. This splits one large image into a large number of small grid images. When the user zooms in on the area, you calculate which tiles the user is looking for, and you only render them, not the other areas of the image. You can use ImageMagick to split an image into a fragment, such as ImageMagick. What is the correct way to copy an image into sub-chapters . Documentation http://www.imagemagick.org/Usage/crop/#crop_tile

(Providing an image cache with an appropriate size and images is what allows GoogleEarth and countless other display applications to do so fast but scale the map with incredibly high resolution)

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

There may be others.

Within this scheme, you can implement arbitrary scaling (suitable for scaling or zooming). Within the scaling restrictions that you allow, your algorithm will be something like this:

  • For the zoom level selected by the user, select the closest higher resolution cache. For example, if you have 100%, 50%, 25% and 12.5% ​​tiles, and the user selects 33% scaling, select 50% tiles
  • Set the layout for the tiles so that the squares of the tiles have the correct size for the selected enlargement (this can be one tile with minimal zoom levels). For example, with 33% scaling using 50% of the tiles, with the tiles being 100 pixels, the grid will be 67 pixels.
  • Individually upload and scale tile images according to the screen (it can be multithreaded, which works well on modern processor architectures).

There are a few comments:

  • The scaling algorithm changes when you reach the highest resolution for which you have tiles.
    • Use up to 100% image scaling using bilinear or bicubic scaling. This provides a great look for photos with a little serration.
    • Above 100%, you probably want to show pixels, so the closest neighbor might be a good choice.
  • For higher accuracy, use a higher scale and zoom out> 50%. For example, suppose you have a tile cooked at 100%, 50%, 25%, and 12.5%. To show 40% scaling, do not reduce 50% of the tile; instead, use 100% of the tiles and reduce them to 40%. This is useful:
    • If your images are text or diagrams (i.e. bitmaps containing many straight lines). Scaling these types of images often leads to unpleasant artifacts if you do not overfulfill
    • If you need very high precision photographic style images
  • If you need to make a preview of the zoom (for example, while the user is still holding and zooming), take a screenshot at the beginning of the gestures and zoom in. This is much more important than the smooth animation than the zoom preview, perfect for the pixel.
  • Choosing the right tile size is important. Very large tiles (<1 per screen) are slowly displayed. Too small tiles create other overheads and often create unpleasant rendering artifacts where you see the screen filling accidentally. A good trade-off between performance and complexity is to make tiles about a quarter of the full-screen size.

When using these methods, images should load very quickly, so the progress indicator is not so important. If so, then you need to register IIOReadProgressListener on ImageReader :

From JavaDoc:

The interface used by ImageReader implementations to notify callers about methods of viewing images and showing thumbnails of progress.

This interface receives general indications of decoding progress (using the imageProgress and thumbnailProgress methods) and events indicating when the whole image was updated (using the imageStarted, imageComplete, thumbnailStarted and thumbnailComplete methods). Applications that want to receive information about pixel updates as they occur (for example, with progressive decoding) must provide the IIOReadUpdateListener identifier.

+2
source

All Articles