tumble_tiff.c

Thu, 20 Mar 2003 06:54:08 +0000

author
eric
date
Thu, 20 Mar 2003 06:54:08 +0000
changeset 141
752599b50ff3
child 142
cfa664f3129c
permissions
-rw-r--r--

more JPEG support. added input file handler API.

     1 /*
     2  * tumble: build a PDF file from image files
     3  *
     4  * $Id: tumble_tiff.c,v 1.1 2003/03/19 22:54:08 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 <string.h>
    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 bool close_tiff_input_file (void)
    48 {
    49   TIFFClose (tiff_in);
    50   return (1);
    51 }
    54 bool open_tiff_input_file (FILE *f, char *name)
    55 {
    56   uint8_t buf [2];
    57   size_t l;
    59   l = fread (& buf [0], 1, sizeof (buf), f);
    60   if (l != sizeof (buf))
    61     return (0);
    63   rewind (f);
    65   if ((buf [0] != 0x49) || (buf [1] != 0x49))
    66     return (0);
    68   /* $$$ should we dup the file descriptor here, so that later closing f
    69      won't cause problems? */
    70   tiff_in = TIFFFdOpen (fileno (f), name, "r");
    71   if (! tiff_in)
    72     {
    73       fprintf (stderr, "can't open input file '%s'\n", name);
    74       return (0);
    75     }
    76   return (1);
    77 }
    80 bool last_tiff_input_page (void)
    81 {
    82   return (TIFFLastDirectory (tiff_in));
    83 }
    86 bool get_tiff_image_info (int image,
    87 			  input_attributes_t input_attributes,
    88 			  image_info_t *image_info)
    89 {
    90   uint32_t image_height, image_width;
    91   uint16_t samples_per_pixel;
    92   uint16_t bits_per_sample;
    93   uint16_t planar_config;
    95   uint16_t resolution_unit;
    96   float x_resolution, y_resolution;
    98   double dest_x_resolution, dest_y_resolution;
   100 #ifdef CHECK_DEPTH
   101   uint32_t image_depth;
   102 #endif
   104   if (! TIFFSetDirectory (tiff_in, image - 1))
   105     {
   106       fprintf (stderr, "can't find page %d of input file\n", image);
   107       return (0);
   108     }
   109   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_height))
   110     {
   111       fprintf (stderr, "can't get image height\n");
   112       return (0);
   113     }
   114   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
   115     {
   116       fprintf (stderr, "can't get image width\n");
   117       return (0);
   118     }
   120   if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
   121     {
   122       fprintf (stderr, "can't get samples per pixel\n");
   123       return (0);
   124     }
   126 #ifdef CHECK_DEPTH
   127   if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
   128     {
   129       fprintf (stderr, "can't get image depth\n");
   130       return (0);
   131     }
   132 #endif
   134   if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
   135     {
   136       fprintf (stderr, "can't get bits per sample\n");
   137       return (0);
   138     }
   140   if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
   141     planar_config = 1;
   143   if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
   144     resolution_unit = 2;
   145   if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
   146     x_resolution = 300;
   147   if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
   148     y_resolution = 300;
   150   if (samples_per_pixel != 1)
   151     {
   152       fprintf (stderr, "samples per pixel %u, must be 1\n", samples_per_pixel);
   153       return (0);
   154     }
   156 #ifdef CHECK_DEPTH
   157   if (image_depth != 1)
   158     {
   159       fprintf (stderr, "image depth %u, must be 1\n", image_depth);
   160       return (0);
   161     }
   162 #endif
   164   if (bits_per_sample != 1)
   165     {
   166       fprintf (stderr, "bits per sample %u, must be 1\n", bits_per_sample);
   167       return (0);
   168     }
   170   if (planar_config != 1)
   171     {
   172       fprintf (stderr, "planar config %u, must be 1\n", planar_config);
   173       return (0);
   174     }
   176   if (input_attributes.has_resolution)
   177     {
   178       x_resolution = input_attributes.x_resolution;
   179       y_resolution = input_attributes.y_resolution;
   180     }
   182   if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   183     {
   184       image_info->width_samples  = image_height;
   185       image_info->height_samples = image_width;
   186       dest_x_resolution = y_resolution;
   187       dest_y_resolution = x_resolution;
   188       SWAP (double, image_info->width_points, image_info->height_points);
   189     }
   190   else
   191     {
   192       image_info->width_samples = image_width;
   193       image_info->height_samples = image_height;
   194       dest_x_resolution = x_resolution;
   195       dest_y_resolution = y_resolution;
   196     }
   198   image_info->width_points = (image_info->width_samples / dest_x_resolution) * POINTS_PER_INCH;
   199   image_info->height_points = (image_info->height_samples / dest_y_resolution) * POINTS_PER_INCH;
   201   if ((image_info->height_points > PAGE_MAX_POINTS) || 
   202       (image_info->width_points > PAGE_MAX_POINTS))
   203     {
   204       fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
   205       return (0);
   206     }
   208   return (1);
   209 }
   212 /* frees original! */
   213 static Bitmap *resize_bitmap (Bitmap *src,
   214 			      double x_resolution,
   215 			      double y_resolution,
   216 			      input_attributes_t input_attributes)
   217 {
   218   Rect src_rect;
   219   Point dest_min;
   220   Bitmap *dest;
   222   int width_pixels = input_attributes.page_size.width * x_resolution;
   223   int height_pixels = input_attributes.page_size.height * y_resolution;
   225   src_rect.min.x = (rect_width (& src->rect) - width_pixels) / 2;
   226   src_rect.min.y = (rect_height (& src->rect) - height_pixels) / 2;
   227   src_rect.max.x = src_rect.min.x + width_pixels;
   228   src_rect.max.y = src_rect.min.y + height_pixels;
   230   dest_min.x = 0;
   231   dest_min.y = 0;
   233   dest = bitblt (src, & src_rect, NULL, & dest_min, TF_SRC, 0);
   234   free_bitmap (src);
   235   return (dest);
   236 }
   239 /* "in place" rotation */
   240 static void rotate_bitmap (Bitmap *src,
   241 			   input_attributes_t input_attributes)
   242 {
   243   switch (input_attributes.rotation)
   244     {
   245     case 0: break;
   246     case 90: rot_90 (src); break;
   247     case 180: rot_180 (src); break;
   248     case 270: rot_270 (src); break;
   249     default:
   250       fprintf (stderr, "rotation must be 0, 90, 180, or 270\n");
   251     }
   252 }
   255 bool process_tiff_image (int image,  /* range 1 .. n */
   256 			 input_attributes_t input_attributes,
   257 			 image_info_t *image_info,
   258 			 pdf_page_handle page)
   259 {
   260   Rect rect;
   261   Bitmap *bitmap = NULL;
   263   int row;
   265   rect.min.x = 0;
   266   rect.min.y = 0;
   268   if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
   269     {
   270       rect.max.x = image_info->height_samples;
   271       rect.max.y = image_info->width_samples;
   272     }
   273   else
   274     {
   275       rect.max.x = image_info->width_samples;
   276       rect.max.y = image_info->height_samples;
   277     }
   279   bitmap = create_bitmap (& rect);
   281   if (! bitmap)
   282     {
   283       fprintf (stderr, "can't allocate bitmap\n");
   284       fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
   285       goto fail;
   286     }
   288   for (row = 0; row < rect.max.y; row++)
   289     if (1 != TIFFReadScanline (tiff_in,
   290 			       bitmap->bits + row * bitmap->row_words,
   291 			       row,
   292 			       0))
   293       {
   294 	fprintf (stderr, "can't read TIFF scanline\n");
   295 	goto fail;
   296       }
   298 #ifdef TIFF_REVERSE_BITS
   299   reverse_bits ((uint8_t *) bitmap->bits,
   300 		rect.max.y * bitmap->row_words * sizeof (word_t));
   301 #endif /* TIFF_REVERSE_BITS */
   303 #if 0
   304   if (input_attributes.has_page_size)
   305     bitmap = resize_bitmap (bitmap,
   306 			    x_resolution,
   307 			    y_resolution,
   308 			    input_attributes);
   309 #endif
   311   rotate_bitmap (bitmap,
   312 		 input_attributes);
   314 #if 0
   315   pdf_write_text (page);
   316 #else
   317   pdf_write_g4_fax_image (page,
   318 			  0, 0,  /* x, y */
   319 			  image_info->width_points, image_info->height_points,
   320 			  bitmap,
   321 			  0, /* ImageMask */
   322 			  0, 0, 0,  /* r, g, b */
   323 			  0); /* BlackIs1 */
   324 #endif
   326   if (bitmap)
   327     free_bitmap (bitmap);
   328   return (page);
   330  fail:
   331   if (bitmap)
   332     free_bitmap (bitmap);
   334   return (NULL);
   335 }
   338 input_handler_t tiff_handler =
   339   {
   340     open_tiff_input_file,
   341     close_tiff_input_file,
   342     last_tiff_input_page,
   343     get_tiff_image_info,
   344     process_tiff_image
   345   };
   348 void init_tiff_handler (void)
   349 {
   350   install_input_handler (& tiff_handler);
   351 }