Search code examples
image-processinggdalvips

libvips and padding when doing image pyramids


I am trying to do a pyramid of tiles with a non-square image (width: 32768px and height: 18433px)

I am using libvips as follows:

vips dzsave my_image.tif out_folder --layout google --suffix .png

For the same purpose I have also used gdal2tiles:

python gdal2tiles.py -p raster -z 0-7 -w none my_image.tif

Because my image is not square, some padding is necessary when the 256x256 tiles are created. Padding however is different between vips and gdal2tiles. The former adds padding at the bottom of the tile where as the latter at the top (and is trasparent). See image below. What is shown in the the 256x256 tile at the root of the pyramid (ie zoom level=0). I have manually added the yellow background and the black outline.

With vips, is it possible to have similar padding to gdal2tiles so that the bottom-left corner of the tile coincide with that from the image? I am plotting points on my image, hence it helps to have the origin at the bottom-left.

How can I also have transparent background with vips? (that might better be in a separate post though...)

enter image description here


Solution

  • You can run dzsave as the output of any vips operation by using .dz as the file extension and putting the arguments in square brackets after the filename. For example, this command:

    vips dzsave my_image.tif out_folder --layout google --suffix .png
    

    Can also be written as:

    vips copy my_image.tif out_folder.dz[layout=google,suffix=.png]
    

    So you can solve your problem by expanding your input image to a square before running dzsave.

    For example:

    $ vips gravity Chicago.jpg dir.dz[layout=google,suffix=.png,skip_blanks=0] south-west 32768 32768 --extend white
    

    32768 is the nearest power of two above that image width. The skip_blanks option makes dzsave not output tiles equal to the blank background tile.

    That command makes this dir/0/0/0.png:

    enter image description here

    (I added the black lines to show the edges)

    To get a transparent background, you need to add an alpha. This would require another command, and is beyond what the vips CLI is really designed for.

    I would switch to something like Python. With pyvips, for example, you can write:

    import sys
    import pyvips
    
    im = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
    
    im = im.addalpha()
    
    # expand to the nearest power of two larger square ... by default, gravity will
    # extend with 0 (transparent) pixels
    size = 1 << int.bit_length(max(im.width, im.height))
    im = im.gravity('south-west', size, size)
    
    im.dzsave(sys.argv[2], 
              layout='google', suffix='.png', background=0, skip_blanks=0)
    

    Run like this:

    $ ./mkpyr.py ~/pics/Chicago.jpg x
    

    To make this x/0/0/0.png:

    enter image description here

    (added the green background to show the transparency)