0

In reference to the answer (how to convert dzi (deep zoom) files to full image)

I am a noob on this topic, please correct if I am wrong.

I am trying to create a multi-tiled tiff from .dzi (deep zoom image) format, how I am doing is:

(i) Pick the max level folder.

(ii) Vertically Stitch all the n columns of m rows (m_n.jpeg, I am referring to the images saved in this format) as png images. So they are occupying quite a considerable amount of space.

(iii) Finally, I horizontally merge all these vertical png images into a single full image png using pyvips.Image.write_to_file().

(iv) Finally using vips im_save, I convert the full image png to tiff.

My concern now is this process is taking almost 2 hours for it to make full image png for 30,000 base_tiles, and also it accounts to 10+ GB of size (Full Image png).

Is there any better and faster way to do the .dzi to tiff conversion?

  • Yes, that seems like the basic practice. Are you saving each intermediate merge out as a file? I imagine it would be more efficient to do it all in memory if you can. I'm not sure what tool would be best for that (looks like you're using VIPS... maybe they have a technique for batching operations). BTW, if your tiles are approximately 256 pixels on a side and you have 30,000 of them at the max level, that would be an image that's approximately 44,000 pixels on a side, which is approximately 2 billion pixels. I don't know how much compression you're getting, but 10GB for that seems reasonable. – iangilman Nov 15 '19 at 18:17
  • Hi iangilman, thank you for your thoughts, all my images are 512x512, and the final merge is all happening in-memory using pyvips, but this conversion in total takes approx 2 hours for it to write the image to the disk, and that is kind of too much of time that it is taking, is there any better way ? – Harish Kumar Thirugnanam Nov 17 '19 at 05:19
  • I don't really know, but it looks like you're getting some good help from jcupitt! – iangilman Nov 20 '19 at 22:37

1 Answers1

4

libvips has an arrayjoin operator that can join a set of tiles together into a large image.

You can use it like this (on the linux command-line):

vips arrayjoin "$(ls *.jpeg | sort -t_ -k2g -k1g)" x.tif[tile,pyramid,compression=jpeg] --across 20

That will load all the JPG image in the current directory, assemble them into a huge grid, 20 images across, and write as a TIFF pyramid. You'd need to check the size of your grid, obviously, and adjust the across parameter.

The $() part sorts the filenames of the form x_y.jpeg by y first, then x, in numeric order. Without that, the tiles will be transposed, annoyingly.

That's assuming overlap 0. If your tiles have an overlap, you'll need to set the hspacing and vspacing options to control how tiles are positioned. For example:

vips arrayjoin "$(ls *.jpg | sort -t_ -k2g -k1g)" x.tif --across 20 --hspacing 254 --vspacing 254

Will position the tiles every 254 pixels horizontally and vertically.

Here's a worked example. First, create a deepzoom pyramid with no overlaps:

john@kiwi:~/pics/x$ vips dzsave ~/pics/k2.jpg x --overlap 0
john@kiwi:~/pics/x$ cd x_files/11
john@kiwi:~/pics/x/x_files/11$ ls
0_0.jpeg  0_7.jpeg  1_5.jpeg  2_3.jpeg  3_1.jpeg  3_8.jpeg  4_6.jpeg  5_4.jpeg
0_1.jpeg  0_8.jpeg  1_6.jpeg  2_4.jpeg  3_2.jpeg  4_0.jpeg  4_7.jpeg  5_5.jpeg
0_2.jpeg  1_0.jpeg  1_7.jpeg  2_5.jpeg  3_3.jpeg  4_1.jpeg  4_8.jpeg  5_6.jpeg
0_3.jpeg  1_1.jpeg  1_8.jpeg  2_6.jpeg  3_4.jpeg  4_2.jpeg  5_0.jpeg  5_7.jpeg
0_4.jpeg  1_2.jpeg  2_0.jpeg  2_7.jpeg  3_5.jpeg  4_3.jpeg  5_1.jpeg  5_8.jpeg
0_5.jpeg  1_3.jpeg  2_1.jpeg  2_8.jpeg  3_6.jpeg  4_4.jpeg  5_2.jpeg
0_6.jpeg  1_4.jpeg  2_2.jpeg  3_0.jpeg  3_7.jpeg  4_5.jpeg  5_3.jpeg

