Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d3762a4

Browse files
committed
Add Agg filter test
1 parent 03da7e4 commit d3762a4

File tree

2 files changed

+135
-1
lines changed

2 files changed

+135
-1
lines changed

lib/matplotlib/backends/backend_agg.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ def post_processing(image, dpi):
403403
img, ox, oy = post_processing(img.reshape((h, w, 4)) / 255.,
404404
self.dpi)
405405
gc = self.new_gc()
406+
if issubclass(img.dtype.type, np.floating):
407+
img = np.asarray(img * 255., np.uint8)
408+
img = img[::-1]
406409
self._renderer.draw_image(
407410
gc, l + ox, height - b - h + oy, img)
408411

lib/matplotlib/tests/test_agg.py

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
from matplotlib.image import imread
1313
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
1414
from matplotlib.figure import Figure
15-
from matplotlib.testing.decorators import cleanup
15+
from matplotlib.testing.decorators import cleanup, image_comparison
1616
from matplotlib import pyplot as plt
1717
from matplotlib import collections
1818
from matplotlib import path
19+
from matplotlib import transforms as mtransforms
1920

2021

2122
@cleanup
@@ -155,6 +156,136 @@ def test_long_path():
155156
fig.savefig(buff, format='png')
156157

157158

159+
@image_comparison(baseline_images=['agg_filter'],
160+
extensions=['png'], remove_text=True)
161+
def test_agg_filter():
162+
def smooth1d(x, window_len):
163+
# copied from http://www.scipy.org/Cookbook/SignalSmooth
164+
165+
s = np.r_[2*x[0] - x[window_len:1:-1], x, 2*x[-1] - x[-1:-window_len:-1]]
166+
w = np.hanning(window_len)
167+
y = np.convolve(w/w.sum(), s, mode='same')
168+
return y[window_len-1:-window_len+1]
169+
170+
def smooth2d(A, sigma=3):
171+
window_len = max(int(sigma), 3)*2 + 1
172+
A1 = np.array([smooth1d(x, window_len) for x in np.asarray(A)])
173+
A2 = np.transpose(A1)
174+
A3 = np.array([smooth1d(x, window_len) for x in A2])
175+
A4 = np.transpose(A3)
176+
177+
return A4
178+
179+
class BaseFilter(object):
180+
def prepare_image(self, src_image, dpi, pad):
181+
ny, nx, depth = src_image.shape
182+
#tgt_image = np.zeros([pad*2+ny, pad*2+nx, depth], dtype="d")
183+
padded_src = np.zeros([pad*2 + ny, pad*2 + nx, depth], dtype="d")
184+
padded_src[pad:-pad, pad:-pad, :] = src_image[:, :, :]
185+
186+
return padded_src # , tgt_image
187+
188+
def get_pad(self, dpi):
189+
return 0
190+
191+
def __call__(self, im, dpi):
192+
pad = self.get_pad(dpi)
193+
padded_src = self.prepare_image(im, dpi, pad)
194+
tgt_image = self.process_image(padded_src, dpi)
195+
return tgt_image, -pad, -pad
196+
197+
class OffsetFilter(BaseFilter):
198+
def __init__(self, offsets=None):
199+
if offsets is None:
200+
self.offsets = (0, 0)
201+
else:
202+
self.offsets = offsets
203+
204+
def get_pad(self, dpi):
205+
return int(max(*self.offsets)/72.*dpi)
206+
207+
def process_image(self, padded_src, dpi):
208+
ox, oy = self.offsets
209+
a1 = np.roll(padded_src, int(ox/72.*dpi), axis=1)
210+
a2 = np.roll(a1, -int(oy/72.*dpi), axis=0)
211+
return a2
212+
213+
class GaussianFilter(BaseFilter):
214+
"simple gauss filter"
215+
216+
def __init__(self, sigma, alpha=0.5, color=None):
217+
self.sigma = sigma
218+
self.alpha = alpha
219+
if color is None:
220+
self.color = (0, 0, 0)
221+
else:
222+
self.color = color
223+
224+
def get_pad(self, dpi):
225+
return int(self.sigma*3/72.*dpi)
226+
227+
def process_image(self, padded_src, dpi):
228+
#offsetx, offsety = int(self.offsets[0]), int(self.offsets[1])
229+
tgt_image = np.zeros_like(padded_src)
230+
aa = smooth2d(padded_src[:, :, -1]*self.alpha,
231+
self.sigma/72.*dpi)
232+
tgt_image[:, :, -1] = aa
233+
tgt_image[:, :, :-1] = self.color
234+
return tgt_image
235+
236+
class DropShadowFilter(BaseFilter):
237+
def __init__(self, sigma, alpha=0.3, color=None, offsets=None):
238+
self.gauss_filter = GaussianFilter(sigma, alpha, color)
239+
self.offset_filter = OffsetFilter(offsets)
240+
241+
def get_pad(self, dpi):
242+
return max(self.gauss_filter.get_pad(dpi),
243+
self.offset_filter.get_pad(dpi))
244+
245+
def process_image(self, padded_src, dpi):
246+
t1 = self.gauss_filter.process_image(padded_src, dpi)
247+
t2 = self.offset_filter.process_image(t1, dpi)
248+
return t2
249+
250+
fig = plt.figure()
251+
ax = fig.add_subplot(111)
252+
253+
# draw lines
254+
l1, = ax.plot([0.1, 0.5, 0.9], [0.1, 0.9, 0.5], "bo-",
255+
mec="b", mfc="w", lw=5, mew=3, ms=10, label="Line 1")
256+
l2, = ax.plot([0.1, 0.5, 0.9], [0.5, 0.2, 0.7], "ro-",
257+
mec="r", mfc="w", lw=5, mew=3, ms=10, label="Line 1")
258+
259+
gauss = DropShadowFilter(4)
260+
261+
for l in [l1, l2]:
262+
263+
# draw shadows with same lines with slight offset.
264+
265+
xx = l.get_xdata()
266+
yy = l.get_ydata()
267+
shadow, = ax.plot(xx, yy)
268+
shadow.update_from(l)
269+
270+
# offset transform
271+
ot = mtransforms.offset_copy(l.get_transform(), ax.figure,
272+
x=4.0, y=-6.0, units='points')
273+
274+
shadow.set_transform(ot)
275+
276+
# adjust zorder of the shadow lines so that it is drawn below the
277+
# original lines
278+
shadow.set_zorder(l.get_zorder() - 0.5)
279+
shadow.set_agg_filter(gauss)
280+
shadow.set_rasterized(True) # to support mixed-mode renderers
281+
282+
ax.set_xlim(0., 1.)
283+
ax.set_ylim(0., 1.)
284+
285+
ax.xaxis.set_visible(False)
286+
ax.yaxis.set_visible(False)
287+
288+
158289
if __name__ == "__main__":
159290
import nose
160291
nose.runmodule(argv=['-s', '--with-doctest'], exit=False)

0 commit comments

Comments
 (0)