tumble_jpeg.c

Mon, 18 Aug 2003 09:59:41 +0000

author
eric
date
Mon, 18 Aug 2003 09:59:41 +0000
changeset 159
2af017feadca
parent 151
83a99cc69861
permissions
-rw-r--r--

added big-endian support

     1 /*
     2  * tumble: build a PDF file from image files
     3  *
     4  * $Id: tumble_jpeg.c,v 1.4 2003/03/20 06:55:27 eric Exp $
     5  * Copyright 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 <strings.h>  /* strcasecmp() is a BSDism */
    28 #include <jpeglib.h>
    31 #include "semantics.h"
    32 #include "tumble.h"
    33 #include "bitblt.h"
    34 #include "pdf.h"
    35 #include "tumble_input.h"
    38 static FILE *jpeg_f;
    40 static struct jpeg_decompress_struct cinfo;
    41 static struct jpeg_error_mgr jerr;
    44 static bool match_jpeg_suffix (char *suffix)
    45 {
    46   return ((strcasecmp (suffix, ".jpg") == 0) ||
    47 	  (strcasecmp (suffix, ".jpeg") == 0));
    48 }
    50 static bool close_jpeg_input_file (void)
    51 {
    52   return (1);
    53 }
    56 static bool open_jpeg_input_file (FILE *f, char *name)
    57 {
    58   uint8_t buf [2];
    59   size_t l;
    61   l = fread (& buf [0], 1, sizeof (buf), f);
    62   if (l != sizeof (buf))
    63     return (0);
    65   rewind (f);
    67   if ((buf [0] != 0xff) || (buf [1] != 0xd8))
    68     return (0);
    70   cinfo.err = jpeg_std_error (& jerr);
    71   jpeg_create_decompress (& cinfo);
    73   jpeg_stdio_src (& cinfo, f);
    75   jpeg_read_header (& cinfo, TRUE);
    77   rewind (f);
    79   jpeg_f = f;
    81   return (1);
    82 }
    85 static bool last_jpeg_input_page (void)
    86 {
    87   return (1);
    88 }
    91 static bool get_jpeg_image_info (int image,
    92 				 input_attributes_t input_attributes,
    93 				 image_info_t *image_info)
    94 {
    95   double unit;
    97 #ifdef DEBUG_JPEG
    98   printf ("color space: %d\n", cinfo.jpeg_color_space);
    99   printf ("components: %d\n", cinfo.num_components);
   100   printf ("density unit: %d\n", cinfo.density_unit);
   101   printf ("x density: %d\n", cinfo.X_density);
   102   printf ("y density: %d\n", cinfo.Y_density);
   103   printf ("width: %d\n", cinfo.image_width);
   104   printf ("height: %d\n", cinfo.image_height);
   105 #endif
   107   switch (cinfo.jpeg_color_space)
   108     {
   109     case JCS_GRAYSCALE:
   110       if (cinfo.num_components != 1)
   111 	{
   112 	  fprintf (stderr, "JPEG grayscale image has %d components, should have 1\n",
   113 		   cinfo.num_components);
   114 	  return (0);
   115 	}
   116       image_info->color = 0;
   117       break;
   118     case JCS_RGB:
   119     case JCS_YCbCr:
   120       if (cinfo.num_components != 3)
   121 	{
   122 	  fprintf (stderr, "JPEG RGB or YCbCr image has %d components, should have 3\n",
   123 		   cinfo.num_components);
   124 	  return (0);
   125 	}
   126       image_info->color = 1;
   127       break;
   128     default:
   129       fprintf (stderr, "JPEG color space %d not supported\n", cinfo.jpeg_color_space);
   130       return (0);
   131     }
   132   image_info->width_samples = cinfo.image_width;
   133   image_info->height_samples = cinfo.image_height;
   135   if (cinfo.saw_JFIF_marker & cinfo.density_unit)
   136     {
   137       switch (cinfo.density_unit)
   138 	{
   139 	case 1:  /* samples per inch */
   140 	  unit = 1.0;
   141 	  break;
   142 	case 2:  /* samples per cm */
   143 	  unit = 2.54;
   144 	  break;
   145 	default:
   146 	  fprintf (stderr, "JFIF density unit %d not supported\n", cinfo.density_unit);
   147 	  return (0);
   148 	}
   149       image_info->width_points = ((image_info->width_samples * POINTS_PER_INCH) /
   150 				  (cinfo.X_density * unit));
   151       image_info->height_points = ((image_info->height_samples * POINTS_PER_INCH) /
   152 				   (cinfo.Y_density * unit));
   153     }
   154   else
   155     {
   156       /* assume 300 DPI - not great, but what else can we do? */
   157       image_info->width_points = (image_info->width_samples * POINTS_PER_INCH) / 300.0;
   158       image_info->height_points = (image_info->height_samples * POINTS_PER_INCH) / 300.0;
   159     }
   161   return (1);
   162 }
   165 static bool process_jpeg_image (int image,  /* range 1 .. n */
   166 				input_attributes_t input_attributes,
   167 				image_info_t *image_info,
   168 				pdf_page_handle page)
   169 {
   170   pdf_write_jpeg_image (page,
   171 			0, 0,  /* x, y */
   172 			image_info->width_points,
   173 			image_info->height_points,
   174 			image_info->color,
   175 			image_info->width_samples,
   176 			image_info->height_samples,
   177 			jpeg_f);
   179   return (1);
   180 }
   183 input_handler_t jpeg_handler =
   184   {
   185     match_jpeg_suffix,
   186     open_jpeg_input_file,
   187     close_jpeg_input_file,
   188     last_jpeg_input_page,
   189     get_jpeg_image_info,
   190     process_jpeg_image
   191   };
   194 void init_jpeg_handler (void)
   195 {
   196   install_input_handler (& jpeg_handler);
   197 }