From: <md...@us...> - 2007-11-20 22:00:54
|
Revision: 4399 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4399&view=rev Author: mdboom Date: 2007-11-20 14:00:51 -0800 (Tue, 20 Nov 2007) Log Message: ----------- Reduce file sizes for mixed-mode PDFs by only outputting the part of the image with non-transparent pixels. Minor speed improvement in MixedModeRenderer. Modified Paths: -------------- branches/transforms/lib/matplotlib/backends/backend_agg.py branches/transforms/lib/matplotlib/backends/backend_mixed.py branches/transforms/src/_backend_agg.cpp branches/transforms/src/_backend_agg.h Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-11-20 21:00:20 UTC (rev 4398) +++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-11-20 22:00:51 UTC (rev 4399) @@ -68,6 +68,7 @@ self.draw_image = self._renderer.draw_image self.copy_from_bbox = self._renderer.copy_from_bbox self.restore_region = self._renderer.restore_region + self.tostring_rgba_minimized = self._renderer.tostring_rgba_minimized self.mathtext_parser = MathTextParser('Agg') self._fontd = {} Modified: branches/transforms/lib/matplotlib/backends/backend_mixed.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_mixed.py 2007-11-20 21:00:20 UTC (rev 4398) +++ branches/transforms/lib/matplotlib/backends/backend_mixed.py 2007-11-20 22:00:51 UTC (rev 4399) @@ -34,14 +34,28 @@ assert not vector_renderer.option_image_nocomposite() self._vector_renderer = vector_renderer - vector_renderer.start_rasterizing = self.start_rasterizing - vector_renderer.stop_rasterizing = self.stop_rasterizing self._raster_renderer = None self._rasterizing = False - self._renderer = self._vector_renderer + self._set_current_renderer(vector_renderer) + _methods = """ + open_group close_group draw_path draw_markers + draw_path_collection draw_quad_mesh get_image_magnification + draw_image draw_tex draw_text flipy option_image_nocomposite + get_texmanager get_text_width_height_descent new_gc + points_to_pixels strip_math finalize + """.split() + def _set_current_renderer(self, renderer): + self._renderer = renderer + + for method in self._methods: + if hasattr(renderer, method): + setattr(self, method, getattr(renderer, method)) + renderer.start_rasterizing = self.start_rasterizing + renderer.stop_rasterizing = self.stop_rasterizing + def start_rasterizing(self): """ Enter "raster" mode. All subsequent drawing commands (until @@ -54,9 +68,7 @@ if not self._rasterizing: self._raster_renderer = self._raster_renderer_class( self._width*self._dpi, self._height*self._dpi, self._dpi) - self._raster_renderer.start_rasterizing = self.start_rasterizing - self._raster_renderer.stop_rasterizing = self.stop_rasterizing - self._renderer = self._raster_renderer + self._set_current_renderer(self._raster_renderer) self._rasterizing = True def stop_rasterizing(self): @@ -69,74 +81,19 @@ start_rasterizing is called, this method has no effect. """ if self._rasterizing: + self._set_current_renderer(self._vector_renderer) + width, height = self._width * self._dpi, self._height * self._dpi - buffer = self._raster_renderer.buffer_rgba(0, 0) - image = frombuffer(buffer, width, height, True) - image.is_grayscale = False + buffer, bounds = self._raster_renderer.tostring_rgba_minimized() + l, b, w, h = bounds + if w > 0 and h > 0: + image = frombuffer(buffer, w, h, True) + image.is_grayscale = False - self._renderer = self._vector_renderer - self._renderer.draw_image(0, 0, image, None) + self._renderer.draw_image(l, height - b - h, image, None) self._raster_renderer = None self._rasterizing = False def get_canvas_width_height(self): 'return the canvas width and height in display coords' return self._width, self._height - - # The rest of this methods simply delegate to the currently active - # rendering backend. - - def open_group(self, *args, **kwargs): - return self._renderer.open_group(*args, **kwargs) - - def close_group(self, *args, **kwargs): - return self._renderer.close_group(*args, **kwargs) - - def draw_path(self, *args, **kwargs): - return self._renderer.draw_path(*args, **kwargs) - - def draw_markers(self, *args, **kwargs): - return self._renderer.draw_markers(*args, **kwargs) - - def draw_path_collection(self, *args, **kwargs): - return self._renderer.draw_path_collection(*args, **kwargs) - - def draw_quad_mesh(self, *args, **kwargs): - return self._renderer.draw_quad_mesh(*args, **kwargs) - - def get_image_magnification(self, *args, **kwargs): - return self._renderer.get_image_magnification(*args, **kwargs) - - def draw_image(self, *args, **kwargs): - return self._renderer.draw_image(*args, **kwargs) - - def draw_tex(self, *args, **kwargs): - return self._renderer.draw_tex(*args, **kwargs) - - def draw_text(self, *args, **kwargs): - return self._renderer.draw_text(*args, **kwargs) - - def flipy(self, *args, **kwargs): - return self._renderer.flipy(*args, **kwargs) - - def option_image_nocomposite(self, *args, **kwargs): - return self._vector_renderer.option_image_nocomposite(*args, **kwargs) - - def get_texmanager(self, *args, **kwargs): - return self._renderer.get_texmanager(*args, **kwargs) - - def get_text_width_height_descent(self, *args, **kwargs): - return self._renderer.get_text_width_height_descent(*args, **kwargs) - - def new_gc(self, *args, **kwargs): - return self._renderer.new_gc(*args, **kwargs) - - def points_to_pixels(self, *args, **kwargs): - return self._renderer.points_to_pixels(*args, **kwargs) - - def strip_math(self, *args, **kwargs): - return self._renderer(*args, **kwargs) - - def finalize(self, *args, **kwargs): - return self._renderer.finalize(*args, **kwargs) - Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-11-20 21:00:20 UTC (rev 4398) +++ branches/transforms/src/_backend_agg.cpp 2007-11-20 22:00:51 UTC (rev 4399) @@ -1474,8 +1474,66 @@ return Py::asObject(PyBuffer_FromMemory( pixBuffer+start, row_len*height-start)); } +Py::Object +RendererAgg::tostring_rgba_minimized(const Py::Tuple& args) { + args.verify_length(0); + int xmin = width; + int ymin = height; + int xmax = 0; + int ymax = 0; + + // Looks at the alpha channel to find the minimum extents of the image + unsigned char* pixel = pixBuffer + 3; + for (int y = 0; y < (int)height; ++y) { + for (int x = 0; x < (int)width; ++x) { + if (*pixel) { + if (x < xmin) xmin = x; + if (y < ymin) ymin = y; + if (x > xmax) xmax = x; + if (y > ymax) ymax = y; + } + pixel += 4; + } + } + int newwidth = 0; + int newheight = 0; + Py::String data; + if (xmin < xmax and ymin < ymax) { + // Expand the bounds by 1 pixel on all sides + xmin = std::max(0, xmin - 1); + ymin = std::max(0, ymin - 1); + xmax = std::min(xmax, (int)width); + ymax = std::min(ymax, (int)height); + + newwidth = xmax - xmin; + newheight = ymax - ymin; + int newsize = newwidth * newheight * 4; + + unsigned char* buf = new unsigned char[newsize]; + unsigned int* dst = (unsigned int*)buf; + unsigned int* src = (unsigned int*)pixBuffer; + for (int y = ymin; y < ymax; ++y) + for (int x = xmin; x < xmax; ++x, ++dst) + *dst = src[y * width + x]; + + data = Py::String((const char *)buf, (int)newsize); + } + + Py::Tuple bounds(4); + bounds[0] = Py::Int(xmin); + bounds[1] = Py::Int(ymin); + bounds[2] = Py::Int(newwidth); + bounds[3] = Py::Int(newheight); + + Py::Tuple result(2); + result[0] = data; + result[1] = bounds; + + return result; +} + Py::Object RendererAgg::clear(const Py::Tuple& args) { //"clear the rendered buffer"; @@ -1605,6 +1663,8 @@ "s = tostring_argb()"); add_varargs_method("tostring_bgra", &RendererAgg::tostring_bgra, "s = tostring_bgra()"); + add_varargs_method("tostring_rgba_minimized", &RendererAgg::tostring_rgba_minimized, + "s = tostring_rgba_minimized()"); add_varargs_method("buffer_rgba", &RendererAgg::buffer_rgba, "buffer = buffer_rgba()"); add_varargs_method("clear", &RendererAgg::clear, Modified: branches/transforms/src/_backend_agg.h =================================================================== --- branches/transforms/src/_backend_agg.h 2007-11-20 21:00:20 UTC (rev 4398) +++ branches/transforms/src/_backend_agg.h 2007-11-20 22:00:51 UTC (rev 4399) @@ -179,6 +179,7 @@ Py::Object tostring_rgb(const Py::Tuple & args); Py::Object tostring_argb(const Py::Tuple & args); Py::Object tostring_bgra(const Py::Tuple & args); + Py::Object tostring_rgba_minimized(const Py::Tuple & args); Py::Object buffer_rgba(const Py::Tuple & args); Py::Object clear(const Py::Tuple & args); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |