The Independent JPEG Group's JPEG software v6
diff --git a/jcmarker.c b/jcmarker.c
index 5454658..f4d290b 100644
--- a/jcmarker.c
+++ b/jcmarker.c
@@ -1,7 +1,7 @@
 /*
  * jcmarker.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.
  *
@@ -295,7 +295,7 @@
 emit_sos (j_compress_ptr cinfo)
 /* Emit a SOS marker */
 {
-  int i;
+  int i, td, ta;
   jpeg_component_info *compptr;
   
   emit_marker(cinfo, M_SOS);
@@ -307,12 +307,28 @@
   for (i = 0; i < cinfo->comps_in_scan; i++) {
     compptr = cinfo->cur_comp_info[i];
     emit_byte(cinfo, compptr->component_id);
-    emit_byte(cinfo, (compptr->dc_tbl_no << 4) + compptr->ac_tbl_no);
+    td = compptr->dc_tbl_no;
+    ta = compptr->ac_tbl_no;
+    if (cinfo->progressive_mode) {
+      /* Progressive mode: only DC or only AC tables are used in one scan;
+       * furthermore, Huffman coding of DC refinement uses no table at all.
+       * We emit 0 for unused field(s); this is recommended by the P&M text
+       * but does not seem to be specified in the standard.
+       */
+      if (cinfo->Ss == 0) {
+	ta = 0;			/* DC scan */
+	if (cinfo->Ah != 0 && !cinfo->arith_code)
+	  td = 0;		/* no DC table either */
+      } else {
+	td = 0;			/* AC scan */
+      }
+    }
+    emit_byte(cinfo, (td << 4) + ta);
   }
 
-  emit_byte(cinfo, 0);		/* Spectral selection start */
-  emit_byte(cinfo, DCTSIZE2-1);	/* Spectral selection end */
-  emit_byte(cinfo, 0);		/* Successive approximation */
+  emit_byte(cinfo, cinfo->Ss);
+  emit_byte(cinfo, cinfo->Se);
+  emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
 }
 
 
@@ -434,7 +450,7 @@
  * be used for any other JPEG colorspace.  The Adobe marker is helpful
  * to distinguish RGB, CMYK, and YCCK colorspaces.
  * Note that an application can write additional header markers after
- * jpeg_start_decompress returns.
+ * jpeg_start_compress returns.
  */
 
 METHODDEF void
@@ -477,27 +493,34 @@
   /* Check for a non-baseline specification.
    * Note we assume that Huffman table numbers won't be changed later.
    */
-  is_baseline = TRUE;
-  if (cinfo->arith_code || (cinfo->data_precision != 8))
+  if (cinfo->arith_code || cinfo->progressive_mode ||
+      cinfo->data_precision != 8) {
     is_baseline = FALSE;
-  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
-       ci++, compptr++) {
-    if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
+  } else {
+    is_baseline = TRUE;
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+	 ci++, compptr++) {
+      if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
+	is_baseline = FALSE;
+    }
+    if (prec && is_baseline) {
       is_baseline = FALSE;
-  }
-  if (prec && is_baseline) {
-    is_baseline = FALSE;
-    /* If it's baseline except for quantizer size, warn the user */
-    TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
+      /* If it's baseline except for quantizer size, warn the user */
+      TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
+    }
   }
 
   /* Emit the proper SOF marker */
-  if (cinfo->arith_code)
+  if (cinfo->arith_code) {
     emit_sof(cinfo, M_SOF9);	/* SOF code for arithmetic coding */
-  else if (is_baseline)
-    emit_sof(cinfo, M_SOF0);	/* SOF code for baseline implementation */
-  else
-    emit_sof(cinfo, M_SOF1);	/* SOF code for non-baseline Huffman file */
+  } else {
+    if (cinfo->progressive_mode)
+      emit_sof(cinfo, M_SOF2);	/* SOF code for progressive Huffman */
+    else if (is_baseline)
+      emit_sof(cinfo, M_SOF0);	/* SOF code for baseline implementation */
+    else
+      emit_sof(cinfo, M_SOF1);	/* SOF code for non-baseline Huffman file */
+  }
 }
 
 
@@ -525,8 +548,19 @@
      */
     for (i = 0; i < cinfo->comps_in_scan; i++) {
       compptr = cinfo->cur_comp_info[i];
-      emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
-      emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+      if (cinfo->progressive_mode) {
+	/* Progressive mode: only DC or only AC tables are used in one scan */
+	if (cinfo->Ss == 0) {
+	  if (cinfo->Ah == 0)	/* DC needs no table for refinement scan */
+	    emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+	} else {
+	  emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+	}
+      } else {
+	/* Sequential mode: need both DC and AC tables */
+	emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+	emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+      }
     }
   }