tumble_tiff.c

Thu, 10 Apr 2003 09:02:12 +0000

author
eric
date
Thu, 10 Apr 2003 09:02:12 +0000
changeset 158
e5452e27f518
parent 152
e69798068425
child 168
ad0b9a8990ac
permissions
-rw-r--r--

include tumble version in usage message.

     1 /*
     2  * tumble: build a PDF file from image files
     3  *
     4  * $Id: tumble_tiff.c,v 1.5 2003/03/20 07:22:23 eric Exp $
     5  * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
     6  *
     7  * This program is free software; you can redistribute it and/or modify
     8  * it under the terms of the GNU General Public License version 2 as
     9  * published by the Free Software Foundation.  Note that permission is
    10  * not granted to redistribute this program under the terms of any
    11  * other version of the General Public License.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU General Public License
    19  * along with this program; if not, write to the Free Software
    20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    21  */
    24 #include <stdbool.h>
    25 #include <stdint.h>
    26 #include <stdio.h>
    27 #include <stdlib.h>
    28 #include <strings.h>  /* strcasecmp() is a BSDism */
    30 #include <tiffio.h>
    31 /*
    32  * On the x86, libtiff defaults to bit-endian bit order for no good reason.
    33  * In theory, the '-L' (and maybe '-H') should give us little-endian bit
    34  * order, but it doesn't seem to work.  Thus we reverse the bits ourselves
    35  * after we read in the file.
    36  */
    37 #define TIFF_REVERSE_BITS
    40 #include "semantics.h"
    41 #include "tumble.h"
    42 #include "bitblt.h"
    43 #include "pdf.h"
    44 #include "tumble_input.h"
    47 TIFF *tiff_in;
    50 #define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
    53 static bool match_tiff_suffix (char *suffix)
    54 {
    55   return ((strcasecmp (suffix, ".tif") == 0) ||
    56 	  (strcasecmp (suffix, ".tiff") == 0));
    57 }
    60 static bool close_tiff_input_file (void)
    61 {
    62   TIFFClose (tiff_in);
    63   return (1);
    64 }
    67 static bool open_tiff_input_file (FILE *f, char *name)
    68 {
    69   uint8_t buf [2];
    70   size_t l;
    72   l = fread (& buf [0], 1, sizeof (buf), f);
    73   if (l != sizeof (buf))
    74     return (0);
    76   rewind (f);
    78   if (! (((buf [0] == 0x49) && (buf [1] == 0x49)) ||
    79 	 ((buf [0] == 0x4d) && (buf [1] == 0x4d))))
    80     return (0);
    82   tiff_in = TIFFFdOpen (fileno (f), name, "r");
    83   if (! tiff_in)
    84     {
    85       fprintf (stderr, "can't open input file '%s'\n", name);
    86       return (0);
    87     }
    88   return (1);
    89 }
    92 static bool last_tiff_input_page (void)
    93 {
    94   return (TIFFLastDirectory (tiff_in));
    95 }
    98 static bool get_tiff_image_info (int image,
    99 				 input_attributes_t input_attributes,
   100 				 image_info_t *image_info)
   101 {
   102   uint32_t image_height, image_width;
   103   uint16_t samples_per_pixel;
   104   uint16_t bits_per_sample;
   105   uint16_t planar_config;
   107   uint16_t resolution_unit;
   108   float x_resolution, y_resolution;
   110   double dest_x_resolution, dest_y_resolution;
   112 #ifdef CHECK_DEPTH
   113   uint32_t image_depth;
   114 #endif
   116   if (! TIFFSetDirectory (tiff_in, image - 1))
   117     {
   118       fprintf (stderr, "can't find page %d of input file\n", image);
   119       return (0);
   120     }
   121   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
   122     {
   123       fprintf (stderr, "can't get image height\n");
   124       return (0);
   125     }
   126   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
   127     {
   128       fprintf (stderr, "can't get image width\n");
   129       return (0);
   130     }
   132   if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
   133     {
   134       fprintf (stderr, "can't get samples per pixel\n");
   135       return (0);
   136     }
   138 #ifdef CHECK_DEPTH
   139   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
   140     {
   141       fprintf (stderr, "can't get image depth\n");
   142       return (0);
   143     }
   144 #endif
   146   if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
   147     {
   148       fprintf (stderr, "can't get bits per sample\n");
   149       return (0);
   150     }
   152   if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
   153     planar_config = 1;
   155   if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
   156     resolution_unit = 2;
   157   if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
   158     x_resolution = 300;
   159   if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
   160     y_resolution = 300;
   162   if (samples_per_pixel != 1)
   163     {
   164       fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
   165       return (0);
   166     }
   168 #ifdef CHECK_DEPTH
   169   if (image_depth != 1)
   170     {
   171       fprintf (stderr, "image depth %u, must be 1\n", image_depth);
   172       return (0);
   173     }
   174 #endif
   176   if (bits_per_sample != 1)
   177     {
   178       fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
   179       return (0);
   180     }
   182   if (planar_config != 1)
   183     {
   184       fprintf (stderr, "planar config %u, must be 1\n", planar_config);
   185       return (0);
   186     }
   188   if (input_attributes.has_resolution)
   189     {
   190       x_resolution = input_attributes.x_resolution;
   191       y_resolution = input_attributes.y_resolution;
   192     }
   194   if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   195     {
   196       image_info->width_samples  = image_height;
   197       image_info->height_samples = image_width;
   198       dest_x_resolution = y_resolution;
   199       dest_y_resolution = x_resolution;
   200       SWAP (double, image_info->width_points, image_info->height_points);
   201     }
   202   else
   203     {
   204       image_info->width_samples = image_width;
   205       image_info->height_samples = image_height;
   206       dest_x_resolution = x_resolution;
   207       dest_y_resolution = y_resolution;
   208     }
   210   image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
   211   image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
   213   if ((image_info->height_points > PAGE_MAX_POINTS) || 
   214       (image_info->width_points > PAGE_MAX_POINTS))
   215     {
   216       fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
   217       return (0);
   218     }
   220   return (1);
   221 }
   224 /* frees original! */
   225 static Bitmap *resize_bitmap (Bitmap *src,
   226 			      double x_resolution,
   227 			      double y_resolution,
   228 			      input_attributes_t input_attributes)
   229 {
   230   Rect src_rect;
   231   Point dest_min;
   232   Bitmap *dest;
   234   int width_pixels = input_attributes.page_size.width * x_resolution;
   235   int height_pixels = input_attributes.page_size.height * y_resolution;
   237   src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
   238   src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
   239   src_rect.max.x = src_rect.min.x + width_pixels;
   240   src_rect.max.y = src_rect.min.y + height_pixels;
   242   dest_min.x = 0;
   243   dest_min.y = 0;
   245   dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
   246   free_bitmap (src);
   247   return (dest);
   248 }
   251 /* "in place" rotation */
   252 static void rotate_bitmap (Bitmap *src,
   253 			   input_attributes_t input_attributes)
   254 {
   255   switch (input_attributes.rotation)
   256     {
   257     case 0: break;
   258     case 90: rot_90 (src); break;
   259     case 180: rot_180 (src); break;
   260     case 270: rot_270 (src); break;
   261     default:
   262       fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
   263     }
   264 }
   267 static bool process_tiff_image (int image,  /* range 1 .. n */
   268 				input_attributes_t input_attributes,
   269 				image_info_t *image_info,
   270 				pdf_page_handle page)
   271 {
   272   bool result = 0;
   273   Rect rect;
   274   Bitmap *bitmap = NULL;
   276   int row;
   278   rect.min.x = 0;
   279   rect.min.y = 0;
   281   if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   282     {
   283       rect.max.x = image_info->height_samples;
   284       rect.max.y = image_info->width_samples;
   285     }
   286   else
   287     {
   288       rect.max.x = image_info->width_samples;
   289       rect.max.y = image_info->height_samples;
   290     }
   292   bitmap = create_bitmap (& rect);
   294   if (! bitmap)
   295     {
   296       fprintf (stderr, "can't allocate bitmap\n");
   297       fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
   298       goto fail;
   299     }
   301   for (row = 0; row < rect.max.y; row++)
   302     if (1 != TIFFReadScanline (tiff_in,
   303 			       bitmap->bits + row * bitmap->row_words,
   304 			       row,
   305 			       0))
   306       {
   307 	fprintf (stderr, "can't read TIFF scanline\n");
   308 	goto fail;
   309       }
   311 #ifdef TIFF_REVERSE_BITS
   312   reverse_bits ((uint8_t *) bitmap->bits,
   313 		rect.max.y * bitmap->row_words * sizeof (word_t));
   314 #endif /* TIFF_REVERSE_BITS */
   316 #if 0
   317   if (input_attributes.has_page_size)
   318     bitmap = resize_bitmap (bitmap,
   319 			    x_resolution,
   320 			    y_resolution,
   321 			    input_attributes);
   322 #endif
   324   rotate_bitmap (bitmap,
   325 		 input_attributes);
   327 #if 0
   328   pdf_write_text (page);
   329 #else
   330   pdf_write_g4_fax_image (page,
   331 			  0, 0,  /* x, y */
   332 			  image_info->width_points, image_info->height_points,
   333 			  bitmap,
   334 			  0, /* ImageMask */
   335 			  0, 0, 0,  /* r, g, b */
   336 			  0); /* BlackIs1 */
   337 #endif
   339   result = 1;
   341  fail:
   342   if (bitmap)
   343     free_bitmap (bitmap);
   344   return (result);
   345 }
   348 input_handler_t tiff_handler =
   349   {
   350     match_tiff_suffix,
   351     open_tiff_input_file,
   352     close_tiff_input_file,
   353     last_tiff_input_page,
   354     get_tiff_image_info,
   355     process_tiff_image
   356   };
   359 void init_tiff_handler (void)
   360 {
   361   install_input_handler (& tiff_handler);
   362 }