The Independent JPEG Group's JPEG software v6
diff --git a/jquant2.c b/jquant2.c
index 7984f58..2504398 100644
--- a/jquant2.c
+++ b/jquant2.c
@@ -1,7 +1,7 @@
 /*
  * jquant2.c
  *
- * Copyright (C) 1991-1994, Thomas G. Lane.
+ * Copyright (C) 1991-1995, Thomas G. Lane.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -193,9 +193,15 @@
 typedef struct {
   struct jpeg_color_quantizer pub; /* public fields */
 
+  /* Space for the eventually created colormap is stashed here */
+  JSAMPARRAY sv_colormap;	/* colormap allocated at init time */
+  int desired;			/* desired # of colors = size of colormap */
+
   /* Variables for accumulating image statistics */
   hist3d histogram;		/* pointer to the histogram */
 
+  boolean needs_zeroed;		/* TRUE if next pass must zero histogram */
+
   /* Variables for Floyd-Steinberg dithering */
   FSERRPTR fserrors;		/* accumulated errors */
   boolean on_odd_row;		/* flag to remember which row we are on */
@@ -530,17 +536,16 @@
 
 
 LOCAL void
-select_colors (j_decompress_ptr cinfo)
+select_colors (j_decompress_ptr cinfo, int desired_colors)
 /* Master routine for color selection */
 {
   boxptr boxlist;
   int numboxes;
-  int desired = cinfo->desired_number_of_colors;
   int i;
 
   /* Allocate workspace for box list */
   boxlist = (boxptr) (*cinfo->mem->alloc_small)
-    ((j_common_ptr) cinfo, JPOOL_IMAGE, desired * SIZEOF(box));
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
   /* Initialize one box containing whole space */
   numboxes = 1;
   boxlist[0].c0min = 0;
@@ -552,7 +557,7 @@
   /* Shrink it to actually-used volume and set its statistics */
   update_box(cinfo, & boxlist[0]);
   /* Perform median-cut to produce final box list */
-  numboxes = median_cut(cinfo, boxlist, numboxes, desired);
+  numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
   /* Compute the representative color for each box, fill colormap */
   for (i = 0; i < numboxes; i++)
     compute_color(cinfo, & boxlist[i], i);
@@ -1137,8 +1142,13 @@
 METHODDEF void
 finish_pass1 (j_decompress_ptr cinfo)
 {
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
   /* Select the representative colors and fill in cinfo->colormap */
-  select_colors(cinfo);
+  cinfo->colormap = cquantize->sv_colormap;
+  select_colors(cinfo, cquantize->desired);
+  /* Force next pass to zero the color index table */
+  cquantize->needs_zeroed = TRUE;
 }
 
 
@@ -1160,10 +1170,16 @@
   hist3d histogram = cquantize->histogram;
   int i;
 
+  /* Only F-S dithering or no dithering is supported. */
+  /* If user asks for ordered dither, give him F-S. */
+  if (cinfo->dither_mode != JDITHER_NONE)
+    cinfo->dither_mode = JDITHER_FS;
+
   if (is_pre_scan) {
     /* Set up method pointers */
     cquantize->pub.color_quantize = prescan_quantize;
     cquantize->pub.finish_pass = finish_pass1;
+    cquantize->needs_zeroed = TRUE; /* Always zero histogram */
   } else {
     /* Set up method pointers */
     if (cinfo->dither_mode == JDITHER_FS)
@@ -1171,16 +1187,56 @@
     else
       cquantize->pub.color_quantize = pass2_no_dither;
     cquantize->pub.finish_pass = finish_pass2;
+
+    /* Make sure color count is acceptable */
+    i = cinfo->actual_number_of_colors;
+    if (i < 1)
+      ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
+    if (i > MAXNUMCOLORS)
+      ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+
+    if (cinfo->dither_mode == JDITHER_FS) {
+      size_t arraysize = (size_t) ((cinfo->output_width + 2) *
+				   (3 * SIZEOF(FSERROR)));
+      /* Allocate Floyd-Steinberg workspace if we didn't already. */
+      if (cquantize->fserrors == NULL)
+	cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+	  ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+      /* Initialize the propagated errors to zero. */
+      jzero_far((void FAR *) cquantize->fserrors, arraysize);
+      /* Make the error-limit table if we didn't already. */
+      if (cquantize->error_limiter == NULL)
+	init_error_limit(cinfo);
+      cquantize->on_odd_row = FALSE;
+    }
+
   }
-  /* Zero the histogram or inverse color map */
-  for (i = 0; i < HIST_C0_ELEMS; i++) {
-    jzero_far((void FAR *) histogram[i],
-	      HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+  /* Zero the histogram or inverse color map, if necessary */
+  if (cquantize->needs_zeroed) {
+    for (i = 0; i < HIST_C0_ELEMS; i++) {
+      jzero_far((void FAR *) histogram[i],
+		HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+    }
+    cquantize->needs_zeroed = FALSE;
   }
 }
 
 
 /*
+ * Switch to a new external colormap between output passes.
+ */
+
+METHODDEF void
+new_color_map_2_quant (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+  /* Reset the inverse color map */
+  cquantize->needs_zeroed = TRUE;
+}
+
+
+/*
  * Module initialization routine for 2-pass color quantization.
  */
 
@@ -1195,26 +1251,14 @@
 				SIZEOF(my_cquantizer));
   cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
   cquantize->pub.start_pass = start_pass_2_quant;
+  cquantize->pub.new_color_map = new_color_map_2_quant;
+  cquantize->fserrors = NULL;	/* flag optional arrays not allocated */
+  cquantize->error_limiter = NULL;
 
   /* Make sure jdmaster didn't give me a case I can't handle */
   if (cinfo->out_color_components != 3)
     ERREXIT(cinfo, JERR_NOTIMPL);
 
-  /* Only F-S dithering or no dithering is supported. */
-  /* If user asks for ordered dither, give him F-S. */
-  if (cinfo->dither_mode != JDITHER_NONE)
-    cinfo->dither_mode = JDITHER_FS;
-
-  /* Make sure color count is acceptable */
-  i = (cinfo->colormap != NULL) ? cinfo->actual_number_of_colors
-				: cinfo->desired_number_of_colors;
-  /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
-  if (i < 8)
-    ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
-  /* Make sure colormap indexes can be represented by JSAMPLEs */
-  if (i > MAXNUMCOLORS)
-    ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
-
   /* Allocate the histogram/inverse colormap storage */
   cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
     ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
@@ -1223,29 +1267,42 @@
       ((j_common_ptr) cinfo, JPOOL_IMAGE,
        HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
   }
+  cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
 
-  /* Allocate storage for the completed colormap,
-   * unless it has been supplied by the application.
+  /* Allocate storage for the completed colormap, if required.
    * We do this now since it is FAR storage and may affect
    * the memory manager's space calculations.
    */
-  if (cinfo->colormap == NULL) {
-    cinfo->colormap = (*cinfo->mem->alloc_sarray)
-      ((j_common_ptr) cinfo, JPOOL_IMAGE,
-       (JDIMENSION) cinfo->desired_number_of_colors, (JDIMENSION) 3);
-  }
+  if (cinfo->enable_2pass_quant) {
+    /* Make sure color count is acceptable */
+    int desired = cinfo->desired_number_of_colors;
+    /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
+    if (desired < 8)
+      ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
+    /* Make sure colormap indexes can be represented by JSAMPLEs */
+    if (desired > MAXNUMCOLORS)
+      ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+    cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
+      ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+    cquantize->desired = desired;
+  } else
+    cquantize->sv_colormap = NULL;
 
-  /* Allocate Floyd-Steinberg workspace if necessary. */
-  /* This isn't needed until pass 2, but again it is FAR storage. */
+  /* Only F-S dithering or no dithering is supported. */
+  /* If user asks for ordered dither, give him F-S. */
+  if (cinfo->dither_mode != JDITHER_NONE)
+    cinfo->dither_mode = JDITHER_FS;
+
+  /* Allocate Floyd-Steinberg workspace if necessary.
+   * This isn't really needed until pass 2, but again it is FAR storage.
+   * Although we will cope with a later change in dither_mode,
+   * we do not promise to honor max_memory_to_use if dither_mode changes.
+   */
   if (cinfo->dither_mode == JDITHER_FS) {
-    size_t arraysize = (size_t) ((cinfo->output_width + 2) *
-				 (3 * SIZEOF(FSERROR)));
-
     cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
-      ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
-    /* Initialize the propagated errors to zero. */
-    jzero_far((void FAR *) cquantize->fserrors, arraysize);
-    cquantize->on_odd_row = FALSE;
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
+    /* Might as well create the error-limiting table too. */
     init_error_limit(cinfo);
   }
 }