Como abordar la implementacion del API
La idea principal es añadir los metodos que hemos definido que debe tener nuestro API de scripting a la clase FLyrRaster.
Como para gestionar la implementacion precisamos de propiedades y metodos, he metido las nuevas propiedades junto con los metodos que las manejan en una clase "RasterLayerExtensions" y cuando necesito acceder a ellas creo una instancia y la mantengo en un map asociada a la clase FLyrRaster.
Para hacer las pruebas con comodidad trabajaremos con un script desde el composer, pero luego generaremos un fichero gvsig_raster.py junto al gvsig.py.
No he llegado a probar el codigo, puede tener errores, de sintaxis y de ejecucion.
Cuando tenga otro rato intentare probarlo y añadir mas explicaciones al codigo.
Ya me comentas como lo ves y si puedes o no continuar por ahi. Espero comentatios sobre el codigo:
- Que te parece
- Que entiendes y que no (describe con detalle lo que no entiendas).
- Si lo harias de otra forma, y en ese caso describela.
from gvsig import *
#--------------------------------------------------------------
# This code will go to the module gvsig_raster.py
# Now is here to debug more easily
# Begin module gvsig_raster
from org.gvsig.fmap.dal.coverage import RasterLocator
from org.gvsig.fmap.dal import DALLocator
from org.gvsig.fmap.dal.coverage.dataset import Buffer, BufferParam
from org.gvsig.raster.fmap.layers import FLyrRaster
from java.lang import Byte, Short, Integer, Float, Double
from os.path import splitext
def loadRasterLayer(rasterfile ,mode="r"):
"""
Load a raster file in a layer
"""
if not isinstance(rasterfile, File):
rasterfile = File(rasterfile)
name, ext = splitext(rasterfile.getName())[0]
# Get the manager to use
dalManager = DALLocator.getDataManager()
if ext.lower() == ".ecw" or ext.lower() == ".jp2" :
# FIXME
pass
elif ext.lower() == ".mrsid":
# FIXME
pass
else:
# Create the parameters to open the raster store based in GDAL
params = dalManager.createStoreParameters("Gdal Store")
params.setFile()
# Create the raster store
dataStore = dalManager.createStore(params)
# Create a raster layer based in this raster store
layer = mapContextManager.createLayer(name, dataStore);
return layer
rasterLayerExtensions = dict()
class RasterLayerExtensions(object):
"""
This class hold aditional properties and operations need to manage the scripting raster layer
(query, buffer, values....)
"""
def __init__(self, store=None):
self.store = store
self.buffer = None
self.query = None
self.values = None
self.kernel = None
self.setElem = None
self.getElem = None
def prepareQuery(self):
## See RasterManager in javadocs for more info
self.query = RasterLocator.getManager().createQuery();
## See RasterQuery in javadocs for more info
self.query.setAllDrawableBands()
self.query.setAreaOfInterest()
self.buffer = None
self.values = None
self.kernel = None
def createBuffer(self):
self.buffer = self.store.query(self.getQuery())
def createNewBuffer(with,height,bandcount, datatype):
if self.store != None:
raise RuntimeException("Can't create a new buffer associated to a store")
# FIXME: workaround to work with a jython bug passing byte, short and
# double values as parameters
if datatype in (Buffer.TYPE_BYTE, Buffer.TYPE_SHORT, Buffer.TYPE_INT):
datatype = Buffer.TYPE_INT
else:
Buffer.TYPE_FLOAT
# End workaround
params = RasterLocator.getManager().getBufferFactory().createBufferParams(
width,
height,
bandcount,
datatype,
BufferParam.CACHED
)
self.buffer = RasterLocator.getManager().getBufferFactory().createBuffer(params)
self.prepareBuffer()
def prepareBuffer(self):
def setElemByte(buffer, line, col, band, data):
buffer.setElem(line, col, band, Byte(data).byteValue())
def setElemShort(buffer, line, col, band, data):
buffer.setElem(line, col, band, Short(data).shortValue())
def setElemInt(buffer, line, col, band, data):
buffer.setElem(line, col, band, Integer(data).intValue())
def setElemFloat(buffer, line, col, band, data):
buffer.setElem(line, col, band, Float(data).floatValue())
def setElemDouble(buffer, line, col, band, data):
buffer.setElem(line, col, band, Double(data).doubleValue())
t = buffer.getDataType()
if t == Buffer.TYPE_BYTE:
this.getElem = this.buffer.getElemByte
this.setElem = setElemByte
elif t == Buffer.TYPE__SHORT or t == Buffer.TYPE__USHORT:
this.getElem = this.buffer.getElemShort
this.setElem = setElemShort
elif t == Buffer.TYPE__INT:
this.getElem = this.buffer.getElemInt
this.setElem = setElemInt
elif t == Buffer.TYPE__FLOAT:
this.getElem = this.buffer.getElemFloat
this.setElem = setElemFloat
elif t == Buffer.TYPE__DOUBLE:
this.getElem = this.buffer.getElemDouble
this.setElem = setElemDouble
self.values = [0] * this.buffer.getBandCount()
self.kernel = [[self.values * 3 ] * 3
def getQuery(self):
if self.query == None:
self.prepareQuery()
return self.query
def getBuffer(self, store):
if self.buffer == None:
self.createBuffer()
self.prepareBuffer()
return self.buffer
def getValue(self, band, row, column):
if self.getElem == None:
self.createBuffer()
self.prepareBuffer()
return self.getElem(row,column,band)
def getBandValues(row, column):
if self.getElem == None:
self.createBuffer()
self.prepareBuffer()
for b in xrange(self.buffer.getBancCount()):
self.values[b] = self.getElem(row, column, b)
return self.values
def setBandValues(row,column,values):
for b in xrange(self.buffer.getBancCount()):
self.setElem(self.buffer, row, column, b, values[b])
def saveBuffer(filename):
manager = DALLocator.getDataManager()
eparams = manager.createServerExplorerParameters("FilesystemExplorer")
eparams.setDynValue("initialpath", "/tmp")
serverExplorer = manager.openServerExplorer(eparams.getExplorerName(), eparams)
sparams = (NewRasterStoreParameters)serverExplorer.getAddParameters("Gdal Store")
sparams.setFileName(filename)
sparams.setBuffer(buffer)
serverExplorer.add("Gdal Store", sparams, True)
def getExtensions(self):
global rasterLayerExtensions
extensions = rasterLayerExtensions.get(self.hashCode(),None)
if extensions == None :
extensions = RasterLayerExtensions(self.getDataStore())
rasterLayerExtensions[self.hashCode()] = extensions
return extensions
def getBandsCount(self):
return self.getDataStore().getBandCount()
def getWidth(self):
return self.getDataStore().getWidth()
def getHeight(self):
return self.getDataStore().getHeight()
def getDataType(self):
return self.getDataStore().getDataType()
def getData(self, band, row, column):
return self.getExtensions().getValue(band, row, column)
def walk(self, operation):
extension = self.getExtensions()
store = self.getDataStore()
for band in xrange(store.getBandCount()):
for line in xrange(store.getHeight()):
for column in xrange(store.getWidth()):
operation(extension.getBandValues(line, column))
def walkKernel(self, operation):
pass
def filter(self, filter, targetfilename, targetdatatype=None, targetbandcount=None):
extension = self.getExtensions()
store = self.getDataStore()
targetExtension = RasterLayerExtensions()
targetExtension.createNewBuffer(
store.getWidth(),
store.getHeight(),
targetbandcount,
targetdatatype
)
for band in xrange(store.getBandCount()):
for line in xrange(store.getHeight()):
for column in xrange(store.getWidth()):
values = filter(extension.getBandValues(line, column))
targetExtension.setBandValues(line, column, values)
targetExtension.saveBuffer(targetfilename);
def filterKernel(self, filter, targetfilename, targettype):
pass
def operation(self, oepration, layer2, targetfilename, targettype):
pass
def operationKernel(self, oepration, layer2, targetfilename, targettype):
pass
#
# Inject new methods in the class FLyrRaster
#
FLyrRaster.getExtensions = getExtensions
FLyrRaster.getBandsCount = getBandsCount
FLyrRaster.getWidth = getWidth
FLyrRaster.getHeight = getHeight
FLyrRaster.getDataType = getDataType
FLyrRaster.getData = getData
FLyrRaster.walk = walk
FLyrRaster.walkKernel = walkKernel
FLyrRaster.filter = filter
FLyrRaster.filterKernel = filterKernel
FLyrRaster.operation = operation
FLyrRaster.operationKernel = operationKernel
#
# end module gvsig_raster.py
#-------------------------------------------------------------
#
# Here, code to test the new API.
#
def incrShine(values):
x = list()
for value in values:
x.append(value+20)
return x
def main():
layer = loadRasterLayer("/tmp/Costa1.tif")
layer.filter(incrShine, "/tmp/Costa1-B.tif")