diff --git a/TODO b/TODO
index 5a2ca0b6..d53cc726 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,13 @@
-- region needs to be broken up
+- load 500 jpegs, shrink, save
 
-  split prepare, generate etc. out to another chapter, maybe generate.h
+  VM use is huge, ouch, could we use a bit less?
 
-  man page for im_demand_hint() has some nice notes on SMALLTILE etc we could
-  paste into the VipsDemandStyle comment
+  maybe free all windows on evalend? are there regions left about? how come we
+  use so many resources?
 
+  get about 300 images in on the laptop
+
+  
 
 - VipsFormat next? where should we document the im_vip2jpeg() options?
 
diff --git a/doc/reference/libvips-docs.sgml.in b/doc/reference/libvips-docs.sgml.in
index 6e8fd432..528e72fc 100644
--- a/doc/reference/libvips-docs.sgml.in
+++ b/doc/reference/libvips-docs.sgml.in
@@ -23,6 +23,7 @@
     <xi:include href="xml/error.xml"/>
     <xi:include href="xml/meta.xml"/>
     <xi:include href="xml/region.xml"/>
+    <xi:include href="xml/generate.xml"/>
     <xi:include href="xml/buf.xml"/>
   </chapter>
 
diff --git a/libvips/include/vips/Makefile.am b/libvips/include/vips/Makefile.am
index f207979a..11cfddc4 100644
--- a/libvips/include/vips/Makefile.am
+++ b/libvips/include/vips/Makefile.am
@@ -18,6 +18,7 @@ pkginclude_HEADERS = \
 	image.h \
 	rect.h \
 	region.h \
+	generate.h \
 	r_access.h \
 	struct.h \
 	private.h \
diff --git a/libvips/include/vips/generate.h b/libvips/include/vips/generate.h
new file mode 100644
index 00000000..e3685b44
--- /dev/null
+++ b/libvips/include/vips/generate.h
@@ -0,0 +1,89 @@
+/* Definitions for partial image regions.
+ *
+ * J.Cupitt, 8/4/93
+ */
+
+/*
+
+    This file is part of VIPS.
+
+    VIPS is free software; you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+ */
+
+/*
+
+    These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
+
+ */
+
+#ifndef IM_GENERATE_H
+#define IM_GENERATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+/* IMAGE functions which use regions. 
+ */
+int im_prepare( REGION *reg, Rect *r );
+int im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y );
+
+typedef void *(*im_start_fn)( IMAGE *out, void *a, void *b );
+typedef int (*im_generate_fn)( REGION *out, void *seq, void *a, void *b );
+typedef int (*im_stop_fn)( void *seq, void *a, void *b );
+
+void *im_start_one( IMAGE *out, void *in, void *dummy );
+int im_stop_one( void *seq, void *dummy1, void *dummy2 );
+void *im_start_many( IMAGE *out, void *in, void *dummy );
+int im_stop_many( void *seq, void *dummy1, void *dummy2 );
+IMAGE **im_allocate_input_array( IMAGE *out, ... )
+	__attribute__((sentinel));
+
+int im_generate( IMAGE *im,
+	im_start_fn start, im_generate_fn generate, im_stop_fn stop,
+	void *a, void *b
+);
+int im_iterate( IMAGE *im,
+	im_start_fn start, im_generate_fn generate, im_stop_fn stop,
+	void *a, void *b
+);
+
+int im_demand_hint_array( IMAGE *im, im_demand_type hint, IMAGE **in );
+int im_demand_hint( IMAGE *im, im_demand_type hint, ... )
+	__attribute__((sentinel));
+
+/* Buffer processing.
+ */
+typedef void (*im_wrapone_fn)( void *in, void *out, int width,
+	void *a, void *b );
+int im_wrapone( IMAGE *in, IMAGE *out,
+	im_wrapone_fn fn, void *a, void *b );
+
+typedef void (*im_wraptwo_fn)( void *in1, void *in2, void *out, 
+        int width, void *a, void *b );
+int im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out,
+	im_wraptwo_fn fn, void *a, void *b );
+
+typedef void (*im_wrapmany_fn)( void **in, void *out, int width,
+	void *a, void *b );
+int im_wrapmany( IMAGE **in, IMAGE *out,
+	im_wrapmany_fn fn, void *a, void *b );
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+
+#endif /*IM_GENERATE_H*/
diff --git a/libvips/include/vips/region.h b/libvips/include/vips/region.h
index 6c3da04f..59e38d05 100644
--- a/libvips/include/vips/region.h
+++ b/libvips/include/vips/region.h
@@ -76,52 +76,6 @@ int im_region_region( REGION *reg, REGION *to, Rect *r, int x, int y );
 int im_region_equalsregion( REGION *reg1, REGION *reg2 );
 int im_region_position( REGION *reg1, int x, int y );
 
