class GeoPackageImageProvider implements ImageProvider<ZYXImageKey> {

    @Override
    public Image getImage(ZYXImageKey key)
    {
        DataModelCategory imageCategory = new DataModelCategory(myLayer.getPackageFile(), myLayer.getName(),
                Image.class.getName());
        List<PropertyMatcher<?>> matchers = New.list();
        ZYXKeyPropertyMatcher keyMatcher = new ZYXKeyPropertyMatcher(GeoPackagePropertyDescriptors.KEY_PROPERTY_DESCRIPTOR, key);
        matchers.add(keyMatcher);
        SimpleQuery<InputStream> query = new SimpleQuery<>(imageCategory, GeoPackagePropertyDescriptors.IMAGE_PROPERTY_DESCRIPTOR,
                matchers);

        Image image = null;
        myTracker.upCounter();

        try
        {
            QueryTracker tracker = myRegistry.performQuery(query);

            if (query.getResults() != null && !query.getResults().isEmpty())
            {
                try
                {
                    if (myImageReader == null)
                    {
                        InputStream stream = query.getResults().get(0);

                        if (StringUtils.isNotEmpty(myLayer.getExtensions().get(Constants.TERRAIN_EXTENSION)))
                        {
                            StreamReader reader = new StreamReader(stream);
                            ByteBuffer buffer = reader.readStreamIntoBuffer();
                            image = new StreamingImage<>(new GeoPackageStreamingImageProvider(buffer), key, 512, 512);
                        }
                        else
                        {
                            StreamingDDSImage.setThreadByteBufferPool(ourByteBufferPool);
                            try (ObjectInputStream ois = new ObjectInputStream(stream))
                            {
                                image = (Image)ois.readObject();
                            }
                            catch (ClassNotFoundException e)
                            {
                                LOGGER.error(e, e);
                            }
                            finally
                            {
                                StreamingDDSImage.setThreadByteBufferPool(null);
                            }
                        }
                    }
                    else
                    {
                        StreamReader reader = new StreamReader(query.getResults().get(0));
                        image = myImageReader.readImage(reader.readStreamIntoBuffer());
                    }
                }
                catch (ClosedByInterruptException e)
                {
                    if (LOGGER.isDebugEnabled())
                    {
                        LOGGER.debug(e, e);
                    }
                }
                catch (IOException e)
                {
                    LOGGER.error(e, e);
                }
            }
            else if (tracker.getException() != null)
            {
                LOGGER.error(tracker.getException(), tracker.getException());
            }
        }
        finally
        {
            myTracker.subtractCounter();
        }

        return image;
    }

    public  GeoPackageImageProvider(DataRegistry registry, GeoPackageTileLayer layer, GeoPackageQueryTracker queryTracker);

}