tumble_pbm.c

Mon, 14 Dec 2009 16:18:21 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 14 Dec 2009 16:18:21 +0000
changeset 172
2fae6df568f6
parent 162
fe3ef27156c4
permissions
-rw-r--r--

remove erroneous 0.33-philpem1 tag

eric@157 1 /*
eric@157 2 * tumble: build a PDF file from image files
eric@157 3 *
eric@157 4 * $Id: tumble_pbm.c,v 1.1 2003/04/10 00:47:30 eric Exp $
eric@157 5 * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
eric@157 6 *
eric@157 7 * This program is free software; you can redistribute it and/or modify
eric@157 8 * it under the terms of the GNU General Public License version 2 as
eric@157 9 * published by the Free Software Foundation. Note that permission is
eric@157 10 * not granted to redistribute this program under the terms of any
eric@157 11 * other version of the General Public License.
eric@157 12 *
eric@157 13 * This program is distributed in the hope that it will be useful,
eric@157 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
eric@157 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
eric@157 16 * GNU General Public License for more details.
eric@157 17 *
eric@157 18 * You should have received a copy of the GNU General Public License
eric@157 19 * along with this program; if not, write to the Free Software
eric@157 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
eric@157 21 */
eric@157 22
eric@157 23
eric@157 24 #include <stdint.h>
eric@157 25 #include <stdio.h>
eric@157 26 #include <stdlib.h>
eric@157 27 #include <strings.h> /* strcasecmp() is a BSDism */
eric@157 28
eric@157 29 #include <pbm.h>
eric@157 30 /*
eric@157 31 * pbm_readpbmrow_packed always uses big-endian bit ordering.
eric@157 32 * On little-endian processors (such as the x86), we want little-endian
eric@157 33 * bit order, so we must reverse the bits ourselves after we read in the
eric@157 34 * file.
eric@157 35 */
eric@157 36 #define PBM_REVERSE_BITS
eric@157 37
eric@162 38 #include <stdbool.h>
eric@162 39
eric@157 40
eric@157 41 #include "semantics.h"
eric@157 42 #include "tumble.h"
eric@157 43 #include "bitblt.h"
eric@157 44 #include "pdf.h"
eric@157 45 #include "tumble_input.h"
eric@157 46
eric@157 47
eric@157 48 typedef struct
eric@157 49 {
eric@157 50 FILE *f;
eric@157 51 int rows;
eric@157 52 int cols;
eric@157 53 int format;
eric@157 54 } pbm_info_t;
eric@157 55
eric@157 56 static pbm_info_t pbm;
eric@157 57
eric@157 58
eric@157 59 #define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
eric@157 60
eric@157 61
eric@157 62 static bool match_pbm_suffix (char *suffix)
eric@157 63 {
eric@157 64 return (strcasecmp (suffix, ".pbm") == 0);
eric@157 65 }
eric@157 66
eric@157 67
eric@157 68 static bool close_pbm_input_file (void)
eric@157 69 {
eric@157 70 pbm.f = NULL;
eric@157 71 return (1);
eric@157 72 }
eric@157 73
eric@157 74
eric@157 75 static bool open_pbm_input_file (FILE *f, char *name)
eric@157 76 {
eric@157 77 uint8_t buf [2];
eric@157 78 size_t l;
eric@157 79
eric@157 80 l = fread (& buf [0], 1, sizeof (buf), f);
eric@157 81 if (l != sizeof (buf))
eric@157 82 return (0);
eric@157 83
eric@157 84 rewind (f);
eric@157 85
eric@157 86 if (! (((buf [0] == 'P') && (buf [1] == '1')) ||
eric@157 87 ((buf [0] == 'P') && (buf [1] == '4'))))
eric@157 88 return (0);
eric@157 89
eric@157 90 pbm.f = f;
eric@157 91
eric@157 92 pbm_readpbminit (f, & pbm.cols, & pbm.rows, & pbm.format);
eric@157 93
eric@157 94 return (1);
eric@157 95 }
eric@157 96
eric@157 97
eric@157 98 static bool last_pbm_input_page (void)
eric@157 99 {
eric@157 100 /* only handle single-page PBM files for now */
eric@157 101 return (1);
eric@157 102 }
eric@157 103
eric@157 104
eric@157 105 static bool get_pbm_image_info (int image,
eric@157 106 input_attributes_t input_attributes,
eric@157 107 image_info_t *image_info)
eric@157 108 {
eric@157 109 double x_resolution = 300;
eric@157 110 double y_resolution = 300;
eric@157 111
eric@157 112 /* $$$ need to handle rotation! */
eric@157 113 if (input_attributes.has_resolution)
eric@157 114 {
eric@157 115 x_resolution = input_attributes.x_resolution;
eric@157 116 y_resolution = input_attributes.y_resolution;
eric@157 117 }
eric@157 118
eric@157 119 image_info->width_points = (pbm.cols / x_resolution) * POINTS_PER_INCH;
eric@157 120 image_info->height_points = (pbm.rows / y_resolution) * POINTS_PER_INCH;
eric@157 121
eric@157 122 if ((image_info->height_points > PAGE_MAX_POINTS) ||
eric@157 123 (image_info->width_points > PAGE_MAX_POINTS))
eric@157 124 {
eric@157 125 fprintf (stdout, "image too large (max %d inches on a side\n", PAGE_MAX_INCHES);
eric@157 126 return (0);
eric@157 127 }
eric@157 128
eric@157 129 return (1);
eric@157 130 }
eric@157 131
eric@157 132
eric@157 133 static bool process_pbm_image (int image, /* range 1 .. n */
eric@157 134 input_attributes_t input_attributes,
eric@157 135 image_info_t *image_info,
eric@157 136 pdf_page_handle page)
eric@157 137 {
eric@157 138 bool result = 0;
eric@157 139 Rect rect;
eric@157 140 Bitmap *bitmap = NULL;
eric@157 141
eric@157 142 int row;
eric@157 143
eric@157 144 rect.min.x = 0;
eric@157 145 rect.min.y = 0;
eric@157 146
eric@157 147 if ((input_attributes.rotation == 90) || (input_attributes.rotation == 270))
eric@157 148 {
eric@157 149 rect.max.x = image_info->height_samples;
eric@157 150 rect.max.y = image_info->width_samples;
eric@157 151 }
eric@157 152 else
eric@157 153 {
eric@157 154 rect.max.x = image_info->width_samples;
eric@157 155 rect.max.y = image_info->height_samples;
eric@157 156 }
eric@157 157
eric@157 158 bitmap = create_bitmap (& rect);
eric@157 159
eric@157 160 if (! bitmap)
eric@157 161 {
eric@157 162 fprintf (stderr, "can't allocate bitmap\n");
eric@157 163 fprintf (stderr, "width %d height %d\n", image_info->width_samples, image_info->height_samples);
eric@157 164 goto fail;
eric@157 165 }
eric@157 166
eric@157 167 for (row = 0; row < rect.max.y; row++)
eric@157 168 {
eric@157 169 pbm_readpbmrow_packed (pbm.f,
eric@157 170 (unsigned char *) (bitmap->bits + row * bitmap->row_words),
eric@157 171 pbm.cols,
eric@157 172 pbm.format);
eric@157 173 }
eric@157 174
eric@157 175 #ifdef PBM_REVERSE_BITS
eric@157 176 reverse_bits ((uint8_t *) bitmap->bits,
eric@157 177 rect.max.y * bitmap->row_words * sizeof (word_t));
eric@157 178 #endif /* PBM_REVERSE_BITS */
eric@157 179
eric@157 180 /* $$$ need to invert bits here */
eric@157 181
eric@157 182 #if 0
eric@157 183 if (input_attributes.has_page_size)
eric@157 184 bitmap = resize_bitmap (bitmap,
eric@157 185 x_resolution,
eric@157 186 y_resolution,
eric@157 187 input_attributes);
eric@157 188 #endif
eric@157 189
eric@157 190 #if 0
eric@157 191 rotate_bitmap (bitmap,
eric@157 192 input_attributes);
eric@157 193 #endif
eric@157 194
eric@157 195 pdf_write_g4_fax_image (page,
eric@157 196 0, 0, /* x, y */
eric@157 197 image_info->width_points, image_info->height_points,
eric@157 198 bitmap,
eric@157 199 0, /* ImageMask */
eric@157 200 0, 0, 0, /* r, g, b */
eric@157 201 0); /* BlackIs1 */
eric@157 202
eric@157 203 result = 1;
eric@157 204
eric@157 205 fail:
eric@157 206 if (bitmap)
eric@157 207 free_bitmap (bitmap);
eric@157 208 return (result);
eric@157 209 }
eric@157 210
eric@157 211
eric@157 212 input_handler_t pbm_handler =
eric@157 213 {
eric@157 214 match_pbm_suffix,
eric@157 215 open_pbm_input_file,
eric@157 216 close_pbm_input_file,
eric@157 217 last_pbm_input_page,
eric@157 218 get_pbm_image_info,
eric@157 219 process_pbm_image
eric@157 220 };
eric@157 221
eric@157 222
eric@157 223 void init_pbm_handler (void)
eric@157 224 {
eric@157 225 /* why should we let libpbm look at the real args? */
eric@157 226 int fake_argc = 1;
eric@157 227 char *fake_argv [] = { "tumble" };
eric@157 228
eric@157 229 pbm_init (& fake_argc, fake_argv);
eric@157 230 install_input_handler (& pbm_handler);
eric@157 231 }