1
0
mirror of synced 2026-04-07 22:20:51 +00:00

more JPEG support.

This commit is contained in:
Eric Smith
2003-03-19 15:39:55 +00:00
parent 01a019cccf
commit 0a019217f0
4 changed files with 187 additions and 82 deletions

View File

@@ -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);
}

View File

@@ -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
View File

@@ -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);
}

View File

@@ -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