tumble_tiff.c

Thu, 20 Mar 2003 14:55:28 +0000

author
eric
date
Thu, 20 Mar 2003 14:55:28 +0000
changeset 151
83a99cc69861
parent 148
d4a6e303703a
child 152
e69798068425
permissions
-rw-r--r--

added match_suffix() to input handlers.

     1 /*
     2  * tumble: build a PDF file from image files
     3  *
     4  * $Id: tumble_tiff.c,v 1.4 2003/03/20 06:55:28 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 #define TIFF_REVERSE_BITS
    34 #include "semantics.h"
    35 #include "tumble.h"
    36 #include "bitblt.h"
    37 #include "pdf.h"
    38 #include "tumble_input.h"
    41 TIFF *tiff_in;
    44 #define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
    47 static bool match_tiff_suffix (char *suffix)
    48 {
    49   return ((strcasecmp (suffix, ".tif") == 0) ||
    50 	  (strcasecmp (suffix, ".tiff") == 0));
    51 }
    54 static bool close_tiff_input_file (void)
    55 {
    56   TIFFClose (tiff_in);
    57   return (1);
    58 }
    61 static bool open_tiff_input_file (FILE *f, char *name)
    62 {
    63   uint8_t buf [2];
    64   size_t l;
    66   l = fread (& buf [0], 1, sizeof (buf), f);
    67   if (l != sizeof (buf))
    68     return (0);
    70   rewind (f);
    72   if ((buf [0] != 0x49) || (buf [1] != 0x49))
    73     return (0);
    75   tiff_in = TIFFFdOpen (fileno (f), name, "r");
    76   if (! tiff_in)
    77     {
    78       fprintf (stderr, "can't open input file '%s'\n", name);
    79       return (0);
    80     }
    81   return (1);
    82 }
    85 static bool last_tiff_input_page (void)
    86 {
    87   return (TIFFLastDirectory (tiff_in));
    88 }
    91 static bool get_tiff_image_info (int image,
    92 				 input_attributes_t input_attributes,
    93 				 image_info_t *image_info)
    94 {
    95   uint32_t image_height, image_width;
    96   uint16_t samples_per_pixel;
    97   uint16_t bits_per_sample;
    98   uint16_t planar_config;
   100   uint16_t resolution_unit;
   101   float x_resolution, y_resolution;
   103   double dest_x_resolution, dest_y_resolution;
   105 #ifdef CHECK_DEPTH
   106   uint32_t image_depth;
   107 #endif
   109   if (! TIFFSetDirectory (tiff_in, image - 1))
   110     {
   111       fprintf (stderr, "can't find page %d of input file\n", image);
   112       return (0);
   113     }
   114   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
   115     {
   116       fprintf (stderr, "can't get image height\n");
   117       return (0);
   118     }
   119   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
   120     {
   121       fprintf (stderr, "can't get image width\n");
   122       return (0);
   123     }
   125   if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
   126     {
   127       fprintf (stderr, "can't get samples per pixel\n");
   128       return (0);
   129     }
   131 #ifdef CHECK_DEPTH
   132   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
   133     {
   134       fprintf (stderr, "can't get image depth\n");
   135       return (0);
   136     }
   137 #endif
   139   if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
   140     {
   141       fprintf (stderr, "can't get bits per sample\n");
   142       return (0);
   143     }
   145   if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
   146     planar_config = 1;
   148   if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
   149     resolution_unit = 2;
   150   if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
   151     x_resolution = 300;
   152   if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
   153     y_resolution = 300;
   155   if (samples_per_pixel != 1)
   156     {
   157       fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
   158       return (0);
   159     }
   161 #ifdef CHECK_DEPTH
   162   if (image_depth != 1)
   163     {
   164       fprintf (stderr, "image depth %u, must be 1\n", image_depth);
   165       return (0);
   166     }
   167 #endif
   169   if (bits_per_sample != 1)
   170     {
   171       fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
   172       return (0);
   173     }
   175   if (planar_config != 1)
   176     {
   177       fprintf (stderr, "planar config %u, must be 1\n", planar_config);
   178       return (0);
   179     }
   181   if (input_attributes.has_resolution)
   182     {
   183       x_resolution = input_attributes.x_resolution;
   184       y_resolution = input_attributes.y_resolution;
   185     }
   187   if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   188     {
   189       image_info->width_samples  = image_height;
   190       image_info->height_samples = image_width;
   191       dest_x_resolution = y_resolution;
   192       dest_y_resolution = x_resolution;
   193       SWAP (double, image_info->width_points, image_info->height_points);
   194     }
   195   else
   196     {
   197       image_info->width_samples = image_width;
   198       image_info->height_samples = image_height;
   199       dest_x_resolution = x_resolution;
   200       dest_y_resolution = y_resolution;
   201     }
   203   image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
   204   image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
   206   if ((image_info->height_points > PAGE_MAX_POINTS) || 
   207       (image_info->width_points > PAGE_MAX_POINTS))
   208     {
   209       fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
   210       return (0);
   211     }
   213   return (1);
   214 }
   217 /* frees original! */
   218 static Bitmap *resize_bitmap (Bitmap *src,
   219 			      double x_resolution,
   220 			      double y_resolution,
   221 			      input_attributes_t input_attributes)
   222 {
   223   Rect src_rect;
   224   Point dest_min;
   225   Bitmap *dest;
   227   int width_pixels = input_attributes.page_size.width * x_resolution;
   228   int height_pixels = input_attributes.page_size.height * y_resolution;
   230   src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
   231   src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
   232   src_rect.max.x = src_rect.min.x + width_pixels;
   233   src_rect.max.y = src_rect.min.y + height_pixels;
   235   dest_min.x = 0;
   236   dest_min.y = 0;
   238   dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
   239   free_bitmap (src);
   240   return (dest);
   241 }
   244 /* "in place" rotation */
   245 static void rotate_bitmap (Bitmap *src,
   246 			   input_attributes_t input_attributes)
   247 {
   248   switch (input_attributes.rotation)
   249     {
   250     case 0: break;
   251     case 90: rot_90 (src); break;
   252     case 180: rot_180 (src); break;
   253     case 270: rot_270 (src); break;
   254     default:
   255       fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
   256     }
   257 }
   260 static bool process_tiff_image (int image,  /* range 1 .. n */
   261 				input_attributes_t input_attributes,
   262 				image_info_t *image_info,
   263 				pdf_page_handle page)
   264 {
   265   bool result = 0;
   266   Rect rect;
   267   Bitmap *bitmap = NULL;
   269   int row;
   271   rect.min.x = 0;
   272   rect.min.y = 0;
   274   if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   275     {
   276       rect.max.x = image_info->height_samples;
   277       rect.max.y = image_info->width_samples;
   278     }
   279   else
   280     {
   281       rect.max.x = image_info->width_samples;
   282       rect.max.y = image_info->height_samples;
   283     }
   285   bitmap = create_bitmap (& rect);
   287   if (! bitmap)
   288     {
   289       fprintf (stderr, "can't allocate bitmap\n");
   290       fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
   291       goto fail;
   292     }
   294   for (row = 0; row < rect.max.y; row++)
   295     if (1 != TIFFReadScanline (tiff_in,
   296 			       bitmap->bits + row * bitmap->row_words,
   297 			       row,
   298 			       0))
   299       {
   300 	fprintf (stderr, "can't read TIFF scanline\n");
   301 	goto fail;
   302       }
   304 #ifdef TIFF_REVERSE_BITS
   305   reverse_bits ((uint8_t *) bitmap->bits,
   306 		rect.max.y * bitmap->row_words * sizeof (word_t));
   307 #endif /* TIFF_REVERSE_BITS */
   309 #if 0
   310   if (input_attributes.has_page_size)
   311     bitmap = resize_bitmap (bitmap,
   312 			    x_resolution,
   313 			    y_resolution,
   314 			    input_attributes);
   315 #endif
   317   rotate_bitmap (bitmap,
   318 		 input_attributes);
   320 #if 0
   321   pdf_write_text (page);
   322 #else
   323   pdf_write_g4_fax_image (page,
   324 			  0, 0,  /* x, y */
   325 			  image_info->width_points, image_info->height_points,
   326 			  bitmap,
   327 			  0, /* ImageMask */
   328 			  0, 0, 0,  /* r, g, b */
   329 			  0); /* BlackIs1 */
   330 #endif
   332   result = 1;
   334  fail:
   335   if (bitmap)
   336     free_bitmap (bitmap);
   337   return (result);
   338 }
   341 input_handler_t tiff_handler =
   342   {
   343     match_tiff_suffix,
   344     open_tiff_input_file,
   345     close_tiff_input_file,
   346     last_tiff_input_page,
   347     get_tiff_image_info,
   348     process_tiff_image
   349   };
   352 void init_tiff_handler (void)
   353 {
   354   install_input_handler (& tiff_handler);
   355 }