source: DPPP/ukcip02_server/trunk/ukcip_server/ukcip_server/model/pywms/render_imp.py @ 3495

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/DPPP/ukcip02_server/trunk/ukcip_server/ukcip_server/model/pywms/render_imp.py@3495
Revision 3495, 4.4 KB checked in by spascoe, 14 years ago (diff)

Dimensions reported properly in capabilities. GetMap? confirmed as working with cdms2

Line 
1"""
2Implementation of grid rendering classes.
3
4@author: Stephen Pascoe
5"""
6
7from view import GridRenderer
8import ImageColor, Image
9import Numeric as N
10import logging
11from matplotlib import cm, colors
12
13logger = logging.getLogger(__name__)
14
15class RGBARenderer(GridRenderer):
16    """Creates an RGBA PNG with a selectable matplotlib colour scale.
17    """
18
19    mimeType = 'image/png'
20
21    def __init__(self, varmin, varmax):
22        self.varmin = varmin
23        self.varmax = varmax
24        self._norm = colors.normalize(varmin, varmax)
25
26    def renderColourbar(self, width, height, cmap, isVertical=True):
27        a = N.arrayrange(0, 1.0, 1.0/256)
28        if isVertical:
29            a = a[-1::-1]
30            shape = (1, 256)
31        else:
32            shape = (256, 1)
33
34        cbar = (cmap(a) * 255).astype('b').tostring()
35        img = Image.frombuffer("RGBA", shape, cbar, "raw", "RGBA", 0, 1)
36        img = img.resize((width, height))
37
38        return img
39
40    def renderGrid(self, grid, bbox, width, height, cmap):
41        cmap.set_bad('#ffffff', 0.0)
42
43        logger.debug('grid %s, %s, %s, %s, %s, %s %s, %s' %
44                    (grid.x0, grid.y0, grid.dx, grid.dy, grid.nx, grid.ny,
45                     grid.ix, grid.iy))
46        logger.debug('bbox %s' % (bbox,))
47
48        # Get a pixel = grid-box image for the grid
49        img = self._grid2Img(grid, cmap)
50        img.save('raw.png')
51
52        # Calculate the pixel-size of a grid box
53        pxPerDeg_x = float(width) / (bbox[2] - bbox[0])
54        pxPerDeg_y = float(height) / (bbox[3] - bbox[1])
55        pxPerGrid_x = grid.dx * pxPerDeg_x
56        pxPerGrid_y = grid.dy * pxPerDeg_y
57
58        # Scale Img to the right size
59        img = img.resize(((abs(pxPerGrid_x * grid.nx),
60                           abs(pxPerGrid_y * grid.ny))))
61
62        # We assume the grid points represent the centre of the grid boxes
63        # therefore we can calculate the upper-left position of the image
64
65        # Find top-left corner of grid
66        if grid.dx > 0:
67            leftX = grid.x0
68        else:
69            leftX = grid.x0 + (grid.dx * (grid.nx - 1))
70        if grid.dy > 0:
71            topY = grid.y0 + (grid.dy * (grid.ny - 1))
72        else:
73            topY = grid.y0
74
75        logger.debug('top-left = %s x, %s y' % (leftX, topY))
76
77        # Find pixel position of top left centre grid box
78        cx = width * ((leftX - bbox[0])/ (bbox[2] - bbox[0]))
79        cy = height * ((bbox[3] - topY) / (bbox[3] - bbox[1]))
80        logger.debug('top-left centre pixel = %s x, %s y' % (cx, cy))
81
82        # Apply half width of grid box
83        ox = int(cx - pxPerGrid_x / 2)
84        oy = int(cy - pxPerGrid_y / 2)
85        logger.debug('Offset: %s x, %s y' % (ox, oy))
86
87
88        # Paste the grid image into the tile image
89        tileImg = Image.new('RGBA', (width, height))
90        logger.debug('Pasting image img%s into tileImg%s at (%s,%s)' % (img.size, tileImg.size, ox, oy))
91        tileImg.paste(img, (ox, oy))
92
93        return tileImg
94
95
96    def _grid2Img(self, grid, cmap):
97        """Returns the grid as an image where each pixel is one grid box.
98
99        """
100        a = self._norm(grid.value)
101        img_buf = (cmap(a) * 255).astype('b')
102        if a.mask is not False:
103            logger.debug('Masking grid')
104            alpha_buf = (-a.mask*255 + 255).astype('b')
105        else:
106            alpha_buf = None
107
108        # This code assumes the axis ordering is either (y, x, time) or (x, y, time)
109        if min(grid.iy, grid.ix) != 0 and max(grid.iy, grid.ix) != 1:
110            raise ValueError("X and Y must be the first 2 dimensions!")
111
112        if grid.iy < grid.ix:
113            yxOrdering = True
114        else:
115            yxOrdering = False
116   
117        img = Image.frombuffer("RGBA", img_buf.shape[1::-1], img_buf.tostring(), "raw", "RGBA", 0, 1)
118        if alpha_buf is not None:
119            alpha = Image.frombuffer("L", img_buf.shape[1::-1], alpha_buf.tostring(), "raw", "L", 0, 1)
120            img.putalpha(alpha)
121
122        img.save('raw2.png')
123
124        # Rotate if axis order is x, y
125        if not yxOrdering:
126            img = img.transpose(Image.ROTATE_90)
127
128        # Flip if x or y are ordered the wrong way
129        if grid.dy > 0:
130            logger.debug('Flipping y')
131            img = img.transpose(Image.FLIP_TOP_BOTTOM)
132        if grid.dx < 0:
133            logger.debug('Flipping x')
134            img = img.transpose(Image.FLIP_LEFT_RIGHT)
135
136
137        return img
138
139
140#---------------------------------------------------------------------------------
141
Note: See TracBrowser for help on using the repository browser.