home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / tiff.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-13  |  48.7 KB  |  1,674 lines

  1. /* tiff loading and saving for the GIMP
  2.  *  -Peter Mattis
  3.  * The TIFF loading code has been completely revamped by Nick Lamb
  4.  * njl195@zepler.org.uk -- 18 May 1998
  5.  * And it now gains support for tiles (and doubtless a zillion bugs)
  6.  * njl195@zepler.org.uk -- 12 June 1999
  7.  * LZW patent fuss continues :(
  8.  * njl195@zepler.org.uk -- 20 April 2000
  9.  * The code for this filter is based on "tifftopnm" and "pnmtotiff",
  10.  *  2 programs that are a part of the netpbm package.
  11.  * khk@khk.net -- 13 May 2000
  12.  * Added support for ICCPROFILE tiff tag. If this tag is present in a 
  13.  * TIFF file, then a parasite is created and vice versa.
  14.  */
  15.  
  16. /*
  17. ** tifftopnm.c - converts a Tagged Image File to a portable anymap
  18. **
  19. ** Derived by Jef Poskanzer from tif2ras.c, which is:
  20. **
  21. ** Copyright (c) 1990 by Sun Microsystems, Inc.
  22. **
  23. ** Author: Patrick J. Naughton
  24. ** naughton@wind.sun.com
  25. **
  26. ** Permission to use, copy, modify, and distribute this software and its
  27. ** documentation for any purpose and without fee is hereby granted,
  28. ** provided that the above copyright notice appear in all copies and that
  29. ** both that copyright notice and this permission notice appear in
  30. ** supporting documentation.
  31. **
  32. ** This file is provided AS IS with no warranties of any kind.  The author
  33. ** shall have no liability with respect to the infringement of copyrights,
  34. ** trade secrets or any patents by this file or any part thereof.  In no
  35. ** event will the author be liable for any lost revenue or profits or
  36. ** other special, indirect and consequential damages.
  37. */
  38.  
  39. #include "config.h"
  40.  
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <tiffio.h>
  44.  
  45. #include <libgimp/gimp.h>
  46. #include <libgimp/gimpui.h>
  47.  
  48. #include "libgimp/stdplugins-intl.h"
  49.  
  50.  
  51. typedef struct
  52. {
  53.   gint  compression;
  54.   gint  fillorder;
  55. } TiffSaveVals;
  56.  
  57. typedef struct
  58. {
  59.   gint  run;
  60. } TiffSaveInterface;
  61.  
  62. typedef struct
  63. {
  64.   gint32     ID;
  65.   GimpDrawable *drawable;
  66.   GimpPixelRgn  pixel_rgn;
  67.   guchar    *pixels;
  68.   guchar    *pixel;
  69. } channel_data;
  70.  
  71. /* Declare some local functions.
  72.  */
  73. static void   query   (void);
  74. static void   run     (gchar   *name,
  75.                gint     nparams,
  76.                GimpParam  *param,
  77.                gint    *nreturn_vals,
  78.                GimpParam **return_vals);
  79.  
  80. static gint32 load_image    (gchar        *filename);
  81.  
  82. static void   load_rgba     (TIFF         *tif,
  83.                  channel_data *channel);
  84. static void   load_lines    (TIFF         *tif,
  85.                  channel_data *channel,
  86.                  gushort       bps,
  87.                  gushort       photomet,
  88.                  gint          alpha,
  89.                  gint          extra);
  90. static void   load_tiles    (TIFF         *tif,
  91.                  channel_data *channel,
  92.                  gushort       bps,
  93.                  gushort       photomet,
  94.                  gint          alpha,
  95.                  gint          extra);
  96.  
  97. static void   read_separate (guchar       *source,
  98.                  channel_data *channel,
  99.                              gushort       bps,
  100.                  gushort       photomet,
  101.                              gint          startcol,
  102.                  gint          startrow,
  103.                  gint          rows,
  104.                  gint          cols,
  105.                              gint          alpha,
  106.                  gint          extra,
  107.                  gint          sample);
  108. static void   read_16bit    (guchar       *source,
  109.                  channel_data *channel,
  110.                  gushort       photomet,
  111.                  gint          startcol,
  112.                  gint          startrow,
  113.                  gint          rows,
  114.                  gint          cols,
  115.                  gint          alpha,
  116.                  gint          extra,
  117.                  gint          align);
  118. static void   read_8bit     (guchar       *source,
  119.                  channel_data *channel,
  120.                  gushort       photomet,
  121.                  gint          startcol,
  122.                  gint          startrow,
  123.                  gint          rows,
  124.                  gint          cols,
  125.                  gint          alpha,
  126.                  gint          extra,
  127.                  gint          align);
  128. static void   read_default  (guchar       *source,
  129.                  channel_data *channel,
  130.                  gushort       bps,
  131.                  gushort       photomet,
  132.                  gint          startcol,
  133.                  gint          startrow,
  134.                  gint          rows,
  135.                  gint          cols,
  136.                  gint          alpha,
  137.                  gint          extra,
  138.                  gint          align);
  139.  
  140. static gint   save_image             (gchar     *filename,
  141.                       gint32     image,
  142.                       gint32     drawable,
  143.                       gint32     orig_image);
  144.  
  145. static gint   save_dialog            (void);
  146.  
  147. static void   save_ok_callback       (GtkWidget *widget,
  148.                       gpointer   data);
  149. static void   comment_entry_callback (GtkWidget *widget,
  150.                       gpointer   data);
  151.  
  152. #define DEFAULT_COMMENT "Created with The GIMP"
  153.  
  154. GimpPlugInInfo PLUG_IN_INFO =
  155. {
  156.   NULL,  /* init_proc  */
  157.   NULL,  /* quit_proc  */
  158.   query, /* query_proc */
  159.   run,   /* run_proc   */
  160. };
  161.  
  162. static TiffSaveVals tsvals =
  163. {
  164.   COMPRESSION_NONE,    /*  compression  */
  165. };
  166.  
  167. static TiffSaveInterface tsint =
  168. {
  169.   FALSE               /*  run  */
  170. };
  171.  
  172. static char *image_comment= NULL;
  173.  
  174. MAIN ()
  175.  
  176. static void
  177. query (void)
  178. {
  179.   static GimpParamDef load_args[] =
  180.   {
  181.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  182.     { GIMP_PDB_STRING, "filename", "The name of the file to load" },
  183.     { GIMP_PDB_STRING, "raw_filename", "The name of the file to load" }
  184.   };
  185.   static GimpParamDef load_return_vals[] =
  186.   {
  187.     { GIMP_PDB_IMAGE, "image", "Output image" }
  188.   };
  189.   static gint nload_args = sizeof (load_args) / sizeof (load_args[0]);
  190.   static gint nload_return_vals = (sizeof (load_return_vals) /
  191.                    sizeof (load_return_vals[0]));
  192.  
  193.   static GimpParamDef save_args[] =
  194.   {
  195.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  196.     { GIMP_PDB_IMAGE, "image", "Input image" },
  197.     { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
  198.     { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
  199.     { GIMP_PDB_STRING, "raw_filename", "The name of the file to save the image in" },
  200.     { GIMP_PDB_INT32, "compression", "Compression type: { NONE (0), LZW (1), PACKBITS (2), DEFLATE (3), JPEG (4)" }
  201.   };
  202.   static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  203.  
  204.   gimp_install_procedure ("file_tiff_load",
  205.                           "loads files of the tiff file format",
  206.                           "FIXME: write help for tiff_load",
  207.                           "Spencer Kimball, Peter Mattis & Nick Lamb",
  208.                           "Nick Lamb <njl195@zepler.org.uk>",
  209.                           "1995-1996,1998-2000",
  210.                           "<Load>/Tiff",
  211.               NULL,
  212.                           GIMP_PLUGIN,
  213.                           nload_args, nload_return_vals,
  214.                           load_args, load_return_vals);
  215.  
  216.   gimp_install_procedure ("file_tiff_save",
  217.                           "saves files in the tiff file format",
  218.                           "Saves files in the Tagged Image File Format.  "
  219.               "The value for the saved comment is taken "
  220.               "from the 'gimp-comment' parasite.",
  221.                           "Spencer Kimball & Peter Mattis",
  222.                           "Spencer Kimball & Peter Mattis",
  223.                           "1995-1996,2000",
  224.                           "<Save>/Tiff",
  225.               "RGB*, GRAY*, INDEXED",
  226.                           GIMP_PLUGIN,
  227.                           nsave_args, 0,
  228.                           save_args, NULL);
  229.  
  230.   gimp_register_magic_load_handler ("file_tiff_load",
  231.                     "tif,tiff",
  232.                     "",
  233.                     "0,string,II*\\0,0,string,MM\\0*");
  234.   gimp_register_save_handler       ("file_tiff_save",
  235.                     "tif,tiff",
  236.                     "");
  237. }
  238.  
  239. static void
  240. run (gchar   *name,
  241.      gint     nparams,
  242.      GimpParam  *param,
  243.      gint    *nreturn_vals,
  244.      GimpParam **return_vals)
  245. {
  246.   static GimpParam values[2];
  247.   GimpRunModeType  run_mode;
  248.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  249. #ifdef GIMP_HAVE_PARASITES
  250.   GimpParasite *parasite;
  251. #endif /* GIMP_HAVE_PARASITES */
  252.   gint32        image;
  253.   gint32        drawable;
  254.   gint32        orig_image;
  255.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  256.  
  257.   run_mode = param[0].data.d_int32;
  258.  
  259.   *nreturn_vals = 1;
  260.   *return_vals  = values;
  261.   values[0].type          = GIMP_PDB_STATUS;
  262.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  263.  
  264.   if (strcmp (name, "file_tiff_load") == 0)
  265.     {
  266.       INIT_I18N();
  267.       image = load_image (param[1].data.d_string);
  268.  
  269.       if (image != -1)
  270.     {
  271.       *nreturn_vals = 2;
  272.       values[1].type         = GIMP_PDB_IMAGE;
  273.       values[1].data.d_image = image;
  274.     }
  275.       else
  276.     {
  277.       status = GIMP_PDB_EXECUTION_ERROR;
  278.     }
  279.     }
  280.   else if (strcmp (name, "file_tiff_save") == 0)
  281.     {
  282.       image = orig_image = param[1].data.d_int32;
  283.       drawable = param[2].data.d_int32;
  284.  
  285.       /* Do this right this time, if POSSIBLE query for parasites, otherwise
  286.      or if there isn't one, choose the DEFAULT_COMMENT */
  287.  
  288.       /*  eventually export the image */ 
  289.       switch (run_mode)
  290.     {
  291.     case GIMP_RUN_INTERACTIVE:
  292.     case GIMP_RUN_WITH_LAST_VALS:
  293.       INIT_I18N_UI();
  294.       gimp_ui_init ("tiff", FALSE);
  295.       export = gimp_export_image (&image, &drawable, "TIFF", 
  296.                       (GIMP_EXPORT_CAN_HANDLE_RGB |
  297.                        GIMP_EXPORT_CAN_HANDLE_GRAY |
  298.                        GIMP_EXPORT_CAN_HANDLE_INDEXED | 
  299.                        GIMP_EXPORT_CAN_HANDLE_ALPHA ));
  300.       if (export == GIMP_EXPORT_CANCEL)
  301.         {
  302.           values[0].data.d_status = GIMP_PDB_CANCEL;
  303.           return;
  304.         }
  305.       break;
  306.     default:
  307.       break;
  308.     }
  309.  
  310. #ifdef GIMP_HAVE_PARASITES
  311.       parasite = gimp_image_parasite_find (orig_image, "gimp-comment");
  312.       if (parasite)
  313.         image_comment = g_strdup (parasite->data);
  314.       gimp_parasite_free (parasite);
  315. #endif /* GIMP_HAVE_PARASITES */
  316.  
  317.       if (!image_comment)
  318.     image_comment = g_strdup (DEFAULT_COMMENT);      
  319.  
  320.       switch (run_mode)
  321.     {
  322.     case GIMP_RUN_INTERACTIVE:
  323.       /*  Possibly retrieve data  */
  324.       gimp_get_data ("file_tiff_save", &tsvals);
  325.  
  326. #ifdef GIMP_HAVE_PARASITES
  327.       parasite = gimp_image_parasite_find (orig_image, "tiff-save-options");
  328.       if (parasite)
  329.         {
  330.           tsvals.compression =
  331.         ((TiffSaveVals *) parasite->data)->compression;
  332.         }
  333.       gimp_parasite_free (parasite);
  334. #endif /* GIMP_HAVE_PARASITES */
  335.  
  336.       /*  First acquire information with a dialog  */
  337.       if (! save_dialog ())
  338.         status = GIMP_PDB_CANCEL;
  339.       break;
  340.  
  341.     case GIMP_RUN_NONINTERACTIVE:
  342.       INIT_I18N();
  343.       /*  Make sure all the arguments are there!  */
  344.       if (nparams != 6)
  345.         {
  346.           status = GIMP_PDB_CALLING_ERROR;
  347.         }
  348.       else
  349.         {
  350.           switch (param[5].data.d_int32)
  351.         {
  352.         case 0: tsvals.compression = COMPRESSION_NONE;     break;
  353.         case 1: tsvals.compression = COMPRESSION_LZW;      break;
  354.         case 2: tsvals.compression = COMPRESSION_PACKBITS; break;
  355.         case 3: tsvals.compression = COMPRESSION_DEFLATE;  break;
  356.         case 4: tsvals.compression = COMPRESSION_JPEG;  break;
  357.         default: status = GIMP_PDB_CALLING_ERROR; break;
  358.         }
  359.         }
  360.       break;
  361.  
  362.     case GIMP_RUN_WITH_LAST_VALS:
  363.       /*  Possibly retrieve data  */
  364.       gimp_get_data ("file_tiff_save", &tsvals);
  365.  
  366. #ifdef GIMP_HAVE_PARASITES
  367.       parasite = gimp_image_parasite_find (orig_image, "tiff-save-options");
  368.       if (parasite)
  369.         {
  370.           tsvals.compression =
  371.         ((TiffSaveVals *) parasite->data)->compression;
  372.         }
  373.       gimp_parasite_free (parasite);
  374. #endif /* GIMP_HAVE_PARASITES */
  375.       break;
  376.  
  377.     default:
  378.       break;
  379.     }
  380.  
  381.       if (status == GIMP_PDB_SUCCESS)
  382.     {
  383.       if (save_image (param[3].data.d_string, image, drawable, orig_image))
  384.         {
  385.           /*  Store mvals data  */
  386.           gimp_set_data ("file_tiff_save", &tsvals, sizeof (TiffSaveVals));
  387.         }
  388.       else
  389.         {
  390.           status = GIMP_PDB_EXECUTION_ERROR;
  391.         }
  392.     }
  393.  
  394.       if (export == GIMP_EXPORT_EXPORT)
  395.     gimp_image_delete (image);
  396.     }
  397.   else
  398.     {
  399.       status = GIMP_PDB_CALLING_ERROR;
  400.     }
  401.  
  402.   values[0].data.d_status = status;
  403. }
  404.  
  405. static void
  406. tiff_warning(const char* module, const char* fmt, va_list ap)
  407. {
  408.   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
  409. }
  410.   
  411. static void
  412. tiff_error(const char* module, const char* fmt, va_list ap)
  413. {
  414.   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
  415. }
  416.   
  417. static gint32
  418. load_image (gchar *filename) 
  419. {
  420.   TIFF    *tif;
  421.   gushort  bps, spp, photomet;
  422.   gint     cols, rows, alpha;
  423.   gint     image, image_type = GIMP_RGB;
  424.   gint     layer, layer_type = GIMP_RGB_IMAGE;
  425.   gushort  extra, *extra_types;
  426.   channel_data *channel= NULL;
  427.  
  428.   gushort *redmap, *greenmap, *bluemap;
  429.   guchar   colors[3]= {0, 0, 0};
  430.   guchar   cmap[768];
  431.  
  432.   gint   i, j, worst_case = 0;
  433.   gchar *name;
  434.  
  435.   TiffSaveVals save_vals;
  436. #ifdef GIMP_HAVE_PARASITES
  437.   GimpParasite *parasite;
  438. #endif /* GIMP_HAVE_PARASITES */
  439.   guint16 tmp;
  440. #ifdef TIFFTAG_ICCPROFILE
  441.   uint32 profile_size;
  442.   guchar *icc_profile;
  443. #endif
  444.  
  445.   TIFFSetWarningHandler (tiff_warning);
  446.   TIFFSetErrorHandler (tiff_error);
  447.  
  448.   tif = TIFFOpen (filename, "r");
  449.   if (!tif) {
  450.     g_message ("TIFF Can't open %s\n", filename);
  451.     gimp_quit ();
  452.   }
  453.  
  454.   name = g_strdup_printf( _("Loading %s:"), filename);
  455.   gimp_progress_init (name);
  456.   g_free (name);
  457.  
  458.   TIFFGetFieldDefaulted (tif, TIFFTAG_BITSPERSAMPLE, &bps);
  459.  
  460.   if (bps > 8 && bps != 16) {
  461.     worst_case = 1; /* Wrong sample width => RGBA */
  462.   }
  463.  
  464.   TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
  465.  
  466.   if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
  467.     extra = 0;
  468.  
  469.   if (!TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols)) {
  470.     g_message ("TIFF Can't get image width\n");
  471.     gimp_quit ();
  472.   }
  473.  
  474.   if (!TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &rows)) {
  475.     g_message ("TIFF Can't get image length\n");
  476.     gimp_quit ();
  477.   }
  478.  
  479.   if (!TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet)) {
  480.     g_message("TIFF Can't get photometric\nAssuming min-is-black\n");
  481.     /* old AppleScan software misses out the photometric tag (and
  482.      * incidentally assumes min-is-white, but xv assumes min-is-black,
  483.      * so we follow xv's lead.  It's not much hardship to invert the
  484.      * image later). */
  485.     photomet = PHOTOMETRIC_MINISBLACK;
  486.   }
  487.  
  488.   /* test if the extrasample represents an associated alpha channel... */
  489.   if (extra > 0 && (extra_types[0] == EXTRASAMPLE_ASSOCALPHA)) {
  490.     alpha = 1;
  491.     --extra;
  492.   } else {
  493.     alpha = 0;
  494.   }
  495.  
  496.   if (photomet == PHOTOMETRIC_RGB && spp > 3 + extra) {
  497.     alpha= 1;
  498.     extra= spp - 4; 
  499.   } else if (photomet != PHOTOMETRIC_RGB && spp > 1 + extra) {
  500.     alpha= 1;
  501.     extra= spp - 2;
  502.   }
  503.  
  504.   switch (photomet) {
  505.     case PHOTOMETRIC_MINISBLACK:
  506.     case PHOTOMETRIC_MINISWHITE:
  507.       image_type = GIMP_GRAY;
  508.       layer_type = (alpha) ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
  509.       break;
  510.  
  511.     case PHOTOMETRIC_RGB:
  512.       image_type = GIMP_RGB;
  513.       layer_type = (alpha) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
  514.       break;
  515.  
  516.     case PHOTOMETRIC_PALETTE:
  517.       image_type = GIMP_INDEXED;
  518.       layer_type = (alpha) ? GIMP_INDEXEDA_IMAGE : GIMP_INDEXED_IMAGE;
  519.       break;
  520.  
  521.     default:
  522.       worst_case = 1;
  523.   }
  524.  
  525.   if (worst_case) {
  526.     image_type = GIMP_RGB;
  527.     layer_type = GIMP_RGBA_IMAGE;
  528.   }
  529.  
  530.   if ((image = gimp_image_new (cols, rows, image_type)) == -1) {
  531.     g_message("TIFF Can't create a new image\n");
  532.     gimp_quit ();
  533.   }
  534.   gimp_image_set_filename (image, filename);
  535.  
  536.   /* attach a parasite containing an ICC profile - if found in the TIFF file */
  537.  
  538. #ifdef TIFFTAG_ICCPROFILE
  539.     /* If TIFFTAG_ICCPROFILE is defined we are dealing with a libtiff version 
  540.          * that can handle ICC profiles. Otherwise just ignore this section. */
  541.   if (TIFFGetField (tif, TIFFTAG_ICCPROFILE, &profile_size, &icc_profile)) {
  542. #ifdef GIMP_HAVE_PARASITES
  543.     parasite = gimp_parasite_new("icc-profile", 0,
  544.                 profile_size, icc_profile);
  545.     gimp_image_parasite_attach(image, parasite);
  546.     gimp_parasite_free(parasite);
  547. #endif
  548.   }    
  549. #endif
  550.  
  551.   /* attach a parasite containing the compression */
  552.   if (!TIFFGetField (tif, TIFFTAG_COMPRESSION, &tmp))
  553.     save_vals.compression = COMPRESSION_NONE;
  554.   else
  555.     save_vals.compression = tmp;
  556. #ifdef GIMP_HAVE_PARASITES
  557.   parasite = gimp_parasite_new ("tiff-save-options", 0,
  558.                 sizeof (save_vals), &save_vals);
  559.   gimp_image_parasite_attach (image, parasite);
  560.   gimp_parasite_free (parasite);
  561. #endif /* GIMP_HAVE_PARASITES */
  562.  
  563.  
  564.   /* Attach a parasite containing the image description.  Pretend to
  565.    * be a gimp comment so other plugins will use this description as
  566.    * an image comment where appropriate. */
  567. #ifdef GIMP_HAVE_PARASITES
  568.   {
  569.     char *img_desc;
  570.  
  571.     if (TIFFGetField (tif, TIFFTAG_IMAGEDESCRIPTION, &img_desc))
  572.     {
  573.       int len;
  574.  
  575.       len = strlen(img_desc) + 1;
  576.       len = MIN(len, 241);
  577.       img_desc[len-1] = '\000';
  578.  
  579.       parasite = gimp_parasite_new ("gimp-comment",
  580.                     GIMP_PARASITE_PERSISTENT,
  581.                     len, img_desc);
  582.       gimp_image_parasite_attach (image, parasite);
  583.       gimp_parasite_free (parasite);
  584.     }
  585.   }
  586. #endif /* GIMP_HAVE_PARASITES */
  587.  
  588.   /* any resolution info in the file? */
  589. #ifdef GIMP_HAVE_RESOLUTION_INFO
  590.   {
  591.     gfloat   xres = 72.0, yres = 72.0;
  592.     gushort  read_unit;
  593.     GimpUnit unit = GIMP_UNIT_PIXEL; /* invalid unit */
  594.  
  595.     if (TIFFGetField (tif, TIFFTAG_XRESOLUTION, &xres)) {
  596.       if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &yres)) {
  597.  
  598.     if (TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT, &read_unit)) 
  599.       {
  600.         switch (read_unit) 
  601.           {
  602.           case RESUNIT_NONE:
  603.         /* ImageMagick writes files with this silly resunit */
  604.         g_message ("TIFF warning: resolution units meaningless\n");
  605.         break;
  606.         
  607.           case RESUNIT_INCH:
  608.         unit = GIMP_UNIT_INCH;
  609.         break;
  610.         
  611.           case RESUNIT_CENTIMETER:
  612.         xres *= 2.54;
  613.         yres *= 2.54;
  614.         unit = GIMP_UNIT_MM; /* as this is our default metric unit */
  615.         break;
  616.         
  617.           default:
  618.         g_message ("TIFF file error: unknown resolution unit type %d, "
  619.                "assuming dpi\n", read_unit);
  620.         break;
  621.           }
  622.       } 
  623.     else 
  624.       { /* no res unit tag */
  625.         /* old AppleScan software produces these */
  626.         g_message ("TIFF warning: resolution specified without\n"
  627.                "any units tag, assuming dpi\n");
  628.       }
  629.       }
  630.       else 
  631.     { /* xres but no yres */
  632.       g_message("TIFF warning: no y resolution info, assuming same as x\n");
  633.       yres = xres;
  634.     }
  635.  
  636.       /* now set the new image's resolution info */
  637.  
  638.       /* If it is invalid, instead of forcing 72dpi, do not set the resolution 
  639.      at all. Gimp will then use the default set by the user */
  640.       if (read_unit != RESUNIT_NONE)
  641.     {
  642.       gimp_image_set_resolution (image, xres, yres);
  643.       if (unit != GIMP_UNIT_PIXEL)
  644.         gimp_image_set_unit (image, unit);
  645.     }
  646.     }
  647.  
  648.     /* no x res tag => we assume we have no resolution info, so we
  649.      * don't care.  Older versions of this plugin used to write files
  650.      * with no resolution tags at all. */
  651.  
  652.     /* TODO: haven't caught the case where yres tag is present, but
  653.        not xres.  This is left as an exercise for the reader - they
  654.        should feel free to shoot the author of the broken program
  655.        that produced the damaged TIFF file in the first place. */
  656.   }
  657. #endif /* GIMP_HAVE_RESOLUTION_INFO */
  658.  
  659.  
  660.   /* Install colormap for INDEXED images only */
  661.   if (image_type == GIMP_INDEXED) 
  662.     {
  663.       if (!TIFFGetField (tif, TIFFTAG_COLORMAP, &redmap, &greenmap, &bluemap)) 
  664.     {
  665.       g_message ("TIFF Can't get colormaps\n");
  666.       gimp_quit ();
  667.     }
  668.  
  669.       for (i = 0, j = 0; i < (1 << bps); i++) 
  670.     {
  671.       cmap[j++] = redmap[i] >> 8;
  672.       cmap[j++] = greenmap[i] >> 8;
  673.       cmap[j++] = bluemap[i] >> 8;
  674.     }
  675.       gimp_image_set_cmap (image, cmap, (1 << bps));
  676.     }
  677.  
  678.   /* Allocate channel_data for all channels, even the background layer */
  679.   channel = g_new (channel_data, extra + 1);
  680.   layer = gimp_layer_new (image, _("Background"), cols, rows, layer_type,
  681.                  100, GIMP_NORMAL_MODE);
  682.   channel[0].ID= layer;
  683.   gimp_image_add_layer (image, layer, 0);
  684.   channel[0].drawable= gimp_drawable_get(layer);
  685.  
  686.   if (extra > 0 && !worst_case) {
  687.     /* Add alpha channels as appropriate */
  688.     for (i= 1; i <= extra; ++i) {
  689.       channel[i].ID= gimp_channel_new(image, _("TIFF Channel"), cols, rows,
  690.                                                             100.0, colors);
  691.       gimp_image_add_channel(image, channel[i].ID, 0);
  692.       channel[i].drawable= gimp_drawable_get (channel[i].ID);
  693.     }
  694.   }
  695.  
  696.   if (worst_case) {
  697.     g_message("TIFF Fell back to RGBA, image may be inverted\n");
  698.     load_rgba (tif, channel);
  699.   } else if (TIFFIsTiled(tif)) {
  700.     load_tiles (tif, channel, bps, photomet, alpha, extra);
  701.   } else { /* Load scanlines in tile_height chunks */
  702.     load_lines (tif, channel, bps, photomet, alpha, extra);
  703.   }
  704.  
  705.   for (i= 0; !worst_case && i < extra; ++i) {
  706.     gimp_drawable_flush (channel[i].drawable);
  707.     gimp_drawable_detach (channel[i].drawable);
  708.   }
  709.  
  710.   return image;
  711. }
  712.  
  713. static void
  714. load_rgba (TIFF *tif, channel_data *channel)
  715. {
  716.   uint32 imageWidth, imageLength;
  717.   gulong *buffer;
  718.  
  719.   TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
  720.   TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
  721.   gimp_pixel_rgn_init (&(channel[0].pixel_rgn), channel[0].drawable,
  722.                           0, 0, imageWidth, imageLength, TRUE, FALSE);
  723.   buffer = g_new(gulong, imageWidth * imageLength);
  724.   channel[0].pixels = (guchar*) buffer;
  725.   if (buffer == NULL) {
  726.     g_message("TIFF Unable to allocate temporary buffer\n");
  727.   }
  728.   if (!TIFFReadRGBAImage(tif, imageWidth, imageLength, buffer, 0))
  729.     g_message("TIFF Unsupported layout, no RGBA loader\n");
  730.  
  731.   gimp_pixel_rgn_set_rect(&(channel[0].pixel_rgn), channel[0].pixels,
  732.                               0, 0, imageWidth, imageLength);
  733. }
  734.  
  735. static void
  736. load_tiles (TIFF *tif, channel_data *channel,
  737.        unsigned short bps, unsigned short photomet,
  738.        int alpha, int extra)
  739. {
  740.   uint16 planar= PLANARCONFIG_CONTIG;
  741.   uint32 imageWidth, imageLength;
  742.   uint32 tileWidth, tileLength;
  743.   uint32 x, y, rows, cols;
  744.   guchar *buffer;
  745.   double progress= 0.0, one_row;
  746.   int i;
  747.  
  748.   TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar);
  749.   TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
  750.   TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
  751.   TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
  752.   TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileLength);
  753.   one_row = (double) tileLength / (double) imageLength;
  754.   buffer = g_malloc(TIFFTileSize(tif));
  755.  
  756.   for (i= 0; i <= extra; ++i) {
  757.     channel[i].pixels= g_new(guchar, tileWidth * tileLength *
  758.                                       channel[i].drawable->bpp);
  759.   }
  760.  
  761.   for (y = 0; y < imageLength; y += tileLength) {
  762.     for (x = 0; x < imageWidth; x += tileWidth) {
  763.       gimp_progress_update (progress + one_row *
  764.                             ( (double) x / (double) imageWidth));
  765.       TIFFReadTile(tif, buffer, x, y, 0, 0);
  766.       cols= MIN(imageWidth - x, tileWidth);
  767.       rows= MIN(imageLength - y, tileLength);
  768.       if (bps == 16) {
  769.         read_16bit(buffer, channel, photomet, y, x, rows, cols, alpha,
  770.                    extra, tileWidth - cols);
  771.       } else if (bps == 8) {
  772.         read_8bit(buffer, channel, photomet, y, x, rows, cols, alpha,
  773.                   extra, tileWidth - cols);
  774.       } else {
  775.         read_default(buffer, channel, bps, photomet, y, x, rows, cols,
  776.                      alpha, extra, tileWidth - cols);
  777.       }
  778.     }
  779.     progress+= one_row;
  780.   }
  781.   for (i= 0; i <= extra; ++i) {
  782.     g_free(channel[i].pixels);
  783.   }
  784.   g_free(buffer);
  785. }
  786.  
  787. static void
  788. load_lines (TIFF *tif, channel_data *channel,
  789.         unsigned short bps, unsigned short photomet,
  790.         int alpha, int extra)
  791. {
  792.   uint16 planar= PLANARCONFIG_CONTIG;
  793.   uint32 imageLength, lineSize, cols, rows;
  794.   guchar *buffer;
  795.   int i, y, tile_height = gimp_tile_height ();
  796.  
  797.   TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar);
  798.   TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
  799.   TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &cols);
  800.   lineSize= TIFFScanlineSize(tif);
  801.  
  802.   for (i= 0; i <= extra; ++i) {
  803.     channel[i].pixels= g_new(guchar, tile_height * cols
  804.                                           * channel[i].drawable->bpp);
  805.   }
  806.  
  807.   buffer = g_malloc(lineSize * tile_height);
  808.   if (planar == PLANARCONFIG_CONTIG) {
  809.     for (y = 0; y < imageLength; y+= tile_height ) {
  810.       gimp_progress_update ( (double) y / (double) imageLength);
  811.       rows = MIN(tile_height, imageLength - y);
  812.       for (i = 0; i < rows; ++i)
  813.     TIFFReadScanline(tif, buffer + i * lineSize, y + i, 0);
  814.       if (bps == 16) {
  815.     read_16bit(buffer, channel, photomet, y, 0, rows, cols,
  816.                    alpha, extra, 0);
  817.       } else if (bps == 8) {
  818.     read_8bit(buffer, channel, photomet, y, 0, rows, cols,
  819.                   alpha, extra, 0);
  820.       } else {
  821.     read_default(buffer, channel, bps, photomet, y, 0, rows, cols,
  822.                      alpha, extra, 0);
  823.       }
  824.     }
  825.   } else { /* PLANARCONFIG_SEPARATE  -- Just say "No" */
  826.     uint16 s, samples;
  827.     TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples);
  828.     for (s = 0; s < samples; ++s) {
  829.       for (y = 0; y < imageLength; y+= tile_height ) {
  830.     gimp_progress_update ( (double) y / (double) imageLength);
  831.     rows = MIN(tile_height, imageLength - y);
  832.     for (i = 0; i < rows; ++i)
  833.       TIFFReadScanline(tif, buffer + i * lineSize, y + i, s);
  834.     read_separate (buffer, channel, bps, photomet,
  835.                  y, 0, rows, cols, alpha, extra, s);
  836.       }
  837.     }
  838.   }
  839.   for (i= 0; i <= extra; ++i) {
  840.     g_free(channel[i].pixels);
  841.   }
  842.   g_free(buffer);
  843. }
  844.  
  845. static void
  846. read_16bit (guchar       *source,
  847.         channel_data *channel,
  848.         gushort       photomet,
  849.         gint          startrow,
  850.         gint          startcol,
  851.         gint          rows,
  852.         gint          cols,
  853.         gint          alpha,
  854.             gint          extra,
  855.             gint          align)
  856. {
  857.   guchar *dest;
  858.   gint    gray_val, red_val, green_val, blue_val, alpha_val;
  859.   gint    col, row, i;
  860.  
  861.   for (i= 0; i <= extra; ++i) {
  862.     gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
  863.                           startcol, startrow, cols, rows, TRUE, FALSE);
  864.   }
  865.  
  866. #if G_BYTE_ORDER == G_LITTLE_ENDIAN
  867.   source++; /* offset source once, to look at the high byte */
  868. #endif
  869.  
  870.   for (row = 0; row < rows; ++row) {
  871.     dest= channel[0].pixels + row * cols * channel[0].drawable->bpp;
  872.  
  873.     for (i= 1; i <= extra; ++i) {
  874.       channel[i].pixel= channel[i].pixels + row * cols;
  875.     }
  876.  
  877.     for (col = 0; col < cols; col++) {
  878.       switch (photomet) {
  879.         case PHOTOMETRIC_MINISBLACK:
  880.           if (alpha) {
  881.             gray_val= *source; source+= 2;
  882.             alpha_val= *source; source+= 2;
  883.             if (alpha_val)
  884.               *dest++ = gray_val * 255 / alpha_val;
  885.             else
  886.               *dest++ = 0;
  887.             *dest++ = alpha_val;
  888.           } else {
  889.             *dest++ = *source; source+= 2;
  890.           }
  891.           break;
  892.  
  893.         case PHOTOMETRIC_MINISWHITE:
  894.           if (alpha) {
  895.             gray_val= *source; source+= 2;
  896.             alpha_val= *source; source+= 2;
  897.             if (alpha_val)
  898.               *dest++ = ((255 - gray_val) * 255) / alpha_val;
  899.             else
  900.               *dest++ = 0;
  901.             *dest++ = alpha_val;
  902.           } else {
  903.             *dest++ = ~(*source); source+= 2;
  904.           }
  905.           break;
  906.  
  907.         case PHOTOMETRIC_PALETTE:
  908.           *dest++= *source; source+= 2;
  909.           if (alpha) *dest++= *source; source+= 2;
  910.           break;
  911.   
  912.         case PHOTOMETRIC_RGB:
  913.           if (alpha) {
  914.             red_val= *source; source+= 2;
  915.             green_val= *source; source+= 2;
  916.             blue_val= *source; source+= 2;
  917.             alpha_val= *source; source+= 2;
  918.             if (alpha_val) {
  919.               *dest++ = (red_val * 255) / alpha_val;
  920.               *dest++ = (green_val * 255) / alpha_val;
  921.               *dest++ = (blue_val * 255) / alpha_val;
  922.             } else {
  923.               *dest++ = 0;
  924.               *dest++ = 0;
  925.               *dest++ = 0;
  926.         }
  927.         *dest++ = alpha_val;
  928.       } else {
  929.         *dest++ = *source; source+= 2;
  930.         *dest++ = *source; source+= 2;
  931.         *dest++ = *source; source+= 2;
  932.       }
  933.           break;
  934.  
  935.         default:
  936.           /* This case was handled earlier */
  937.           g_assert_not_reached();
  938.       }
  939.       for (i= 1; i <= extra; ++i) {
  940.         *channel[i].pixel++ = *source; source+= 2;
  941.       }
  942.     }
  943.     if (align) {
  944.       switch (photomet) {
  945.         case PHOTOMETRIC_MINISBLACK:
  946.         case PHOTOMETRIC_MINISWHITE:
  947.         case PHOTOMETRIC_PALETTE:
  948.           source+= align * (1 + alpha + extra) * 2;
  949.           break;
  950.         case PHOTOMETRIC_RGB:
  951.           source+= align * (3 + alpha + extra) * 2;
  952.           break;
  953.       }
  954.     }
  955.   }
  956.   for (i= 0; i <= extra; ++i) {
  957.     gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
  958.                               startcol, startrow, cols, rows);
  959.   }
  960. }
  961.  
  962. static void
  963. read_8bit (guchar       *source,
  964.        channel_data *channel,
  965.        gushort       photomet,
  966.        gint          startrow,
  967.        gint          startcol,
  968.        gint          rows,
  969.        gint          cols,
  970.        gint          alpha,
  971.        gint          extra,
  972.        gint          align)
  973. {
  974.   guchar *dest;
  975.   gint    gray_val, red_val, green_val, blue_val, alpha_val;
  976.   gint    col, row, i;
  977.  
  978.   for (i= 0; i <= extra; ++i) {
  979.     gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
  980.                           startcol, startrow, cols, rows, TRUE, FALSE);
  981.   }
  982.  
  983.   for (row = 0; row < rows; ++row) {
  984.     dest= channel[0].pixels + row * cols * channel[0].drawable->bpp;
  985.  
  986.     for (i= 1; i <= extra; ++i) {
  987.       channel[i].pixel= channel[i].pixels + row * cols;
  988.     }
  989.  
  990.     for (col = 0; col < cols; col++) {
  991.       switch (photomet) {
  992.         case PHOTOMETRIC_MINISBLACK:
  993.           if (alpha) {
  994.             gray_val= *source++;
  995.             alpha_val= *source++;
  996.             if (alpha_val)
  997.               *dest++ = gray_val * 255 / alpha_val;
  998.             else
  999.               *dest++ = 0;
  1000.             *dest++ = alpha_val;
  1001.           } else {
  1002.             *dest++ = *source++;
  1003.           }
  1004.           break;
  1005.  
  1006.         case PHOTOMETRIC_MINISWHITE:
  1007.           if (alpha) {
  1008.             gray_val= *source++;
  1009.             alpha_val= *source++;
  1010.             if (alpha_val)
  1011.               *dest++ = ((255 - gray_val) * 255) / alpha_val;
  1012.             else
  1013.               *dest++ = 0;
  1014.             *dest++ = alpha_val;
  1015.           } else {
  1016.             *dest++ = ~(*source++);
  1017.           }
  1018.           break;
  1019.  
  1020.         case PHOTOMETRIC_PALETTE:
  1021.           *dest++= *source++;
  1022.           if (alpha) *dest++= *source++;
  1023.           break;
  1024.   
  1025.         case PHOTOMETRIC_RGB:
  1026.           if (alpha) {
  1027.             red_val= *source++;
  1028.             green_val= *source++;
  1029.             blue_val= *source++;
  1030.             alpha_val= *source++;
  1031.             if (alpha_val) {
  1032.               *dest++ = (red_val * 255) / alpha_val;
  1033.               *dest++ = (green_val * 255) / alpha_val;
  1034.               *dest++ = (blue_val * 255) / alpha_val;
  1035.             } else {
  1036.               *dest++ = 0;
  1037.               *dest++ = 0;
  1038.               *dest++ = 0;
  1039.         }
  1040.         *dest++ = alpha_val;
  1041.       } else {
  1042.         *dest++ = *source++;
  1043.         *dest++ = *source++;
  1044.         *dest++ = *source++;
  1045.       }
  1046.           break;
  1047.  
  1048.         default:
  1049.           /* This case was handled earlier */
  1050.           g_assert_not_reached();
  1051.       }
  1052.       for (i= 1; i <= extra; ++i) {
  1053.         *channel[i].pixel++ = *source++;
  1054.       }
  1055.     }
  1056.     if (align) {
  1057.       switch (photomet) {
  1058.         case PHOTOMETRIC_MINISBLACK:
  1059.         case PHOTOMETRIC_MINISWHITE:
  1060.         case PHOTOMETRIC_PALETTE:
  1061.           source+= align * (1 + alpha + extra);
  1062.           break;
  1063.         case PHOTOMETRIC_RGB:
  1064.           source+= align * (3 + alpha + extra);
  1065.           break;
  1066.       }
  1067.     }
  1068.   }
  1069.   for (i= 0; i <= extra; ++i) {
  1070.     gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
  1071.                               startcol, startrow, cols, rows);
  1072.   }
  1073. }
  1074.  
  1075. /* Step through all <= 8-bit samples in an image */
  1076.  
  1077. #define NEXTSAMPLE(var)                       \
  1078.   {                                           \
  1079.       if (bitsleft == 0)                      \
  1080.       {                                       \
  1081.       source++;                           \
  1082.       bitsleft = 8;                       \
  1083.       }                                       \
  1084.       bitsleft -= bps;                        \
  1085.       var = ( *source >> bitsleft ) & maxval; \
  1086.   }
  1087.  
  1088. static void
  1089. read_default (guchar       *source,
  1090.           channel_data *channel,
  1091.           gushort       bps,
  1092.           gushort       photomet,
  1093.           gint          startrow,
  1094.           gint          startcol,
  1095.           gint          rows,
  1096.           gint          cols,
  1097.           gint          alpha,
  1098.           gint          extra,
  1099.               gint          align)
  1100. {
  1101.   guchar *dest;
  1102.   gint    gray_val, red_val, green_val, blue_val, alpha_val;
  1103.   gint    col, row, i;
  1104.   gint    bitsleft = 8, maxval = (1 << bps) - 1;
  1105.  
  1106.   for (i= 0; i <= extra; ++i) {
  1107.     gimp_pixel_rgn_init (&(channel[i].pixel_rgn), channel[i].drawable,
  1108.         startcol, startrow, cols, rows, TRUE, FALSE);
  1109.   }
  1110.  
  1111.   for (row = 0; row < rows; ++row) {
  1112.     dest= channel[0].pixels + row * cols * channel[0].drawable->bpp;
  1113.  
  1114.     for (i= 1; i <= extra; ++i) {
  1115.       channel[i].pixel= channel[i].pixels + row * cols;
  1116.     }
  1117.  
  1118.     for (col = 0; col < cols; col++) {
  1119.       switch (photomet) {
  1120.         case PHOTOMETRIC_MINISBLACK:
  1121.           NEXTSAMPLE(gray_val);
  1122.           if (alpha) {
  1123.             NEXTSAMPLE(alpha_val);
  1124.             if (alpha_val)
  1125.               *dest++ = (gray_val * 65025) / (alpha_val * maxval);
  1126.             else
  1127.               *dest++ = 0;
  1128.             *dest++ = alpha_val;
  1129.           } else {
  1130.             *dest++ = (gray_val * 255) / maxval;
  1131.           }
  1132.           break;
  1133.  
  1134.         case PHOTOMETRIC_MINISWHITE:
  1135.           NEXTSAMPLE(gray_val);
  1136.           if (alpha) {
  1137.             NEXTSAMPLE(alpha_val);
  1138.             if (alpha_val)
  1139.               *dest++ = ((maxval - gray_val) * 65025) / (alpha_val * maxval);
  1140.             else
  1141.               *dest++ = 0;
  1142.             *dest++ = alpha_val;
  1143.           } else {
  1144.             *dest++ = ((maxval - gray_val) * 255) / maxval;
  1145.           }
  1146.           break;
  1147.  
  1148.         case PHOTOMETRIC_PALETTE:
  1149.           NEXTSAMPLE(*dest++);
  1150.           if (alpha) {
  1151.             NEXTSAMPLE(*dest++);
  1152.           }
  1153.           break;
  1154.   
  1155.         case PHOTOMETRIC_RGB:
  1156.           NEXTSAMPLE(red_val)
  1157.           NEXTSAMPLE(green_val)
  1158.           NEXTSAMPLE(blue_val)
  1159.           if (alpha) {
  1160.             NEXTSAMPLE(alpha_val)
  1161.             if (alpha_val) {
  1162.               *dest++ = (red_val * 255) / alpha_val;
  1163.               *dest++ = (green_val * 255) / alpha_val;
  1164.               *dest++ = (blue_val * 255) / alpha_val;
  1165.             } else {
  1166.               *dest++ = 0;
  1167.               *dest++ = 0;
  1168.               *dest++ = 0;
  1169.         }
  1170.         *dest++ = alpha_val;
  1171.       } else {
  1172.         *dest++ = red_val;
  1173.         *dest++ = green_val;
  1174.         *dest++ = blue_val;
  1175.       }
  1176.           break;
  1177.  
  1178.         default:
  1179.           /* This case was handled earlier */
  1180.           g_assert_not_reached();
  1181.       }
  1182.       for (i= 1; i <= extra; ++i) {
  1183.         NEXTSAMPLE(alpha_val);
  1184.         *channel[i].pixel++ = alpha_val;
  1185.       }
  1186.     }
  1187.     if (align) {
  1188.       switch (photomet) {
  1189.         case PHOTOMETRIC_MINISBLACK:
  1190.         case PHOTOMETRIC_MINISWHITE:
  1191.         case PHOTOMETRIC_PALETTE:
  1192.           for (i= 0; i < align * (1 + alpha + extra); ++i) {
  1193.             NEXTSAMPLE(alpha_val);
  1194.           }
  1195.           break;
  1196.         case PHOTOMETRIC_RGB:
  1197.           for (i= 0; i < align * (3 + alpha + extra); ++i) {
  1198.             NEXTSAMPLE(alpha_val);
  1199.           }
  1200.           break;
  1201.       }
  1202.     }
  1203.     bitsleft= 0;
  1204.   }
  1205.   for (i= 0; i <= extra; ++i) {
  1206.     gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
  1207.                               startcol, startrow, cols, rows);
  1208.   }
  1209. }
  1210.  
  1211. static void
  1212. read_separate (guchar       *source,
  1213.            channel_data *channel,
  1214.                gushort       bps,
  1215.            gushort       photomet,
  1216.                gint          startrow,
  1217.            gint          startcol,
  1218.            gint          rows,
  1219.            gint          cols,
  1220.                gint          alpha,
  1221.            gint          extra,
  1222.            gint          sample)
  1223. {
  1224.   guchar *dest;
  1225.   gint    col, row, c;
  1226.   gint    bitsleft = 8, maxval = (1 << bps) - 1;
  1227.  
  1228.   if (bps > 8) {
  1229.     g_message("TIFF Unsupported layout\n");
  1230.     gimp_quit();
  1231.   }
  1232.  
  1233.   if (sample < channel[0].drawable->bpp) {
  1234.     c = 0;
  1235.   } else {
  1236.     c = (sample - channel[0].drawable->bpp) + 4;
  1237.     photomet = PHOTOMETRIC_MINISBLACK;
  1238.   }
  1239.  
  1240.   gimp_pixel_rgn_init (&(channel[c].pixel_rgn), channel[c].drawable,
  1241.                          startcol, startrow, cols, rows, TRUE, FALSE);
  1242.  
  1243.   gimp_pixel_rgn_get_rect(&(channel[c].pixel_rgn), channel[c].pixels,
  1244.                             startcol, startrow, cols, rows);
  1245.   for (row = 0; row < rows; ++row) {
  1246.     dest = channel[c].pixels + row * cols * channel[c].drawable->bpp;
  1247.     if (c == 0) {
  1248.       for (col = 0; col < cols; ++col) {
  1249.         NEXTSAMPLE(dest[col * channel[0].drawable->bpp + sample]);
  1250.       }
  1251.     } else {
  1252.       for (col = 0; col < cols; ++col)
  1253.         NEXTSAMPLE(dest[col]);
  1254.     }
  1255.   }
  1256.   gimp_pixel_rgn_set_rect(&(channel[c].pixel_rgn), channel[c].pixels,
  1257.                             startcol, startrow, cols, rows);
  1258. }
  1259.  
  1260. /*
  1261. ** pnmtotiff.c - converts a portable anymap to a Tagged Image File
  1262. **
  1263. ** Derived by Jef Poskanzer from ras2tif.c, which is:
  1264. **
  1265. ** Copyright (c) 1990 by Sun Microsystems, Inc.
  1266. **
  1267. ** Author: Patrick J. Naughton
  1268. ** naughton@wind.sun.com
  1269. **
  1270. ** Permission to use, copy, modify, and distribute this software and its
  1271. ** documentation for any purpose and without fee is hereby granted,
  1272. ** provided that the above copyright notice appear in all copies and that
  1273. ** both that copyright notice and this permission notice appear in
  1274. ** supporting documentation.
  1275. **
  1276. ** This file is provided AS IS with no warranties of any kind.  The author
  1277. ** shall have no liability with respect to the infringement of copyrights,
  1278. ** trade secrets or any patents by this file or any part thereof.  In no
  1279. ** event will the author be liable for any lost revenue or profits or
  1280. ** other special, indirect and consequential damages.
  1281. */
  1282.  
  1283. static gint
  1284. save_image (gchar   *filename, 
  1285.         gint32   image, 
  1286.         gint32   layer,
  1287.         gint32   orig_image)  /* the export function might have created a duplicate */  
  1288. {
  1289.   TIFF          *tif;
  1290.   gushort        red[256];
  1291.   gushort        grn[256];
  1292.   gushort        blu[256];
  1293.   gint           cols, col, rows, row, i;
  1294.   glong          rowsperstrip;
  1295.   gushort        compression;
  1296.   gushort        extra_samples[1];
  1297.   gint           alpha;
  1298.   gshort         predictor;
  1299.   gshort         photometric;
  1300.   gshort         samplesperpixel;
  1301.   gshort         bitspersample;
  1302.   gint           bytesperrow;
  1303.   guchar        *t, *src, *data;
  1304.   guchar        *cmap;
  1305.   gint           colors;
  1306.   gint           success;
  1307.   GimpDrawable     *drawable;
  1308.   GimpImageType  drawable_type;
  1309.   GimpPixelRgn      pixel_rgn;
  1310.   gint           tile_height;
  1311.   gint           y, yend;
  1312.   gchar         *name;
  1313.  
  1314.   compression = tsvals.compression;
  1315.  
  1316.   /* Disabled because this isn't in older releases of libtiff, and it
  1317.      wasn't helping much anyway */
  1318. #if 0
  1319.   if (TIFFFindCODEC((uint16) compression) == NULL)
  1320.     compression = COMPRESSION_NONE; /* CODEC not available */
  1321. #endif
  1322.  
  1323.   predictor = 0;
  1324.   tile_height = gimp_tile_height ();
  1325.   rowsperstrip = tile_height;
  1326.  
  1327.   TIFFSetWarningHandler (tiff_warning);
  1328.   TIFFSetErrorHandler (tiff_error);
  1329.  
  1330.   tif = TIFFOpen (filename, "w");
  1331.   if (!tif) 
  1332.     {
  1333.       g_print ("Can't write image to\n%s", filename);
  1334.       return 0;
  1335.     }
  1336.  
  1337.   name = g_strdup_printf( _("Saving %s:"), filename);
  1338.   gimp_progress_init (name);
  1339.   g_free (name);
  1340.  
  1341.   drawable = gimp_drawable_get (layer);
  1342.   drawable_type = gimp_drawable_type (layer);
  1343.   gimp_pixel_rgn_init (&pixel_rgn, drawable,
  1344.                0, 0, drawable->width, drawable->height, FALSE, FALSE);
  1345.  
  1346.   cols = drawable->width;
  1347.   rows = drawable->height;
  1348.  
  1349.   switch (drawable_type)
  1350.     {
  1351.     case GIMP_RGB_IMAGE:
  1352.       predictor = 2;
  1353.       samplesperpixel = 3;
  1354.       bitspersample = 8;
  1355.       photometric = PHOTOMETRIC_RGB;
  1356.       bytesperrow = cols * 3;
  1357.       alpha = 0;
  1358.       break;
  1359.     case GIMP_GRAY_IMAGE:
  1360.       samplesperpixel = 1;
  1361.       bitspersample = 8;
  1362.       photometric = PHOTOMETRIC_MINISBLACK;
  1363.       bytesperrow = cols;
  1364.       alpha = 0;
  1365.       break;
  1366.     case GIMP_RGBA_IMAGE:
  1367.       predictor = 2;
  1368.       samplesperpixel = 4;
  1369.       bitspersample = 8;
  1370.       photometric = PHOTOMETRIC_RGB;
  1371.       bytesperrow = cols * 4;
  1372.       alpha = 1;
  1373.       break;
  1374.     case GIMP_GRAYA_IMAGE:
  1375.       samplesperpixel = 2;
  1376.       bitspersample = 8;
  1377.       photometric = PHOTOMETRIC_MINISBLACK;
  1378.       bytesperrow = cols * 2;
  1379.       alpha = 1;
  1380.       break;
  1381.     case GIMP_INDEXED_IMAGE:
  1382.       samplesperpixel = 1;
  1383.       bitspersample = 8;
  1384.       photometric = PHOTOMETRIC_PALETTE;
  1385.       bytesperrow = cols;
  1386.       alpha = 0;
  1387.  
  1388.       cmap = gimp_image_get_cmap (image, &colors);
  1389.  
  1390.       for (i = 0; i < colors; i++)
  1391.     {
  1392.       red[i] = *cmap++ * 65535 / 255;
  1393.       grn[i] = *cmap++ * 65535 / 255;
  1394.       blu[i] = *cmap++ * 65535 / 255;
  1395.     }
  1396.       break;
  1397.     case GIMP_INDEXEDA_IMAGE:
  1398.       return 0;
  1399.      default:
  1400.       return 0;
  1401.     }
  1402.  
  1403.   /* Set TIFF parameters. */
  1404.   TIFFSetField (tif, TIFFTAG_SUBFILETYPE, 0);
  1405.   TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, cols);
  1406.   TIFFSetField (tif, TIFFTAG_IMAGELENGTH, rows);
  1407.   TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
  1408.   TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
  1409.   TIFFSetField (tif, TIFFTAG_COMPRESSION, compression);
  1410.   if ((compression == COMPRESSION_LZW || compression == COMPRESSION_DEFLATE)
  1411.      && (predictor != 0)) {
  1412.     TIFFSetField (tif, TIFFTAG_PREDICTOR, predictor);
  1413.   }
  1414.   if (alpha) {
  1415.       extra_samples [0] = EXTRASAMPLE_ASSOCALPHA;
  1416.       TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
  1417.   }
  1418.   TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, photometric);
  1419.   TIFFSetField (tif, TIFFTAG_DOCUMENTNAME, filename);
  1420.   TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
  1421.   TIFFSetField (tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
  1422.   /* TIFFSetField( tif, TIFFTAG_STRIPBYTECOUNTS, rows / rowsperstrip ); */
  1423.   TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  1424.  
  1425. #ifdef GIMP_HAVE_RESOLUTION_INFO
  1426.   /* resolution fields */
  1427.   {
  1428.     gdouble  xresolution;
  1429.     gdouble  yresolution;
  1430.     gushort  save_unit = RESUNIT_INCH;
  1431.     GimpUnit unit;
  1432.     gfloat   factor;
  1433.  
  1434.     gimp_image_get_resolution (orig_image, &xresolution, &yresolution);
  1435.     unit = gimp_image_get_unit (orig_image);
  1436.     factor = gimp_unit_get_factor (unit);
  1437.  
  1438.     /*  if we have a metric unit, save the resolution as centimeters
  1439.      */
  1440.     if ((ABS (factor - 0.0254) < 1e-5) ||  /* m  */
  1441.     (ABS (factor - 0.254) < 1e-5) ||   /* dm */
  1442.     (ABS (factor - 2.54) < 1e-5) ||    /* cm */
  1443.     (ABS (factor - 25.4) < 1e-5))      /* mm */
  1444.       {
  1445.     save_unit = RESUNIT_CENTIMETER;
  1446.     xresolution /= 2.54;
  1447.     yresolution /= 2.54;
  1448.       }
  1449.  
  1450.     if (xresolution > 1e-5 && yresolution > 1e-5)
  1451.       {
  1452.     TIFFSetField (tif, TIFFTAG_XRESOLUTION, xresolution);
  1453.     TIFFSetField (tif, TIFFTAG_YRESOLUTION, yresolution);
  1454.     TIFFSetField (tif, TIFFTAG_RESOLUTIONUNIT, save_unit);
  1455.       }
  1456.   }
  1457. #endif /* GIMP_HAVE_RESOLUTION_INFO */
  1458.  
  1459.   /* do we have a comment?  If so, create a new parasite to hold it,
  1460.    * and attach it to the image. The attach function automatically
  1461.    * detaches a previous incarnation of the parasite. */
  1462. #ifdef GIMP_HAVE_PARASITES
  1463.   if (image_comment && *image_comment != '\000')
  1464.     {
  1465.       GimpParasite *parasite;
  1466.       
  1467.       TIFFSetField (tif, TIFFTAG_IMAGEDESCRIPTION, image_comment);
  1468.       parasite = gimp_parasite_new ("gimp-comment",
  1469.                     GIMP_PARASITE_PERSISTENT,
  1470.                     strlen (image_comment) + 1, image_comment);
  1471.       gimp_image_parasite_attach (orig_image, parasite);
  1472.       gimp_parasite_free (parasite);
  1473.     }
  1474. #endif /* GIMP_HAVE_PARASITES */
  1475.  
  1476.   /* do we have an ICC profile? If so, write it to the TIFF file */
  1477. #ifdef GIMP_HAVE_PARASITES
  1478. #ifdef TIFFTAG_ICCPROFILE
  1479.   {
  1480.     GimpParasite *parasite;
  1481.     uint32 profile_size;
  1482.     guchar *icc_profile;
  1483.  
  1484.     parasite = gimp_image_parasite_find (orig_image, "icc-profile");
  1485.     if (parasite)
  1486.       {
  1487.         profile_size = gimp_parasite_data_size(parasite);
  1488.     icc_profile = gimp_parasite_data(parasite);
  1489.  
  1490.     TIFFSetField(tif, TIFFTAG_ICCPROFILE, profile_size, icc_profile);
  1491.         gimp_parasite_free(parasite);
  1492.       }
  1493.   }
  1494. #endif
  1495. #endif
  1496.  
  1497.   if (drawable_type == GIMP_INDEXED_IMAGE)
  1498.     TIFFSetField (tif, TIFFTAG_COLORMAP, red, grn, blu);
  1499.  
  1500.   /* array to rearrange data */
  1501.   src = g_new (guchar, bytesperrow * tile_height);
  1502.   data = g_new (guchar, bytesperrow);
  1503.  
  1504.   /* Now write the TIFF data. */
  1505.   for (y = 0; y < rows; y = yend)
  1506.     {
  1507.       yend = y + tile_height;
  1508.       yend = MIN (yend, rows);
  1509.  
  1510.       gimp_pixel_rgn_get_rect (&pixel_rgn, src, 0, y, cols, yend - y);
  1511.  
  1512.       for (row = y; row < yend; row++)
  1513.     {
  1514.       t = src + bytesperrow * (row - y);
  1515.  
  1516.       switch (drawable_type)
  1517.         {
  1518.         case GIMP_INDEXED_IMAGE:
  1519.           success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
  1520.           break;
  1521.         case GIMP_GRAY_IMAGE:
  1522.           success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
  1523.           break;
  1524.         case GIMP_GRAYA_IMAGE:
  1525.           for (col = 0; col < cols*samplesperpixel; col+=samplesperpixel)
  1526.         {
  1527.           /* pre-multiply gray by alpha */
  1528.           data[col + 0] = (t[col + 0] * t[col + 1]) / 255;
  1529.           data[col + 1] = t[col + 1];  /* alpha channel */
  1530.         }
  1531.           success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
  1532.           break;
  1533.         case GIMP_RGB_IMAGE:
  1534.           success = (TIFFWriteScanline (tif, t, row, 0) >= 0);
  1535.           break;
  1536.         case GIMP_RGBA_IMAGE:
  1537.           for (col = 0; col < cols*samplesperpixel; col+=samplesperpixel)
  1538.         {
  1539.           /* pre-multiply rgb by alpha */
  1540.           data[col+0] = t[col + 0] * t[col + 3] / 255;
  1541.           data[col+1] = t[col + 1] * t[col + 3] / 255;
  1542.           data[col+2] = t[col + 2] * t[col + 3] / 255;
  1543.           data[col+3] = t[col + 3];  /* alpha channel */
  1544.         }
  1545.           success = (TIFFWriteScanline (tif, data, row, 0) >= 0);
  1546.           break;
  1547.         default:
  1548.           success = FALSE;
  1549.           break;
  1550.         }
  1551.  
  1552.       if (!success) {
  1553.         g_message ("TIFF Failed a scanline write on row %d", row);
  1554.         return 0;
  1555.       }
  1556.     }
  1557.  
  1558.       gimp_progress_update ((double) row / (double) rows);
  1559.     }
  1560.  
  1561.   TIFFFlushData (tif);
  1562.   TIFFClose (tif);
  1563.  
  1564.   gimp_drawable_detach (drawable);
  1565.   g_free (data);
  1566.  
  1567.   return 1;
  1568. }
  1569.  
  1570. static gint
  1571. save_dialog (void)
  1572. {
  1573.   GtkWidget *dlg;
  1574.   GtkWidget *vbox;
  1575.   GtkWidget *frame;
  1576.   GtkWidget *hbox;
  1577.   GtkWidget *label;
  1578.   GtkWidget *entry;
  1579.  
  1580.   dlg = gimp_dialog_new ( _("Save as TIFF"), "tiff",
  1581.              gimp_standard_help_func, "filters/tiff.html",
  1582.              GTK_WIN_POS_MOUSE,
  1583.              FALSE, TRUE, FALSE,
  1584.  
  1585.              _("OK"), save_ok_callback,
  1586.              NULL, NULL, NULL, TRUE, FALSE,
  1587.              _("Cancel"), gtk_widget_destroy,
  1588.              NULL, 1, NULL, FALSE, TRUE,
  1589.  
  1590.              NULL);
  1591.  
  1592.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  1593.               GTK_SIGNAL_FUNC (gtk_main_quit),
  1594.               NULL);
  1595.  
  1596.   vbox = gtk_vbox_new (FALSE, 4);
  1597.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
  1598.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), vbox, FALSE, TRUE, 0);
  1599.  
  1600.   /*  compression  */
  1601.   frame =
  1602.     gimp_radio_group_new2 (TRUE, _("Compression"),
  1603.                gimp_radio_button_update,
  1604.                &tsvals.compression, (gpointer) tsvals.compression,
  1605.  
  1606.                _("None"),      (gpointer) COMPRESSION_NONE, NULL,
  1607.                _("LZW"),       (gpointer) COMPRESSION_LZW, NULL,
  1608.                _("Pack Bits"), (gpointer) COMPRESSION_PACKBITS, NULL,
  1609.                _("Deflate"),   (gpointer) COMPRESSION_DEFLATE, NULL,
  1610.                _("JPEG"),      (gpointer) COMPRESSION_JPEG, NULL,
  1611.  
  1612.                NULL);
  1613.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  1614.   gtk_widget_show (frame);
  1615.  
  1616.   /* comment entry */
  1617.   hbox = gtk_hbox_new (FALSE, 4);
  1618.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  1619.   gtk_widget_show (hbox);
  1620.  
  1621.   label = gtk_label_new ( _("Comment:"));
  1622.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  1623.   gtk_widget_show (label);
  1624.  
  1625.   entry = gtk_entry_new ();
  1626.   gtk_widget_show (entry);
  1627.   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
  1628.   gtk_entry_set_text (GTK_ENTRY (entry), image_comment);
  1629.   gtk_signal_connect (GTK_OBJECT (entry), "changed",
  1630.                       GTK_SIGNAL_FUNC (comment_entry_callback),
  1631.                       NULL);
  1632.  
  1633.   gtk_widget_show (frame);
  1634.  
  1635.   gtk_widget_show (vbox);
  1636.   gtk_widget_show (dlg);
  1637.  
  1638.   gtk_main ();
  1639.   gdk_flush ();
  1640.  
  1641.   return tsint.run;
  1642. }
  1643.  
  1644. static void
  1645. save_ok_callback (GtkWidget *widget,
  1646.           gpointer   data)
  1647. {
  1648.   tsint.run = TRUE;
  1649.   gtk_widget_destroy (GTK_WIDGET (data));
  1650. }
  1651.  
  1652. static void
  1653. comment_entry_callback (GtkWidget *widget,
  1654.             gpointer   data)
  1655. {
  1656.   gint len;
  1657.   gchar *text;
  1658.  
  1659.   text = gtk_entry_get_text (GTK_ENTRY (widget));
  1660.   len = strlen (text);
  1661.  
  1662.   /* Temporary kludge for overlength strings - just return */
  1663.   if (len > 240)
  1664.     {
  1665.       g_message ("TIFF save: Your comment string is too long.\n");
  1666.       return;
  1667.     }
  1668.  
  1669.   g_free (image_comment);
  1670.   image_comment = g_strdup (text);
  1671.  
  1672.   /* g_print ("COMMENT: %s\n", image_comment); */
  1673. }
  1674.