5

Is there any way to retrieve info about tile compression (JPEG/PNG, PNG, etc.) which geopackege file uses? I have tried a gdalinfo command, but it does not provide this type of information.

3

Only way to get that information is to read all the tiles. Gdalinfo gives common information about the whole raster layer but the layer may be a mixture of PNG and JPEG tiles. By the GeoPackage definition

Images of multiple MIME types MAY be stored in given table. For example, in a tiles table, image/png format tiles COULD be used for transparency where there is no data on the tile edges, and image/jpeg format tiles COULD be used for storage efficiency where there is image data for all pixels. Images of multiple bit depths of the same MIME type MAY also be stored in a given table, for example image/png tiles in both 8 and 24 bit depths.

PNG and JPEG tiles are always allowed. It is also possible to save tiles as WebP but in this case there must be a row in gpkg_extensions table to tell that a certain table may have WebP tiles. Such table may still contain also PNG and JPEG tiles.

1
  • Thank you for your valued answer. After some googling I have found end solution for me.
    – M.D.93
    Dec 3 '21 at 15:05
3

The GPKG file does not store this information globally, instead any tile can be in a different format. You can try to determine the type of the data in a tile by comparing its first bytes against known "magic bytes".

GPKG is a SQLite database, so you can run queries against the data with an SQLite client.

Here is an example that tries to guess the image data types using this approach:

SELECT
    count(*) FILTER (
        WHERE hex(tile_data) LIKE '89504E470D0A1A0A%'
    ) AS png
    , count(*) FILTER (
        WHERE hex(tile_data ) LIKE 'FFD8FFDB%'
        OR hex(tile_data) LIKE 'FFD8FFEE%'
    ) AS jpeg
    , count(*) FILTER (
        WHERE hex(tile_data) LIKE '52494646%'
    ) AS webp
from table_name;
png jpeg webp
81 0 0
3
  • Nice idea! I wonder if should use hex(left(tile_data,4)) to avoid the overhead of converting each whole tile? (I don't have SQL on the machine I'm writing this from to test.)
    – Houska
    Dec 3 '21 at 16:59
  • 1
    Idea is great, but this syntax didn't work for me, as it is stated at modern-sql.com/feature/filter#emulate-count, count(*) needs special treatment and second syntax stated there: COUNT(CASE WHEN <condition> THEN 1 END) worked for me.
    – M.D.93
    Dec 3 '21 at 18:34
  • 1
    My Geopackage has another (JFIF) magic byte for jpeg, so I must add 2 other magic bytes from your wikipedia link to make it work
    – M.D.93
    Dec 3 '21 at 19:52
2

Based on user30184's answer, I have found this final solution for my question (Tested on Ubuntu 18.04):

sudo apt install sqlite3
sqlite3 gepackage_name.gpkg "SELECT * FROM 'table_name';" | tr -cd "[:print:]" | less
  • it shows string parts of all images in a given table in the database, and in case of png files, it shows PNG after an 8 signs sequence like this 1|8|0|0|
  • in case of JPG, after the 8 signs sequence it shows nothing
  • for reliable using it could be more polished (how to distinguish jpeg and webp, png bit depth, and so on), but for my case it is enough
  • I used this tutorial and this answer

Based on bugmenot123's answer and my comments there, the final one line solution to reliably count png, jpeg and webp tiles (in this order) was this:

sqlite3 geopackage_name.gpkg "SELECT count(CASE WHEN hex(tile_data) LIKE '89504E470D0A1A0A%' THEN 1 END) AS png , count(CASE WHEN (hex(tile_data ) LIKE 'FFD8FFDB%' OR hex(tile_data) LIKE 'FFD8FFEE%' OR hex(tile_data) LIKE 'FFD8FFE000104A4649460001%' OR hex(tile_data) LIKE 'FFD8FFE1%') THEN 1 END) AS jpeg , count(CASE WHEN hex(tile_data) LIKE '52494646%' THEN 1 END) AS webp from 'table_name';"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.