openwisp / django-rest-framework-gis

Geographic add-ons for Django REST Framework. Maintained by the OpenWISP Project.
http://openwisp.org
MIT License
1.07k stars 200 forks source link

Serializing to RasterField() #260

Closed simon-tarr closed 3 years ago

simon-tarr commented 3 years ago

Hello django-rest-framework-gis team, thanks for your work on this package, it's been super helpful for me recently. I have a quick question that I'm hoping someone can help me with. I have read through the ReadMe and also searched issues, but I can't see a mention of 'raster' so I hope it's okay to post a quick question here.

Question Is it possible to easily serialize a raster (.tif) image so that it can be saved to a geodjango RasterField()?

Use Case I have an app which grabs some Corine landcover data via the API. With the .tif file in memory, I wish to save the data to a RasterField:

# bbox = <add_bbox_coords_here>
corine_lc = requests.get("https://image.discomap.eea.europa.eu/arcgis/rest/services/Corine/CLC2018_WM/MapServer/export?bbox="+bbox+"&bboxSR=4326&layers=&layerDefs=&size=800%2C800&imageSR=&historicMoment=&format=tif&transparent=true&dpi=300&time=&layerTimeOptions=&dynamicLayers=&gdbVersion=&mapScale=&rotation=&datumTransformations=&layerParameterValues=&mapRangeValues=&layerRangeValues=&clipping=&spatialFilter=&f=json")
corine_lc = corine_lc.json()
file = rasterio.open(corine_lc['href'])

# Use 'file' to save to a RasterField

If this is a ridiculous way to approach the problem, does anyone know a better way of doing this? Perhaps some sort of ByteIO way, saving the .tif as raw data into a different model field type?

Thanks!

nemesifier commented 3 years ago

I honestly have no idea, nor I know if this is on-topic for this project or not. In this org we maintain a lot of packages we use in OpenWISP and we are generally overloaded with work to do and have very little time available to answer questions like this one.

I am closing this because it's not a bug report nor an explicit feature request. If you find an answer to your question and you think this can become a feature request please reopen and add the necessary deatails and motivations.

I wish you good luck with your search!

Best regards Federico

henriod commented 3 years ago

Hello @simon-tarr i would like to help..what i will do is first receive the file as image tiff file the have a signal file in geodjango do these

from django.contrib.gis.gdal import GDALRaster

raster = GDALRaster('/path/to/your/raster.tif', write=False)

my_raster_model.objects.filter(pk=instance.pk).update(raster=raster)

where raster is RasterField in my_raster_model

simon-tarr commented 3 years ago

Hi @henriod thanks for your answer but it doesn't demonstrate how to serialise the raster. Your solution uses Django's ORM, which is not a viable solution when moving data via an API (hence the existence of the django-rest-framework-gis library). I need to serialize the .tif so that it can be sent via requests.post (or similar.)

Apologies if I've misunderstood your response, however!

henriod commented 3 years ago

Hi @simon-tarr thank for pointing that out. Having looked at Django rest framework serializer fields i found this under imageField.

from django.forms import ImageField as DjangoImageField
class ImageField(FileField):
    default_error_messages = {
        'invalid_image': _(
            'Upload a valid image. The file you uploaded was either not an image or a corrupted image.'
        ),
    }

    def __init__(self, **kwargs):
        self._DjangoImageField = kwargs.pop('_DjangoImageField', DjangoImageField)
        super().__init__(**kwargs)

    def to_internal_value(self, data):
        # Image validation is a bit grungy, so we'll just outright
        # defer to Django's implementation so we don't need to
        # consider it, or treat PIL as a test dependency.
        file_object = super().to_internal_value(data)
        django_field = self._DjangoImageField()
        django_field.error_messages = self.error_messages
        return django_field.clean(file_object)

which is used in serializer for image. Which mean this have to be developed in this project too for raster fields as they have done for geometry fields. we can try it out then create a pull request

simon-tarr commented 3 years ago

Hi @henriod thanks for the detective work in DRF's ImageField.

Unfortunately I'm a bit rookie to fully understand how to implement this within djang-rest-framework-gis. I'd have to do some research to see how this would be possible.