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.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to