more JPEG support.
This commit is contained in:
51
pdf_jpeg.c
51
pdf_jpeg.c
@@ -2,7 +2,7 @@
|
||||
* tumble: build a PDF file from image files
|
||||
*
|
||||
* PDF routines
|
||||
* $Id: pdf_jpeg.c,v 1.2 2003/03/13 00:57:05 eric Exp $
|
||||
* $Id: pdf_jpeg.c,v 1.3 2003/03/19 07:39:55 eric Exp $
|
||||
* Copyright 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -40,9 +40,9 @@ struct pdf_jpeg_image
|
||||
{
|
||||
double width, height;
|
||||
double x, y;
|
||||
bool color; /* false for grayscale */
|
||||
uint32_t width_samples, height_samples;
|
||||
FILE *f;
|
||||
unsigned long Columns;
|
||||
unsigned long Rows;
|
||||
char XObject_name [4];
|
||||
};
|
||||
|
||||
@@ -69,14 +69,13 @@ static void pdf_write_jpeg_image_callback (pdf_file_handle pdf_file,
|
||||
void *app_data)
|
||||
{
|
||||
struct pdf_jpeg_image *image = app_data;
|
||||
FILE *f;
|
||||
int rlen, wlen;
|
||||
uint8_t *wp;
|
||||
uint8_t buffer [8192];
|
||||
|
||||
while (! feof (image->f))
|
||||
{
|
||||
rlen = fread (& buffer [0], 1, JPEG_BUFFER_SIZE, f);
|
||||
rlen = fread (& buffer [0], 1, JPEG_BUFFER_SIZE, image->f);
|
||||
wp = & buffer [0];
|
||||
while (rlen)
|
||||
{
|
||||
@@ -88,9 +87,11 @@ static void pdf_write_jpeg_image_callback (pdf_file_handle pdf_file,
|
||||
rlen -= wlen;
|
||||
wp += wlen;
|
||||
}
|
||||
if (ferror (f))
|
||||
if (ferror (image->f))
|
||||
pdf_fatal ("error on input file\n");
|
||||
}
|
||||
|
||||
pdf_stream_printf (pdf_file, stream, "\r\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +106,6 @@ void pdf_write_jpeg_image (pdf_page_handle pdf_page,
|
||||
|
||||
struct pdf_obj *stream;
|
||||
struct pdf_obj *stream_dict;
|
||||
struct pdf_obj *decode_parms;
|
||||
|
||||
struct pdf_obj *content_stream;
|
||||
|
||||
@@ -117,10 +117,14 @@ void pdf_write_jpeg_image (pdf_page_handle pdf_page,
|
||||
image->y = y;
|
||||
|
||||
image->f = f;
|
||||
#if 0
|
||||
image->Columns = bitmap->rect.max.x - bitmap->rect.min.x;
|
||||
image->Rows = bitmap->rect.max.y - bitmap->rect.min.y;
|
||||
#endif
|
||||
|
||||
/* $$$ quick hack, should read these from file! */
|
||||
image->color = 1;
|
||||
image->width_samples = 71;
|
||||
image->height_samples = 88;
|
||||
|
||||
pdf_add_array_elem_unique (pdf_page->procset,
|
||||
pdf_new_name (image->color ? "ImageC" : "ImageB"));
|
||||
|
||||
stream_dict = pdf_new_obj (PT_DICTIONARY);
|
||||
|
||||
@@ -135,26 +139,14 @@ void pdf_write_jpeg_image (pdf_page_handle pdf_page,
|
||||
|
||||
pdf_set_dict_entry (stream_dict, "Type", pdf_new_name ("XObject"));
|
||||
pdf_set_dict_entry (stream_dict, "Subtype", pdf_new_name ("Image"));
|
||||
pdf_set_dict_entry (stream_dict, "Name", pdf_new_name (& image->XObject_name [0]));
|
||||
pdf_set_dict_entry (stream_dict, "Width", pdf_new_integer (image->Columns));
|
||||
pdf_set_dict_entry (stream_dict, "Height", pdf_new_integer (image->Rows));
|
||||
// Name is required in PDF 1.0 but obsoleted in later PDF versions
|
||||
// pdf_set_dict_entry (stream_dict, "Name", pdf_new_name (& image->XObject_name [0]));
|
||||
pdf_set_dict_entry (stream_dict, "Width", pdf_new_integer (image->width_samples));
|
||||
pdf_set_dict_entry (stream_dict, "Height", pdf_new_integer (image->height_samples));
|
||||
pdf_set_dict_entry (stream_dict, "ColorSpace", pdf_new_name (image->color ? "DeviceRGB" : "DeviceGray"));
|
||||
pdf_set_dict_entry (stream_dict, "BitsPerComponent", pdf_new_integer (8));
|
||||
|
||||
decode_parms = pdf_new_obj (PT_DICTIONARY);
|
||||
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"K",
|
||||
pdf_new_integer (-1));
|
||||
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"Columns",
|
||||
pdf_new_integer (image->Columns));
|
||||
|
||||
pdf_set_dict_entry (decode_parms,
|
||||
"Rows",
|
||||
pdf_new_integer (image->Rows));
|
||||
|
||||
pdf_stream_add_filter (stream, "DCTDecode", decode_parms);
|
||||
pdf_stream_add_filter (stream, "DCTDecode", NULL);
|
||||
|
||||
/* the following will write the stream, using our callback function to
|
||||
get the actual data */
|
||||
@@ -170,4 +162,3 @@ void pdf_write_jpeg_image (pdf_page_handle pdf_page,
|
||||
|
||||
pdf_write_ind_obj (pdf_page->pdf_file, content_stream);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* tumble: build a PDF file from image files
|
||||
*
|
||||
* Semantic routines for spec file parser
|
||||
* $Id: semantics.c,v 1.22 2003/03/16 05:58:25 eric Exp $
|
||||
* $Id: semantics.c,v 1.23 2003/03/19 07:39:55 eric Exp $
|
||||
* Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -667,10 +667,10 @@ bool process_controls (void)
|
||||
i = 0;
|
||||
input_fn = get_input_filename (image->input_context);
|
||||
if (verbose)
|
||||
fprintf (stderr, "opening TIFF file '%s'\n", input_fn);
|
||||
if (! open_tiff_input_file (input_fn))
|
||||
fprintf (stderr, "opening input file '%s'\n", input_fn);
|
||||
if (! open_input_file (input_fn))
|
||||
{
|
||||
fprintf (stderr, "error opening TIFF file '%s'\n", input_fn);
|
||||
fprintf (stderr, "error opening input file '%s'\n", input_fn);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
203
tumble.c
203
tumble.c
@@ -2,7 +2,7 @@
|
||||
* tumble: build a PDF file from image files
|
||||
*
|
||||
* Main program
|
||||
* $Id: tumble.c,v 1.36 2003/03/16 05:58:26 eric Exp $
|
||||
* $Id: tumble.c,v 1.37 2003/03/19 07:39:55 eric Exp $
|
||||
* Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -60,8 +60,18 @@ typedef struct output_file_t
|
||||
int verbose;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INPUT_FILE_TYPE_NONE,
|
||||
INPUT_FILE_TYPE_TIFF,
|
||||
INPUT_FILE_TYPE_JPEG
|
||||
} input_file_type_t;
|
||||
|
||||
|
||||
char *in_filename;
|
||||
TIFF *in;
|
||||
input_file_type_t in_type;
|
||||
FILE *in;
|
||||
TIFF *tiff_in;
|
||||
output_file_t *output_files;
|
||||
output_file_t *out;
|
||||
|
||||
@@ -92,6 +102,8 @@ void usage (void)
|
||||
|
||||
|
||||
/* generate fatal error message to stderr, doesn't return */
|
||||
void fatal (int ret, char *format, ...) __attribute__ ((noreturn));
|
||||
|
||||
void fatal (int ret, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -108,7 +120,7 @@ void fatal (int ret, char *format, ...)
|
||||
fprintf (stderr, "\n");
|
||||
if (ret == 1)
|
||||
usage ();
|
||||
close_tiff_input_file ();
|
||||
close_input_file ();
|
||||
close_pdf_output_files ();
|
||||
exit (ret);
|
||||
}
|
||||
@@ -116,24 +128,49 @@ void fatal (int ret, char *format, ...)
|
||||
|
||||
bool close_tiff_input_file (void)
|
||||
{
|
||||
if (in)
|
||||
{
|
||||
free (in_filename);
|
||||
TIFFClose (in);
|
||||
}
|
||||
in = NULL;
|
||||
in_filename = NULL;
|
||||
TIFFClose (tiff_in);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
bool open_tiff_input_file (char *name)
|
||||
bool open_tiff_input_file (FILE *f, char *name)
|
||||
{
|
||||
tiff_in = TIFFFdOpen (fileno (f), name, "r");
|
||||
if (! tiff_in)
|
||||
{
|
||||
fprintf (stderr, "can't open input file '%s'\n", name);
|
||||
free (in_filename);
|
||||
return (0);
|
||||
}
|
||||
in_type = INPUT_FILE_TYPE_TIFF;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
bool close_jpeg_input_file (void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
bool open_jpeg_input_file (FILE *f, char *name)
|
||||
{
|
||||
in_type = INPUT_FILE_TYPE_JPEG;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
bool open_input_file (char *name)
|
||||
{
|
||||
bool result;
|
||||
uint8_t buf [2];
|
||||
size_t l;
|
||||
|
||||
if (in)
|
||||
{
|
||||
if (strcmp (name, in_filename) == 0)
|
||||
return (1);
|
||||
close_tiff_input_file ();
|
||||
close_input_file ();
|
||||
}
|
||||
in_filename = strdup (name);
|
||||
if (! in_filename)
|
||||
@@ -141,17 +178,90 @@ bool open_tiff_input_file (char *name)
|
||||
fprintf (stderr, "can't strdup input filename '%s'\n", name);
|
||||
return (0);
|
||||
}
|
||||
in = TIFFOpen (name, "r");
|
||||
|
||||
in = fopen (name, "rb");
|
||||
if (! in)
|
||||
return (0);
|
||||
|
||||
l = fread (& buf [0], 1, sizeof (buf), in);
|
||||
if (l != sizeof (buf))
|
||||
return (0);
|
||||
|
||||
rewind (in);
|
||||
|
||||
if ((buf [0] == 0x49) && (buf [1] == 0x49))
|
||||
result = open_tiff_input_file (in, name);
|
||||
else if ((buf [0] == 0xff) && (buf [1] == 0xd8))
|
||||
result = open_jpeg_input_file (in, name);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "can't open input file '%s'\n", name);
|
||||
free (in_filename);
|
||||
return (0);
|
||||
fprintf (stderr, "unrecognized file header in file '%s'\n", name);
|
||||
result = 0;
|
||||
}
|
||||
if (! result)
|
||||
{
|
||||
if (in)
|
||||
fclose (in);
|
||||
in = NULL;
|
||||
in_type = INPUT_FILE_TYPE_NONE;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
bool close_input_file (void)
|
||||
{
|
||||
bool result;
|
||||
|
||||
switch (in_type)
|
||||
{
|
||||
case INPUT_FILE_TYPE_NONE:
|
||||
return (1);
|
||||
case INPUT_FILE_TYPE_TIFF:
|
||||
result = close_tiff_input_file ();
|
||||
break;
|
||||
case INPUT_FILE_TYPE_JPEG:
|
||||
result = close_jpeg_input_file ();
|
||||
break;
|
||||
default:
|
||||
fatal (3, "internal error: bad input file type\n");
|
||||
}
|
||||
|
||||
if (in_filename)
|
||||
free (in_filename);
|
||||
fclose (in);
|
||||
in = NULL;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
bool last_tiff_input_page (void)
|
||||
{
|
||||
return (TIFFLastDirectory (tiff_in));
|
||||
}
|
||||
|
||||
|
||||
bool last_jpeg_input_page (void)
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
bool last_input_page (void)
|
||||
{
|
||||
switch (in_type)
|
||||
{
|
||||
case INPUT_FILE_TYPE_TIFF:
|
||||
return (last_tiff_input_page ());
|
||||
case INPUT_FILE_TYPE_JPEG:
|
||||
return (last_jpeg_input_page ());
|
||||
default:
|
||||
fatal (3, "internal error: bad input file type\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool close_pdf_output_files (void)
|
||||
{
|
||||
output_file_t *o, *n;
|
||||
@@ -271,12 +381,6 @@ static void rotate_bitmap (Bitmap *src,
|
||||
#define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
|
||||
|
||||
|
||||
bool last_tiff_page (void)
|
||||
{
|
||||
return (TIFFLastDirectory (in));
|
||||
}
|
||||
|
||||
|
||||
static pdf_page_handle process_tiff_page (int image, /* range 1 .. n */
|
||||
input_attributes_t input_attributes)
|
||||
{
|
||||
@@ -304,50 +408,50 @@ static pdf_page_handle process_tiff_page (int image, /* range 1 .. n */
|
||||
|
||||
pdf_page_handle page = NULL;
|
||||
|
||||
if (! TIFFSetDirectory (in, image - 1))
|
||||
if (! TIFFSetDirectory (tiff_in, image - 1))
|
||||
{
|
||||
fprintf (stderr, "can't find page %d of input file\n", image);
|
||||
goto fail;
|
||||
}
|
||||
if (1 != TIFFGetField (in, TIFFTAG_IMAGELENGTH, & image_length))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGELENGTH, & image_length))
|
||||
{
|
||||
fprintf (stderr, "can't get image length\n");
|
||||
goto fail;
|
||||
}
|
||||
if (1 != TIFFGetField (in, TIFFTAG_IMAGEWIDTH, & image_width))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEWIDTH, & image_width))
|
||||
{
|
||||
fprintf (stderr, "can't get image width\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (1 != TIFFGetField (in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_SAMPLESPERPIXEL, & samples_per_pixel))
|
||||
{
|
||||
fprintf (stderr, "can't get samples per pixel\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CHECK_DEPTH
|
||||
if (1 != TIFFGetField (in, TIFFTAG_IMAGEDEPTH, & image_depth))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_IMAGEDEPTH, & image_depth))
|
||||
{
|
||||
fprintf (stderr, "can't get image depth\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (1 != TIFFGetField (in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_BITSPERSAMPLE, & bits_per_sample))
|
||||
{
|
||||
fprintf (stderr, "can't get bits per sample\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (1 != TIFFGetField (in, TIFFTAG_PLANARCONFIG, & planar_config))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_PLANARCONFIG, & planar_config))
|
||||
planar_config = 1;
|
||||
|
||||
if (1 != TIFFGetField (in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_RESOLUTIONUNIT, & resolution_unit))
|
||||
resolution_unit = 2;
|
||||
if (1 != TIFFGetField (in, TIFFTAG_XRESOLUTION, & x_resolution))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_XRESOLUTION, & x_resolution))
|
||||
x_resolution = 300;
|
||||
if (1 != TIFFGetField (in, TIFFTAG_YRESOLUTION, & y_resolution))
|
||||
if (1 != TIFFGetField (tiff_in, TIFFTAG_YRESOLUTION, & y_resolution))
|
||||
y_resolution = 300;
|
||||
|
||||
if (samples_per_pixel != 1)
|
||||
@@ -412,7 +516,7 @@ static pdf_page_handle process_tiff_page (int image, /* range 1 .. n */
|
||||
}
|
||||
|
||||
for (row = 0; row < image_length; row++)
|
||||
if (1 != TIFFReadScanline (in,
|
||||
if (1 != TIFFReadScanline (tiff_in,
|
||||
bitmap->bits + row * bitmap->row_words,
|
||||
row,
|
||||
0))
|
||||
@@ -472,27 +576,26 @@ static pdf_page_handle process_tiff_page (int image, /* range 1 .. n */
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
pdf_page_handle process_jpeg_page (int image, /* range 1 .. n */
|
||||
input_attributes_t input_attributes)
|
||||
{
|
||||
FILE *f;
|
||||
pdf_page_handle page;
|
||||
double width_points, height_points; /* really 1/72 inch units rather than
|
||||
points */
|
||||
|
||||
f = fopen (filename, "rb");
|
||||
if (! f)
|
||||
fatal ("error opening input file '%s'\n", filename);
|
||||
/* $$$ need to get these from somewhere else, hardcoded for now */
|
||||
width_points = 4 * 72.0;
|
||||
height_points = 4 * 72.0;
|
||||
|
||||
page = pdf_new_page (out->pdf, width_points, height_points);
|
||||
|
||||
pdf_write_jpeg_image (page,
|
||||
0, 0, /* x, y */
|
||||
width_points, height_points,
|
||||
f);
|
||||
in);
|
||||
|
||||
return (page);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool process_page (int image, /* range 1 .. n */
|
||||
@@ -502,7 +605,17 @@ bool process_page (int image, /* range 1 .. n */
|
||||
{
|
||||
pdf_page_handle page;
|
||||
|
||||
page = process_tiff_page (image, input_attributes);
|
||||
switch (in_type)
|
||||
{
|
||||
case INPUT_FILE_TYPE_TIFF:
|
||||
page = process_tiff_page (image, input_attributes);
|
||||
break;
|
||||
case INPUT_FILE_TYPE_JPEG:
|
||||
page = process_jpeg_page (image, input_attributes);
|
||||
break;
|
||||
default:
|
||||
fatal (3, "internal error: bad input file type\n");
|
||||
}
|
||||
|
||||
while (bookmarks)
|
||||
{
|
||||
@@ -608,7 +721,7 @@ void main_args (char *out_fn,
|
||||
fatal (3, "error opening output file \"%s\"\n", out_fn);
|
||||
for (i = 0; i < inf_count; i++)
|
||||
{
|
||||
if (! open_tiff_input_file (in_fn [i]))
|
||||
if (! open_input_file (in_fn [i]))
|
||||
fatal (3, "error opening input file \"%s\"\n", in_fn [i]);
|
||||
for (ip = 1;; ip++)
|
||||
{
|
||||
@@ -622,12 +735,12 @@ void main_args (char *out_fn,
|
||||
bookmark_fmt ? & bookmark : NULL,
|
||||
NULL))
|
||||
fatal (3, "error processing page %d of input file \"%s\"\n", ip, in_fn [i]);
|
||||
if (last_tiff_page ())
|
||||
if (last_input_page ())
|
||||
break;
|
||||
}
|
||||
if (verbose)
|
||||
fprintf (stderr, "processed %d pages of input file \"%s\"\n", ip, in_fn [i]);
|
||||
if (! close_tiff_input_file ())
|
||||
if (! close_input_file ())
|
||||
fatal (3, "error closing input file \"%s\"\n", in_fn [i]);
|
||||
}
|
||||
if (! close_pdf_output_files ())
|
||||
@@ -719,7 +832,7 @@ int main (int argc, char *argv[])
|
||||
else
|
||||
main_args (out_fn, inf_count, in_fn, bookmark_fmt);
|
||||
|
||||
close_tiff_input_file ();
|
||||
close_input_file ();
|
||||
close_pdf_output_files ();
|
||||
exit (0);
|
||||
}
|
||||
|
||||
7
tumble.h
7
tumble.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* tumble: build a PDF file from image files
|
||||
*
|
||||
* $Id: tumble.h,v 1.15 2003/03/14 00:57:40 eric Exp $
|
||||
* $Id: tumble.h,v 1.16 2003/03/19 07:39:55 eric Exp $
|
||||
* Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -39,8 +39,9 @@ typedef struct
|
||||
crop_t crop;
|
||||
} input_attributes_t;
|
||||
|
||||
bool open_tiff_input_file (char *name);
|
||||
bool close_tiff_input_file (void);
|
||||
|
||||
bool open_input_file (char *name);
|
||||
bool close_input_file (void);
|
||||
|
||||
|
||||
typedef struct
|
||||
|
||||
Reference in New Issue
Block a user