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

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

Quick import of code I have been working on to server ukcip02 data.
This code may well move soon.

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():
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:
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.