-/* IMAGE functions which use regions. 
- */
-int im_prepare( REGION *reg, Rect *r );
-int im_prepare_to( REGION *reg, REGION *dest, Rect *r, int x, int y );
-
-typedef void *(*im_start_fn)( IMAGE *out, void *a, void *b );
-typedef int (*im_generate_fn)( REGION *out, void *seq, void *a, void *b );
-typedef int (*im_stop_fn)( void *seq, void *a, void *b );
-
-void *im_start_one( IMAGE *out, void *in, void *dummy );
-int im_stop_one( void *seq, void *dummy1, void *dummy2 );
-void *im_start_many( IMAGE *out, void *in, void *dummy );
-int im_stop_many( void *seq, void *dummy1, void *dummy2 );
-IMAGE **im_allocate_input_array( IMAGE *out, ... )
-	__attribute__((sentinel));
-
-int im_generate( IMAGE *im,
-	im_start_fn start, im_generate_fn generate, im_stop_fn stop,
-	void *a, void *b
-);
-int im_iterate( IMAGE *im,
-	im_start_fn start, im_generate_fn generate, im_stop_fn stop,
-	void *a, void *b
-);
-
-int im_demand_hint_array( IMAGE *im, im_demand_type hint, IMAGE **in );
-int im_demand_hint( IMAGE *im, im_demand_type hint, ... )
-	__attribute__((sentinel));
-
-/* Buffer processing.
- */
-typedef void (*im_wrapone_fn)( void *in, void *out, int width,
-	void *a, void *b );
-int im_wrapone( IMAGE *in, IMAGE *out,
-	im_wrapone_fn fn, void *a, void *b );
-
-typedef void (*im_wraptwo_fn)( void *in1, void *in2, void *out, 
-        int width, void *a, void *b );
-int im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out,
-	im_wraptwo_fn fn, void *a, void *b );
-
-typedef void (*im_wrapmany_fn)( void **in, void *out, int width,
-	void *a, void *b );
-int im_wrapmany( IMAGE **in, IMAGE *out,
-	im_wrapmany_fn fn, void *a, void *b );
-
 /* Macros on REGIONs.
  *	IM_REGION_LSKIP()		add to move down line
  *	IM_REGION_N_ELEMENTS()		number of elements across region
diff --git a/libvips/include/vips/vips.h b/libvips/include/vips/vips.h
index 7a239f64..faf11cd3 100644
--- a/libvips/include/vips/vips.h
+++ b/libvips/include/vips/vips.h
@@ -132,6 +132,7 @@ typedef struct im__DOUBLEMASK {
 #include <vips/format.h>
 #include <vips/dispatch.h>
 #include <vips/region.h>
+#include <vips/generate.h>
 #include <vips/interpolate.h>
 #include <vips/semaphore.h>
 #include <vips/threadgroup.h>
diff --git a/libvips/iofuncs/im_generate.c b/libvips/iofuncs/im_generate.c
index da6614e5..f71b8d4e 100644
--- a/libvips/iofuncs/im_generate.c
+++ b/libvips/iofuncs/im_generate.c
@@ -102,6 +102,18 @@
 #include <dmalloc.h>
 #endif /*WITH_DMALLOC*/
 
+/**
+ * SECTION: generate
+ * @short_description: calculate pixels and pixel buffers
+ * @stability: Stable
+ * @see_also: <link linkend="libvips-image">image</link>, 
+ * <link linkend="libvips-region">region</link>
+ * @include: vips/vips.h
+ *
+ * These functions let you generate regions of pixels in an image
+ * processing operation, and ask for regions of image to be calculated.
+ */
+
 /**
  * im_start_one:
  *
diff --git a/libvips/iofuncs/im_open_vips.c b/libvips/iofuncs/im_open_vips.c
index 4caebdff..2889d9b9 100644
--- a/libvips/iofuncs/im_open_vips.c
+++ b/libvips/iofuncs/im_open_vips.c
@@ -109,7 +109,34 @@
  * @IM_THINSTRIP: demand in thin (typically 1 pixel high) strips
  * @IM_ANY: demand geometry does not matter
  *
- * Demand style. See im_demand_hint().
+ * See im_demand_hint(). Operations can hint to the VIPS image IO system about
+ * the kind of demand geometry they prefer. 
+ *
+ * These demand styles are given below in order of increasing
+ * restrictiveness.  When demanding output from a pipeline, im_generate()
+ * will use the most restrictive of the styles requested by the operations 
+ * in the pipeline.
+ *
+ * IM_THINSTRIP --- This operation would like to output strips the width 
+ * of the image and a few pels high. This is option suitable for 
+ * point-to-point operations, such as those in the arithmetic package.
+ *
+ * This option is only efficient for cases where each output pel depends 
+ * upon the pel in the corresponding position in the input image.
+ *
+ * IM_FATSTRIP --- This operation would like to output strips the width 
+ * of the image and as high as possible. This option is suitable for area 
+ * operations which do not violently transform coordinates, such as im_conv(). 
+ *
+ * IM_SMALLTILE --- This is the most general demand format.
+ * Output is demanded in small (around 100x100 pel) sections. This style works 
+ * reasonably efficiently, even for bizzare operations like 45 degree rotate.
+ *
+ * IM_ANY --- This image is not being demand-read from a disc file (even 
+ * indirectly) so any demand style is OK. It's used for things like
+ * im_black() where the pixels are calculated.
+ *
+ * See also: im_demand_hint().
  */
 
 /**
diff --git a/libvips/iofuncs/region.c b/libvips/iofuncs/region.c
index 1a10e15b..5a982417 100644
--- a/libvips/iofuncs/region.c
+++ b/libvips/iofuncs/region.c
@@ -106,7 +106,8 @@
  * SECTION: region
  * @short_description: small, rectangular parts of images
  * @stability: Stable
- * @see_also: <link linkend="libvips-image">image</link>
+ * @see_also: <link linkend="libvips-image">image</link>, 
+ * <link linkend="libvips-generate">generate</link>
  * @include: vips/vips.h
  *
  * A #REGION is a small part of an image and some pixels. You use regions to