You can see it's made a grid of tiles 6 across and 9 down.

Now reassemble the tiles and write as a TIFF pyramid:

john@kiwi:~/pics/x/x_files/11$ vips arrayjoin "$(ls *.jpeg | sort -t_ -k2g -k1g)" x.tif[tile,pyramid,compression=jpeg] --across 6
john@kiwi:~/pics/x/x_files/11$ vipsheader x.tif 
x.tif: 1524x2286 uchar, 3 bands, srgb, tiffload_stream

With pyvips it would be something like:

#!/usr/bin/env python3
  
import pyvips

tiles_across = 142
tiles_down = 150

tiles = [pyvips.Image.new_from_file(f"{x}_{y}.jpeg", access="sequential")
         for y in range(tiles_down) for x in range(tiles_across)]
im = pyvips.Image.arrayjoin(tiles, across=tiles_across)

im.write_to_file("x.jpg")

That took about 10 minutes and 6gb of ram to join 21,000 tiles on this laptop.

jcupitt
  • 10,213
  • 2
  • 23
  • 39
  • Hi jcupitt, thank you so much for the reply, but I don't understand what is the parameter --across, like what does it do ? and how should be my command for a folder with 0_0.jpeg to 146_216.jpeg, I am new to this topic so require more help. Thank You. – Harish Kumar Thirugnanam Nov 19 '19 at 07:15
  • `across` is the number of tiles across the grid, have a look at the docs. You'd need `--across 217`. I would experiment with a small grid, perhaps 20 by 20, to start with. – jcupitt Nov 19 '19 at 07:39
  • Hi jcupitt, it worked really good for tiles with 31 columns, but as the number of files grows more say for example where there are 124 columns, I get the following error: Command: /var/www/html/eqtribe/acquired_data/131/grid_1/base_tiles/000_files/14 Error: bash: /usr/bin/vips: Argument list too long – Harish Kumar Thirugnanam Nov 19 '19 at 09:49
  • If your command has become too long for bash, you'll need to switch to something like Python. Just open all the tiles and pass the list to `pyvips.Image.arrayjoin()`. – jcupitt Nov 19 '19 at 13:46
  • I added a pyvips example. – jcupitt Nov 19 '19 at 14:01
  • Hi jucpitt, the function arrayjoin() works like a charm, but I had to do some alteration though as in to segregate my files, I had 12500+ jpegs of size 512x512, comprising of 102 rows & 122 columns, I split these as 4 quads so that the open files open would be less than 4096 (that's the max for ubuntu according to a source in internet), now I have 4 jpeg images that has to be converted to tiff, I follow your first command to execute on the terminal, the tiff generated is not pyramidal/multi-tilled tiff. – Harish Kumar Thirugnanam Nov 22 '19 at 08:27
  • In that case, in order to convert it into multi-tiled tiff I follow the command from your official page for the same " vips im_vips2tiff final.tiff image.tiff:jpeg:75,tile:256x256,pyramid,,,,8 ", but I am getting line cache error at 0x27392, and the conversion exits with an vips read error. Please help me on how to figure out this issue. Thank You. – Harish Kumar Thirugnanam Nov 22 '19 at 08:31
  • You've found some old page with out of date docs that are no longer correct. Don't build in two steps --- you can assemble the DZI tiles and build the tiff pyramid with the single command in the answer above. – jcupitt Nov 22 '19 at 09:57
  • Hi jcupitt, but the tiff that is generated from that is not a multi-tiled tiff, and I am unable to open that using ASAP viewer. Or is there any viewer software that supports this tiff format to be viewed. Thank you. – Harish Kumar Thirugnanam Nov 22 '19 at 16:36
  • Hello again, using `x.tif[tile,pyramid,compression=jpeg]` as the output name will generate a tiled, pyramidal tiff with jpeg compression. I don't know what ASAP viewer is, but I guess it's not compatible. – jcupitt Nov 22 '19 at 23:14
  • Thank you again, I will look for other tiff viewers, in that case. – Harish Kumar Thirugnanam Nov 23 '19 at 07:16