--- a/quantize.c
+++ b/quantize.c
# SortRGBAxis is static and not locked, qsort recoded
# GAErrorToken is also static and not locked, not fixed
@@ -25,8 +25,6 @@
 #define BITS_PER_PRIM_COLOR 5
 #define MAX_PRIM_COLOR 0x1f
 
-static int SortRGBAxis;
-
 typedef struct QuantizedColorType {
 	GifByteType RGB[3];
 	GifByteType NewColorIndex;
@@ -34,6 +32,40 @@
 	struct QuantizedColorType *Pnext;
 } QuantizedColorType;
 
+static int QCmpr(QuantizedColorType *a, QuantizedColorType *b, int i)
+{
+       int i0 = i, i1 = i+1, i2 = i+2;
+       if( i1 >= 3 ) i1 -= 3;
+       if( i2 >= 3 ) i2 -= 3;
+       /* sort on all axes of the color space! */
+       int hash_a = (a->RGB[i0] << 16) | (a->RGB[i1] << 8) | (a->RGB[i2] << 0);
+       int hash_b = (b->RGB[i0] << 16) | (b->RGB[i1] << 8) | (b->RGB[i2] << 0);
+       return hash_a - hash_b;
+}
+
+static int QSplit(QuantizedColorType **q, int l, int r, int i)
+{
+       int m;
+       QuantizedColorType *t;
+       for(;;) {
+               while( QCmpr(q[r],q[l], i) >= 0 ) if( ++l == r ) return r;
+               t = q[l];  q[l] = q[r];  q[r] = t;  m = l;  l = r;  r = m;
+               while( QCmpr(q[l],q[r], i) >= 0 ) if( r == --l ) return r;
+               t = q[l];  q[l] = q[r];  q[r] = t;  m = l;  l = r;  r = m;
+       }
+}
+
+static void QSort(QuantizedColorType **q, int ll, int rr, int i)
+{
+       for(;;) {
+               int l = ll+1;  if( l == rr ) return;
+               int r = rr-1;  if( l == r ) return;
+               int m = QSplit(q, l, r, i);
+               QSort(q, ll, m, i);
+               ll = m;
+       }
+}
+
 typedef struct NewColorMapType {
 	GifByteType RGBMin[3], RGBWidth[3];
 	unsigned int
@@ -45,7 +77,6 @@
 static int SubdivColorMap(NewColorMapType *NewColorSubdiv,
                           unsigned int ColorMapSize,
                           unsigned int *NewColorMapSize);
-static int SortCmpRtn(const void *Entry1, const void *Entry2);
 
 /******************************************************************************
  Quantize high resolution image into lower one. Input image consists of a
@@ -215,6 +246,7 @@
                           unsigned int ColorMapSize,
                           unsigned int *NewColorMapSize) {
 
+	int SortRGBAxis = 0;
 	unsigned int i, j, Index = 0;
 	QuantizedColorType *QuantizedColor, **SortArray;
 
@@ -257,19 +289,7 @@
 			SortArray[j] = QuantizedColor;
 		}
 
-		/*
-		 * Because qsort isn't stable, this can produce differing
-		 * results for the order of tuples depending on platform
-		 * details of how qsort() is implemented.
-		 *
-		 * We mitigate this problem by sorting on all three axes rather
-		 * than only the one specied by SortRGBAxis; that way the
-		 * instability can only become an issue if there are multiple
-		 * color indices referring to identical RGB tuples.  Older
-		 * versions of this sorted on only the one axis.
-		 */
-		qsort(SortArray, NewColorSubdiv[Index].NumEntries,
-		      sizeof(QuantizedColorType *), SortCmpRtn);
+		QSort(SortArray, -1, NewColorSubdiv[Index].NumEntries, SortRGBAxis);
 
 		/* Relink the sorted list into one: */
 		for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++) {
@@ -339,19 +359,4 @@
  Routine called by qsort to compare two entries.
  *****************************************************************************/
 
-static int SortCmpRtn(const void *Entry1, const void *Entry2) {
-	QuantizedColorType *entry1 = (*((QuantizedColorType **)Entry1));
-	QuantizedColorType *entry2 = (*((QuantizedColorType **)Entry2));
-
-	/* sort on all axes of the color space! */
-	int hash1 = entry1->RGB[SortRGBAxis] * 256 * 256 +
-	            entry1->RGB[(SortRGBAxis + 1) % 3] * 256 +
-	            entry1->RGB[(SortRGBAxis + 2) % 3];
-	int hash2 = entry2->RGB[SortRGBAxis] * 256 * 256 +
-	            entry2->RGB[(SortRGBAxis + 1) % 3] * 256 +
-	            entry2->RGB[(SortRGBAxis + 2) % 3];
-
-	return hash1 - hash2;
-}
-
 /* end */
