1 """
2 Some miscellaneous helpers for making images and such.
3
4 As this may turn into a fairly expensive import, this should *not* be imported
5 by utils.__init__. Hence, none of these functions are in gavo.api or
6 gavo.utils.
7 """
8
9
10
11
12
13
14
15 from cStringIO import StringIO
16
17 from PIL import Image
18 import numpy
19
20
22 """helps jpegFromNumpyArray and friends.
23 """
24 pixels = numpy.flipud(pixels)
25 pixMax, pixMin = numpy.max(pixels), numpy.min(pixels)
26 return numpy.asarray(numpy.power(
27 (pixels-pixMin)/(pixMax-pixMin), gamma)*255, 'uint8')
28
29
31 """returns a normalized JPEG for numpy pixels.
32
33 pixels is assumed to come from FITS arrays, which are flipped wrt to
34 jpeg coordinates, which is why we're flipping here.
35
36 The normalized intensities are scaled by v^gamma; we believe the default
37 helps with many astronomical images
38 """
39 f = StringIO()
40 Image.fromarray(_normalizeForImage(pixels, gamma)
41 ).save(f, format="jpeg")
42 return f.getvalue()
43
44
46 """as jpegFromNumpyArray, except a color jpeg is built from red, green,
47 and blue pixels.
48 """
49 pixels = numpy.array([
50 _normalizeForImage(rPix, gamma),
51 _normalizeForImage(gPix, gamma),
52 _normalizeForImage(bPix, gamma)]).transpose(1,2,0)
53
54 f = StringIO()
55 Image.fromarray(pixels, mode="RGB").save(f, format="jpeg")
56 return f.getvalue()
57
58
60 """returns the numpy array arr scaled down to approximately destSize.
61 """
62 origWidth, origHeight = arr.shape
63 size = max(origWidth, origHeight)
64 scale = max(1, size//destSize+1)
65 destWidth, destHeight = origWidth//scale, origHeight//scale
66
67
68
69 img = numpy.zeros((destWidth, destHeight), 'float32')
70
71 for rowInd in range(destHeight):
72 wideRow = (numpy.sum(
73 arr[:,rowInd*scale:(rowInd+1)*scale], 1, 'float32'
74 )/scale)[:destWidth*scale]
75
76
77 newRow = numpy.sum(
78 numpy.transpose(wideRow.reshape((destWidth, scale))), 0)/scale
79 img[:,rowInd] = newRow
80
81 return img
82
83
85 """returns a PNG string that is a scaled version of an image in srcFile.
86
87 srcFile must correspond to something that PIL can read. Since scaling
88 really sucks for non-RGB images, we unconditionally convert whatever we
89 get to 3-band RGB.
90 """
91 im = Image.open(srcFile).convert("RGB")
92 scale = newWidth/float(im.size[0])
93 scaled = im.resize((newWidth, int(im.size[1]*scale)), Image.ANTIALIAS)
94 f = StringIO()
95 scaled.save(f, format="png")
96 return f.getvalue()
97