27 Jul 2018

Viewing Large OCR/Terrain Images in Forge Viewer

While visiting a Forge customer in Brisbane, Australia, I was asked... "can the Forge-Viewer display large bitmap images, like a scanned document, or a large terrain-map?"   Yes it can - here's how....  

Forge Viewer has a Leaflet viewer, built-in.

DEMO - Terrain

DEMO - PDF document

GitHub Source Code

Using the Forge Viewer for large-images, let's you take advantage of the built-in markup and measure tools - this is the same feature found in BIM360 for viewing PDF's.

> How does it work?


1. Generating the tiles

Large images are broken up into 'tiles' of bitmaps, at different 'Levels of resolution', forming what is called a 'tile pyramid'.

Here's a 'tile pyramid' diagram...

Let's dig in...

At the top of the pyramid, level 0, a single tile, it shows a blurry, low-resolution, version of the map-of-the-world image.

Like the terrain map example (left image): 

The next level down, level 1 (middle image), the map-of-the-world is split into four tiles and the resolution is higher, less blurry.

Similarly level 2 (right image), we now have 16 tiles.  Sharper, more detail.

We keep going, generating many levels, and more image detail.

2. Viewing the tiles

When a browser wants to view a city, say Paris, from google maps, it doesn't load the entire map of the world and every tile in the 'tile pyramid'.  It's too big.

Instead, the browser figures out the right 'level' in the pyramid, and only loads the tiles that are specific to Paris, at a resolution that fits our screen resolution.

3. Faster UX

For a faster loading experience, the viewer, can  load, a low-quality 'preview' of the "Paris tiles" first, before loading the final tiles.  This is easy to do with a tile-pyramid.  

DEMO - PDF document

Say, the "Paris tiles" are at level 14.  First, load a single 256x256 tile of Paris, probably level 12, and stretch it to fill the screen (blurry).  Now, switch to the "level 13" tile set, which is sharper.  Finally, load level 14, sharper again.

You can see this in the animation above.  The Forge Viewer is showing a PDF made of tile images.  It loads level 10, then 11, 12 and finally settles on level 13 to match my viewport and MacBook Retina pixel density.  On the righthand side, I have the network debug console open, showing the image tiles steaming in.  I set the network load performance to 'slow 3G' to slow things down, so you can see the effect.

256x256 tile - Level 12 

256x256 tile - Level 11

 A 256x256 pixel resolution tile is loaded and stretched to fit the canvas (right image), then that stretched tile is replaced by four 256x256 pixel tiles (left image).


> How to create your own tile-pyramid


1. Pulling a Terrain map

To provide some sample content for my demo, I'm going to pull a tile-pyramid from OpenTopoMap, specifically, a terrain map, so I can demostrate the measure tool.

Here is the bash script I used...

gettiles () {
mkdir $1; cd $1;
 for (( y=0; y<=$2; y++ )) do
  for (( x=0; x<=$2; x++ )) do
      curl https://a.tile.opentopomap.org/$(($1-6))/$(($y+$4))/$(($x+$3)).png -o $x-$y.png &
cd ..;

mkdir 9; cd 9;
curl https://a.tile.opentopomap.org/1/0/0.png -o 0-0.png &
cd ..;

gettiles 10 1 5 3
gettiles 11 3 10 6
gettiles 12 6 20 12
gettiles 13 12 40 24
gettiles 14 30 80 48

The script only downloads a section of the TopoMap tiles into a local folder.  Each tile is 256x256, yet the full terrain width and height comes to 6k x 6k pixels, for this sample set (a set region surrounding Chicago at maximum level 13).

Now I modify the bubble.json file to point to the new folder containing all those image tiles.  And I upated the pixel resolution too.

When I open the index.html file, and point the documentId to the topo/bubble.json file, I now see my terrain map !

I can zoom in and out to get more terrain details. I can also add markup and measurements.

Here's a live DEMO - Terrain

Note: I use window.location.hash, to specify the tile folder name. i.e.. topo/ is the folder, so I use #topo in the URL.

2. Converting a large image (an OCR scan)

Say you have scanned a large document (OCR) and now have a really large 6k by 6k TIFF file.  It's 200MB is size, which is too big and clunky to load quickly in a browser, and also ... you want to add markup and measurements.

So, let's first convert the scanned TIFF image to a jpeg tile-pyramid, like we did with the two examples above (PDF and Terrain). I'll use imagemagick to do this.

From the commandline, I type in...

convert image.tif -resize 1.5625% -crop 256x256 +repage +adjoin out/1/tile_1_%d.jpg
convert image.tif -resize 3.125% -crop 256x256 +repage +adjoin out/2/tile_2_%d.jpg
convert image.tif -resize 6.25% -crop 256x256 +repage +adjoin out/3/tile_3_%d.jpg
convert image.tif -resize 12.5% -crop 256x256 +repage +adjoin out/4/tile_4_%d.jpg
convert image.tif -resize 25% -crop 256x256 +repage +adjoin out/5/tile_5_%d.jpg
convert image.tif -resize 50% -crop 256x256 +repage +adjoin out/6/tile_6_%d.jpg
convert image.tif -crop 256x256 +repage +adjoin out/7/tile_7_%d.jpg

I then create a bubble.json file.  This tells Forge Viewer where the folder of tile images is, and also the mask, for example: out/z/y/x.jpg.  I also set the pixel resolution, as done in the terrain demo.

I open the ./index.html#out file and my OCR scanned document appears - it loads quickly and I can measure and do markup's.

Offline Markup and Measure 

Included in this example are the files you need to take this 2D demo 'offline' including the markup and measure tools.  See the files listed in the GitHub repo.


  • modify the CSS to create a custom markup UI.
  • you will need to calibrate measure, to start making measurements.


That's it - stay tuned for more handy 2D Forge Viewer ideas in my next blog post.

Don't forget to follow me on twitter...

Related Article