Index: tiff.c
===================================================================
RCS file: /cvs/gnome/gimp/plug-ins/common/tiff.c,v
retrieving revision 1.102
diff -u -p -r1.102 tiff.c
--- tiff.c	14 Jul 2004 10:57:13 -0000	1.102
+++ tiff.c	24 Aug 2004 16:28:21 -0000
@@ -141,6 +141,10 @@ static gboolean  save_image             
                                          gint32       image,
                                          gint32       drawable,
                                          gint32       orig_image);
+static void      byte2bit               (guchar      *byteline,
+                                         gint         width,
+                                         guchar      *bitline,
+                                         gboolean     invert);
 
 static gboolean  save_dialog            (gboolean     alpha);
 
@@ -1786,6 +1790,9 @@ save_image (const gchar *filename,
   gint           tile_height;
   gint           y, yend;
   gchar         *name;
+  gboolean       is_bw = FALSE, invert = TRUE;
+  guchar         bw_map[] = { 0, 0, 0, 255, 255, 255 };
+  guchar         wb_map[] = { 255, 255, 255, 0, 0, 0 };
 
   compression = tsvals.compression;
 
@@ -1857,20 +1864,42 @@ save_image (const gchar *filename,
       alpha           = TRUE;
       break;
     case GIMP_INDEXED_IMAGE:
-      samplesperpixel = 1;
-      bitspersample   = 8;
-      photometric     = PHOTOMETRIC_PALETTE;
-      bytesperrow     = cols;
-      alpha           = FALSE;
-
       cmap = gimp_image_get_cmap (image, &colors);
 
-      for (i = 0; i < colors; i++)
+      if (colors == 2)
+        {
+          is_bw = (memcmp (cmap, bw_map, 6) == 0);
+          photometric = PHOTOMETRIC_MINISWHITE;
+  
+          if (!is_bw)
+            {
+              is_bw = (memcmp (cmap, wb_map, 6) == 0);
+
+              if (is_bw)
+                invert = FALSE;
+            }
+       }
+
+      if (is_bw)
         {
-          red[i] = *cmap++ * 65535 / 255;
-          grn[i] = *cmap++ * 65535 / 255;
-          blu[i] = *cmap++ * 65535 / 255;
+          bitspersample = 1;
         }
+      else
+        {
+          bitspersample = 8;
+          photometric   = PHOTOMETRIC_PALETTE;
+
+          for (i = 0; i < colors; i++)
+            {
+              red[i] = *cmap++ * 65535 / 255;
+              grn[i] = *cmap++ * 65535 / 255;
+              blu[i] = *cmap++ * 65535 / 255;
+            }
+       }
+
+      samplesperpixel = 1;
+      bytesperrow     = cols;
+      alpha           = FALSE;
       break;
     case GIMP_INDEXEDA_IMAGE:
     default:
@@ -1992,7 +2021,7 @@ save_image (const gchar *filename,
   }
 #endif
 
-  if (drawable_type == GIMP_INDEXED_IMAGE)
+  if (!is_bw && drawable_type == GIMP_INDEXED_IMAGE)
     TIFFSetField (tif, TIFFTAG_COLORMAP, red, grn, blu);
 
   /* array to rearrange data */
@@ -2014,7 +2043,14 @@ save_image (const gchar *filename,
           switch (drawable_type)
             {
             case GIMP_INDEXED_IMAGE:
-              success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
+              if (is_bw)
+                {
+                  byte2bit (t, bytesperrow, data, invert);
+                  success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
+                }
+              else
+                  success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
+
               break;
             case GIMP_GRAY_IMAGE:
               success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
@@ -2082,6 +2118,47 @@ save_image (const gchar *filename,
   g_free (data);
 
   return TRUE;
+}
+
+/* Convert n bytes of 0/1 to a line of bits */
+static void
+byte2bit (guchar   *byteline,
+          gint      width,
+          guchar   *bitline,
+          gboolean  invert)
+{
+  register guchar bitval;
+  guchar rest[8];
+
+  while (width >= 8)
+    {
+      bitval = 0;
+      if (*(byteline++)) bitval |= 0x80;
+      if (*(byteline++)) bitval |= 0x40;
+      if (*(byteline++)) bitval |= 0x20;
+      if (*(byteline++)) bitval |= 0x10;
+      if (*(byteline++)) bitval |= 0x08;
+      if (*(byteline++)) bitval |= 0x04;
+      if (*(byteline++)) bitval |= 0x02;
+      if (*(byteline++)) bitval |= 0x01;
+      *(bitline++) = invert ? ~bitval : bitval;
+      width -= 8;
+    }
+  if (width > 0)
+    {
+      memset (rest, 0, 8);
+      memcpy (rest, byteline, width);
+      bitval = 0;
+      byteline = rest;
+      if (*(byteline++)) bitval |= 0x80;
+      if (*(byteline++)) bitval |= 0x40;
+      if (*(byteline++)) bitval |= 0x20;
+      if (*(byteline++)) bitval |= 0x10;
+      if (*(byteline++)) bitval |= 0x08;
+      if (*(byteline++)) bitval |= 0x04;
+      if (*(byteline++)) bitval |= 0x02;
+      *bitline = invert ? ~bitval : bitval;
+    }
 }
 
 static gboolean
