]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/tools/tiffcrop.c
Don't use DDEExec registry key in wxMSW wxExecute() if it's empty.
[wxWidgets.git] / src / tiff / tools / tiffcrop.c
1
2 /* tiffcrop.c -- a port of tiffcp.c extended to include manipulations of
3 * the image data through additional options listed below
4 *
5 * Original code:
6 * Copyright (c) 1988-1997 Sam Leffler
7 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
8 * Additions (c) Richard Nolde 2006-2010
9 *
10 * Permission to use, copy, modify, distribute, and sell this software and
11 * its documentation for any purpose is hereby granted without fee, provided
12 * that (i) the above copyright notices and this permission notice appear in
13 * all copies of the software and related documentation, and (ii) the names of
14 * Sam Leffler and Silicon Graphics may not be used in any advertising or
15 * publicity relating to the software without the specific, prior written
16 * permission of Sam Leffler and Silicon Graphics.
17 *
18 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
20 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
21 *
22 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS OR ANY OTHER COPYRIGHT
23 * HOLDERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL
24 * DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
25 * DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND
26 * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
27 * OR PERFORMANCE OF THIS SOFTWARE.
28 *
29 * Some portions of the current code are derived from tiffcp, primarly in
30 * the areas of lowlevel reading and writing of TAGS, scanlines and tiles though
31 * some of the original functions have been extended to support arbitrary bit
32 * depths. These functions are presented at the top of this file.
33 *
34 * Add support for the options below to extract sections of image(s)
35 * and to modify the whole image or selected portions of each image by
36 * rotations, mirroring, and colorscale/colormap inversion of selected
37 * types of TIFF images when appropriate. Some color model dependent
38 * functions are restricted to bilevel or 8 bit per sample data.
39 * See the man page for the full explanations.
40 *
41 * New Options:
42 * -h Display the syntax guide.
43 * -v Report the version and last build date for tiffcrop and libtiff.
44 * -z x1,y1,x2,y2:x3,y3,x4,y4:..xN,yN,xN + 1, yN + 1
45 * Specify a series of coordinates to define rectangular
46 * regions by the top left and lower right corners.
47 * -e c|d|i|m|s export mode for images and selections from input images
48 * combined All images and selections are written to a single file (default)
49 * with multiple selections from one image combined into a single image
50 * divided All images and selections are written to a single file
51 * with each selection from one image written to a new image
52 * image Each input image is written to a new file (numeric filename sequence)
53 * with multiple selections from the image combined into one image
54 * multiple Each input image is written to a new file (numeric filename sequence)
55 * with each selection from the image written to a new image
56 * separated Individual selections from each image are written to separate files
57 * -U units [in, cm, px ] inches, centimeters or pixels
58 * -H # Set horizontal resolution of output images to #
59 * -V # Set vertical resolution of output images to #
60 * -J # Horizontal margin of output page to # expressed in current
61 * units when sectioning image into columns x rows
62 * using the -S cols:rows option.
63 * -K # Vertical margin of output page to # expressed in current
64 * units when sectioning image into columns x rows
65 * using the -S cols:rows option.
66 * -X # Horizontal dimension of region to extract expressed in current
67 * units
68 * -Y # Vertical dimension of region to extract expressed in current
69 * units
70 * -O orient Orientation for output image, portrait, landscape, auto
71 * -P page Page size for output image segments, eg letter, legal, tabloid,
72 * etc.
73 * -S cols:rows Divide the image into equal sized segments using cols across
74 * and rows down
75 * -E t|l|r|b Edge to use as origin
76 * -m #,#,#,# Margins from edges for selection: top, left, bottom, right
77 * (commas separated)
78 * -Z #:#,#:# Zones of the image designated as zone X of Y,
79 * eg 1:3 would be first of three equal portions measured
80 * from reference edge
81 * -N odd|even|#,#-#,#|last
82 * Select sequences and/or ranges of images within file
83 * to process. The words odd or even may be used to specify
84 * all odd or even numbered images the word last may be used
85 * in place of a number in the sequence to indicate the final
86 * image in the file without knowing how many images there are.
87 * -R # Rotate image or crop selection by 90,180,or 270 degrees
88 * clockwise
89 * -F h|v Flip (mirror) image or crop selection horizontally
90 * or vertically
91 * -I [black|white|data|both]
92 * Invert color space, eg dark to light for bilevel and grayscale images
93 * If argument is white or black, set the PHOTOMETRIC_INTERPRETATION
94 * tag to MinIsBlack or MinIsWhite without altering the image data
95 * If the argument is data or both, the image data are modified:
96 * both inverts the data and the PHOTOMETRIC_INTERPRETATION tag,
97 * data inverts the data but not the PHOTOMETRIC_INTERPRETATION tag
98 * -D input:<filename1>,output:<filename2>,format:<raw|txt>,level:N,debug:N
99 * Dump raw data for input and/or output images to individual files
100 * in raw (binary) format or text (ASCII) representing binary data
101 * as strings of 1s and 0s. The filename arguments are used as stems
102 * from which individual files are created for each image. Text format
103 * includes annotations for image parameters and scanline info. Level
104 * selects which functions dump data, with higher numbers selecting
105 * lower level, scanline level routines. Debug reports a limited set
106 * of messages to monitor progess without enabling dump logs.
107 */
108
109 static char tiffcrop_version_id[] = "2.4";
110 static char tiffcrop_rev_date[] = "12-13-2010";
111
112 #include "tif_config.h"
113 #include "tiffiop.h"
114
115 #include <stdio.h>
116 #include <stdlib.h>
117 #include <string.h>
118 #include <math.h>
119 #include <ctype.h>
120 #include <limits.h>
121 #include <sys/stat.h>
122 #include <assert.h>
123
124 #ifdef HAVE_UNISTD_H
125 # include <unistd.h>
126 #endif
127
128 #ifdef HAVE_STDINT_H
129 # include <stdint.h>
130 #endif
131
132 #ifndef HAVE_GETOPT
133 extern int getopt(int, char**, char*);
134 #endif
135
136 #ifdef NEED_LIBPORT
137 # include "libport.h"
138 #endif
139
140 #include "tiffio.h"
141
142 #if defined(VMS)
143 # define unlink delete
144 #endif
145
146 #ifndef PATH_MAX
147 #define PATH_MAX 1024
148 #endif
149
150 #ifndef streq
151 #define streq(a,b) (strcmp((a),(b)) == 0)
152 #endif
153 #define strneq(a,b,n) (strncmp((a),(b),(n)) == 0)
154
155 #define TRUE 1
156 #define FALSE 0
157
158 #ifndef TIFFhowmany
159 #define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
160 #define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
161 #endif
162
163 /*
164 * Definitions and data structures required to support cropping and image
165 * manipulations.
166 */
167
168 #define EDGE_TOP 1
169 #define EDGE_LEFT 2
170 #define EDGE_BOTTOM 3
171 #define EDGE_RIGHT 4
172 #define EDGE_CENTER 5
173
174 #define MIRROR_HORIZ 1
175 #define MIRROR_VERT 2
176 #define MIRROR_BOTH 3
177 #define ROTATECW_90 8
178 #define ROTATECW_180 16
179 #define ROTATECW_270 32
180 #define ROTATE_ANY ROTATECW_90 || ROTATECW_180 || ROTATECW_270
181
182 #define CROP_NONE 0
183 #define CROP_MARGINS 1
184 #define CROP_WIDTH 2
185 #define CROP_LENGTH 4
186 #define CROP_ZONES 8
187 #define CROP_REGIONS 16
188 #define CROP_ROTATE 32
189 #define CROP_MIRROR 64
190 #define CROP_INVERT 128
191
192 /* Modes for writing out images and selections */
193 #define ONE_FILE_COMPOSITE 0 /* One file, sections combined sections */
194 #define ONE_FILE_SEPARATED 1 /* One file, sections to new IFDs */
195 #define FILE_PER_IMAGE_COMPOSITE 2 /* One file per image, combined sections */
196 #define FILE_PER_IMAGE_SEPARATED 3 /* One file per input image */
197 #define FILE_PER_SELECTION 4 /* One file per selection */
198
199 #define COMPOSITE_IMAGES 0 /* Selections combined into one image */
200 #define SEPARATED_IMAGES 1 /* Selections saved to separate images */
201
202 #define STRIP 1
203 #define TILE 2
204
205 #define MAX_REGIONS 8 /* number of regions to extract from a single page */
206 #define MAX_OUTBUFFS 8 /* must match larger of zones or regions */
207 #define MAX_SECTIONS 32 /* number of sections per page to write to output */
208 #define MAX_IMAGES 2048 /* number of images in descrete list, not in the file */
209 #define MAX_SAMPLES 8 /* maximum number of samples per pixel supported */
210 #define MAX_BITS_PER_SAMPLE 64 /* maximum bit depth supported */
211 #define MAX_EXPORT_PAGES 999999 /* maximum number of export pages per file */
212
213 #define DUMP_NONE 0
214 #define DUMP_TEXT 1
215 #define DUMP_RAW 2
216
217 /* Offsets into buffer for margins and fixed width and length segments */
218 struct offset {
219 uint32 tmargin;
220 uint32 lmargin;
221 uint32 bmargin;
222 uint32 rmargin;
223 uint32 crop_width;
224 uint32 crop_length;
225 uint32 startx;
226 uint32 endx;
227 uint32 starty;
228 uint32 endy;
229 };
230
231 /* Description of a zone within the image. Position 1 of 3 zones would be
232 * the first third of the image. These are computed after margins and
233 * width/length requests are applied so that you can extract multiple
234 * zones from within a larger region for OCR or barcode recognition.
235 */
236
237 struct buffinfo {
238 uint32 size; /* size of this buffer */
239 unsigned char *buffer; /* address of the allocated buffer */
240 };
241
242 struct zone {
243 int position; /* ordinal of segment to be extracted */
244 int total; /* total equal sized divisions of crop area */
245 };
246
247 struct pageseg {
248 uint32 x1; /* index of left edge */
249 uint32 x2; /* index of right edge */
250 uint32 y1; /* index of top edge */
251 uint32 y2; /* index of bottom edge */
252 int position; /* ordinal of segment to be extracted */
253 int total; /* total equal sized divisions of crop area */
254 uint32 buffsize; /* size of buffer needed to hold the cropped zone */
255 };
256
257 struct coordpairs {
258 double X1; /* index of left edge in current units */
259 double X2; /* index of right edge in current units */
260 double Y1; /* index of top edge in current units */
261 double Y2; /* index of bottom edge in current units */
262 };
263
264 struct region {
265 uint32 x1; /* pixel offset of left edge */
266 uint32 x2; /* pixel offset of right edge */
267 uint32 y1; /* pixel offset of top edge */
268 uint32 y2; /* picel offset of bottom edge */
269 uint32 width; /* width in pixels */
270 uint32 length; /* length in pixels */
271 uint32 buffsize; /* size of buffer needed to hold the cropped region */
272 unsigned char *buffptr; /* address of start of the region */
273 };
274
275 /* Cropping parameters from command line and image data
276 * Note: This should be renamed to proc_opts and expanded to include all current globals
277 * if possible, but each function that accesses global variables will have to be redone.
278 */
279 struct crop_mask {
280 double width; /* Selection width for master crop region in requested units */
281 double length; /* Selection length for master crop region in requesed units */
282 double margins[4]; /* Top, left, bottom, right margins */
283 float xres; /* Horizontal resolution read from image*/
284 float yres; /* Vertical resolution read from image */
285 uint32 combined_width; /* Width of combined cropped zones */
286 uint32 combined_length; /* Length of combined cropped zones */
287 uint32 bufftotal; /* Size of buffer needed to hold all the cropped region */
288 uint16 img_mode; /* Composite or separate images created from zones or regions */
289 uint16 exp_mode; /* Export input images or selections to one or more files */
290 uint16 crop_mode; /* Crop options to be applied */
291 uint16 res_unit; /* Resolution unit for margins and selections */
292 uint16 edge_ref; /* Reference edge for sections extraction and combination */
293 uint16 rotation; /* Clockwise rotation of the extracted region or image */
294 uint16 mirror; /* Mirror extracted region or image horizontally or vertically */
295 uint16 invert; /* Invert the color map of image or region */
296 uint16 photometric; /* Status of photometric interpretation for inverted image */
297 uint16 selections; /* Number of regions or zones selected */
298 uint16 regions; /* Number of regions delimited by corner coordinates */
299 struct region regionlist[MAX_REGIONS]; /* Regions within page or master crop region */
300 uint16 zones; /* Number of zones delimited by Ordinal:Total requested */
301 struct zone zonelist[MAX_REGIONS]; /* Zones indices to define a region */
302 struct coordpairs corners[MAX_REGIONS]; /* Coordinates of upper left and lower right corner */
303 };
304
305 #define MAX_PAPERNAMES 49
306 #define MAX_PAPERNAME_LENGTH 15
307 #define DEFAULT_RESUNIT RESUNIT_INCH
308 #define DEFAULT_PAGE_HEIGHT 14.0
309 #define DEFAULT_PAGE_WIDTH 8.5
310 #define DEFAULT_RESOLUTION 300
311 #define DEFAULT_PAPER_SIZE "legal"
312
313 #define ORIENTATION_NONE 0
314 #define ORIENTATION_PORTRAIT 1
315 #define ORIENTATION_LANDSCAPE 2
316 #define ORIENTATION_SEASCAPE 4
317 #define ORIENTATION_AUTO 16
318
319 #define PAGE_MODE_NONE 0
320 #define PAGE_MODE_RESOLUTION 1
321 #define PAGE_MODE_PAPERSIZE 2
322 #define PAGE_MODE_MARGINS 4
323 #define PAGE_MODE_ROWSCOLS 8
324
325 #define INVERT_DATA_ONLY 10
326 #define INVERT_DATA_AND_TAG 11
327
328 struct paperdef {
329 char name[MAX_PAPERNAME_LENGTH];
330 double width;
331 double length;
332 double asratio;
333 };
334
335 /* European page sizes corrected from update sent by
336 * thomas . jarosch @ intra2net . com on 5/7/2010
337 * Paper Size Width Length Aspect Ratio */
338 struct paperdef PaperTable[MAX_PAPERNAMES] = {
339 {"default", 8.500, 14.000, 0.607},
340 {"pa4", 8.264, 11.000, 0.751},
341 {"letter", 8.500, 11.000, 0.773},
342 {"legal", 8.500, 14.000, 0.607},
343 {"half-letter", 8.500, 5.514, 1.542},
344 {"executive", 7.264, 10.528, 0.690},
345 {"tabloid", 11.000, 17.000, 0.647},
346 {"11x17", 11.000, 17.000, 0.647},
347 {"ledger", 17.000, 11.000, 1.545},
348 {"archa", 9.000, 12.000, 0.750},
349 {"archb", 12.000, 18.000, 0.667},
350 {"archc", 18.000, 24.000, 0.750},
351 {"archd", 24.000, 36.000, 0.667},
352 {"arche", 36.000, 48.000, 0.750},
353 {"csheet", 17.000, 22.000, 0.773},
354 {"dsheet", 22.000, 34.000, 0.647},
355 {"esheet", 34.000, 44.000, 0.773},
356 {"superb", 11.708, 17.042, 0.687},
357 {"commercial", 4.139, 9.528, 0.434},
358 {"monarch", 3.889, 7.528, 0.517},
359 {"envelope-dl", 4.333, 8.681, 0.499},
360 {"envelope-c5", 6.389, 9.028, 0.708},
361 {"europostcard", 4.139, 5.833, 0.710},
362 {"a0", 33.110, 46.811, 0.707},
363 {"a1", 23.386, 33.110, 0.706},
364 {"a2", 16.535, 23.386, 0.707},
365 {"a3", 11.693, 16.535, 0.707},
366 {"a4", 8.268, 11.693, 0.707},
367 {"a5", 5.827, 8.268, 0.705},
368 {"a6", 4.134, 5.827, 0.709},
369 {"a7", 2.913, 4.134, 0.705},
370 {"a8", 2.047, 2.913, 0.703},
371 {"a9", 1.457, 2.047, 0.712},
372 {"a10", 1.024, 1.457, 0.703},
373 {"b0", 39.370, 55.669, 0.707},
374 {"b1", 27.835, 39.370, 0.707},
375 {"b2", 19.685, 27.835, 0.707},
376 {"b3", 13.898, 19.685, 0.706},
377 {"b4", 9.843, 13.898, 0.708},
378 {"b5", 6.929, 9.843, 0.704},
379 {"b6", 4.921, 6.929, 0.710},
380 {"c0", 36.102, 51.063, 0.707},
381 {"c1", 25.512, 36.102, 0.707},
382 {"c2", 18.031, 25.512, 0.707},
383 {"c3", 12.756, 18.031, 0.707},
384 {"c4", 9.016, 12.756, 0.707},
385 {"c5", 6.378, 9.016, 0.707},
386 {"c6", 4.488, 6.378, 0.704},
387 {"", 0.000, 0.000, 1.000}
388 };
389
390 /* Structure to define input image parameters */
391 struct image_data {
392 float xres;
393 float yres;
394 uint32 width;
395 uint32 length;
396 uint16 res_unit;
397 uint16 bps;
398 uint16 spp;
399 uint16 planar;
400 uint16 photometric;
401 uint16 orientation;
402 uint16 compression;
403 uint16 adjustments;
404 };
405
406 /* Structure to define the output image modifiers */
407 struct pagedef {
408 char name[16];
409 double width; /* width in pixels */
410 double length; /* length in pixels */
411 double hmargin; /* margins to subtract from width of sections */
412 double vmargin; /* margins to subtract from height of sections */
413 double hres; /* horizontal resolution for output */
414 double vres; /* vertical resolution for output */
415 uint32 mode; /* bitmask of modifiers to page format */
416 uint16 res_unit; /* resolution unit for output image */
417 unsigned int rows; /* number of section rows */
418 unsigned int cols; /* number of section cols */
419 unsigned int orient; /* portrait, landscape, seascape, auto */
420 };
421
422 struct dump_opts {
423 int debug;
424 int format;
425 int level;
426 char mode[4];
427 char infilename[PATH_MAX + 1];
428 char outfilename[PATH_MAX + 1];
429 FILE *infile;
430 FILE *outfile;
431 };
432
433 /* globals */
434 static int outtiled = -1;
435 static uint32 tilewidth = 0;
436 static uint32 tilelength = 0;
437
438 static uint16 config = 0;
439 static uint16 compression = 0;
440 static uint16 predictor = 0;
441 static uint16 fillorder = 0;
442 static uint32 rowsperstrip = 0;
443 static uint32 g3opts = 0;
444 static int ignore = FALSE; /* if true, ignore read errors */
445 static uint32 defg3opts = (uint32) -1;
446 static int quality = 100; /* JPEG quality */
447 /* static int jpegcolormode = -1; was JPEGCOLORMODE_RGB; */
448 static int jpegcolormode = JPEGCOLORMODE_RGB;
449 static uint16 defcompression = (uint16) -1;
450 static uint16 defpredictor = (uint16) -1;
451 static int pageNum = 0;
452 static int little_endian = 1;
453
454 /* Functions adapted from tiffcp with additions or significant modifications */
455 static int readContigStripsIntoBuffer (TIFF*, uint8*);
456 static int readSeparateStripsIntoBuffer (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
457 static int readContigTilesIntoBuffer (TIFF*, uint8*, uint32, uint32, uint32, uint32, tsample_t, uint16);
458 static int readSeparateTilesIntoBuffer (TIFF*, uint8*, uint32, uint32, uint32, uint32, tsample_t, uint16);
459 static int writeBufferToContigStrips (TIFF*, uint8*, uint32);
460 static int writeBufferToContigTiles (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
461 static int writeBufferToSeparateStrips (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
462 static int writeBufferToSeparateTiles (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
463 static int extractContigSamplesToBuffer (uint8 *, uint8 *, uint32, uint32, tsample_t,
464 uint16, uint16, struct dump_opts *);
465 static int processCompressOptions(char*);
466 static void usage(void);
467
468 /* All other functions by Richard Nolde, not found in tiffcp */
469 static void initImageData (struct image_data *);
470 static void initCropMasks (struct crop_mask *);
471 static void initPageSetup (struct pagedef *, struct pageseg *, struct buffinfo []);
472 static void initDumpOptions(struct dump_opts *);
473
474 /* Command line and file naming functions */
475 void process_command_opts (int, char *[], char *, char *, uint32 *,
476 uint16 *, uint16 *, uint32 *, uint32 *, uint32 *,
477 struct crop_mask *, struct pagedef *,
478 struct dump_opts *,
479 unsigned int *, unsigned int *);
480 static int update_output_file (TIFF **, char *, int, char *, unsigned int *);
481
482
483 /* * High level functions for whole image manipulation */
484 static int get_page_geometry (char *, struct pagedef*);
485 static int computeInputPixelOffsets(struct crop_mask *, struct image_data *,
486 struct offset *);
487 static int computeOutputPixelOffsets (struct crop_mask *, struct image_data *,
488 struct pagedef *, struct pageseg *,
489 struct dump_opts *);
490 static int loadImage(TIFF *, struct image_data *, struct dump_opts *, unsigned char **);
491 static int correct_orientation(struct image_data *, unsigned char **);
492 static int getCropOffsets(struct image_data *, struct crop_mask *, struct dump_opts *);
493 static int processCropSelections(struct image_data *, struct crop_mask *,
494 unsigned char **, struct buffinfo []);
495 static int writeSelections(TIFF *, TIFF **, struct crop_mask *, struct image_data *,
496 struct dump_opts *, struct buffinfo [],
497 char *, char *, unsigned int*, unsigned int);
498
499 /* Section functions */
500 static int createImageSection(uint32, unsigned char **);
501 static int extractImageSection(struct image_data *, struct pageseg *,
502 unsigned char *, unsigned char *);
503 static int writeSingleSection(TIFF *, TIFF *, struct image_data *,
504 struct dump_opts *, uint32, uint32,
505 double, double, unsigned char *);
506 static int writeImageSections(TIFF *, TIFF *, struct image_data *,
507 struct pagedef *, struct pageseg *,
508 struct dump_opts *, unsigned char *,
509 unsigned char **);
510 /* Whole image functions */
511 static int createCroppedImage(struct image_data *, struct crop_mask *,
512 unsigned char **, unsigned char **);
513 static int writeCroppedImage(TIFF *, TIFF *, struct image_data *image,
514 struct dump_opts * dump,
515 uint32, uint32, unsigned char *, int, int);
516
517 /* Image manipulation functions */
518 static int rotateContigSamples8bits(uint16, uint16, uint16, uint32,
519 uint32, uint32, uint8 *, uint8 *);
520 static int rotateContigSamples16bits(uint16, uint16, uint16, uint32,
521 uint32, uint32, uint8 *, uint8 *);
522 static int rotateContigSamples24bits(uint16, uint16, uint16, uint32,
523 uint32, uint32, uint8 *, uint8 *);
524 static int rotateContigSamples32bits(uint16, uint16, uint16, uint32,
525 uint32, uint32, uint8 *, uint8 *);
526 static int rotateImage(uint16, struct image_data *, uint32 *, uint32 *,
527 unsigned char **);
528 static int mirrorImage(uint16, uint16, uint16, uint32, uint32,
529 unsigned char *);
530 static int invertImage(uint16, uint16, uint16, uint32, uint32,
531 unsigned char *);
532
533 /* Functions to reverse the sequence of samples in a scanline */
534 static int reverseSamples8bits (uint16, uint16, uint32, uint8 *, uint8 *);
535 static int reverseSamples16bits (uint16, uint16, uint32, uint8 *, uint8 *);
536 static int reverseSamples24bits (uint16, uint16, uint32, uint8 *, uint8 *);
537 static int reverseSamples32bits (uint16, uint16, uint32, uint8 *, uint8 *);
538 static int reverseSamplesBytes (uint16, uint16, uint32, uint8 *, uint8 *);
539
540 /* Functions for manipulating individual samples in an image */
541 static int extractSeparateRegion(struct image_data *, struct crop_mask *,
542 unsigned char *, unsigned char *, int);
543 static int extractCompositeRegions(struct image_data *, struct crop_mask *,
544 unsigned char *, unsigned char *);
545 static int extractContigSamples8bits (uint8 *, uint8 *, uint32,
546 tsample_t, uint16, uint16,
547 tsample_t, uint32, uint32);
548 static int extractContigSamples16bits (uint8 *, uint8 *, uint32,
549 tsample_t, uint16, uint16,
550 tsample_t, uint32, uint32);
551 static int extractContigSamples24bits (uint8 *, uint8 *, uint32,
552 tsample_t, uint16, uint16,
553 tsample_t, uint32, uint32);
554 static int extractContigSamples32bits (uint8 *, uint8 *, uint32,
555 tsample_t, uint16, uint16,
556 tsample_t, uint32, uint32);
557 static int extractContigSamplesBytes (uint8 *, uint8 *, uint32,
558 tsample_t, uint16, uint16,
559 tsample_t, uint32, uint32);
560 static int extractContigSamplesShifted8bits (uint8 *, uint8 *, uint32,
561 tsample_t, uint16, uint16,
562 tsample_t, uint32, uint32,
563 int);
564 static int extractContigSamplesShifted16bits (uint8 *, uint8 *, uint32,
565 tsample_t, uint16, uint16,
566 tsample_t, uint32, uint32,
567 int);
568 static int extractContigSamplesShifted24bits (uint8 *, uint8 *, uint32,
569 tsample_t, uint16, uint16,
570 tsample_t, uint32, uint32,
571 int);
572 static int extractContigSamplesShifted32bits (uint8 *, uint8 *, uint32,
573 tsample_t, uint16, uint16,
574 tsample_t, uint32, uint32,
575 int);
576 static int extractContigSamplesToTileBuffer(uint8 *, uint8 *, uint32, uint32,
577 uint32, uint32, tsample_t, uint16,
578 uint16, uint16, struct dump_opts *);
579
580 /* Functions to combine separate planes into interleaved planes */
581 static int combineSeparateSamples8bits (uint8 *[], uint8 *, uint32, uint32,
582 uint16, uint16, FILE *, int, int);
583 static int combineSeparateSamples16bits (uint8 *[], uint8 *, uint32, uint32,
584 uint16, uint16, FILE *, int, int);
585 static int combineSeparateSamples24bits (uint8 *[], uint8 *, uint32, uint32,
586 uint16, uint16, FILE *, int, int);
587 static int combineSeparateSamples32bits (uint8 *[], uint8 *, uint32, uint32,
588 uint16, uint16, FILE *, int, int);
589 static int combineSeparateSamplesBytes (unsigned char *[], unsigned char *,
590 uint32, uint32, tsample_t, uint16,
591 FILE *, int, int);
592
593 static int combineSeparateTileSamples8bits (uint8 *[], uint8 *, uint32, uint32,
594 uint32, uint32, uint16, uint16,
595 FILE *, int, int);
596 static int combineSeparateTileSamples16bits (uint8 *[], uint8 *, uint32, uint32,
597 uint32, uint32, uint16, uint16,
598 FILE *, int, int);
599 static int combineSeparateTileSamples24bits (uint8 *[], uint8 *, uint32, uint32,
600 uint32, uint32, uint16, uint16,
601 FILE *, int, int);
602 static int combineSeparateTileSamples32bits (uint8 *[], uint8 *, uint32, uint32,
603 uint32, uint32, uint16, uint16,
604 FILE *, int, int);
605 static int combineSeparateTileSamplesBytes (unsigned char *[], unsigned char *,
606 uint32, uint32, uint32, uint32,
607 tsample_t, uint16, FILE *, int, int);
608
609 /* Dump functions for debugging */
610 static void dump_info (FILE *, int, char *, char *, ...);
611 static int dump_data (FILE *, int, char *, unsigned char *, uint32);
612 static int dump_byte (FILE *, int, char *, unsigned char);
613 static int dump_short (FILE *, int, char *, uint16);
614 static int dump_long (FILE *, int, char *, uint32);
615 static int dump_wide (FILE *, int, char *, uint64);
616 static int dump_buffer (FILE *, int, uint32, uint32, uint32, unsigned char *);
617
618 /* End function declarations */
619 /* Functions derived in whole or in part from tiffcp */
620 /* The following functions are taken largely intact from tiffcp */
621
622 static char* usage_info[] = {
623 "usage: tiffcrop [options] source1 ... sourceN destination",
624 "where options are:",
625 " -h Print this syntax listing",
626 " -v Print tiffcrop version identifier and last revision date",
627 " ",
628 " -a Append to output instead of overwriting",
629 " -d offset Set initial directory offset, counting first image as one, not zero",
630 " -p contig Pack samples contiguously (e.g. RGBRGB...)",
631 " -p separate Store samples separately (e.g. RRR...GGG...BBB...)",
632 " -s Write output in strips",
633 " -t Write output in tiles",
634 " -i Ignore read errors",
635 " ",
636 " -r # Make each strip have no more than # rows",
637 " -w # Set output tile width (pixels)",
638 " -l # Set output tile length (pixels)",
639 " ",
640 " -f lsb2msb Force lsb-to-msb FillOrder for output",
641 " -f msb2lsb Force msb-to-lsb FillOrder for output",
642 "",
643 " -c lzw[:opts] Compress output with Lempel-Ziv & Welch encoding",
644 " -c zip[:opts] Compress output with deflate encoding",
645 " -c jpeg[:opts] Compress output with JPEG encoding",
646 " -c packbits Compress output with packbits encoding",
647 " -c g3[:opts] Compress output with CCITT Group 3 encoding",
648 " -c g4 Compress output with CCITT Group 4 encoding",
649 " -c none Use no compression algorithm on output",
650 " ",
651 "Group 3 options:",
652 " 1d Use default CCITT Group 3 1D-encoding",
653 " 2d Use optional CCITT Group 3 2D-encoding",
654 " fill Byte-align EOL codes",
655 "For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
656 " ",
657 "JPEG options:",
658 " # Set compression quality level (0-100, default 100)",
659 " raw Output color image as raw YCbCr",
660 " rgb Output color image as RGB",
661 "For example, -c jpeg:rgb:50 to get JPEG-encoded RGB data with 50% comp. quality",
662 " ",
663 "LZW and deflate options:",
664 " # Set predictor value",
665 "For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
666 " ",
667 "Page and selection options:",
668 " -N odd|even|#,#-#,#|last sequences and ranges of images within file to process",
669 " The words odd or even may be used to specify all odd or even numbered images.",
670 " The word last may be used in place of a number in the sequence to indicate.",
671 " The final image in the file without knowing how many images there are.",
672 " Numbers are counted from one even though TIFF IFDs are counted from zero.",
673 " ",
674 " -E t|l|r|b edge to use as origin for width and length of crop region",
675 " -U units [in, cm, px ] inches, centimeters or pixels",
676 " ",
677 " -m #,#,#,# margins from edges for selection: top, left, bottom, right separated by commas",
678 " -X # horizontal dimension of region to extract expressed in current units",
679 " -Y # vertical dimension of region to extract expressed in current units",
680 " -Z #:#,#:# zones of the image designated as position X of Y,",
681 " eg 1:3 would be first of three equal portions measured from reference edge",
682 " -z x1,y1,x2,y2:...:xN,yN,xN+1,yN+1",
683 " regions of the image designated by upper left and lower right coordinates",
684 "",
685 "Export grouping options:",
686 " -e c|d|i|m|s export mode for images and selections from input images.",
687 " When exporting a composite image from multiple zones or regions",
688 " (combined and image modes), the selections must have equal sizes",
689 " for the axis perpendicular to the edge specified with -E.",
690 " c|combined All images and selections are written to a single file (default).",
691 " with multiple selections from one image combined into a single image.",
692 " d|divided All images and selections are written to a single file",
693 " with each selection from one image written to a new image.",
694 " i|image Each input image is written to a new file (numeric filename sequence)",
695 " with multiple selections from the image combined into one image.",
696 " m|multiple Each input image is written to a new file (numeric filename sequence)",
697 " with each selection from the image written to a new image.",
698 " s|separated Individual selections from each image are written to separate files.",
699 "",
700 "Output options:",
701 " -H # Set horizontal resolution of output images to #",
702 " -V # Set vertical resolution of output images to #",
703 " -J # Set horizontal margin of output page to # expressed in current units",
704 " when sectioning image into columns x rows using the -S cols:rows option",
705 " -K # Set verticalal margin of output page to # expressed in current units",
706 " when sectioning image into columns x rows using the -S cols:rows option",
707 " ",
708 " -O orient orientation for output image, portrait, landscape, auto",
709 " -P page page size for output image segments, eg letter, legal, tabloid, etc",
710 " use #.#x#.# to specify a custom page size in the currently defined units",
711 " where #.# represents the width and length",
712 " -S cols:rows Divide the image into equal sized segments using cols across and rows down.",
713 " ",
714 " -F hor|vert|both",
715 " flip (mirror) image or region horizontally, vertically, or both",
716 " -R # [90,180,or 270] degrees clockwise rotation of image or extracted region",
717 " -I [black|white|data|both]",
718 " invert color space, eg dark to light for bilevel and grayscale images",
719 " If argument is white or black, set the PHOTOMETRIC_INTERPRETATION ",
720 " tag to MinIsBlack or MinIsWhite without altering the image data",
721 " If the argument is data or both, the image data are modified:",
722 " both inverts the data and the PHOTOMETRIC_INTERPRETATION tag,",
723 " data inverts the data but not the PHOTOMETRIC_INTERPRETATION tag",
724 " ",
725 "-D opt1:value1,opt2:value2,opt3:value3:opt4:value4",
726 " Debug/dump program progress and/or data to non-TIFF files.",
727 " Options include the following and must be joined as a comma",
728 " separate list. The use of this option is generally limited to",
729 " program debugging and development of future options.",
730 " ",
731 " debug:N Display limited program progress indicators where larger N",
732 " increase the level of detail. Note: Tiffcrop may be compiled with",
733 " -DDEVELMODE to enable additional very low level debug reporting.",
734 "",
735 " Format:txt|raw Format any logged data as ASCII text or raw binary ",
736 " values. ASCII text dumps include strings of ones and zeroes",
737 " representing the binary values in the image data plus identifying headers.",
738 " ",
739 " level:N Specify the level of detail presented in the dump files.",
740 " This can vary from dumps of the entire input or output image data to dumps",
741 " of data processed by specific functions. Current range of levels is 1 to 3.",
742 " ",
743 " input:full-path-to-directory/input-dumpname",
744 " ",
745 " output:full-path-to-directory/output-dumpnaem",
746 " ",
747 " When dump files are being written, each image will be written to a separate",
748 " file with the name built by adding a numeric sequence value to the dumpname",
749 " and an extension of .txt for ASCII dumps or .bin for binary dumps.",
750 " ",
751 " The four debug/dump options are independent, though it makes little sense to",
752 " specify a dump file without specifying a detail level.",
753 " ",
754 NULL
755 };
756
757 /* This function could be modified to pass starting sample offset
758 * and number of samples as args to select fewer than spp
759 * from input image. These would then be passed to individual
760 * extractContigSampleXX routines.
761 */
762 static int readContigTilesIntoBuffer (TIFF* in, uint8* buf,
763 uint32 imagelength,
764 uint32 imagewidth,
765 uint32 tw, uint32 tl,
766 tsample_t spp, uint16 bps)
767 {
768 int status = 1;
769 tsample_t sample = 0;
770 tsample_t count = spp;
771 uint32 row, col, trow;
772 uint32 nrow, ncol;
773 uint32 dst_rowsize, shift_width;
774 uint32 bytes_per_sample, bytes_per_pixel;
775 uint32 trailing_bits, prev_trailing_bits;
776 uint32 tile_rowsize = TIFFTileRowSize(in);
777 uint32 src_offset, dst_offset;
778 uint32 row_offset, col_offset;
779 uint8 *bufp = (uint8*) buf;
780 unsigned char *src = NULL;
781 unsigned char *dst = NULL;
782 tsize_t tbytes = 0, tile_buffsize = 0;
783 tsize_t tilesize = TIFFTileSize(in);
784 unsigned char *tilebuf = NULL;
785
786 bytes_per_sample = (bps + 7) / 8;
787 bytes_per_pixel = ((bps * spp) + 7) / 8;
788
789 if ((bps % 8) == 0)
790 shift_width = 0;
791 else
792 {
793 if (bytes_per_pixel < (bytes_per_sample + 1))
794 shift_width = bytes_per_pixel;
795 else
796 shift_width = bytes_per_sample + 1;
797 }
798
799 tile_buffsize = tilesize;
800
801 if (tilesize < (tsize_t)(tl * tile_rowsize))
802 {
803 #ifdef DEBUG2
804 TIFFError("readContigTilesIntoBuffer",
805 "Tilesize %lu is too small, using alternate calculation %u",
806 tilesize, tl * tile_rowsize);
807 #endif
808 tile_buffsize = tl * tile_rowsize;
809 }
810
811 tilebuf = _TIFFmalloc(tile_buffsize);
812 if (tilebuf == 0)
813 return 0;
814
815 dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
816 for (row = 0; row < imagelength; row += tl)
817 {
818 nrow = (row + tl > imagelength) ? imagelength - row : tl;
819 for (col = 0; col < imagewidth; col += tw)
820 {
821 tbytes = TIFFReadTile(in, tilebuf, col, row, 0, 0);
822 if (tbytes < tilesize && !ignore)
823 {
824 TIFFError(TIFFFileName(in),
825 "Error, can't read tile at row %lu col %lu, Read %lu bytes of %lu",
826 (unsigned long) col, (unsigned long) row, (unsigned long)tbytes,
827 (unsigned long)tilesize);
828 status = 0;
829 _TIFFfree(tilebuf);
830 return status;
831 }
832
833 row_offset = row * dst_rowsize;
834 col_offset = ((col * bps * spp) + 7)/ 8;
835 bufp = buf + row_offset + col_offset;
836
837 if (col + tw > imagewidth)
838 ncol = imagewidth - col;
839 else
840 ncol = tw;
841
842 /* Each tile scanline will start on a byte boundary but it
843 * has to be merged into the scanline for the entire
844 * image buffer and the previous segment may not have
845 * ended on a byte boundary
846 */
847 /* Optimization for common bit depths, all samples */
848 if (((bps % 8) == 0) && (count == spp))
849 {
850 for (trow = 0; trow < nrow; trow++)
851 {
852 src_offset = trow * tile_rowsize;
853 _TIFFmemcpy (bufp, tilebuf + src_offset, (ncol * spp * bps) / 8);
854 bufp += (imagewidth * bps * spp) / 8;
855 }
856 }
857 else
858 {
859 /* Bit depths not a multiple of 8 and/or extract fewer than spp samples */
860 prev_trailing_bits = trailing_bits = 0;
861 trailing_bits = (ncol * bps * spp) % 8;
862
863 /* for (trow = 0; tl < nrow; trow++) */
864 for (trow = 0; trow < nrow; trow++)
865 {
866 src_offset = trow * tile_rowsize;
867 src = tilebuf + src_offset;
868 dst_offset = (row + trow) * dst_rowsize;
869 dst = buf + dst_offset + col_offset;
870 switch (shift_width)
871 {
872 case 0: if (extractContigSamplesBytes (src, dst, ncol, sample,
873 spp, bps, count, 0, ncol))
874 {
875 TIFFError("readContigTilesIntoBuffer",
876 "Unable to extract row %d from tile %lu",
877 row, (unsigned long)TIFFCurrentTile(in));
878 return 1;
879 }
880 break;
881 case 1: if (bps == 1)
882 {
883 if (extractContigSamplesShifted8bits (src, dst, ncol,
884 sample, spp,
885 bps, count,
886 0, ncol,
887 prev_trailing_bits))
888 {
889 TIFFError("readContigTilesIntoBuffer",
890 "Unable to extract row %d from tile %lu",
891 row, (unsigned long)TIFFCurrentTile(in));
892 return 1;
893 }
894 break;
895 }
896 else
897 if (extractContigSamplesShifted16bits (src, dst, ncol,
898 sample, spp,
899 bps, count,
900 0, ncol,
901 prev_trailing_bits))
902 {
903 TIFFError("readContigTilesIntoBuffer",
904 "Unable to extract row %d from tile %lu",
905 row, (unsigned long)TIFFCurrentTile(in));
906 return 1;
907 }
908 break;
909 case 2: if (extractContigSamplesShifted24bits (src, dst, ncol,
910 sample, spp,
911 bps, count,
912 0, ncol,
913 prev_trailing_bits))
914 {
915 TIFFError("readContigTilesIntoBuffer",
916 "Unable to extract row %d from tile %lu",
917 row, (unsigned long)TIFFCurrentTile(in));
918 return 1;
919 }
920 break;
921 case 3:
922 case 4:
923 case 5: if (extractContigSamplesShifted32bits (src, dst, ncol,
924 sample, spp,
925 bps, count,
926 0, ncol,
927 prev_trailing_bits))
928 {
929 TIFFError("readContigTilesIntoBuffer",
930 "Unable to extract row %d from tile %lu",
931 row, (unsigned long)TIFFCurrentTile(in));
932 return 1;
933 }
934 break;
935 default: TIFFError("readContigTilesIntoBuffer", "Unsupported bit depth %d", bps);
936 return 1;
937 }
938 }
939 prev_trailing_bits += trailing_bits;
940 if (prev_trailing_bits > 7)
941 prev_trailing_bits-= 8;
942 }
943 }
944 }
945
946 _TIFFfree(tilebuf);
947 return status;
948 }
949
950 static int readSeparateTilesIntoBuffer (TIFF* in, uint8 *obuf,
951 uint32 imagelength, uint32 imagewidth,
952 uint32 tw, uint32 tl,
953 uint16 spp, uint16 bps)
954 {
955 int i, status = 1, sample;
956 int shift_width, bytes_per_pixel;
957 uint16 bytes_per_sample;
958 uint32 row, col; /* Current row and col of image */
959 uint32 nrow, ncol; /* Number of rows and cols in current tile */
960 uint32 row_offset, col_offset; /* Output buffer offsets */
961 tsize_t tbytes = 0, tilesize = TIFFTileSize(in);
962 tsample_t s;
963 uint8* bufp = (uint8*)obuf;
964 unsigned char *srcbuffs[MAX_SAMPLES];
965 unsigned char *tbuff = NULL;
966
967 bytes_per_sample = (bps + 7) / 8;
968
969 for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
970 {
971 srcbuffs[sample] = NULL;
972 tbuff = (unsigned char *)_TIFFmalloc(tilesize + 8);
973 if (!tbuff)
974 {
975 TIFFError ("readSeparateTilesIntoBuffer",
976 "Unable to allocate tile read buffer for sample %d", sample);
977 for (i = 0; i < sample; i++)
978 _TIFFfree (srcbuffs[i]);
979 return 0;
980 }
981 srcbuffs[sample] = tbuff;
982 }
983 /* Each tile contains only the data for a single plane
984 * arranged in scanlines of tw * bytes_per_sample bytes.
985 */
986 for (row = 0; row < imagelength; row += tl)
987 {
988 nrow = (row + tl > imagelength) ? imagelength - row : tl;
989 for (col = 0; col < imagewidth; col += tw)
990 {
991 for (s = 0; s < spp; s++)
992 { /* Read each plane of a tile set into srcbuffs[s] */
993 tbytes = TIFFReadTile(in, srcbuffs[s], col, row, 0, s);
994 if (tbytes < 0 && !ignore)
995 {
996 TIFFError(TIFFFileName(in),
997 "Error, can't read tile for row %lu col %lu, "
998 "sample %lu",
999 (unsigned long) col, (unsigned long) row,
1000 (unsigned long) s);
1001 status = 0;
1002 for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
1003 {
1004 tbuff = srcbuffs[sample];
1005 if (tbuff != NULL)
1006 _TIFFfree(tbuff);
1007 }
1008 return status;
1009 }
1010 }
1011 /* Tiles on the right edge may be padded out to tw
1012 * which must be a multiple of 16.
1013 * Ncol represents the visible (non padding) portion.
1014 */
1015 if (col + tw > imagewidth)
1016 ncol = imagewidth - col;
1017 else
1018 ncol = tw;
1019
1020 row_offset = row * (((imagewidth * spp * bps) + 7) / 8);
1021 col_offset = ((col * spp * bps) + 7) / 8;
1022 bufp = obuf + row_offset + col_offset;
1023
1024 if ((bps % 8) == 0)
1025 {
1026 if (combineSeparateTileSamplesBytes(srcbuffs, bufp, ncol, nrow, imagewidth,
1027 tw, spp, bps, NULL, 0, 0))
1028 {
1029 status = 0;
1030 break;
1031 }
1032 }
1033 else
1034 {
1035 bytes_per_pixel = ((bps * spp) + 7) / 8;
1036 if (bytes_per_pixel < (bytes_per_sample + 1))
1037 shift_width = bytes_per_pixel;
1038 else
1039 shift_width = bytes_per_sample + 1;
1040
1041 switch (shift_width)
1042 {
1043 case 1: if (combineSeparateTileSamples8bits (srcbuffs, bufp, ncol, nrow,
1044 imagewidth, tw, spp, bps,
1045 NULL, 0, 0))
1046 {
1047 status = 0;
1048 break;
1049 }
1050 break;
1051 case 2: if (combineSeparateTileSamples16bits (srcbuffs, bufp, ncol, nrow,
1052 imagewidth, tw, spp, bps,
1053 NULL, 0, 0))
1054 {
1055 status = 0;
1056 break;
1057 }
1058 break;
1059 case 3: if (combineSeparateTileSamples24bits (srcbuffs, bufp, ncol, nrow,
1060 imagewidth, tw, spp, bps,
1061 NULL, 0, 0))
1062 {
1063 status = 0;
1064 break;
1065 }
1066 break;
1067 case 4:
1068 case 5:
1069 case 6:
1070 case 7:
1071 case 8: if (combineSeparateTileSamples32bits (srcbuffs, bufp, ncol, nrow,
1072 imagewidth, tw, spp, bps,
1073 NULL, 0, 0))
1074 {
1075 status = 0;
1076 break;
1077 }
1078 break;
1079 default: TIFFError ("readSeparateTilesIntoBuffer", "Unsupported bit depth: %d", bps);
1080 status = 0;
1081 break;
1082 }
1083 }
1084 }
1085 }
1086
1087 for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
1088 {
1089 tbuff = srcbuffs[sample];
1090 if (tbuff != NULL)
1091 _TIFFfree(tbuff);
1092 }
1093
1094 return status;
1095 }
1096
1097 static int writeBufferToContigStrips(TIFF* out, uint8* buf, uint32 imagelength)
1098 {
1099 uint32 row, nrows, rowsperstrip;
1100 tstrip_t strip = 0;
1101 tsize_t stripsize;
1102
1103 TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1104 for (row = 0; row < imagelength; row += rowsperstrip)
1105 {
1106 nrows = (row + rowsperstrip > imagelength) ?
1107 imagelength - row : rowsperstrip;
1108 stripsize = TIFFVStripSize(out, nrows);
1109 if (TIFFWriteEncodedStrip(out, strip++, buf, stripsize) < 0)
1110 {
1111 TIFFError(TIFFFileName(out), "Error, can't write strip %u", strip - 1);
1112 return 1;
1113 }
1114 buf += stripsize;
1115 }
1116
1117 return 0;
1118 }
1119
1120 /* Abandon plans to modify code so that plannar orientation separate images
1121 * do not have all samples for each channel written before all samples
1122 * for the next channel have been abandoned.
1123 * Libtiff internals seem to depend on all data for a given sample
1124 * being contiguous within a strip or tile when PLANAR_CONFIG is
1125 * separate. All strips or tiles of a given plane are written
1126 * before any strips or tiles of a different plane are stored.
1127 */
1128 static int
1129 writeBufferToSeparateStrips (TIFF* out, uint8* buf,
1130 uint32 length, uint32 width, uint16 spp,
1131 struct dump_opts *dump)
1132 {
1133 uint8 *src;
1134 uint16 bps;
1135 uint32 row, nrows, rowsize, rowsperstrip;
1136 uint32 bytes_per_sample;
1137 tsample_t s;
1138 tstrip_t strip = 0;
1139 tsize_t stripsize = TIFFStripSize(out);
1140 tsize_t rowstripsize, scanlinesize = TIFFScanlineSize(out);
1141 tsize_t total_bytes = 0;
1142 tdata_t obuf;
1143
1144 (void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
1145 (void) TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
1146 bytes_per_sample = (bps + 7) / 8;
1147 rowsize = ((bps * spp * width) + 7) / 8; /* source has interleaved samples */
1148 rowstripsize = rowsperstrip * bytes_per_sample * (width + 1);
1149
1150 obuf = _TIFFmalloc (rowstripsize);
1151 if (obuf == NULL)
1152 return 1;
1153
1154 for (s = 0; s < spp; s++)
1155 {
1156 for (row = 0; row < length; row += rowsperstrip)
1157 {
1158 nrows = (row + rowsperstrip > length) ? length - row : rowsperstrip;
1159
1160 stripsize = TIFFVStripSize(out, nrows);
1161 src = buf + (row * rowsize);
1162 total_bytes += stripsize;
1163 memset (obuf, '\0', rowstripsize);
1164 if (extractContigSamplesToBuffer(obuf, src, nrows, width, s, spp, bps, dump))
1165 {
1166 _TIFFfree(obuf);
1167 return 1;
1168 }
1169 if ((dump->outfile != NULL) && (dump->level == 1))
1170 {
1171 dump_info(dump->outfile, dump->format,"",
1172 "Sample %2d, Strip: %2d, bytes: %4d, Row %4d, bytes: %4d, Input offset: %6d",
1173 s + 1, strip + 1, stripsize, row + 1, scanlinesize, src - buf);
1174 dump_buffer(dump->outfile, dump->format, nrows, scanlinesize, row, obuf);
1175 }
1176
1177 if (TIFFWriteEncodedStrip(out, strip++, obuf, stripsize) < 0)
1178 {
1179 TIFFError(TIFFFileName(out), "Error, can't write strip %u", strip - 1);
1180 _TIFFfree(obuf);
1181 return 1;
1182 }
1183 }
1184 }
1185
1186 _TIFFfree(obuf);
1187 return 0;
1188 }
1189
1190 /* Extract all planes from contiguous buffer into a single tile buffer
1191 * to be written out as a tile.
1192 */
1193 static int writeBufferToContigTiles (TIFF* out, uint8* buf, uint32 imagelength,
1194 uint32 imagewidth, tsample_t spp,
1195 struct dump_opts* dump)
1196 {
1197 uint16 bps;
1198 uint32 tl, tw;
1199 uint32 row, col, nrow, ncol;
1200 uint32 src_rowsize, col_offset;
1201 uint32 tile_rowsize = TIFFTileRowSize(out);
1202 uint8* bufp = (uint8*) buf;
1203 tsize_t tile_buffsize = 0;
1204 tsize_t tilesize = TIFFTileSize(out);
1205 unsigned char *tilebuf = NULL;
1206
1207 TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
1208 TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
1209 TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
1210
1211 tile_buffsize = tilesize;
1212 if (tilesize < (tsize_t)(tl * tile_rowsize))
1213 {
1214 #ifdef DEBUG2
1215 TIFFError("writeBufferToContigTiles",
1216 "Tilesize %lu is too small, using alternate calculation %u",
1217 tilesize, tl * tile_rowsize);
1218 #endif
1219 tile_buffsize = tl * tile_rowsize;
1220 }
1221
1222 tilebuf = _TIFFmalloc(tile_buffsize);
1223 if (tilebuf == 0)
1224 return 1;
1225
1226 src_rowsize = ((imagewidth * spp * bps) + 7) / 8;
1227 for (row = 0; row < imagelength; row += tl)
1228 {
1229 nrow = (row + tl > imagelength) ? imagelength - row : tl;
1230 for (col = 0; col < imagewidth; col += tw)
1231 {
1232 /* Calculate visible portion of tile. */
1233 if (col + tw > imagewidth)
1234 ncol = imagewidth - col;
1235 else
1236 ncol = tw;
1237
1238 col_offset = (((col * bps * spp) + 7) / 8);
1239 bufp = buf + (row * src_rowsize) + col_offset;
1240 if (extractContigSamplesToTileBuffer(tilebuf, bufp, nrow, ncol, imagewidth,
1241 tw, 0, spp, spp, bps, dump) > 0)
1242 {
1243 TIFFError("writeBufferToContigTiles",
1244 "Unable to extract data to tile for row %lu, col %lu",
1245 (unsigned long) row, (unsigned long)col);
1246 _TIFFfree(tilebuf);
1247 return 1;
1248 }
1249
1250 if (TIFFWriteTile(out, tilebuf, col, row, 0, 0) < 0)
1251 {
1252 TIFFError("writeBufferToContigTiles",
1253 "Cannot write tile at %lu %lu",
1254 (unsigned long) col, (unsigned long) row);
1255 _TIFFfree(tilebuf);
1256 return 1;
1257 }
1258 }
1259 }
1260 _TIFFfree(tilebuf);
1261
1262 return 0;
1263 } /* end writeBufferToContigTiles */
1264
1265 /* Extract each plane from contiguous buffer into a single tile buffer
1266 * to be written out as a tile.
1267 */
1268 static int writeBufferToSeparateTiles (TIFF* out, uint8* buf, uint32 imagelength,
1269 uint32 imagewidth, tsample_t spp,
1270 struct dump_opts * dump)
1271 {
1272 tdata_t obuf = _TIFFmalloc(TIFFTileSize(out));
1273 uint32 tl, tw;
1274 uint32 row, col, nrow, ncol;
1275 uint32 src_rowsize, col_offset;
1276 uint16 bps;
1277 tsample_t s;
1278 uint8* bufp = (uint8*) buf;
1279
1280 if (obuf == NULL)
1281 return 1;
1282
1283 TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
1284 TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
1285 TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
1286 src_rowsize = ((imagewidth * spp * bps) + 7) / 8;
1287
1288 for (row = 0; row < imagelength; row += tl)
1289 {
1290 nrow = (row + tl > imagelength) ? imagelength - row : tl;
1291 for (col = 0; col < imagewidth; col += tw)
1292 {
1293 /* Calculate visible portion of tile. */
1294 if (col + tw > imagewidth)
1295 ncol = imagewidth - col;
1296 else
1297 ncol = tw;
1298
1299 col_offset = (((col * bps * spp) + 7) / 8);
1300 bufp = buf + (row * src_rowsize) + col_offset;
1301
1302 for (s = 0; s < spp; s++)
1303 {
1304 if (extractContigSamplesToTileBuffer(obuf, bufp, nrow, ncol, imagewidth,
1305 tw, s, 1, spp, bps, dump) > 0)
1306 {
1307 TIFFError("writeBufferToSeparateTiles",
1308 "Unable to extract data to tile for row %lu, col %lu sample %d",
1309 (unsigned long) row, (unsigned long)col, (int)s);
1310 _TIFFfree(obuf);
1311 return 1;
1312 }
1313
1314 if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0)
1315 {
1316 TIFFError("writeBufferToseparateTiles",
1317 "Cannot write tile at %lu %lu sample %lu",
1318 (unsigned long) col, (unsigned long) row,
1319 (unsigned long) s);
1320 _TIFFfree(obuf);
1321 return 1;
1322 }
1323 }
1324 }
1325 }
1326 _TIFFfree(obuf);
1327
1328 return 0;
1329 } /* end writeBufferToSeparateTiles */
1330
1331 static void
1332 processG3Options(char* cp)
1333 {
1334 if( (cp = strchr(cp, ':')) ) {
1335 if (defg3opts == (uint32) -1)
1336 defg3opts = 0;
1337 do {
1338 cp++;
1339 if (strneq(cp, "1d", 2))
1340 defg3opts &= ~GROUP3OPT_2DENCODING;
1341 else if (strneq(cp, "2d", 2))
1342 defg3opts |= GROUP3OPT_2DENCODING;
1343 else if (strneq(cp, "fill", 4))
1344 defg3opts |= GROUP3OPT_FILLBITS;
1345 else
1346 usage();
1347 } while( (cp = strchr(cp, ':')) );
1348 }
1349 }
1350
1351 static int
1352 processCompressOptions(char* opt)
1353 {
1354 char* cp = NULL;
1355
1356 if (strneq(opt, "none",4))
1357 {
1358 defcompression = COMPRESSION_NONE;
1359 }
1360 else if (streq(opt, "packbits"))
1361 {
1362 defcompression = COMPRESSION_PACKBITS;
1363 }
1364 else if (strneq(opt, "jpeg", 4))
1365 {
1366 cp = strchr(opt, ':');
1367 defcompression = COMPRESSION_JPEG;
1368
1369 while (cp)
1370 {
1371 if (isdigit((int)cp[1]))
1372 quality = atoi(cp + 1);
1373 else if (strneq(cp + 1, "raw", 3 ))
1374 jpegcolormode = JPEGCOLORMODE_RAW;
1375 else if (strneq(cp + 1, "rgb", 3 ))
1376 jpegcolormode = JPEGCOLORMODE_RGB;
1377 else
1378 usage();
1379 cp = strchr(cp + 1, ':');
1380 }
1381 }
1382 else if (strneq(opt, "g3", 2))
1383 {
1384 processG3Options(opt);
1385 defcompression = COMPRESSION_CCITTFAX3;
1386 }
1387 else if (streq(opt, "g4"))
1388 {
1389 defcompression = COMPRESSION_CCITTFAX4;
1390 }
1391 else if (strneq(opt, "lzw", 3))
1392 {
1393 cp = strchr(opt, ':');
1394 if (cp)
1395 defpredictor = atoi(cp+1);
1396 defcompression = COMPRESSION_LZW;
1397 }
1398 else if (strneq(opt, "zip", 3))
1399 {
1400 cp = strchr(opt, ':');
1401 if (cp)
1402 defpredictor = atoi(cp+1);
1403 defcompression = COMPRESSION_ADOBE_DEFLATE;
1404 }
1405 else
1406 return (0);
1407
1408 return (1);
1409 }
1410
1411 static void
1412 usage(void)
1413 {
1414 int i;
1415
1416 fprintf(stderr, "\n%s\n", TIFFGetVersion());
1417 for (i = 0; usage_info[i] != NULL; i++)
1418 fprintf(stderr, "%s\n", usage_info[i]);
1419 exit(-1);
1420 }
1421
1422 #define CopyField(tag, v) \
1423 if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
1424 #define CopyField2(tag, v1, v2) \
1425 if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
1426 #define CopyField3(tag, v1, v2, v3) \
1427 if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
1428 #define CopyField4(tag, v1, v2, v3, v4) \
1429 if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
1430
1431 static void
1432 cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
1433 {
1434 switch (type) {
1435 case TIFF_SHORT:
1436 if (count == 1) {
1437 uint16 shortv;
1438 CopyField(tag, shortv);
1439 } else if (count == 2) {
1440 uint16 shortv1, shortv2;
1441 CopyField2(tag, shortv1, shortv2);
1442 } else if (count == 4) {
1443 uint16 *tr, *tg, *tb, *ta;
1444 CopyField4(tag, tr, tg, tb, ta);
1445 } else if (count == (uint16) -1) {
1446 uint16 shortv1;
1447 uint16* shortav;
1448 CopyField2(tag, shortv1, shortav);
1449 }
1450 break;
1451 case TIFF_LONG:
1452 { uint32 longv;
1453 CopyField(tag, longv);
1454 }
1455 break;
1456 case TIFF_RATIONAL:
1457 if (count == 1) {
1458 float floatv;
1459 CopyField(tag, floatv);
1460 } else if (count == (uint16) -1) {
1461 float* floatav;
1462 CopyField(tag, floatav);
1463 }
1464 break;
1465 case TIFF_ASCII:
1466 { char* stringv;
1467 CopyField(tag, stringv);
1468 }
1469 break;
1470 case TIFF_DOUBLE:
1471 if (count == 1) {
1472 double doublev;
1473 CopyField(tag, doublev);
1474 } else if (count == (uint16) -1) {
1475 double* doubleav;
1476 CopyField(tag, doubleav);
1477 }
1478 break;
1479 default:
1480 TIFFError(TIFFFileName(in),
1481 "Data type %d is not supported, tag %d skipped",
1482 tag, type);
1483 }
1484 }
1485
1486 static struct cpTag {
1487 uint16 tag;
1488 uint16 count;
1489 TIFFDataType type;
1490 } tags[] = {
1491 { TIFFTAG_SUBFILETYPE, 1, TIFF_LONG },
1492 { TIFFTAG_THRESHHOLDING, 1, TIFF_SHORT },
1493 { TIFFTAG_DOCUMENTNAME, 1, TIFF_ASCII },
1494 { TIFFTAG_IMAGEDESCRIPTION, 1, TIFF_ASCII },
1495 { TIFFTAG_MAKE, 1, TIFF_ASCII },
1496 { TIFFTAG_MODEL, 1, TIFF_ASCII },
1497 { TIFFTAG_MINSAMPLEVALUE, 1, TIFF_SHORT },
1498 { TIFFTAG_MAXSAMPLEVALUE, 1, TIFF_SHORT },
1499 { TIFFTAG_XRESOLUTION, 1, TIFF_RATIONAL },
1500 { TIFFTAG_YRESOLUTION, 1, TIFF_RATIONAL },
1501 { TIFFTAG_PAGENAME, 1, TIFF_ASCII },
1502 { TIFFTAG_XPOSITION, 1, TIFF_RATIONAL },
1503 { TIFFTAG_YPOSITION, 1, TIFF_RATIONAL },
1504 { TIFFTAG_RESOLUTIONUNIT, 1, TIFF_SHORT },
1505 { TIFFTAG_SOFTWARE, 1, TIFF_ASCII },
1506 { TIFFTAG_DATETIME, 1, TIFF_ASCII },
1507 { TIFFTAG_ARTIST, 1, TIFF_ASCII },
1508 { TIFFTAG_HOSTCOMPUTER, 1, TIFF_ASCII },
1509 { TIFFTAG_WHITEPOINT, (uint16) -1, TIFF_RATIONAL },
1510 { TIFFTAG_PRIMARYCHROMATICITIES,(uint16) -1,TIFF_RATIONAL },
1511 { TIFFTAG_HALFTONEHINTS, 2, TIFF_SHORT },
1512 { TIFFTAG_INKSET, 1, TIFF_SHORT },
1513 { TIFFTAG_DOTRANGE, 2, TIFF_SHORT },
1514 { TIFFTAG_TARGETPRINTER, 1, TIFF_ASCII },
1515 { TIFFTAG_SAMPLEFORMAT, 1, TIFF_SHORT },
1516 { TIFFTAG_YCBCRCOEFFICIENTS, (uint16) -1,TIFF_RATIONAL },
1517 { TIFFTAG_YCBCRSUBSAMPLING, 2, TIFF_SHORT },
1518 { TIFFTAG_YCBCRPOSITIONING, 1, TIFF_SHORT },
1519 { TIFFTAG_REFERENCEBLACKWHITE, (uint16) -1,TIFF_RATIONAL },
1520 { TIFFTAG_EXTRASAMPLES, (uint16) -1, TIFF_SHORT },
1521 { TIFFTAG_SMINSAMPLEVALUE, 1, TIFF_DOUBLE },
1522 { TIFFTAG_SMAXSAMPLEVALUE, 1, TIFF_DOUBLE },
1523 { TIFFTAG_STONITS, 1, TIFF_DOUBLE },
1524 };
1525 #define NTAGS (sizeof (tags) / sizeof (tags[0]))
1526
1527 #define CopyTag(tag, count, type) cpTag(in, out, tag, count, type)
1528
1529 /* Functions written by Richard Nolde, with exceptions noted. */
1530 void process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32 *dirnum,
1531 uint16 *defconfig, uint16 *deffillorder, uint32 *deftilewidth,
1532 uint32 *deftilelength, uint32 *defrowsperstrip,
1533 struct crop_mask *crop_data, struct pagedef *page,
1534 struct dump_opts *dump,
1535 unsigned int *imagelist, unsigned int *image_count )
1536 {
1537 int c, good_args = 0;
1538 char *opt_offset = NULL; /* Position in string of value sought */
1539 char *opt_ptr = NULL; /* Pointer to next token in option set */
1540 char *sep = NULL; /* Pointer to a token separator */
1541 unsigned int i, j, start, end;
1542 extern int optind;
1543 extern char* optarg;
1544
1545 *mp++ = 'w';
1546 *mp = '\0';
1547 while ((c = getopt(argc, argv,
1548 "ac:d:e:f:hil:m:p:r:stvw:z:BCD:E:F:H:I:J:K:LMN:O:P:R:S:U:V:X:Y:Z:")) != -1)
1549 {
1550 good_args++;
1551 switch (c) {
1552 case 'a': mode[0] = 'a'; /* append to output */
1553 break;
1554 case 'c': if (!processCompressOptions(optarg)) /* compression scheme */
1555 {
1556 TIFFError ("Unknown compression option", "%s", optarg);
1557 TIFFError ("For valid options type", "tiffcrop -h");
1558 exit (-1);
1559 }
1560 break;
1561 case 'd': start = strtoul(optarg, NULL, 0); /* initial IFD offset */
1562 if (start == 0)
1563 {
1564 TIFFError ("","Directory offset must be greater than zero");
1565 TIFFError ("For valid options type", "tiffcrop -h");
1566 exit (-1);
1567 }
1568 *dirnum = start - 1;
1569 break;
1570 case 'e': switch (tolower(optarg[0])) /* image export modes*/
1571 {
1572 case 'c': crop_data->exp_mode = ONE_FILE_COMPOSITE;
1573 crop_data->img_mode = COMPOSITE_IMAGES;
1574 break; /* Composite */
1575 case 'd': crop_data->exp_mode = ONE_FILE_SEPARATED;
1576 crop_data->img_mode = SEPARATED_IMAGES;
1577 break; /* Divided */
1578 case 'i': crop_data->exp_mode = FILE_PER_IMAGE_COMPOSITE;
1579 crop_data->img_mode = COMPOSITE_IMAGES;
1580 break; /* Image */
1581 case 'm': crop_data->exp_mode = FILE_PER_IMAGE_SEPARATED;
1582 crop_data->img_mode = SEPARATED_IMAGES;
1583 break; /* Multiple */
1584 case 's': crop_data->exp_mode = FILE_PER_SELECTION;
1585 crop_data->img_mode = SEPARATED_IMAGES;
1586 break; /* Sections */
1587 default: TIFFError ("Unknown export mode","%s", optarg);
1588 TIFFError ("For valid options type", "tiffcrop -h");
1589 exit (-1);
1590 }
1591 break;
1592 case 'f': if (streq(optarg, "lsb2msb")) /* fill order */
1593 *deffillorder = FILLORDER_LSB2MSB;
1594 else if (streq(optarg, "msb2lsb"))
1595 *deffillorder = FILLORDER_MSB2LSB;
1596 else
1597 {
1598 TIFFError ("Unknown fill order", "%s", optarg);
1599 TIFFError ("For valid options type", "tiffcrop -h");
1600 exit (-1);
1601 }
1602 break;
1603 case 'h': usage();
1604 break;
1605 case 'i': ignore = TRUE; /* ignore errors */
1606 break;
1607 case 'l': outtiled = TRUE; /* tile length */
1608 *deftilelength = atoi(optarg);
1609 break;
1610 case 'p': /* planar configuration */
1611 if (streq(optarg, "separate"))
1612 *defconfig = PLANARCONFIG_SEPARATE;
1613 else if (streq(optarg, "contig"))
1614 *defconfig = PLANARCONFIG_CONTIG;
1615 else
1616 {
1617 TIFFError ("Unkown planar configuration", "%s", optarg);
1618 TIFFError ("For valid options type", "tiffcrop -h");
1619 exit (-1);
1620 }
1621 break;
1622 case 'r': /* rows/strip */
1623 *defrowsperstrip = atol(optarg);
1624 break;
1625 case 's': /* generate stripped output */
1626 outtiled = FALSE;
1627 break;
1628 case 't': /* generate tiled output */
1629 outtiled = TRUE;
1630 break;
1631 case 'v': TIFFError("Library Release", "%s", TIFFGetVersion());
1632 TIFFError ("Tiffcrop version", "%s, last updated: %s",
1633 tiffcrop_version_id, tiffcrop_rev_date);
1634 TIFFError ("Tiffcp code", "Copyright (c) 1988-1997 Sam Leffler");
1635 TIFFError (" ", "Copyright (c) 1991-1997 Silicon Graphics, Inc");
1636 TIFFError ("Tiffcrop additions", "Copyright (c) 2007-2010 Richard Nolde");
1637 exit (0);
1638 break;
1639 case 'w': /* tile width */
1640 outtiled = TRUE;
1641 *deftilewidth = atoi(optarg);
1642 break;
1643 case 'z': /* regions of an image specified as x1,y1,x2,y2:x3,y3,x4,y4 etc */
1644 crop_data->crop_mode |= CROP_REGIONS;
1645 for (i = 0, opt_ptr = strtok (optarg, ":");
1646 ((opt_ptr != NULL) && (i < MAX_REGIONS));
1647 (opt_ptr = strtok (NULL, ":")), i++)
1648 {
1649 crop_data->regions++;
1650 if (sscanf(opt_ptr, "%lf,%lf,%lf,%lf",
1651 &crop_data->corners[i].X1, &crop_data->corners[i].Y1,
1652 &crop_data->corners[i].X2, &crop_data->corners[i].Y2) != 4)
1653 {
1654 TIFFError ("Unable to parse coordinates for region", "%d %s", i, optarg);
1655 TIFFError ("For valid options type", "tiffcrop -h");
1656 exit (-1);
1657 }
1658 }
1659 /* check for remaining elements over MAX_REGIONS */
1660 if ((opt_ptr != NULL) && (i >= MAX_REGIONS))
1661 {
1662 TIFFError ("Region list exceeds limit of", "%d regions %s", MAX_REGIONS, optarg);
1663 TIFFError ("For valid options type", "tiffcrop -h");
1664 exit (-1);;
1665 }
1666 break;
1667 /* options for file open modes */
1668 case 'B': *mp++ = 'b'; *mp = '\0';
1669 break;
1670 case 'L': *mp++ = 'l'; *mp = '\0';
1671 break;
1672 case 'M': *mp++ = 'm'; *mp = '\0';
1673 break;
1674 case 'C': *mp++ = 'c'; *mp = '\0';
1675 break;
1676 /* options for Debugging / data dump */
1677 case 'D': for (i = 0, opt_ptr = strtok (optarg, ",");
1678 (opt_ptr != NULL);
1679 (opt_ptr = strtok (NULL, ",")), i++)
1680 {
1681 opt_offset = strpbrk(opt_ptr, ":=");
1682 if (opt_offset == NULL)
1683 {
1684 TIFFError("Invalid dump option", "%s", optarg);
1685 TIFFError ("For valid options type", "tiffcrop -h");
1686 exit (-1);
1687 }
1688
1689 *opt_offset = '\0';
1690 /* convert option to lowercase */
1691 end = strlen (opt_ptr);
1692 for (i = 0; i < end; i++)
1693 *(opt_ptr + i) = tolower(*(opt_ptr + i));
1694 /* Look for dump format specification */
1695 if (strncmp(opt_ptr, "for", 3) == 0)
1696 {
1697 /* convert value to lowercase */
1698 end = strlen (opt_offset + 1);
1699 for (i = 1; i <= end; i++)
1700 *(opt_offset + i) = tolower(*(opt_offset + i));
1701 /* check dump format value */
1702 if (strncmp (opt_offset + 1, "txt", 3) == 0)
1703 {
1704 dump->format = DUMP_TEXT;
1705 strcpy (dump->mode, "w");
1706 }
1707 else
1708 {
1709 if (strncmp(opt_offset + 1, "raw", 3) == 0)
1710 {
1711 dump->format = DUMP_RAW;
1712 strcpy (dump->mode, "wb");
1713 }
1714 else
1715 {
1716 TIFFError("parse_command_opts", "Unknown dump format %s", opt_offset + 1);
1717 TIFFError ("For valid options type", "tiffcrop -h");
1718 exit (-1);
1719 }
1720 }
1721 }
1722 else
1723 { /* Look for dump level specification */
1724 if (strncmp (opt_ptr, "lev", 3) == 0)
1725 dump->level = atoi(opt_offset + 1);
1726 /* Look for input data dump file name */
1727 if (strncmp (opt_ptr, "in", 2) == 0)
1728 {
1729 strncpy (dump->infilename, opt_offset + 1, PATH_MAX - 20);
1730 dump->infilename[PATH_MAX - 20] = '\0';
1731 }
1732 /* Look for output data dump file name */
1733 if (strncmp (opt_ptr, "out", 3) == 0)
1734 {
1735 strncpy (dump->outfilename, opt_offset + 1, PATH_MAX - 20);
1736 dump->outfilename[PATH_MAX - 20] = '\0';
1737 }
1738 if (strncmp (opt_ptr, "deb", 3) == 0)
1739 dump->debug = atoi(opt_offset + 1);
1740 }
1741 }
1742 if ((strlen(dump->infilename)) || (strlen(dump->outfilename)))
1743 {
1744 if (dump->level == 1)
1745 TIFFError("","Defaulting to dump level 1, no data.");
1746 if (dump->format == DUMP_NONE)
1747 {
1748 TIFFError("", "You must specify a dump format for dump files");
1749 TIFFError ("For valid options type", "tiffcrop -h");
1750 exit (-1);
1751 }
1752 }
1753 break;
1754
1755 /* image manipulation routine options */
1756 case 'm': /* margins to exclude from selection, uppercase M was already used */
1757 /* order of values must be TOP, LEFT, BOTTOM, RIGHT */
1758 crop_data->crop_mode |= CROP_MARGINS;
1759 for (i = 0, opt_ptr = strtok (optarg, ",:");
1760 ((opt_ptr != NULL) && (i < 4));
1761 (opt_ptr = strtok (NULL, ",:")), i++)
1762 {
1763 crop_data->margins[i] = atof(opt_ptr);
1764 }
1765 break;
1766 case 'E': /* edge reference */
1767 switch (tolower(optarg[0]))
1768 {
1769 case 't': crop_data->edge_ref = EDGE_TOP;
1770 break;
1771 case 'b': crop_data->edge_ref = EDGE_BOTTOM;
1772 break;
1773 case 'l': crop_data->edge_ref = EDGE_LEFT;
1774 break;
1775 case 'r': crop_data->edge_ref = EDGE_RIGHT;
1776 break;
1777 default: TIFFError ("Edge reference must be top, bottom, left, or right", "%s", optarg);
1778 TIFFError ("For valid options type", "tiffcrop -h");
1779 exit (-1);
1780 }
1781 break;
1782 case 'F': /* flip eg mirror image or cropped segment, M was already used */
1783 crop_data->crop_mode |= CROP_MIRROR;
1784 switch (tolower(optarg[0]))
1785 {
1786 case 'h': crop_data->mirror = MIRROR_HORIZ;
1787 break;
1788 case 'v': crop_data->mirror = MIRROR_VERT;
1789 break;
1790 case 'b': crop_data->mirror = MIRROR_BOTH;
1791 break;
1792 default: TIFFError ("Flip mode must be horiz, vert, or both", "%s", optarg);
1793 TIFFError ("For valid options type", "tiffcrop -h");
1794 exit (-1);
1795 }
1796 break;
1797 case 'H': /* set horizontal resolution to new value */
1798 page->hres = atof (optarg);
1799 page->mode |= PAGE_MODE_RESOLUTION;
1800 break;
1801 case 'I': /* invert the color space, eg black to white */
1802 crop_data->crop_mode |= CROP_INVERT;
1803 /* The PHOTOMETIC_INTERPRETATION tag may be updated */
1804 if (streq(optarg, "black"))
1805 {
1806 crop_data->photometric = PHOTOMETRIC_MINISBLACK;
1807 continue;
1808 }
1809 if (streq(optarg, "white"))
1810 {
1811 crop_data->photometric = PHOTOMETRIC_MINISWHITE;
1812 continue;
1813 }
1814 if (streq(optarg, "data"))
1815 {
1816 crop_data->photometric = INVERT_DATA_ONLY;
1817 continue;
1818 }
1819 if (streq(optarg, "both"))
1820 {
1821 crop_data->photometric = INVERT_DATA_AND_TAG;
1822 continue;
1823 }
1824
1825 TIFFError("Missing or unknown option for inverting PHOTOMETRIC_INTERPRETATION", "%s", optarg);
1826 TIFFError ("For valid options type", "tiffcrop -h");
1827 exit (-1);
1828 break;
1829 case 'J': /* horizontal margin for sectioned ouput pages */
1830 page->hmargin = atof(optarg);
1831 page->mode |= PAGE_MODE_MARGINS;
1832 break;
1833 case 'K': /* vertical margin for sectioned ouput pages*/
1834 page->vmargin = atof(optarg);
1835 page->mode |= PAGE_MODE_MARGINS;
1836 break;
1837 case 'N': /* list of images to process */
1838 for (i = 0, opt_ptr = strtok (optarg, ",");
1839 ((opt_ptr != NULL) && (i < MAX_IMAGES));
1840 (opt_ptr = strtok (NULL, ",")))
1841 { /* We do not know how many images are in file yet
1842 * so we build a list to include the maximum allowed
1843 * and follow it until we hit the end of the file.
1844 * Image count is not accurate for odd, even, last
1845 * so page numbers won't be valid either.
1846 */
1847 if (streq(opt_ptr, "odd"))
1848 {
1849 for (j = 1; j <= MAX_IMAGES; j += 2)
1850 imagelist[i++] = j;
1851 *image_count = (MAX_IMAGES - 1) / 2;
1852 break;
1853 }
1854 else
1855 {
1856 if (streq(opt_ptr, "even"))
1857 {
1858 for (j = 2; j <= MAX_IMAGES; j += 2)
1859 imagelist[i++] = j;
1860 *image_count = MAX_IMAGES / 2;
1861 break;
1862 }
1863 else
1864 {
1865 if (streq(opt_ptr, "last"))
1866 imagelist[i++] = MAX_IMAGES;
1867 else /* single value between commas */
1868 {
1869 sep = strpbrk(opt_ptr, ":-");
1870 if (!sep)
1871 imagelist[i++] = atoi(opt_ptr);
1872 else
1873 {
1874 *sep = '\0';
1875 start = atoi (opt_ptr);
1876 if (!strcmp((sep + 1), "last"))
1877 end = MAX_IMAGES;
1878 else
1879 end = atoi (sep + 1);
1880 for (j = start; j <= end && j - start + i < MAX_IMAGES; j++)
1881 imagelist[i++] = j;
1882 }
1883 }
1884 }
1885 }
1886 }
1887 *image_count = i;
1888 break;
1889 case 'O': /* page orientation */
1890 switch (tolower(optarg[0]))
1891 {
1892 case 'a': page->orient = ORIENTATION_AUTO;
1893 break;
1894 case 'p': page->orient = ORIENTATION_PORTRAIT;
1895 break;
1896 case 'l': page->orient = ORIENTATION_LANDSCAPE;
1897 break;
1898 default: TIFFError ("Orientation must be portrait, landscape, or auto.", "%s", optarg);
1899 TIFFError ("For valid options type", "tiffcrop -h");
1900 exit (-1);
1901 }
1902 break;
1903 case 'P': /* page size selection */
1904 if (sscanf(optarg, "%lfx%lf", &page->width, &page->length) == 2)
1905 {
1906 strcpy (page->name, "Custom");
1907 page->mode |= PAGE_MODE_PAPERSIZE;
1908 break;
1909 }
1910 if (get_page_geometry (optarg, page))
1911 {
1912 if (!strcmp(optarg, "list"))
1913 {
1914 TIFFError("", "Name Width Length (in inches)");
1915 for (i = 0; i < MAX_PAPERNAMES - 1; i++)
1916 TIFFError ("", "%-15.15s %5.2f %5.2f",
1917 PaperTable[i].name, PaperTable[i].width,
1918 PaperTable[i].length);
1919 exit (-1);
1920 }
1921
1922 TIFFError ("Invalid paper size", "%s", optarg);
1923 TIFFError ("", "Select one of:");
1924 TIFFError("", "Name Width Length (in inches)");
1925 for (i = 0; i < MAX_PAPERNAMES - 1; i++)
1926 TIFFError ("", "%-15.15s %5.2f %5.2f",
1927 PaperTable[i].name, PaperTable[i].width,
1928 PaperTable[i].length);
1929 exit (-1);
1930 }
1931 else
1932 {
1933 page->mode |= PAGE_MODE_PAPERSIZE;
1934 }
1935 break;
1936 case 'R': /* rotate image or cropped segment */
1937 crop_data->crop_mode |= CROP_ROTATE;
1938 switch (strtoul(optarg, NULL, 0))
1939 {
1940 case 90: crop_data->rotation = (uint16)90;
1941 break;
1942 case 180: crop_data->rotation = (uint16)180;
1943 break;
1944 case 270: crop_data->rotation = (uint16)270;
1945 break;
1946 default: TIFFError ("Rotation must be 90, 180, or 270 degrees clockwise", "%s", optarg);
1947 TIFFError ("For valid options type", "tiffcrop -h");
1948 exit (-1);
1949 }
1950 break;
1951 case 'S': /* subdivide into Cols:Rows sections, eg 3:2 would be 3 across and 2 down */
1952 sep = strpbrk(optarg, ",:");
1953 if (sep)
1954 {
1955 *sep = '\0';
1956 page->cols = atoi(optarg);
1957 page->rows = atoi(sep +1);
1958 }
1959 else
1960 {
1961 page->cols = atoi(optarg);
1962 page->rows = atoi(optarg);
1963 }
1964 if ((page->cols * page->rows) > MAX_SECTIONS)
1965 {
1966 TIFFError ("Limit for subdivisions, ie rows x columns, exceeded", "%d", MAX_SECTIONS);
1967 exit (-1);
1968 }
1969 page->mode |= PAGE_MODE_ROWSCOLS;
1970 break;
1971 case 'U': /* units for measurements and offsets */
1972 if (streq(optarg, "in"))
1973 {
1974 crop_data->res_unit = RESUNIT_INCH;
1975 page->res_unit = RESUNIT_INCH;
1976 }
1977 else if (streq(optarg, "cm"))
1978 {
1979 crop_data->res_unit = RESUNIT_CENTIMETER;
1980 page->res_unit = RESUNIT_CENTIMETER;
1981 }
1982 else if (streq(optarg, "px"))
1983 {
1984 crop_data->res_unit = RESUNIT_NONE;
1985 page->res_unit = RESUNIT_NONE;
1986 }
1987 else
1988 {
1989 TIFFError ("Illegal unit of measure","%s", optarg);
1990 TIFFError ("For valid options type", "tiffcrop -h");
1991 exit (-1);
1992 }
1993 break;
1994 case 'V': /* set vertical resolution to new value */
1995 page->vres = atof (optarg);
1996 page->mode |= PAGE_MODE_RESOLUTION;
1997 break;
1998 case 'X': /* selection width */
1999 crop_data->crop_mode |= CROP_WIDTH;
2000 crop_data->width = atof(optarg);
2001 break;
2002 case 'Y': /* selection length */
2003 crop_data->crop_mode |= CROP_LENGTH;
2004 crop_data->length = atof(optarg);
2005 break;
2006 case 'Z': /* zones of an image X:Y read as zone X of Y */
2007 crop_data->crop_mode |= CROP_ZONES;
2008 for (i = 0, opt_ptr = strtok (optarg, ",");
2009 ((opt_ptr != NULL) && (i < MAX_REGIONS));
2010 (opt_ptr = strtok (NULL, ",")), i++)
2011 {
2012 crop_data->zones++;
2013 opt_offset = strchr(opt_ptr, ':');
2014 *opt_offset = '\0';
2015 crop_data->zonelist[i].position = atoi(opt_ptr);
2016 crop_data->zonelist[i].total = atoi(opt_offset + 1);
2017 }
2018 /* check for remaining elements over MAX_REGIONS */
2019 if ((opt_ptr != NULL) && (i >= MAX_REGIONS))
2020 {
2021 TIFFError("Zone list exceeds region limit", "%d", MAX_REGIONS);
2022 exit (-1);
2023 }
2024 break;
2025 case '?': TIFFError ("For valid options type", "tiffcrop -h");
2026 exit (-1);
2027 /*NOTREACHED*/
2028 }
2029 }
2030 } /* end process_command_opts */
2031
2032 /* Start a new output file if one has not been previously opened or
2033 * autoindex is set to non-zero. Update page and file counters
2034 * so TIFFTAG PAGENUM will be correct in image.
2035 */
2036 static int
2037 update_output_file (TIFF **tiffout, char *mode, int autoindex,
2038 char *outname, unsigned int *page)
2039 {
2040 static int findex = 0; /* file sequence indicator */
2041 char *sep;
2042 char filenum[16];
2043 char export_ext[16];
2044 char exportname[PATH_MAX];
2045
2046 if (autoindex && (*tiffout != NULL))
2047 {
2048 /* Close any export file that was previously opened */
2049 TIFFClose (*tiffout);
2050 *tiffout = NULL;
2051 }
2052
2053 strcpy (export_ext, ".tiff");
2054 memset (exportname, '\0', PATH_MAX);
2055
2056 /* Leave room for page number portion of the new filename */
2057 strncpy (exportname, outname, PATH_MAX - 16);
2058 if (*tiffout == NULL) /* This is a new export file */
2059 {
2060 if (autoindex)
2061 { /* create a new filename for each export */
2062 findex++;
2063 if ((sep = strstr(exportname, ".tif")) || (sep = strstr(exportname, ".TIF")))
2064 {
2065 strncpy (export_ext, sep, 5);
2066 *sep = '\0';
2067 }
2068 else
2069 strncpy (export_ext, ".tiff", 5);
2070 export_ext[5] = '\0';
2071
2072 /* MAX_EXPORT_PAGES limited to 6 digits to prevent string overflow of pathname */
2073 if (findex > MAX_EXPORT_PAGES)
2074 {
2075 TIFFError("update_output_file", "Maximum of %d pages per file exceeded", MAX_EXPORT_PAGES);
2076 return 1;
2077 }
2078
2079 sprintf (filenum, "-%03d%s", findex, export_ext);
2080 filenum[14] = '\0';
2081 strncat (exportname, filenum, 15);
2082 }
2083 exportname[PATH_MAX - 1] = '\0';
2084
2085 *tiffout = TIFFOpen(exportname, mode);
2086 if (*tiffout == NULL)
2087 {
2088 TIFFError("update_output_file", "Unable to open output file %s", exportname);
2089 return 1;
2090 }
2091 *page = 0;
2092
2093 return 0;
2094 }
2095 else
2096 (*page)++;
2097
2098 return 0;
2099 } /* end update_output_file */
2100
2101
2102 int
2103 main(int argc, char* argv[])
2104 {
2105 extern int optind;
2106 uint16 defconfig = (uint16) -1;
2107 uint16 deffillorder = 0;
2108 uint32 deftilewidth = (uint32) 0;
2109 uint32 deftilelength = (uint32) 0;
2110 uint32 defrowsperstrip = (uint32) 0;
2111 uint32 dirnum = 0;
2112
2113 TIFF *in = NULL;
2114 TIFF *out = NULL;
2115 char mode[10];
2116 char *mp = mode;
2117
2118 /** RJN additions **/
2119 struct image_data image; /* Image parameters for one image */
2120 struct crop_mask crop; /* Cropping parameters for all images */
2121 struct pagedef page; /* Page definition for output pages */
2122 struct pageseg sections[MAX_SECTIONS]; /* Sections of one output page */
2123 struct buffinfo seg_buffs[MAX_SECTIONS]; /* Segment buffer sizes and pointers */
2124 struct dump_opts dump; /* Data dump options */
2125 unsigned char *read_buff = NULL; /* Input image data buffer */
2126 unsigned char *crop_buff = NULL; /* Crop area buffer */
2127 unsigned char *sect_buff = NULL; /* Image section buffer */
2128 unsigned char *sect_src = NULL; /* Image section buffer pointer */
2129 unsigned int imagelist[MAX_IMAGES + 1]; /* individually specified images */
2130 unsigned int image_count = 0;
2131 unsigned int dump_images = 0;
2132 unsigned int next_image = 0;
2133 unsigned int next_page = 0;
2134 unsigned int total_pages = 0;
2135 unsigned int total_images = 0;
2136 unsigned int end_of_input = FALSE;
2137 int seg, length;
2138 char temp_filename[PATH_MAX + 1];
2139
2140 little_endian = *((unsigned char *)&little_endian) & '1';
2141
2142 initImageData(&image);
2143 initCropMasks(&crop);
2144 initPageSetup(&page, sections, seg_buffs);
2145 initDumpOptions(&dump);
2146
2147 process_command_opts (argc, argv, mp, mode, &dirnum, &defconfig,
2148 &deffillorder, &deftilewidth, &deftilelength, &defrowsperstrip,
2149 &crop, &page, &dump, imagelist, &image_count);
2150
2151 if (argc - optind < 2)
2152 usage();
2153
2154 if ((argc - optind) == 2)
2155 pageNum = -1;
2156 else
2157 total_images = 0;
2158 /* read multiple input files and write to output file(s) */
2159 while (optind < argc - 1)
2160 {
2161 in = TIFFOpen (argv[optind], "r");
2162 if (in == NULL)
2163 return (-3);
2164
2165 /* If only one input file is specified, we can use directory count */
2166 total_images = TIFFNumberOfDirectories(in);
2167 if (image_count == 0)
2168 {
2169 dirnum = 0;
2170 total_pages = total_images; /* Only valid with single input file */
2171 }
2172 else
2173 {
2174 dirnum = (tdir_t)(imagelist[next_image] - 1);
2175 next_image++;
2176
2177 /* Total pages only valid for enumerated list of pages not derived
2178 * using odd, even, or last keywords.
2179 */
2180 if (image_count > total_images)
2181 image_count = total_images;
2182
2183 total_pages = image_count;
2184 }
2185
2186 /* MAX_IMAGES is used for special case "last" in selection list */
2187 if (dirnum == (MAX_IMAGES - 1))
2188 dirnum = total_images - 1;
2189
2190 if (dirnum > (total_images))
2191 {
2192 TIFFError (TIFFFileName(in),
2193 "Invalid image number %d, File contains only %d images",
2194 (int)dirnum + 1, total_images);
2195 if (out != NULL)
2196 (void) TIFFClose(out);
2197 return (1);
2198 }
2199
2200 if (dirnum != 0 && !TIFFSetDirectory(in, (tdir_t)dirnum))
2201 {
2202 TIFFError(TIFFFileName(in),"Error, setting subdirectory at %d", dirnum);
2203 if (out != NULL)
2204 (void) TIFFClose(out);
2205 return (1);
2206 }
2207
2208 end_of_input = FALSE;
2209 while (end_of_input == FALSE)
2210 {
2211 config = defconfig;
2212 compression = defcompression;
2213 predictor = defpredictor;
2214 fillorder = deffillorder;
2215 rowsperstrip = defrowsperstrip;
2216 tilewidth = deftilewidth;
2217 tilelength = deftilelength;
2218 g3opts = defg3opts;
2219
2220 if (dump.format != DUMP_NONE)
2221 {
2222 /* manage input and/or output dump files here */
2223 dump_images++;
2224 length = strlen(dump.infilename);
2225 if (length > 0)
2226 {
2227 if (dump.infile != NULL)
2228 fclose (dump.infile);
2229
2230 /* dump.infilename is guaranteed to be NUL termimated and have 20 bytes
2231 fewer than PATH_MAX */
2232 memset (temp_filename, '\0', PATH_MAX + 1);
2233 sprintf (temp_filename, "%s-read-%03d.%s", dump.infilename, dump_images,
2234 (dump.format == DUMP_TEXT) ? "txt" : "raw");
2235 if ((dump.infile = fopen(temp_filename, dump.mode)) == NULL)
2236 {
2237 TIFFError ("Unable to open dump file for writing", "%s", temp_filename);
2238 exit (-1);
2239 }
2240 dump_info(dump.infile, dump.format, "Reading image","%d from %s",
2241 dump_images, TIFFFileName(in));
2242 }
2243 length = strlen(dump.outfilename);
2244 if (length > 0)
2245 {
2246 if (dump.outfile != NULL)
2247 fclose (dump.outfile);
2248
2249 /* dump.outfilename is guaranteed to be NUL termimated and have 20 bytes
2250 fewer than PATH_MAX */
2251 memset (temp_filename, '\0', PATH_MAX + 1);
2252 sprintf (temp_filename, "%s-write-%03d.%s", dump.outfilename, dump_images,
2253 (dump.format == DUMP_TEXT) ? "txt" : "raw");
2254 if ((dump.outfile = fopen(temp_filename, dump.mode)) == NULL)
2255 {
2256 TIFFError ("Unable to open dump file for writing", "%s", temp_filename);
2257 exit (-1);
2258 }
2259 dump_info(dump.outfile, dump.format, "Writing image","%d from %s",
2260 dump_images, TIFFFileName(in));
2261 }
2262 }
2263
2264 if (dump.debug)
2265 TIFFError("main", "Reading image %4d of %4d total pages.", dirnum + 1, total_pages);
2266
2267 if (loadImage(in, &image, &dump, &read_buff))
2268 {
2269 TIFFError("main", "Unable to load source image");
2270 exit (-1);
2271 }
2272
2273 /* Correct the image orientation if it was not ORIENTATION_TOPLEFT.
2274 */
2275 if (image.adjustments != 0)
2276 {
2277 if (correct_orientation(&image, &read_buff))
2278 TIFFError("main", "Unable to correct image orientation");
2279 }
2280
2281 if (getCropOffsets(&image, &crop, &dump))
2282 {
2283 TIFFError("main", "Unable to define crop regions");
2284 exit (-1);
2285 }
2286
2287 if (crop.selections > 0)
2288 {
2289 if (processCropSelections(&image, &crop, &read_buff, seg_buffs))
2290 {
2291 TIFFError("main", "Unable to process image selections");
2292 exit (-1);
2293 }
2294 }
2295 else /* Single image segment without zones or regions */
2296 {
2297 if (createCroppedImage(&image, &crop, &read_buff, &crop_buff))
2298 {
2299 TIFFError("main", "Unable to create output image");
2300 exit (-1);
2301 }
2302 }
2303 if (page.mode == PAGE_MODE_NONE)
2304 { /* Whole image or sections not based on output page size */
2305 if (crop.selections > 0)
2306 {
2307 writeSelections(in, &out, &crop, &image, &dump, seg_buffs,
2308 mp, argv[argc - 1], &next_page, total_pages);
2309 }
2310 else /* One file all images and sections */
2311 {
2312 if (update_output_file (&out, mp, crop.exp_mode, argv[argc - 1],
2313 &next_page))
2314 exit (1);
2315 if (writeCroppedImage(in, out, &image, &dump,crop.combined_width,
2316 crop.combined_length, crop_buff, next_page, total_pages))
2317 {
2318 TIFFError("main", "Unable to write new image");
2319 exit (-1);
2320 }
2321 }
2322 }
2323 else
2324 {
2325 /* If we used a crop buffer, our data is there, otherwise it is
2326 * in the read_buffer
2327 */
2328 if (crop_buff != NULL)
2329 sect_src = crop_buff;
2330 else
2331 sect_src = read_buff;
2332 /* Break input image into pages or rows and columns */
2333 if (computeOutputPixelOffsets(&crop, &image, &page, sections, &dump))
2334 {
2335 TIFFError("main", "Unable to compute output section data");
2336 exit (-1);
2337 }
2338 /* If there are multiple files on the command line, the final one is assumed
2339 * to be the output filename into which the images are written.
2340 */
2341 if (update_output_file (&out, mp, crop.exp_mode, argv[argc - 1], &next_page))
2342 exit (1);
2343
2344 if (writeImageSections(in, out, &image, &page, sections, &dump, sect_src, &sect_buff))
2345 {
2346 TIFFError("main", "Unable to write image sections");
2347 exit (-1);
2348 }
2349 }
2350
2351 /* No image list specified, just read the next image */
2352 if (image_count == 0)
2353 dirnum++;
2354 else
2355 {
2356 dirnum = (tdir_t)(imagelist[next_image] - 1);
2357 next_image++;
2358 }
2359
2360 if (dirnum == MAX_IMAGES - 1)
2361 dirnum = TIFFNumberOfDirectories(in) - 1;
2362
2363 if (!TIFFSetDirectory(in, (tdir_t)dirnum))
2364 end_of_input = TRUE;
2365 }
2366 TIFFClose(in);
2367 optind++;
2368 }
2369
2370 /* If we did not use the read buffer as the crop buffer */
2371 if (read_buff)
2372 _TIFFfree(read_buff);
2373
2374 if (crop_buff)
2375 _TIFFfree(crop_buff);
2376
2377 if (sect_buff)
2378 _TIFFfree(sect_buff);
2379
2380 /* Clean up any segment buffers used for zones or regions */
2381 for (seg = 0; seg < crop.selections; seg++)
2382 _TIFFfree (seg_buffs[seg].buffer);
2383
2384 if (dump.format != DUMP_NONE)
2385 {
2386 if (dump.infile != NULL)
2387 fclose (dump.infile);
2388
2389 if (dump.outfile != NULL)
2390 {
2391 dump_info (dump.outfile, dump.format, "", "Completed run for %s", TIFFFileName(out));
2392 fclose (dump.outfile);
2393 }
2394 }
2395
2396 TIFFClose(out);
2397
2398 return (0);
2399 } /* end main */
2400
2401
2402 /* Debugging functions */
2403 static int dump_data (FILE *dumpfile, int format, char *dump_tag, unsigned char *data, uint32 count)
2404 {
2405 int j, k;
2406 uint32 i;
2407 char dump_array[10];
2408 unsigned char bitset;
2409
2410 if (dumpfile == NULL)
2411 {
2412 TIFFError ("", "Invalid FILE pointer for dump file");
2413 return (1);
2414 }
2415
2416 if (format == DUMP_TEXT)
2417 {
2418 fprintf (dumpfile," %s ", dump_tag);
2419 for (i = 0; i < count; i++)
2420 {
2421 for (j = 0, k = 7; j < 8; j++, k--)
2422 {
2423 bitset = (*(data + i)) & (((unsigned char)1 << k)) ? 1 : 0;
2424 sprintf(&dump_array[j], (bitset) ? "1" : "0");
2425 }
2426 dump_array[8] = '\0';
2427 fprintf (dumpfile," %s", dump_array);
2428 }
2429 fprintf (dumpfile,"\n");
2430 }
2431 else
2432 {
2433 if ((fwrite (data, 1, count, dumpfile)) != count)
2434 {
2435 TIFFError ("", "Unable to write binary data to dump file");
2436 return (1);
2437 }
2438 }
2439
2440 return (0);
2441 }
2442
2443 static int dump_byte (FILE *dumpfile, int format, char *dump_tag, unsigned char data)
2444 {
2445 int j, k;
2446 char dump_array[10];
2447 unsigned char bitset;
2448
2449 if (dumpfile == NULL)
2450 {
2451 TIFFError ("", "Invalid FILE pointer for dump file");
2452 return (1);
2453 }
2454
2455 if (format == DUMP_TEXT)
2456 {
2457 fprintf (dumpfile," %s ", dump_tag);
2458 for (j = 0, k = 7; j < 8; j++, k--)
2459 {
2460 bitset = data & (((unsigned char)1 << k)) ? 1 : 0;
2461 sprintf(&dump_array[j], (bitset) ? "1" : "0");
2462 }
2463 dump_array[8] = '\0';
2464 fprintf (dumpfile," %s\n", dump_array);
2465 }
2466 else
2467 {
2468 if ((fwrite (&data, 1, 1, dumpfile)) != 1)
2469 {
2470 TIFFError ("", "Unable to write binary data to dump file");
2471 return (1);
2472 }
2473 }
2474
2475 return (0);
2476 }
2477
2478 static int dump_short (FILE *dumpfile, int format, char *dump_tag, uint16 data)
2479 {
2480 int j, k;
2481 char dump_array[20];
2482 unsigned char bitset;
2483
2484 if (dumpfile == NULL)
2485 {
2486 TIFFError ("", "Invalid FILE pointer for dump file");
2487 return (1);
2488 }
2489
2490 if (format == DUMP_TEXT)
2491 {
2492 fprintf (dumpfile," %s ", dump_tag);
2493 for (j = 0, k = 15; k >= 0; j++, k--)
2494 {
2495 bitset = data & (((unsigned char)1 << k)) ? 1 : 0;
2496 sprintf(&dump_array[j], (bitset) ? "1" : "0");
2497 if ((k % 8) == 0)
2498 sprintf(&dump_array[++j], " ");
2499 }
2500 dump_array[17] = '\0';
2501 fprintf (dumpfile," %s\n", dump_array);
2502 }
2503 else
2504 {
2505 if ((fwrite (&data, 2, 1, dumpfile)) != 2)
2506 {
2507 TIFFError ("", "Unable to write binary data to dump file");
2508 return (1);
2509 }
2510 }
2511
2512 return (0);
2513 }
2514
2515 static int dump_long (FILE *dumpfile, int format, char *dump_tag, uint32 data)
2516 {
2517 int j, k;
2518 char dump_array[40];
2519 unsigned char bitset;
2520
2521 if (dumpfile == NULL)
2522 {
2523 TIFFError ("", "Invalid FILE pointer for dump file");
2524 return (1);
2525 }
2526
2527 if (format == DUMP_TEXT)
2528 {
2529 fprintf (dumpfile," %s ", dump_tag);
2530 for (j = 0, k = 31; k >= 0; j++, k--)
2531 {
2532 bitset = data & (((uint32)1 << k)) ? 1 : 0;
2533 sprintf(&dump_array[j], (bitset) ? "1" : "0");
2534 if ((k % 8) == 0)
2535 sprintf(&dump_array[++j], " ");
2536 }
2537 dump_array[35] = '\0';
2538 fprintf (dumpfile," %s\n", dump_array);
2539 }
2540 else
2541 {
2542 if ((fwrite (&data, 4, 1, dumpfile)) != 4)
2543 {
2544 TIFFError ("", "Unable to write binary data to dump file");
2545 return (1);
2546 }
2547 }
2548 return (0);
2549 }
2550
2551 static int dump_wide (FILE *dumpfile, int format, char *dump_tag, uint64 data)
2552 {
2553 int j, k;
2554 char dump_array[80];
2555 unsigned char bitset;
2556
2557 if (dumpfile == NULL)
2558 {
2559 TIFFError ("", "Invalid FILE pointer for dump file");
2560 return (1);
2561 }
2562
2563 if (format == DUMP_TEXT)
2564 {
2565 fprintf (dumpfile," %s ", dump_tag);
2566 for (j = 0, k = 63; k >= 0; j++, k--)
2567 {
2568 bitset = data & (((uint64)1 << k)) ? 1 : 0;
2569 sprintf(&dump_array[j], (bitset) ? "1" : "0");
2570 if ((k % 8) == 0)
2571 sprintf(&dump_array[++j], " ");
2572 }
2573 dump_array[71] = '\0';
2574 fprintf (dumpfile," %s\n", dump_array);
2575 }
2576 else
2577 {
2578 if ((fwrite (&data, 8, 1, dumpfile)) != 8)
2579 {
2580 TIFFError ("", "Unable to write binary data to dump file");
2581 return (1);
2582 }
2583 }
2584
2585 return (0);
2586 }
2587
2588 static void dump_info(FILE *dumpfile, int format, char *prefix, char *msg, ...)
2589 {
2590 if (format == DUMP_TEXT)
2591 {
2592 va_list ap;
2593 va_start(ap, msg);
2594 fprintf(dumpfile, "%s ", prefix);
2595 vfprintf(dumpfile, msg, ap);
2596 fprintf(dumpfile, "\n");
2597 }
2598 }
2599
2600 static int dump_buffer (FILE* dumpfile, int format, uint32 rows, uint32 width,
2601 uint32 row, unsigned char *buff)
2602 {
2603 int j, k;
2604 uint32 i;
2605 unsigned char * dump_ptr;
2606
2607 if (dumpfile == NULL)
2608 {
2609 TIFFError ("", "Invalid FILE pointer for dump file");
2610 return (1);
2611 }
2612
2613 for (i = 0; i < rows; i++)
2614 {
2615 dump_ptr = buff + (i * width);
2616 if (format == DUMP_TEXT)
2617 dump_info (dumpfile, format, "",
2618 "Row %4d, %d bytes at offset %d",
2619 row + i + 1, width, row * width);
2620
2621 for (j = 0, k = width; k >= 10; j += 10, k -= 10, dump_ptr += 10)
2622 dump_data (dumpfile, format, "", dump_ptr, 10);
2623 if (k > 0)
2624 dump_data (dumpfile, format, "", dump_ptr, k);
2625 }
2626 return (0);
2627 }
2628
2629 /* Extract one or more samples from an interleaved buffer. If count == 1,
2630 * only the sample plane indicated by sample will be extracted. If count > 1,
2631 * count samples beginning at sample will be extracted. Portions of a
2632 * scanline can be extracted by specifying a start and end value.
2633 */
2634
2635 static int
2636 extractContigSamplesBytes (uint8 *in, uint8 *out, uint32 cols,
2637 tsample_t sample, uint16 spp, uint16 bps,
2638 tsample_t count, uint32 start, uint32 end)
2639 {
2640 int i, bytes_per_sample, sindex;
2641 uint32 col, dst_rowsize, bit_offset;
2642 uint32 src_byte, src_bit;
2643 uint8 *src = in;
2644 uint8 *dst = out;
2645
2646 if ((src == NULL) || (dst == NULL))
2647 {
2648 TIFFError("extractContigSamplesBytes","Invalid input or output buffer");
2649 return (1);
2650 }
2651
2652 if ((start > end) || (start > cols))
2653 {
2654 TIFFError ("extractContigSamplesBytes",
2655 "Invalid start column value %d ignored", start);
2656 start = 0;
2657 }
2658 if ((end == 0) || (end > cols))
2659 {
2660 TIFFError ("extractContigSamplesBytes",
2661 "Invalid end column value %d ignored", end);
2662 end = cols;
2663 }
2664
2665 dst_rowsize = (bps * (end - start) * count) / 8;
2666
2667 bytes_per_sample = (bps + 7) / 8;
2668 /* Optimize case for copying all samples */
2669 if (count == spp)
2670 {
2671 src = in + (start * spp * bytes_per_sample);
2672 _TIFFmemcpy (dst, src, dst_rowsize);
2673 }
2674 else
2675 {
2676 for (col = start; col < end; col++)
2677 {
2678 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
2679 {
2680 bit_offset = col * bps * spp;
2681 if (sindex == 0)
2682 {
2683 src_byte = bit_offset / 8;
2684 src_bit = bit_offset % 8;
2685 }
2686 else
2687 {
2688 src_byte = (bit_offset + (sindex * bps)) / 8;
2689 src_bit = (bit_offset + (sindex * bps)) % 8;
2690 }
2691 src = in + src_byte;
2692 for (i = 0; i < bytes_per_sample; i++)
2693 *dst++ = *src++;
2694 }
2695 }
2696 }
2697
2698 return (0);
2699 } /* end extractContigSamplesBytes */
2700
2701 static int
2702 extractContigSamples8bits (uint8 *in, uint8 *out, uint32 cols,
2703 tsample_t sample, uint16 spp, uint16 bps,
2704 tsample_t count, uint32 start, uint32 end)
2705 {
2706 int ready_bits = 0, sindex = 0;
2707 uint32 col, src_byte, src_bit, bit_offset;
2708 uint8 maskbits = 0, matchbits = 0;
2709 uint8 buff1 = 0, buff2 = 0;
2710 uint8 *src = in;
2711 uint8 *dst = out;
2712
2713 if ((src == NULL) || (dst == NULL))
2714 {
2715 TIFFError("extractContigSamples8bits","Invalid input or output buffer");
2716 return (1);
2717 }
2718
2719 if ((start > end) || (start > cols))
2720 {
2721 TIFFError ("extractContigSamples8bits",
2722 "Invalid start column value %d ignored", start);
2723 start = 0;
2724 }
2725 if ((end == 0) || (end > cols))
2726 {
2727 TIFFError ("extractContigSamples8bits",
2728 "Invalid end column value %d ignored", end);
2729 end = cols;
2730 }
2731
2732 ready_bits = 0;
2733 maskbits = (uint8)-1 >> ( 8 - bps);
2734 buff1 = buff2 = 0;
2735 for (col = start; col < end; col++)
2736 { /* Compute src byte(s) and bits within byte(s) */
2737 bit_offset = col * bps * spp;
2738 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
2739 {
2740 if (sindex == 0)
2741 {
2742 src_byte = bit_offset / 8;
2743 src_bit = bit_offset % 8;
2744 }
2745 else
2746 {
2747 src_byte = (bit_offset + (sindex * bps)) / 8;
2748 src_bit = (bit_offset + (sindex * bps)) % 8;
2749 }
2750
2751 src = in + src_byte;
2752 matchbits = maskbits << (8 - src_bit - bps);
2753 buff1 = ((*src) & matchbits) << (src_bit);
2754
2755 /* If we have a full buffer's worth, write it out */
2756 if (ready_bits >= 8)
2757 {
2758 *dst++ = buff2;
2759 buff2 = buff1;
2760 ready_bits -= 8;
2761 }
2762 else
2763 buff2 = (buff2 | (buff1 >> ready_bits));
2764 ready_bits += bps;
2765 }
2766 }
2767
2768 while (ready_bits > 0)
2769 {
2770 buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
2771 *dst++ = buff1;
2772 ready_bits -= 8;
2773 }
2774
2775 return (0);
2776 } /* end extractContigSamples8bits */
2777
2778 static int
2779 extractContigSamples16bits (uint8 *in, uint8 *out, uint32 cols,
2780 tsample_t sample, uint16 spp, uint16 bps,
2781 tsample_t count, uint32 start, uint32 end)
2782 {
2783 int ready_bits = 0, sindex = 0;
2784 uint32 col, src_byte, src_bit, bit_offset;
2785 uint16 maskbits = 0, matchbits = 0;
2786 uint16 buff1 = 0, buff2 = 0;
2787 uint8 bytebuff = 0;
2788 uint8 *src = in;
2789 uint8 *dst = out;
2790
2791 if ((src == NULL) || (dst == NULL))
2792 {
2793 TIFFError("extractContigSamples16bits","Invalid input or output buffer");
2794 return (1);
2795 }
2796
2797 if ((start > end) || (start > cols))
2798 {
2799 TIFFError ("extractContigSamples16bits",
2800 "Invalid start column value %d ignored", start);
2801 start = 0;
2802 }
2803 if ((end == 0) || (end > cols))
2804 {
2805 TIFFError ("extractContigSamples16bits",
2806 "Invalid end column value %d ignored", end);
2807 end = cols;
2808 }
2809
2810 ready_bits = 0;
2811 maskbits = (uint16)-1 >> (16 - bps);
2812
2813 for (col = start; col < end; col++)
2814 { /* Compute src byte(s) and bits within byte(s) */
2815 bit_offset = col * bps * spp;
2816 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
2817 {
2818 if (sindex == 0)
2819 {
2820 src_byte = bit_offset / 8;
2821 src_bit = bit_offset % 8;
2822 }
2823 else
2824 {
2825 src_byte = (bit_offset + (sindex * bps)) / 8;
2826 src_bit = (bit_offset + (sindex * bps)) % 8;
2827 }
2828
2829 src = in + src_byte;
2830 matchbits = maskbits << (16 - src_bit - bps);
2831
2832 if (little_endian)
2833 buff1 = (src[0] << 8) | src[1];
2834 else
2835 buff1 = (src[1] << 8) | src[0];
2836
2837 buff1 = (buff1 & matchbits) << (src_bit);
2838 if (ready_bits < 8) /* add another bps bits to the buffer */
2839 {
2840 bytebuff = 0;
2841 buff2 = (buff2 | (buff1 >> ready_bits));
2842 }
2843 else /* If we have a full buffer's worth, write it out */
2844 {
2845 bytebuff = (buff2 >> 8);
2846 *dst++ = bytebuff;
2847 ready_bits -= 8;
2848 /* shift in new bits */
2849 buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
2850 }
2851 ready_bits += bps;
2852 }
2853 }
2854
2855 /* catch any trailing bits at the end of the line */
2856 while (ready_bits > 0)
2857 {
2858 bytebuff = (buff2 >> 8);
2859 *dst++ = bytebuff;
2860 ready_bits -= 8;
2861 }
2862
2863 return (0);
2864 } /* end extractContigSamples16bits */
2865
2866
2867 static int
2868 extractContigSamples24bits (uint8 *in, uint8 *out, uint32 cols,
2869 tsample_t sample, uint16 spp, uint16 bps,
2870 tsample_t count, uint32 start, uint32 end)
2871 {
2872 int ready_bits = 0, sindex = 0;
2873 uint32 col, src_byte, src_bit, bit_offset;
2874 uint32 maskbits = 0, matchbits = 0;
2875 uint32 buff1 = 0, buff2 = 0;
2876 uint8 bytebuff1 = 0, bytebuff2 = 0;
2877 uint8 *src = in;
2878 uint8 *dst = out;
2879
2880 if ((in == NULL) || (out == NULL))
2881 {
2882 TIFFError("extractContigSamples24bits","Invalid input or output buffer");
2883 return (1);
2884 }
2885
2886 if ((start > end) || (start > cols))
2887 {
2888 TIFFError ("extractContigSamples24bits",
2889 "Invalid start column value %d ignored", start);
2890 start = 0;
2891 }
2892 if ((end == 0) || (end > cols))
2893 {
2894 TIFFError ("extractContigSamples24bits",
2895 "Invalid end column value %d ignored", end);
2896 end = cols;
2897 }
2898
2899 ready_bits = 0;
2900 maskbits = (uint32)-1 >> ( 32 - bps);
2901 for (col = start; col < end; col++)
2902 {
2903 /* Compute src byte(s) and bits within byte(s) */
2904 bit_offset = col * bps * spp;
2905 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
2906 {
2907 if (sindex == 0)
2908 {
2909 src_byte = bit_offset / 8;
2910 src_bit = bit_offset % 8;
2911 }
2912 else
2913 {
2914 src_byte = (bit_offset + (sindex * bps)) / 8;
2915 src_bit = (bit_offset + (sindex * bps)) % 8;
2916 }
2917
2918 src = in + src_byte;
2919 matchbits = maskbits << (32 - src_bit - bps);
2920 if (little_endian)
2921 buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
2922 else
2923 buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
2924 buff1 = (buff1 & matchbits) << (src_bit);
2925
2926 if (ready_bits < 16) /* add another bps bits to the buffer */
2927 {
2928 bytebuff1 = bytebuff2 = 0;
2929 buff2 = (buff2 | (buff1 >> ready_bits));
2930 }
2931 else /* If we have a full buffer's worth, write it out */
2932 {
2933 bytebuff1 = (buff2 >> 24);
2934 *dst++ = bytebuff1;
2935 bytebuff2 = (buff2 >> 16);
2936 *dst++ = bytebuff2;
2937 ready_bits -= 16;
2938
2939 /* shift in new bits */
2940 buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
2941 }
2942 ready_bits += bps;
2943 }
2944 }
2945
2946 /* catch any trailing bits at the end of the line */
2947 while (ready_bits > 0)
2948 {
2949 bytebuff1 = (buff2 >> 24);
2950 *dst++ = bytebuff1;
2951
2952 buff2 = (buff2 << 8);
2953 bytebuff2 = bytebuff1;
2954 ready_bits -= 8;
2955 }
2956
2957 return (0);
2958 } /* end extractContigSamples24bits */
2959
2960 static int
2961 extractContigSamples32bits (uint8 *in, uint8 *out, uint32 cols,
2962 tsample_t sample, uint16 spp, uint16 bps,
2963 tsample_t count, uint32 start, uint32 end)
2964 {
2965 int ready_bits = 0, sindex = 0, shift_width = 0;
2966 uint32 col, src_byte, src_bit, bit_offset;
2967 uint32 longbuff1 = 0, longbuff2 = 0;
2968 uint64 maskbits = 0, matchbits = 0;
2969 uint64 buff1 = 0, buff2 = 0, buff3 = 0;
2970 uint8 bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
2971 uint8 *src = in;
2972 uint8 *dst = out;
2973
2974 if ((in == NULL) || (out == NULL))
2975 {
2976 TIFFError("extractContigSamples32bits","Invalid input or output buffer");
2977 return (1);
2978 }
2979
2980
2981 if ((start > end) || (start > cols))
2982 {
2983 TIFFError ("extractContigSamples32bits",
2984 "Invalid start column value %d ignored", start);
2985 start = 0;
2986 }
2987 if ((end == 0) || (end > cols))
2988 {
2989 TIFFError ("extractContigSamples32bits",
2990 "Invalid end column value %d ignored", end);
2991 end = cols;
2992 }
2993
2994 shift_width = ((bps + 7) / 8) + 1;
2995 ready_bits = 0;
2996 maskbits = (uint64)-1 >> ( 64 - bps);
2997 for (col = start; col < end; col++)
2998 {
2999 /* Compute src byte(s) and bits within byte(s) */
3000 bit_offset = col * bps * spp;
3001 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
3002 {
3003 if (sindex == 0)
3004 {
3005 src_byte = bit_offset / 8;
3006 src_bit = bit_offset % 8;
3007 }
3008 else
3009 {
3010 src_byte = (bit_offset + (sindex * bps)) / 8;
3011 src_bit = (bit_offset + (sindex * bps)) % 8;
3012 }
3013
3014 src = in + src_byte;
3015 matchbits = maskbits << (64 - src_bit - bps);
3016 if (little_endian)
3017 {
3018 longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
3019 longbuff2 = longbuff1;
3020 }
3021 else
3022 {
3023 longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
3024 longbuff2 = longbuff1;
3025 }
3026
3027 buff3 = ((uint64)longbuff1 << 32) | longbuff2;
3028 buff1 = (buff3 & matchbits) << (src_bit);
3029
3030 /* If we have a full buffer's worth, write it out */
3031 if (ready_bits >= 32)
3032 {
3033 bytebuff1 = (buff2 >> 56);
3034 *dst++ = bytebuff1;
3035 bytebuff2 = (buff2 >> 48);
3036 *dst++ = bytebuff2;
3037 bytebuff3 = (buff2 >> 40);
3038 *dst++ = bytebuff3;
3039 bytebuff4 = (buff2 >> 32);
3040 *dst++ = bytebuff4;
3041 ready_bits -= 32;
3042
3043 /* shift in new bits */
3044 buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
3045 }
3046 else
3047 { /* add another bps bits to the buffer */
3048 bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
3049 buff2 = (buff2 | (buff1 >> ready_bits));
3050 }
3051 ready_bits += bps;
3052 }
3053 }
3054 while (ready_bits > 0)
3055 {
3056 bytebuff1 = (buff2 >> 56);
3057 *dst++ = bytebuff1;
3058 buff2 = (buff2 << 8);
3059 ready_bits -= 8;
3060 }
3061
3062 return (0);
3063 } /* end extractContigSamples32bits */
3064
3065 static int
3066 extractContigSamplesShifted8bits (uint8 *in, uint8 *out, uint32 cols,
3067 tsample_t sample, uint16 spp, uint16 bps,
3068 tsample_t count, uint32 start, uint32 end,
3069 int shift)
3070 {
3071 int ready_bits = 0, sindex = 0;
3072 uint32 col, src_byte, src_bit, bit_offset;
3073 uint8 maskbits = 0, matchbits = 0;
3074 uint8 buff1 = 0, buff2 = 0;
3075 uint8 *src = in;
3076 uint8 *dst = out;
3077
3078 if ((src == NULL) || (dst == NULL))
3079 {
3080 TIFFError("extractContigSamplesShifted8bits","Invalid input or output buffer");
3081 return (1);
3082 }
3083
3084 if ((start > end) || (start > cols))
3085 {
3086 TIFFError ("extractContigSamplesShifted8bits",
3087 "Invalid start column value %d ignored", start);
3088 start = 0;
3089 }
3090 if ((end == 0) || (end > cols))
3091 {
3092 TIFFError ("extractContigSamplesShifted8bits",
3093 "Invalid end column value %d ignored", end);
3094 end = cols;
3095 }
3096
3097 ready_bits = shift;
3098 maskbits = (uint8)-1 >> ( 8 - bps);
3099 buff1 = buff2 = 0;
3100 for (col = start; col < end; col++)
3101 { /* Compute src byte(s) and bits within byte(s) */
3102 bit_offset = col * bps * spp;
3103 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
3104 {
3105 if (sindex == 0)
3106 {
3107 src_byte = bit_offset / 8;
3108 src_bit = bit_offset % 8;
3109 }
3110 else
3111 {
3112 src_byte = (bit_offset + (sindex * bps)) / 8;
3113 src_bit = (bit_offset + (sindex * bps)) % 8;
3114 }
3115
3116 src = in + src_byte;
3117 matchbits = maskbits << (8 - src_bit - bps);
3118 buff1 = ((*src) & matchbits) << (src_bit);
3119 if ((col == start) && (sindex == sample))
3120 buff2 = *src & ((uint8)-1) << (shift);
3121
3122 /* If we have a full buffer's worth, write it out */
3123 if (ready_bits >= 8)
3124 {
3125 *dst++ |= buff2;
3126 buff2 = buff1;
3127 ready_bits -= 8;
3128 }
3129 else
3130 buff2 = buff2 | (buff1 >> ready_bits);
3131 ready_bits += bps;
3132 }
3133 }
3134
3135 while (ready_bits > 0)
3136 {
3137 buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
3138 *dst++ = buff1;
3139 ready_bits -= 8;
3140 }
3141
3142 return (0);
3143 } /* end extractContigSamplesShifted8bits */
3144
3145 static int
3146 extractContigSamplesShifted16bits (uint8 *in, uint8 *out, uint32 cols,
3147 tsample_t sample, uint16 spp, uint16 bps,
3148 tsample_t count, uint32 start, uint32 end,
3149 int shift)
3150 {
3151 int ready_bits = 0, sindex = 0;
3152 uint32 col, src_byte, src_bit, bit_offset;
3153 uint16 maskbits = 0, matchbits = 0;
3154 uint16 buff1 = 0, buff2 = 0;
3155 uint8 bytebuff = 0;
3156 uint8 *src = in;
3157 uint8 *dst = out;
3158
3159 if ((src == NULL) || (dst == NULL))
3160 {
3161 TIFFError("extractContigSamplesShifted16bits","Invalid input or output buffer");
3162 return (1);
3163 }
3164
3165 if ((start > end) || (start > cols))
3166 {
3167 TIFFError ("extractContigSamplesShifted16bits",
3168 "Invalid start column value %d ignored", start);
3169 start = 0;
3170 }
3171 if ((end == 0) || (end > cols))
3172 {
3173 TIFFError ("extractContigSamplesShifted16bits",
3174 "Invalid end column value %d ignored", end);
3175 end = cols;
3176 }
3177
3178 ready_bits = shift;
3179 maskbits = (uint16)-1 >> (16 - bps);
3180 for (col = start; col < end; col++)
3181 { /* Compute src byte(s) and bits within byte(s) */
3182 bit_offset = col * bps * spp;
3183 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
3184 {
3185 if (sindex == 0)
3186 {
3187 src_byte = bit_offset / 8;
3188 src_bit = bit_offset % 8;
3189 }
3190 else
3191 {
3192 src_byte = (bit_offset + (sindex * bps)) / 8;
3193 src_bit = (bit_offset + (sindex * bps)) % 8;
3194 }
3195
3196 src = in + src_byte;
3197 matchbits = maskbits << (16 - src_bit - bps);
3198 if (little_endian)
3199 buff1 = (src[0] << 8) | src[1];
3200 else
3201 buff1 = (src[1] << 8) | src[0];
3202
3203 if ((col == start) && (sindex == sample))
3204 buff2 = buff1 & ((uint16)-1) << (8 - shift);
3205
3206 buff1 = (buff1 & matchbits) << (src_bit);
3207
3208 if (ready_bits < 8) /* add another bps bits to the buffer */
3209 buff2 = buff2 | (buff1 >> ready_bits);
3210 else /* If we have a full buffer's worth, write it out */
3211 {
3212 bytebuff = (buff2 >> 8);
3213 *dst++ = bytebuff;
3214 ready_bits -= 8;
3215 /* shift in new bits */
3216 buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
3217 }
3218
3219 ready_bits += bps;
3220 }
3221 }
3222
3223 /* catch any trailing bits at the end of the line */
3224 while (ready_bits > 0)
3225 {
3226 bytebuff = (buff2 >> 8);
3227 *dst++ = bytebuff;
3228 ready_bits -= 8;
3229 }
3230
3231 return (0);
3232 } /* end extractContigSamplesShifted16bits */
3233
3234
3235 static int
3236 extractContigSamplesShifted24bits (uint8 *in, uint8 *out, uint32 cols,
3237 tsample_t sample, uint16 spp, uint16 bps,
3238 tsample_t count, uint32 start, uint32 end,
3239 int shift)
3240 {
3241 int ready_bits = 0, sindex = 0;
3242 uint32 col, src_byte, src_bit, bit_offset;
3243 uint32 maskbits = 0, matchbits = 0;
3244 uint32 buff1 = 0, buff2 = 0;
3245 uint8 bytebuff1 = 0, bytebuff2 = 0;
3246 uint8 *src = in;
3247 uint8 *dst = out;
3248
3249 if ((in == NULL) || (out == NULL))
3250 {
3251 TIFFError("extractContigSamplesShifted24bits","Invalid input or output buffer");
3252 return (1);
3253 }
3254
3255 if ((start > end) || (start > cols))
3256 {
3257 TIFFError ("extractContigSamplesShifted24bits",
3258 "Invalid start column value %d ignored", start);
3259 start = 0;
3260 }
3261 if ((end == 0) || (end > cols))
3262 {
3263 TIFFError ("extractContigSamplesShifted24bits",
3264 "Invalid end column value %d ignored", end);
3265 end = cols;
3266 }
3267
3268 ready_bits = shift;
3269 maskbits = (uint32)-1 >> ( 32 - bps);
3270 for (col = start; col < end; col++)
3271 {
3272 /* Compute src byte(s) and bits within byte(s) */
3273 bit_offset = col * bps * spp;
3274 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
3275 {
3276 if (sindex == 0)
3277 {
3278 src_byte = bit_offset / 8;
3279 src_bit = bit_offset % 8;
3280 }
3281 else
3282 {
3283 src_byte = (bit_offset + (sindex * bps)) / 8;
3284 src_bit = (bit_offset + (sindex * bps)) % 8;
3285 }
3286
3287 src = in + src_byte;
3288 matchbits = maskbits << (32 - src_bit - bps);
3289 if (little_endian)
3290 buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
3291 else
3292 buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
3293
3294 if ((col == start) && (sindex == sample))
3295 buff2 = buff1 & ((uint32)-1) << (16 - shift);
3296
3297 buff1 = (buff1 & matchbits) << (src_bit);
3298
3299 if (ready_bits < 16) /* add another bps bits to the buffer */
3300 {
3301 bytebuff1 = bytebuff2 = 0;
3302 buff2 = (buff2 | (buff1 >> ready_bits));
3303 }
3304 else /* If we have a full buffer's worth, write it out */
3305 {
3306 bytebuff1 = (buff2 >> 24);
3307 *dst++ = bytebuff1;
3308 bytebuff2 = (buff2 >> 16);
3309 *dst++ = bytebuff2;
3310 ready_bits -= 16;
3311
3312 /* shift in new bits */
3313 buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
3314 }
3315 ready_bits += bps;
3316 }
3317 }
3318
3319 /* catch any trailing bits at the end of the line */
3320 while (ready_bits > 0)
3321 {
3322 bytebuff1 = (buff2 >> 24);
3323 *dst++ = bytebuff1;
3324
3325 buff2 = (buff2 << 8);
3326 bytebuff2 = bytebuff1;
3327 ready_bits -= 8;
3328 }
3329
3330 return (0);
3331 } /* end extractContigSamplesShifted24bits */
3332
3333 static int
3334 extractContigSamplesShifted32bits (uint8 *in, uint8 *out, uint32 cols,
3335 tsample_t sample, uint16 spp, uint16 bps,
3336 tsample_t count, uint32 start, uint32 end,
3337 int shift)
3338 {
3339 int ready_bits = 0, sindex = 0, shift_width = 0;
3340 uint32 col, src_byte, src_bit, bit_offset;
3341 uint32 longbuff1 = 0, longbuff2 = 0;
3342 uint64 maskbits = 0, matchbits = 0;
3343 uint64 buff1 = 0, buff2 = 0, buff3 = 0;
3344 uint8 bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
3345 uint8 *src = in;
3346 uint8 *dst = out;
3347
3348 if ((in == NULL) || (out == NULL))
3349 {
3350 TIFFError("extractContigSamplesShifted32bits","Invalid input or output buffer");
3351 return (1);
3352 }
3353
3354
3355 if ((start > end) || (start > cols))
3356 {
3357 TIFFError ("extractContigSamplesShifted32bits",
3358 "Invalid start column value %d ignored", start);
3359 start = 0;
3360 }
3361 if ((end == 0) || (end > cols))
3362 {
3363 TIFFError ("extractContigSamplesShifted32bits",
3364 "Invalid end column value %d ignored", end);
3365 end = cols;
3366 }
3367
3368 shift_width = ((bps + 7) / 8) + 1;
3369 ready_bits = shift;
3370 maskbits = (uint64)-1 >> ( 64 - bps);
3371 for (col = start; col < end; col++)
3372 {
3373 /* Compute src byte(s) and bits within byte(s) */
3374 bit_offset = col * bps * spp;
3375 for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
3376 {
3377 if (sindex == 0)
3378 {
3379 src_byte = bit_offset / 8;
3380 src_bit = bit_offset % 8;
3381 }
3382 else
3383 {
3384 src_byte = (bit_offset + (sindex * bps)) / 8;
3385 src_bit = (bit_offset + (sindex * bps)) % 8;
3386 }
3387
3388 src = in + src_byte;
3389 matchbits = maskbits << (64 - src_bit - bps);
3390 if (little_endian)
3391 {
3392 longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
3393 longbuff2 = longbuff1;
3394 }
3395 else
3396 {
3397 longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
3398 longbuff2 = longbuff1;
3399 }
3400
3401 buff3 = ((uint64)longbuff1 << 32) | longbuff2;
3402 if ((col == start) && (sindex == sample))
3403 buff2 = buff3 & ((uint64)-1) << (32 - shift);
3404
3405 buff1 = (buff3 & matchbits) << (src_bit);
3406
3407 if (ready_bits < 32)
3408 { /* add another bps bits to the buffer */
3409 bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
3410 buff2 = (buff2 | (buff1 >> ready_bits));
3411 }
3412 else /* If we have a full buffer's worth, write it out */
3413 {
3414 bytebuff1 = (buff2 >> 56);
3415 *dst++ = bytebuff1;
3416 bytebuff2 = (buff2 >> 48);
3417 *dst++ = bytebuff2;
3418 bytebuff3 = (buff2 >> 40);
3419 *dst++ = bytebuff3;
3420 bytebuff4 = (buff2 >> 32);
3421 *dst++ = bytebuff4;
3422 ready_bits -= 32;
3423
3424 /* shift in new bits */
3425 buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
3426 }
3427 ready_bits += bps;
3428 }
3429 }
3430 while (ready_bits > 0)
3431 {
3432 bytebuff1 = (buff2 >> 56);
3433 *dst++ = bytebuff1;
3434 buff2 = (buff2 << 8);
3435 ready_bits -= 8;
3436 }
3437
3438 return (0);
3439 } /* end extractContigSamplesShifted32bits */
3440
3441 static int
3442 extractContigSamplesToBuffer(uint8 *out, uint8 *in, uint32 rows, uint32 cols,
3443 tsample_t sample, uint16 spp, uint16 bps,
3444 struct dump_opts *dump)
3445 {
3446 int shift_width, bytes_per_sample, bytes_per_pixel;
3447 uint32 src_rowsize, src_offset, row, first_col = 0;
3448 uint32 dst_rowsize, dst_offset;
3449 tsample_t count = 1;
3450 uint8 *src, *dst;
3451
3452 bytes_per_sample = (bps + 7) / 8;
3453 bytes_per_pixel = ((bps * spp) + 7) / 8;
3454 if ((bps % 8) == 0)
3455 shift_width = 0;
3456 else
3457 {
3458 if (bytes_per_pixel < (bytes_per_sample + 1))
3459 shift_width = bytes_per_pixel;
3460 else
3461 shift_width = bytes_per_sample + 1;
3462 }
3463 src_rowsize = ((bps * spp * cols) + 7) / 8;
3464 dst_rowsize = ((bps * cols) + 7) / 8;
3465
3466 if ((dump->outfile != NULL) && (dump->level == 4))
3467 {
3468 dump_info (dump->outfile, dump->format, "extractContigSamplesToBuffer",
3469 "Sample %d, %d rows", sample + 1, rows + 1);
3470 }
3471 for (row = 0; row < rows; row++)
3472 {
3473 src_offset = row * src_rowsize;
3474 dst_offset = row * dst_rowsize;
3475 src = in + src_offset;
3476 dst = out + dst_offset;
3477
3478 /* pack the data into the scanline */
3479 switch (shift_width)
3480 {
3481 case 0: if (extractContigSamplesBytes (src, dst, cols, sample,
3482 spp, bps, count, first_col, cols))
3483 return (1);
3484 break;
3485 case 1: if (bps == 1)
3486 {
3487 if (extractContigSamples8bits (src, dst, cols, sample,
3488 spp, bps, count, first_col, cols))
3489 return (1);
3490 break;
3491 }
3492 else
3493 if (extractContigSamples16bits (src, dst, cols, sample,
3494 spp, bps, count, first_col, cols))
3495 return (1);
3496 break;
3497 case 2: if (extractContigSamples24bits (src, dst, cols, sample,
3498 spp, bps, count, first_col, cols))
3499 return (1);
3500 break;
3501 case 3:
3502 case 4:
3503 case 5: if (extractContigSamples32bits (src, dst, cols, sample,
3504 spp, bps, count, first_col, cols))
3505 return (1);
3506 break;
3507 default: TIFFError ("extractContigSamplesToBuffer", "Unsupported bit depth: %d", bps);
3508 return (1);
3509 }
3510 if ((dump->outfile != NULL) && (dump->level == 4))
3511 dump_buffer(dump->outfile, dump->format, 1, dst_rowsize, row, dst);
3512 }
3513
3514 return (0);
3515 } /* end extractContigSamplesToBuffer */
3516
3517 static int
3518 extractContigSamplesToTileBuffer(uint8 *out, uint8 *in, uint32 rows, uint32 cols,
3519 uint32 imagewidth, uint32 tilewidth, tsample_t sample,
3520 uint16 count, uint16 spp, uint16 bps, struct dump_opts *dump)
3521 {
3522 int shift_width, bytes_per_sample, bytes_per_pixel;
3523 uint32 src_rowsize, src_offset, row;
3524 uint32 dst_rowsize, dst_offset;
3525 uint8 *src, *dst;
3526
3527 bytes_per_sample = (bps + 7) / 8;
3528 bytes_per_pixel = ((bps * spp) + 7) / 8;
3529 if ((bps % 8) == 0)
3530 shift_width = 0;
3531 else
3532 {
3533 if (bytes_per_pixel < (bytes_per_sample + 1))
3534 shift_width = bytes_per_pixel;
3535 else
3536 shift_width = bytes_per_sample + 1;
3537 }
3538
3539 if ((dump->outfile != NULL) && (dump->level == 4))
3540 {
3541 dump_info (dump->outfile, dump->format, "extractContigSamplesToTileBuffer",
3542 "Sample %d, %d rows", sample + 1, rows + 1);
3543 }
3544
3545 src_rowsize = ((bps * spp * imagewidth) + 7) / 8;
3546 dst_rowsize = ((bps * tilewidth * count) + 7) / 8;
3547
3548 for (row = 0; row < rows; row++)
3549 {
3550 src_offset = row * src_rowsize;
3551 dst_offset = row * dst_rowsize;
3552 src = in + src_offset;
3553 dst = out + dst_offset;
3554
3555 /* pack the data into the scanline */
3556 switch (shift_width)
3557 {
3558 case 0: if (extractContigSamplesBytes (src, dst, cols, sample,
3559 spp, bps, count, 0, cols))
3560 return (1);
3561 break;
3562 case 1: if (bps == 1)
3563 {
3564 if (extractContigSamples8bits (src, dst, cols, sample,
3565 spp, bps, count, 0, cols))
3566 return (1);
3567 break;
3568 }
3569 else
3570 if (extractContigSamples16bits (src, dst, cols, sample,
3571 spp, bps, count, 0, cols))
3572 return (1);
3573 break;
3574 case 2: if (extractContigSamples24bits (src, dst, cols, sample,
3575 spp, bps, count, 0, cols))
3576 return (1);
3577 break;
3578 case 3:
3579 case 4:
3580 case 5: if (extractContigSamples32bits (src, dst, cols, sample,
3581 spp, bps, count, 0, cols))
3582 return (1);
3583 break;
3584 default: TIFFError ("extractContigSamplesToTileBuffer", "Unsupported bit depth: %d", bps);
3585 return (1);
3586 }
3587 if ((dump->outfile != NULL) && (dump->level == 4))
3588 dump_buffer(dump->outfile, dump->format, 1, dst_rowsize, row, dst);
3589 }
3590
3591 return (0);
3592 } /* end extractContigSamplesToTileBuffer */
3593
3594 static int readContigStripsIntoBuffer (TIFF* in, uint8* buf)
3595 {
3596 uint8* bufp = buf;
3597 int32 bytes_read = 0;
3598 uint16 strip, nstrips = TIFFNumberOfStrips(in);
3599 uint32 stripsize = TIFFStripSize(in);
3600 uint32 rows = 0;
3601 uint32 rps = TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rps);
3602 tsize_t scanline_size = TIFFScanlineSize(in);
3603
3604 for (strip = 0; strip < nstrips; strip++)
3605 {
3606 bytes_read = TIFFReadEncodedStrip (in, strip, bufp, -1);
3607 rows = bytes_read / scanline_size;
3608 if ((strip < (nstrips - 1)) && (bytes_read != (int32)stripsize))
3609 TIFFError("", "Strip %d: read %lu bytes, strip size %lu",
3610 (int)strip + 1, (unsigned long) bytes_read, (unsigned long)stripsize);
3611
3612 if (bytes_read < 0 && !ignore)
3613 {
3614 TIFFError("", "Error reading strip %lu after %lu rows",
3615 (unsigned long) strip, (unsigned long)rows);
3616 return 0;
3617 }
3618 bufp += bytes_read;
3619 }
3620
3621 return 1;
3622 } /* end readContigStripsIntoBuffer */
3623
3624 static int
3625 combineSeparateSamplesBytes (unsigned char *srcbuffs[], unsigned char *out,
3626 uint32 cols, uint32 rows, uint16 spp, uint16 bps,
3627 FILE *dumpfile, int format, int level)
3628 {
3629 int i, bytes_per_sample;
3630 uint32 row, col, col_offset, src_rowsize, dst_rowsize, row_offset;
3631 unsigned char *src;
3632 unsigned char *dst;
3633 tsample_t s;
3634
3635 src = srcbuffs[0];
3636 dst = out;
3637 if ((src == NULL) || (dst == NULL))
3638 {
3639 TIFFError("combineSeparateSamplesBytes","Invalid buffer address");
3640 return (1);
3641 }
3642
3643 bytes_per_sample = (bps + 7) / 8;
3644
3645 src_rowsize = ((bps * cols) + 7) / 8;
3646 dst_rowsize = ((bps * spp * cols) + 7) / 8;
3647 for (row = 0; row < rows; row++)
3648 {
3649 if ((dumpfile != NULL) && (level == 2))
3650 {
3651 for (s = 0; s < spp; s++)
3652 {
3653 dump_info (dumpfile, format, "combineSeparateSamplesBytes","Input data, Sample %d", s);
3654 dump_buffer(dumpfile, format, 1, cols, row, srcbuffs[s] + (row * src_rowsize));
3655 }
3656 }
3657 dst = out + (row * dst_rowsize);
3658 row_offset = row * src_rowsize;
3659 for (col = 0; col < cols; col++)
3660 {
3661 col_offset = row_offset + (col * (bps / 8));
3662 for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
3663 {
3664 src = srcbuffs[s] + col_offset;
3665 for (i = 0; i < bytes_per_sample; i++)
3666 *(dst + i) = *(src + i);
3667 src += bytes_per_sample;
3668 dst += bytes_per_sample;
3669 }
3670 }
3671
3672 if ((dumpfile != NULL) && (level == 2))
3673 {
3674 dump_info (dumpfile, format, "combineSeparateSamplesBytes","Output data, combined samples");
3675 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
3676 }
3677 }
3678
3679 return (0);
3680 } /* end combineSeparateSamplesBytes */
3681
3682 static int
3683 combineSeparateSamples8bits (uint8 *in[], uint8 *out, uint32 cols,
3684 uint32 rows, uint16 spp, uint16 bps,
3685 FILE *dumpfile, int format, int level)
3686 {
3687 int ready_bits = 0;
3688 int bytes_per_sample = 0;
3689 uint32 src_rowsize, dst_rowsize, src_offset;
3690 uint32 bit_offset;
3691 uint32 row, col, src_byte = 0, src_bit = 0;
3692 uint8 maskbits = 0, matchbits = 0;
3693 uint8 buff1 = 0, buff2 = 0;
3694 tsample_t s;
3695 unsigned char *src = in[0];
3696 unsigned char *dst = out;
3697 char action[32];
3698
3699 if ((src == NULL) || (dst == NULL))
3700 {
3701 TIFFError("combineSeparateSamples8bits","Invalid input or output buffer");
3702 return (1);
3703 }
3704
3705 bytes_per_sample = (bps + 7) / 8;
3706 src_rowsize = ((bps * cols) + 7) / 8;
3707 dst_rowsize = ((bps * cols * spp) + 7) / 8;
3708 maskbits = (uint8)-1 >> ( 8 - bps);
3709
3710 for (row = 0; row < rows; row++)
3711 {
3712 ready_bits = 0;
3713 buff1 = buff2 = 0;
3714 dst = out + (row * dst_rowsize);
3715 src_offset = row * src_rowsize;
3716 for (col = 0; col < cols; col++)
3717 {
3718 /* Compute src byte(s) and bits within byte(s) */
3719 bit_offset = col * bps;
3720 src_byte = bit_offset / 8;
3721 src_bit = bit_offset % 8;
3722
3723 matchbits = maskbits << (8 - src_bit - bps);
3724 /* load up next sample from each plane */
3725 for (s = 0; s < spp; s++)
3726 {
3727 src = in[s] + src_offset + src_byte;
3728 buff1 = ((*src) & matchbits) << (src_bit);
3729
3730 /* If we have a full buffer's worth, write it out */
3731 if (ready_bits >= 8)
3732 {
3733 *dst++ = buff2;
3734 buff2 = buff1;
3735 ready_bits -= 8;
3736 strcpy (action, "Flush");
3737 }
3738 else
3739 {
3740 buff2 = (buff2 | (buff1 >> ready_bits));
3741 strcpy (action, "Update");
3742 }
3743 ready_bits += bps;
3744
3745 if ((dumpfile != NULL) && (level == 3))
3746 {
3747 dump_info (dumpfile, format, "",
3748 "Row %3d, Col %3d, Samples %d, Src byte offset %3d bit offset %2d Dst offset %3d",
3749 row + 1, col + 1, s, src_byte, src_bit, dst - out);
3750 dump_byte (dumpfile, format, "Match bits", matchbits);
3751 dump_byte (dumpfile, format, "Src bits", *src);
3752 dump_byte (dumpfile, format, "Buff1 bits", buff1);
3753 dump_byte (dumpfile, format, "Buff2 bits", buff2);
3754 dump_info (dumpfile, format, "","%s", action);
3755 }
3756 }
3757 }
3758
3759 if (ready_bits > 0)
3760 {
3761 buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
3762 *dst++ = buff1;
3763 if ((dumpfile != NULL) && (level == 3))
3764 {
3765 dump_info (dumpfile, format, "",
3766 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
3767 row + 1, col + 1, src_byte, src_bit, dst - out);
3768 dump_byte (dumpfile, format, "Final bits", buff1);
3769 }
3770 }
3771
3772 if ((dumpfile != NULL) && (level >= 2))
3773 {
3774 dump_info (dumpfile, format, "combineSeparateSamples8bits","Output data");
3775 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
3776 }
3777 }
3778
3779 return (0);
3780 } /* end combineSeparateSamples8bits */
3781
3782 static int
3783 combineSeparateSamples16bits (uint8 *in[], uint8 *out, uint32 cols,
3784 uint32 rows, uint16 spp, uint16 bps,
3785 FILE *dumpfile, int format, int level)
3786 {
3787 int ready_bits = 0, bytes_per_sample = 0;
3788 uint32 src_rowsize, dst_rowsize;
3789 uint32 bit_offset, src_offset;
3790 uint32 row, col, src_byte = 0, src_bit = 0;
3791 uint16 maskbits = 0, matchbits = 0;
3792 uint16 buff1 = 0, buff2 = 0;
3793 uint8 bytebuff = 0;
3794 tsample_t s;
3795 unsigned char *src = in[0];
3796 unsigned char *dst = out;
3797 char action[8];
3798
3799 if ((src == NULL) || (dst == NULL))
3800 {
3801 TIFFError("combineSeparateSamples16bits","Invalid input or output buffer");
3802 return (1);
3803 }
3804
3805 bytes_per_sample = (bps + 7) / 8;
3806 src_rowsize = ((bps * cols) + 7) / 8;
3807 dst_rowsize = ((bps * cols * spp) + 7) / 8;
3808 maskbits = (uint16)-1 >> (16 - bps);
3809
3810 for (row = 0; row < rows; row++)
3811 {
3812 ready_bits = 0;
3813 buff1 = buff2 = 0;
3814 dst = out + (row * dst_rowsize);
3815 src_offset = row * src_rowsize;
3816 for (col = 0; col < cols; col++)
3817 {
3818 /* Compute src byte(s) and bits within byte(s) */
3819 bit_offset = col * bps;
3820 src_byte = bit_offset / 8;
3821 src_bit = bit_offset % 8;
3822
3823 matchbits = maskbits << (16 - src_bit - bps);
3824 for (s = 0; s < spp; s++)
3825 {
3826 src = in[s] + src_offset + src_byte;
3827 if (little_endian)
3828 buff1 = (src[0] << 8) | src[1];
3829 else
3830 buff1 = (src[1] << 8) | src[0];
3831
3832 buff1 = (buff1 & matchbits) << (src_bit);
3833
3834 /* If we have a full buffer's worth, write it out */
3835 if (ready_bits >= 8)
3836 {
3837 bytebuff = (buff2 >> 8);
3838 *dst++ = bytebuff;
3839 ready_bits -= 8;
3840 /* shift in new bits */
3841 buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
3842 strcpy (action, "Flush");
3843 }
3844 else
3845 { /* add another bps bits to the buffer */
3846 bytebuff = 0;
3847 buff2 = (buff2 | (buff1 >> ready_bits));
3848 strcpy (action, "Update");
3849 }
3850 ready_bits += bps;
3851
3852 if ((dumpfile != NULL) && (level == 3))
3853 {
3854 dump_info (dumpfile, format, "",
3855 "Row %3d, Col %3d, Samples %d, Src byte offset %3d bit offset %2d Dst offset %3d",
3856 row + 1, col + 1, s, src_byte, src_bit, dst - out);
3857
3858 dump_short (dumpfile, format, "Match bits", matchbits);
3859 dump_data (dumpfile, format, "Src bits", src, 2);
3860 dump_short (dumpfile, format, "Buff1 bits", buff1);
3861 dump_short (dumpfile, format, "Buff2 bits", buff2);
3862 dump_byte (dumpfile, format, "Write byte", bytebuff);
3863 dump_info (dumpfile, format, "","Ready bits: %d, %s", ready_bits, action);
3864 }
3865 }
3866 }
3867
3868 /* catch any trailing bits at the end of the line */
3869 if (ready_bits > 0)
3870 {
3871 bytebuff = (buff2 >> 8);
3872 *dst++ = bytebuff;
3873 if ((dumpfile != NULL) && (level == 3))
3874 {
3875 dump_info (dumpfile, format, "",
3876 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
3877 row + 1, col + 1, src_byte, src_bit, dst - out);
3878 dump_byte (dumpfile, format, "Final bits", bytebuff);
3879 }
3880 }
3881
3882 if ((dumpfile != NULL) && (level == 2))
3883 {
3884 dump_info (dumpfile, format, "combineSeparateSamples16bits","Output data");
3885 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
3886 }
3887 }
3888
3889 return (0);
3890 } /* end combineSeparateSamples16bits */
3891
3892 static int
3893 combineSeparateSamples24bits (uint8 *in[], uint8 *out, uint32 cols,
3894 uint32 rows, uint16 spp, uint16 bps,
3895 FILE *dumpfile, int format, int level)
3896 {
3897 int ready_bits = 0, bytes_per_sample = 0;
3898 uint32 src_rowsize, dst_rowsize;
3899 uint32 bit_offset, src_offset;
3900 uint32 row, col, src_byte = 0, src_bit = 0;
3901 uint32 maskbits = 0, matchbits = 0;
3902 uint32 buff1 = 0, buff2 = 0;
3903 uint8 bytebuff1 = 0, bytebuff2 = 0;
3904 tsample_t s;
3905 unsigned char *src = in[0];
3906 unsigned char *dst = out;
3907 char action[8];
3908
3909 if ((src == NULL) || (dst == NULL))
3910 {
3911 TIFFError("combineSeparateSamples24bits","Invalid input or output buffer");
3912 return (1);
3913 }
3914
3915 bytes_per_sample = (bps + 7) / 8;
3916 src_rowsize = ((bps * cols) + 7) / 8;
3917 dst_rowsize = ((bps * cols * spp) + 7) / 8;
3918 maskbits = (uint32)-1 >> ( 32 - bps);
3919
3920 for (row = 0; row < rows; row++)
3921 {
3922 ready_bits = 0;
3923 buff1 = buff2 = 0;
3924 dst = out + (row * dst_rowsize);
3925 src_offset = row * src_rowsize;
3926 for (col = 0; col < cols; col++)
3927 {
3928 /* Compute src byte(s) and bits within byte(s) */
3929 bit_offset = col * bps;
3930 src_byte = bit_offset / 8;
3931 src_bit = bit_offset % 8;
3932
3933 matchbits = maskbits << (32 - src_bit - bps);
3934 for (s = 0; s < spp; s++)
3935 {
3936 src = in[s] + src_offset + src_byte;
3937 if (little_endian)
3938 buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
3939 else
3940 buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
3941 buff1 = (buff1 & matchbits) << (src_bit);
3942
3943 /* If we have a full buffer's worth, write it out */
3944 if (ready_bits >= 16)
3945 {
3946 bytebuff1 = (buff2 >> 24);
3947 *dst++ = bytebuff1;
3948 bytebuff2 = (buff2 >> 16);
3949 *dst++ = bytebuff2;
3950 ready_bits -= 16;
3951
3952 /* shift in new bits */
3953 buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
3954 strcpy (action, "Flush");
3955 }
3956 else
3957 { /* add another bps bits to the buffer */
3958 bytebuff1 = bytebuff2 = 0;
3959 buff2 = (buff2 | (buff1 >> ready_bits));
3960 strcpy (action, "Update");
3961 }
3962 ready_bits += bps;
3963
3964 if ((dumpfile != NULL) && (level == 3))
3965 {
3966 dump_info (dumpfile, format, "",
3967 "Row %3d, Col %3d, Samples %d, Src byte offset %3d bit offset %2d Dst offset %3d",
3968 row + 1, col + 1, s, src_byte, src_bit, dst - out);
3969 dump_long (dumpfile, format, "Match bits ", matchbits);
3970 dump_data (dumpfile, format, "Src bits ", src, 4);
3971 dump_long (dumpfile, format, "Buff1 bits ", buff1);
3972 dump_long (dumpfile, format, "Buff2 bits ", buff2);
3973 dump_byte (dumpfile, format, "Write bits1", bytebuff1);
3974 dump_byte (dumpfile, format, "Write bits2", bytebuff2);
3975 dump_info (dumpfile, format, "","Ready bits: %d, %s", ready_bits, action);
3976 }
3977 }
3978 }
3979
3980 /* catch any trailing bits at the end of the line */
3981 while (ready_bits > 0)
3982 {
3983 bytebuff1 = (buff2 >> 24);
3984 *dst++ = bytebuff1;
3985
3986 buff2 = (buff2 << 8);
3987 bytebuff2 = bytebuff1;
3988 ready_bits -= 8;
3989 }
3990
3991 if ((dumpfile != NULL) && (level == 3))
3992 {
3993 dump_info (dumpfile, format, "",
3994 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
3995 row + 1, col + 1, src_byte, src_bit, dst - out);
3996
3997 dump_long (dumpfile, format, "Match bits ", matchbits);
3998 dump_data (dumpfile, format, "Src bits ", src, 4);
3999 dump_long (dumpfile, format, "Buff1 bits ", buff1);
4000 dump_long (dumpfile, format, "Buff2 bits ", buff2);
4001 dump_byte (dumpfile, format, "Write bits1", bytebuff1);
4002 dump_byte (dumpfile, format, "Write bits2", bytebuff2);
4003 dump_info (dumpfile, format, "", "Ready bits: %2d", ready_bits);
4004 }
4005
4006 if ((dumpfile != NULL) && (level == 2))
4007 {
4008 dump_info (dumpfile, format, "combineSeparateSamples24bits","Output data");
4009 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
4010 }
4011 }
4012
4013 return (0);
4014 } /* end combineSeparateSamples24bits */
4015
4016 static int
4017 combineSeparateSamples32bits (uint8 *in[], uint8 *out, uint32 cols,
4018 uint32 rows, uint16 spp, uint16 bps,
4019 FILE *dumpfile, int format, int level)
4020 {
4021 int ready_bits = 0, bytes_per_sample = 0, shift_width = 0;
4022 uint32 src_rowsize, dst_rowsize, bit_offset, src_offset;
4023 uint32 src_byte = 0, src_bit = 0;
4024 uint32 row, col;
4025 uint32 longbuff1 = 0, longbuff2 = 0;
4026 uint64 maskbits = 0, matchbits = 0;
4027 uint64 buff1 = 0, buff2 = 0, buff3 = 0;
4028 uint8 bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
4029 tsample_t s;
4030 unsigned char *src = in[0];
4031 unsigned char *dst = out;
4032 char action[8];
4033
4034 if ((src == NULL) || (dst == NULL))
4035 {
4036 TIFFError("combineSeparateSamples32bits","Invalid input or output buffer");
4037 return (1);
4038 }
4039
4040 bytes_per_sample = (bps + 7) / 8;
4041 src_rowsize = ((bps * cols) + 7) / 8;
4042 dst_rowsize = ((bps * cols * spp) + 7) / 8;
4043 maskbits = (uint64)-1 >> ( 64 - bps);
4044 shift_width = ((bps + 7) / 8) + 1;
4045
4046 for (row = 0; row < rows; row++)
4047 {
4048 ready_bits = 0;
4049 buff1 = buff2 = 0;
4050 dst = out + (row * dst_rowsize);
4051 src_offset = row * src_rowsize;
4052 for (col = 0; col < cols; col++)
4053 {
4054 /* Compute src byte(s) and bits within byte(s) */
4055 bit_offset = col * bps;
4056 src_byte = bit_offset / 8;
4057 src_bit = bit_offset % 8;
4058
4059 matchbits = maskbits << (64 - src_bit - bps);
4060 for (s = 0; s < spp; s++)
4061 {
4062 src = in[s] + src_offset + src_byte;
4063 if (little_endian)
4064 {
4065 longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
4066 longbuff2 = longbuff1;
4067 }
4068 else
4069 {
4070 longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
4071 longbuff2 = longbuff1;
4072 }
4073 buff3 = ((uint64)longbuff1 << 32) | longbuff2;
4074 buff1 = (buff3 & matchbits) << (src_bit);
4075
4076 /* If we have a full buffer's worth, write it out */
4077 if (ready_bits >= 32)
4078 {
4079 bytebuff1 = (buff2 >> 56);
4080 *dst++ = bytebuff1;
4081 bytebuff2 = (buff2 >> 48);
4082 *dst++ = bytebuff2;
4083 bytebuff3 = (buff2 >> 40);
4084 *dst++ = bytebuff3;
4085 bytebuff4 = (buff2 >> 32);
4086 *dst++ = bytebuff4;
4087 ready_bits -= 32;
4088
4089 /* shift in new bits */
4090 buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
4091 strcpy (action, "Flush");
4092 }
4093 else
4094 { /* add another bps bits to the buffer */
4095 bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
4096 buff2 = (buff2 | (buff1 >> ready_bits));
4097 strcpy (action, "Update");
4098 }
4099 ready_bits += bps;
4100
4101 if ((dumpfile != NULL) && (level == 3))
4102 {
4103 dump_info (dumpfile, format, "",
4104 "Row %3d, Col %3d, Sample %d, Src byte offset %3d bit offset %2d Dst offset %3d",
4105 row + 1, col + 1, s, src_byte, src_bit, dst - out);
4106 dump_wide (dumpfile, format, "Match bits ", matchbits);
4107 dump_data (dumpfile, format, "Src bits ", src, 8);
4108 dump_wide (dumpfile, format, "Buff1 bits ", buff1);
4109 dump_wide (dumpfile, format, "Buff2 bits ", buff2);
4110 dump_info (dumpfile, format, "", "Ready bits: %d, %s", ready_bits, action);
4111 }
4112 }
4113 }
4114 while (ready_bits > 0)
4115 {
4116 bytebuff1 = (buff2 >> 56);
4117 *dst++ = bytebuff1;
4118 buff2 = (buff2 << 8);
4119 ready_bits -= 8;
4120 }
4121
4122 if ((dumpfile != NULL) && (level == 3))
4123 {
4124 dump_info (dumpfile, format, "",
4125 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
4126 row + 1, col + 1, src_byte, src_bit, dst - out);
4127
4128 dump_long (dumpfile, format, "Match bits ", matchbits);
4129 dump_data (dumpfile, format, "Src bits ", src, 4);
4130 dump_long (dumpfile, format, "Buff1 bits ", buff1);
4131 dump_long (dumpfile, format, "Buff2 bits ", buff2);
4132 dump_byte (dumpfile, format, "Write bits1", bytebuff1);
4133 dump_byte (dumpfile, format, "Write bits2", bytebuff2);
4134 dump_info (dumpfile, format, "", "Ready bits: %2d", ready_bits);
4135 }
4136
4137 if ((dumpfile != NULL) && (level == 2))
4138 {
4139 dump_info (dumpfile, format, "combineSeparateSamples32bits","Output data");
4140 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out);
4141 }
4142 }
4143
4144 return (0);
4145 } /* end combineSeparateSamples32bits */
4146
4147 static int
4148 combineSeparateTileSamplesBytes (unsigned char *srcbuffs[], unsigned char *out,
4149 uint32 cols, uint32 rows, uint32 imagewidth,
4150 uint32 tw, uint16 spp, uint16 bps,
4151 FILE *dumpfile, int format, int level)
4152 {
4153 int i, bytes_per_sample;
4154 uint32 row, col, col_offset, src_rowsize, dst_rowsize, src_offset;
4155 unsigned char *src;
4156 unsigned char *dst;
4157 tsample_t s;
4158
4159 src = srcbuffs[0];
4160 dst = out;
4161 if ((src == NULL) || (dst == NULL))
4162 {
4163 TIFFError("combineSeparateTileSamplesBytes","Invalid buffer address");
4164 return (1);
4165 }
4166
4167 bytes_per_sample = (bps + 7) / 8;
4168 src_rowsize = ((bps * tw) + 7) / 8;
4169 dst_rowsize = imagewidth * bytes_per_sample * spp;
4170 for (row = 0; row < rows; row++)
4171 {
4172 if ((dumpfile != NULL) && (level == 2))
4173 {
4174 for (s = 0; s < spp; s++)
4175 {
4176 dump_info (dumpfile, format, "combineSeparateTileSamplesBytes","Input data, Sample %d", s);
4177 dump_buffer(dumpfile, format, 1, cols, row, srcbuffs[s] + (row * src_rowsize));
4178 }
4179 }
4180 dst = out + (row * dst_rowsize);
4181 src_offset = row * src_rowsize;
4182 #ifdef DEVELMODE
4183 TIFFError("","Tile row %4d, Src offset %6d Dst offset %6d",
4184 row, src_offset, dst - out);
4185 #endif
4186 for (col = 0; col < cols; col++)
4187 {
4188 col_offset = src_offset + (col * (bps / 8));
4189 for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
4190 {
4191 src = srcbuffs[s] + col_offset;
4192 for (i = 0; i < bytes_per_sample; i++)
4193 *(dst + i) = *(src + i);
4194 dst += bytes_per_sample;
4195 }
4196 }
4197
4198 if ((dumpfile != NULL) && (level == 2))
4199 {
4200 dump_info (dumpfile, format, "combineSeparateTileSamplesBytes","Output data, combined samples");
4201 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
4202 }
4203 }
4204
4205 return (0);
4206 } /* end combineSeparateTileSamplesBytes */
4207
4208 static int
4209 combineSeparateTileSamples8bits (uint8 *in[], uint8 *out, uint32 cols,
4210 uint32 rows, uint32 imagewidth,
4211 uint32 tw, uint16 spp, uint16 bps,
4212 FILE *dumpfile, int format, int level)
4213 {
4214 int ready_bits = 0;
4215 uint32 src_rowsize, dst_rowsize, src_offset;
4216 uint32 bit_offset;
4217 uint32 row, col, src_byte = 0, src_bit = 0;
4218 uint8 maskbits = 0, matchbits = 0;
4219 uint8 buff1 = 0, buff2 = 0;
4220 tsample_t s;
4221 unsigned char *src = in[0];
4222 unsigned char *dst = out;
4223 char action[32];
4224
4225 if ((src == NULL) || (dst == NULL))
4226 {
4227 TIFFError("combineSeparateTileSamples8bits","Invalid input or output buffer");
4228 return (1);
4229 }
4230
4231 src_rowsize = ((bps * tw) + 7) / 8;
4232 dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
4233 maskbits = (uint8)-1 >> ( 8 - bps);
4234
4235 for (row = 0; row < rows; row++)
4236 {
4237 ready_bits = 0;
4238 buff1 = buff2 = 0;
4239 dst = out + (row * dst_rowsize);
4240 src_offset = row * src_rowsize;
4241 for (col = 0; col < cols; col++)
4242 {
4243 /* Compute src byte(s) and bits within byte(s) */
4244 bit_offset = col * bps;
4245 src_byte = bit_offset / 8;
4246 src_bit = bit_offset % 8;
4247
4248 matchbits = maskbits << (8 - src_bit - bps);
4249 /* load up next sample from each plane */
4250 for (s = 0; s < spp; s++)
4251 {
4252 src = in[s] + src_offset + src_byte;
4253 buff1 = ((*src) & matchbits) << (src_bit);
4254
4255 /* If we have a full buffer's worth, write it out */
4256 if (ready_bits >= 8)
4257 {
4258 *dst++ = buff2;
4259 buff2 = buff1;
4260 ready_bits -= 8;
4261 strcpy (action, "Flush");
4262 }
4263 else
4264 {
4265 buff2 = (buff2 | (buff1 >> ready_bits));
4266 strcpy (action, "Update");
4267 }
4268 ready_bits += bps;
4269
4270 if ((dumpfile != NULL) && (level == 3))
4271 {
4272 dump_info (dumpfile, format, "",
4273 "Row %3d, Col %3d, Samples %d, Src byte offset %3d bit offset %2d Dst offset %3d",
4274 row + 1, col + 1, s, src_byte, src_bit, dst - out);
4275 dump_byte (dumpfile, format, "Match bits", matchbits);
4276 dump_byte (dumpfile, format, "Src bits", *src);
4277 dump_byte (dumpfile, format, "Buff1 bits", buff1);
4278 dump_byte (dumpfile, format, "Buff2 bits", buff2);
4279 dump_info (dumpfile, format, "","%s", action);
4280 }
4281 }
4282 }
4283
4284 if (ready_bits > 0)
4285 {
4286 buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
4287 *dst++ = buff1;
4288 if ((dumpfile != NULL) && (level == 3))
4289 {
4290 dump_info (dumpfile, format, "",
4291 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
4292 row + 1, col + 1, src_byte, src_bit, dst - out);
4293 dump_byte (dumpfile, format, "Final bits", buff1);
4294 }
4295 }
4296
4297 if ((dumpfile != NULL) && (level >= 2))
4298 {
4299 dump_info (dumpfile, format, "combineSeparateTileSamples8bits","Output data");
4300 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
4301 }
4302 }
4303
4304 return (0);
4305 } /* end combineSeparateTileSamples8bits */
4306
4307 static int
4308 combineSeparateTileSamples16bits (uint8 *in[], uint8 *out, uint32 cols,
4309 uint32 rows, uint32 imagewidth,
4310 uint32 tw, uint16 spp, uint16 bps,
4311 FILE *dumpfile, int format, int level)
4312 {
4313 int ready_bits = 0;
4314 uint32 src_rowsize, dst_rowsize;
4315 uint32 bit_offset, src_offset;
4316 uint32 row, col, src_byte = 0, src_bit = 0;
4317 uint16 maskbits = 0, matchbits = 0;
4318 uint16 buff1 = 0, buff2 = 0;
4319 uint8 bytebuff = 0;
4320 tsample_t s;
4321 unsigned char *src = in[0];
4322 unsigned char *dst = out;
4323 char action[8];
4324
4325 if ((src == NULL) || (dst == NULL))
4326 {
4327 TIFFError("combineSeparateTileSamples16bits","Invalid input or output buffer");
4328 return (1);
4329 }
4330
4331 src_rowsize = ((bps * tw) + 7) / 8;
4332 dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
4333 maskbits = (uint16)-1 >> (16 - bps);
4334
4335 for (row = 0; row < rows; row++)
4336 {
4337 ready_bits = 0;
4338 buff1 = buff2 = 0;
4339 dst = out + (row * dst_rowsize);
4340 src_offset = row * src_rowsize;
4341 for (col = 0; col < cols; col++)
4342 {
4343 /* Compute src byte(s) and bits within byte(s) */
4344 bit_offset = col * bps;
4345 src_byte = bit_offset / 8;
4346 src_bit = bit_offset % 8;
4347
4348 matchbits = maskbits << (16 - src_bit - bps);
4349 for (s = 0; s < spp; s++)
4350 {
4351 src = in[s] + src_offset + src_byte;
4352 if (little_endian)
4353 buff1 = (src[0] << 8) | src[1];
4354 else
4355 buff1 = (src[1] << 8) | src[0];
4356 buff1 = (buff1 & matchbits) << (src_bit);
4357
4358 /* If we have a full buffer's worth, write it out */
4359 if (ready_bits >= 8)
4360 {
4361 bytebuff = (buff2 >> 8);
4362 *dst++ = bytebuff;
4363 ready_bits -= 8;
4364 /* shift in new bits */
4365 buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
4366 strcpy (action, "Flush");
4367 }
4368 else
4369 { /* add another bps bits to the buffer */
4370 bytebuff = 0;
4371 buff2 = (buff2 | (buff1 >> ready_bits));
4372 strcpy (action, "Update");
4373 }
4374 ready_bits += bps;
4375
4376 if ((dumpfile != NULL) && (level == 3))
4377 {
4378 dump_info (dumpfile, format, "",
4379 "Row %3d, Col %3d, Samples %d, Src byte offset %3d bit offset %2d Dst offset %3d",
4380 row + 1, col + 1, s, src_byte, src_bit, dst - out);
4381
4382 dump_short (dumpfile, format, "Match bits", matchbits);
4383 dump_data (dumpfile, format, "Src bits", src, 2);
4384 dump_short (dumpfile, format, "Buff1 bits", buff1);
4385 dump_short (dumpfile, format, "Buff2 bits", buff2);
4386 dump_byte (dumpfile, format, "Write byte", bytebuff);
4387 dump_info (dumpfile, format, "","Ready bits: %d, %s", ready_bits, action);
4388 }
4389 }
4390 }
4391
4392 /* catch any trailing bits at the end of the line */
4393 if (ready_bits > 0)
4394 {
4395 bytebuff = (buff2 >> 8);
4396 *dst++ = bytebuff;
4397 if ((dumpfile != NULL) && (level == 3))
4398 {
4399 dump_info (dumpfile, format, "",
4400 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
4401 row + 1, col + 1, src_byte, src_bit, dst - out);
4402 dump_byte (dumpfile, format, "Final bits", bytebuff);
4403 }
4404 }
4405
4406 if ((dumpfile != NULL) && (level == 2))
4407 {
4408 dump_info (dumpfile, format, "combineSeparateTileSamples16bits","Output data");
4409 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
4410 }
4411 }
4412
4413 return (0);
4414 } /* end combineSeparateTileSamples16bits */
4415
4416 static int
4417 combineSeparateTileSamples24bits (uint8 *in[], uint8 *out, uint32 cols,
4418 uint32 rows, uint32 imagewidth,
4419 uint32 tw, uint16 spp, uint16 bps,
4420 FILE *dumpfile, int format, int level)
4421 {
4422 int ready_bits = 0;
4423 uint32 src_rowsize, dst_rowsize;
4424 uint32 bit_offset, src_offset;
4425 uint32 row, col, src_byte = 0, src_bit = 0;
4426 uint32 maskbits = 0, matchbits = 0;
4427 uint32 buff1 = 0, buff2 = 0;
4428 uint8 bytebuff1 = 0, bytebuff2 = 0;
4429 tsample_t s;
4430 unsigned char *src = in[0];
4431 unsigned char *dst = out;
4432 char action[8];
4433
4434 if ((src == NULL) || (dst == NULL))
4435 {
4436 TIFFError("combineSeparateTileSamples24bits","Invalid input or output buffer");
4437 return (1);
4438 }
4439
4440 src_rowsize = ((bps * tw) + 7) / 8;
4441 dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
4442 maskbits = (uint32)-1 >> ( 32 - bps);
4443
4444 for (row = 0; row < rows; row++)
4445 {
4446 ready_bits = 0;
4447 buff1 = buff2 = 0;
4448 dst = out + (row * dst_rowsize);
4449 src_offset = row * src_rowsize;
4450 for (col = 0; col < cols; col++)
4451 {
4452 /* Compute src byte(s) and bits within byte(s) */
4453 bit_offset = col * bps;
4454 src_byte = bit_offset / 8;
4455 src_bit = bit_offset % 8;
4456
4457 matchbits = maskbits << (32 - src_bit - bps);
4458 for (s = 0; s < spp; s++)
4459 {
4460 src = in[s] + src_offset + src_byte;
4461 if (little_endian)
4462 buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
4463 else
4464 buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
4465 buff1 = (buff1 & matchbits) << (src_bit);
4466
4467 /* If we have a full buffer's worth, write it out */
4468 if (ready_bits >= 16)
4469 {
4470 bytebuff1 = (buff2 >> 24);
4471 *dst++ = bytebuff1;
4472 bytebuff2 = (buff2 >> 16);
4473 *dst++ = bytebuff2;
4474 ready_bits -= 16;
4475
4476 /* shift in new bits */
4477 buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
4478 strcpy (action, "Flush");
4479 }
4480 else
4481 { /* add another bps bits to the buffer */
4482 bytebuff1 = bytebuff2 = 0;
4483 buff2 = (buff2 | (buff1 >> ready_bits));
4484 strcpy (action, "Update");
4485 }
4486 ready_bits += bps;
4487
4488 if ((dumpfile != NULL) && (level == 3))
4489 {
4490 dump_info (dumpfile, format, "",
4491 "Row %3d, Col %3d, Samples %d, Src byte offset %3d bit offset %2d Dst offset %3d",
4492 row + 1, col + 1, s, src_byte, src_bit, dst - out);
4493 dump_long (dumpfile, format, "Match bits ", matchbits);
4494 dump_data (dumpfile, format, "Src bits ", src, 4);
4495 dump_long (dumpfile, format, "Buff1 bits ", buff1);
4496 dump_long (dumpfile, format, "Buff2 bits ", buff2);
4497 dump_byte (dumpfile, format, "Write bits1", bytebuff1);
4498 dump_byte (dumpfile, format, "Write bits2", bytebuff2);
4499 dump_info (dumpfile, format, "","Ready bits: %d, %s", ready_bits, action);
4500 }
4501 }
4502 }
4503
4504 /* catch any trailing bits at the end of the line */
4505 while (ready_bits > 0)
4506 {
4507 bytebuff1 = (buff2 >> 24);
4508 *dst++ = bytebuff1;
4509
4510 buff2 = (buff2 << 8);
4511 bytebuff2 = bytebuff1;
4512 ready_bits -= 8;
4513 }
4514
4515 if ((dumpfile != NULL) && (level == 3))
4516 {
4517 dump_info (dumpfile, format, "",
4518 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
4519 row + 1, col + 1, src_byte, src_bit, dst - out);
4520
4521 dump_long (dumpfile, format, "Match bits ", matchbits);
4522 dump_data (dumpfile, format, "Src bits ", src, 4);
4523 dump_long (dumpfile, format, "Buff1 bits ", buff1);
4524 dump_long (dumpfile, format, "Buff2 bits ", buff2);
4525 dump_byte (dumpfile, format, "Write bits1", bytebuff1);
4526 dump_byte (dumpfile, format, "Write bits2", bytebuff2);
4527 dump_info (dumpfile, format, "", "Ready bits: %2d", ready_bits);
4528 }
4529
4530 if ((dumpfile != NULL) && (level == 2))
4531 {
4532 dump_info (dumpfile, format, "combineSeparateTileSamples24bits","Output data");
4533 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
4534 }
4535 }
4536
4537 return (0);
4538 } /* end combineSeparateTileSamples24bits */
4539
4540 static int
4541 combineSeparateTileSamples32bits (uint8 *in[], uint8 *out, uint32 cols,
4542 uint32 rows, uint32 imagewidth,
4543 uint32 tw, uint16 spp, uint16 bps,
4544 FILE *dumpfile, int format, int level)
4545 {
4546 int ready_bits = 0, shift_width = 0;
4547 uint32 src_rowsize, dst_rowsize, bit_offset, src_offset;
4548 uint32 src_byte = 0, src_bit = 0;
4549 uint32 row, col;
4550 uint32 longbuff1 = 0, longbuff2 = 0;
4551 uint64 maskbits = 0, matchbits = 0;
4552 uint64 buff1 = 0, buff2 = 0, buff3 = 0;
4553 uint8 bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
4554 tsample_t s;
4555 unsigned char *src = in[0];
4556 unsigned char *dst = out;
4557 char action[8];
4558
4559 if ((src == NULL) || (dst == NULL))
4560 {
4561 TIFFError("combineSeparateTileSamples32bits","Invalid input or output buffer");
4562 return (1);
4563 }
4564
4565 src_rowsize = ((bps * tw) + 7) / 8;
4566 dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
4567 maskbits = (uint64)-1 >> ( 64 - bps);
4568 shift_width = ((bps + 7) / 8) + 1;
4569
4570 for (row = 0; row < rows; row++)
4571 {
4572 ready_bits = 0;
4573 buff1 = buff2 = 0;
4574 dst = out + (row * dst_rowsize);
4575 src_offset = row * src_rowsize;
4576 for (col = 0; col < cols; col++)
4577 {
4578 /* Compute src byte(s) and bits within byte(s) */
4579 bit_offset = col * bps;
4580 src_byte = bit_offset / 8;
4581 src_bit = bit_offset % 8;
4582
4583 matchbits = maskbits << (64 - src_bit - bps);
4584 for (s = 0; s < spp; s++)
4585 {
4586 src = in[s] + src_offset + src_byte;
4587 if (little_endian)
4588 {
4589 longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
4590 longbuff2 = longbuff1;
4591 }
4592 else
4593 {
4594 longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
4595 longbuff2 = longbuff1;
4596 }
4597
4598 buff3 = ((uint64)longbuff1 << 32) | longbuff2;
4599 buff1 = (buff3 & matchbits) << (src_bit);
4600
4601 /* If we have a full buffer's worth, write it out */
4602 if (ready_bits >= 32)
4603 {
4604 bytebuff1 = (buff2 >> 56);
4605 *dst++ = bytebuff1;
4606 bytebuff2 = (buff2 >> 48);
4607 *dst++ = bytebuff2;
4608 bytebuff3 = (buff2 >> 40);
4609 *dst++ = bytebuff3;
4610 bytebuff4 = (buff2 >> 32);
4611 *dst++ = bytebuff4;
4612 ready_bits -= 32;
4613
4614 /* shift in new bits */
4615 buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
4616 strcpy (action, "Flush");
4617 }
4618 else
4619 { /* add another bps bits to the buffer */
4620 bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
4621 buff2 = (buff2 | (buff1 >> ready_bits));
4622 strcpy (action, "Update");
4623 }
4624 ready_bits += bps;
4625
4626 if ((dumpfile != NULL) && (level == 3))
4627 {
4628 dump_info (dumpfile, format, "",
4629 "Row %3d, Col %3d, Sample %d, Src byte offset %3d bit offset %2d Dst offset %3d",
4630 row + 1, col + 1, s, src_byte, src_bit, dst - out);
4631 dump_wide (dumpfile, format, "Match bits ", matchbits);
4632 dump_data (dumpfile, format, "Src bits ", src, 8);
4633 dump_wide (dumpfile, format, "Buff1 bits ", buff1);
4634 dump_wide (dumpfile, format, "Buff2 bits ", buff2);
4635 dump_info (dumpfile, format, "", "Ready bits: %d, %s", ready_bits, action);
4636 }
4637 }
4638 }
4639 while (ready_bits > 0)
4640 {
4641 bytebuff1 = (buff2 >> 56);
4642 *dst++ = bytebuff1;
4643 buff2 = (buff2 << 8);
4644 ready_bits -= 8;
4645 }
4646
4647 if ((dumpfile != NULL) && (level == 3))
4648 {
4649 dump_info (dumpfile, format, "",
4650 "Row %3d, Col %3d, Src byte offset %3d bit offset %2d Dst offset %3d",
4651 row + 1, col + 1, src_byte, src_bit, dst - out);
4652
4653 dump_long (dumpfile, format, "Match bits ", matchbits);
4654 dump_data (dumpfile, format, "Src bits ", src, 4);
4655 dump_long (dumpfile, format, "Buff1 bits ", buff1);
4656 dump_long (dumpfile, format, "Buff2 bits ", buff2);
4657 dump_byte (dumpfile, format, "Write bits1", bytebuff1);
4658 dump_byte (dumpfile, format, "Write bits2", bytebuff2);
4659 dump_info (dumpfile, format, "", "Ready bits: %2d", ready_bits);
4660 }
4661
4662 if ((dumpfile != NULL) && (level == 2))
4663 {
4664 dump_info (dumpfile, format, "combineSeparateTileSamples32bits","Output data");
4665 dump_buffer(dumpfile, format, 1, dst_rowsize, row, out);
4666 }
4667 }
4668
4669 return (0);
4670 } /* end combineSeparateTileSamples32bits */
4671
4672
4673 static int readSeparateStripsIntoBuffer (TIFF *in, uint8 *obuf, uint32 length,
4674 uint32 width, uint16 spp,
4675 struct dump_opts *dump)
4676 {
4677 int i, j, bytes_per_sample, bytes_per_pixel, shift_width, result = 1;
4678 int32 bytes_read = 0;
4679 uint16 bps, nstrips, planar, strips_per_sample;
4680 uint32 src_rowsize, dst_rowsize, rows_processed, rps;
4681 uint32 rows_this_strip = 0;
4682 tsample_t s;
4683 tstrip_t strip;
4684 tsize_t scanlinesize = TIFFScanlineSize(in);
4685 tsize_t stripsize = TIFFStripSize(in);
4686 unsigned char *srcbuffs[MAX_SAMPLES];
4687 unsigned char *buff = NULL;
4688 unsigned char *dst = NULL;
4689
4690 if (obuf == NULL)
4691 {
4692 TIFFError("readSeparateStripsIntoBuffer","Invalid buffer argument");
4693 return (0);
4694 }
4695
4696 memset (srcbuffs, '\0', sizeof(srcbuffs));
4697 TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
4698 TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &planar);
4699 TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rps);
4700 if (rps > length)
4701 rps = length;
4702
4703 bytes_per_sample = (bps + 7) / 8;
4704 bytes_per_pixel = ((bps * spp) + 7) / 8;
4705 if (bytes_per_pixel < (bytes_per_sample + 1))
4706 shift_width = bytes_per_pixel;
4707 else
4708 shift_width = bytes_per_sample + 1;
4709
4710 src_rowsize = ((bps * width) + 7) / 8;
4711 dst_rowsize = ((bps * width * spp) + 7) / 8;
4712 dst = obuf;
4713
4714 if ((dump->infile != NULL) && (dump->level == 3))
4715 {
4716 dump_info (dump->infile, dump->format, "",
4717 "Image width %d, length %d, Scanline size, %4d bytes",
4718 width, length, scanlinesize);
4719 dump_info (dump->infile, dump->format, "",
4720 "Bits per sample %d, Samples per pixel %d, Shift width %d",
4721 bps, spp, shift_width);
4722 }
4723
4724 /* Libtiff seems to assume/require that data for separate planes are
4725 * written one complete plane after another and not interleaved in any way.
4726 * Multiple scanlines and possibly strips of the same plane must be
4727 * written before data for any other plane.
4728 */
4729 nstrips = TIFFNumberOfStrips(in);
4730 strips_per_sample = nstrips /spp;
4731
4732 for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
4733 {
4734 srcbuffs[s] = NULL;
4735 buff = _TIFFmalloc(stripsize);
4736 if (!buff)
4737 {
4738 TIFFError ("readSeparateStripsIntoBuffer",
4739 "Unable to allocate strip read buffer for sample %d", s);
4740 for (i = 0; i < s; i++)
4741 _TIFFfree (srcbuffs[i]);
4742 return 0;
4743 }
4744 srcbuffs[s] = buff;
4745 }
4746
4747 rows_processed = 0;
4748 for (j = 0; (j < strips_per_sample) && (result == 1); j++)
4749 {
4750 for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
4751 {
4752 buff = srcbuffs[s];
4753 strip = (s * strips_per_sample) + j;
4754 bytes_read = TIFFReadEncodedStrip (in, strip, buff, stripsize);
4755 rows_this_strip = bytes_read / src_rowsize;
4756 if (bytes_read < 0 && !ignore)
4757 {
4758 TIFFError(TIFFFileName(in),
4759 "Error, can't read strip %lu for sample %d",
4760 (unsigned long) strip, s + 1);
4761 result = 0;
4762 break;
4763 }
4764 #ifdef DEVELMODE
4765 TIFFError("", "Strip %2d, read %5d bytes for %4d scanlines, shift width %d",
4766 strip, bytes_read, rows_this_strip, shift_width);
4767 #endif
4768 }
4769
4770 if (rps > rows_this_strip)
4771 rps = rows_this_strip;
4772 dst = obuf + (dst_rowsize * rows_processed);
4773 if ((bps % 8) == 0)
4774 {
4775 if (combineSeparateSamplesBytes (srcbuffs, dst, width, rps,
4776 spp, bps, dump->infile,
4777 dump->format, dump->level))
4778 {
4779 result = 0;
4780 break;
4781 }
4782 }
4783 else
4784 {
4785 switch (shift_width)
4786 {
4787 case 1: if (combineSeparateSamples8bits (srcbuffs, dst, width, rps,
4788 spp, bps, dump->infile,
4789 dump->format, dump->level))
4790 {
4791 result = 0;
4792 break;
4793 }
4794 break;
4795 case 2: if (combineSeparateSamples16bits (srcbuffs, dst, width, rps,
4796 spp, bps, dump->infile,
4797 dump->format, dump->level))
4798 {
4799 result = 0;
4800 break;
4801 }
4802 break;
4803 case 3: if (combineSeparateSamples24bits (srcbuffs, dst, width, rps,
4804 spp, bps, dump->infile,
4805 dump->format, dump->level))
4806 {
4807 result = 0;
4808 break;
4809 }
4810 break;
4811 case 4:
4812 case 5:
4813 case 6:
4814 case 7:
4815 case 8: if (combineSeparateSamples32bits (srcbuffs, dst, width, rps,
4816 spp, bps, dump->infile,
4817 dump->format, dump->level))
4818 {
4819 result = 0;
4820 break;
4821 }
4822 break;
4823 default: TIFFError ("readSeparateStripsIntoBuffer", "Unsupported bit depth: %d", bps);
4824 result = 0;
4825 break;
4826 }
4827 }
4828
4829 if ((rows_processed + rps) > length)
4830 {
4831 rows_processed = length;
4832 rps = length - rows_processed;
4833 }
4834 else
4835 rows_processed += rps;
4836 }
4837
4838 /* free any buffers allocated for each plane or scanline and
4839 * any temporary buffers
4840 */
4841 for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
4842 {
4843 buff = srcbuffs[s];
4844 if (buff != NULL)
4845 _TIFFfree(buff);
4846 }
4847
4848 return (result);
4849 } /* end readSeparateStripsIntoBuffer */
4850
4851 static int
4852 get_page_geometry (char *name, struct pagedef *page)
4853 {
4854 char *ptr;
4855 int n;
4856
4857 for (ptr = name; *ptr; ptr++)
4858 *ptr = (char)tolower((int)*ptr);
4859
4860 for (n = 0; n < MAX_PAPERNAMES; n++)
4861 {
4862 if (strcmp(name, PaperTable[n].name) == 0)
4863 {
4864 page->width = PaperTable[n].width;
4865 page->length = PaperTable[n].length;
4866 strncpy (page->name, PaperTable[n].name, 15);
4867 page->name[15] = '\0';
4868 return (0);
4869 }
4870 }
4871
4872 return (1);
4873 }
4874
4875
4876 static void
4877 initPageSetup (struct pagedef *page, struct pageseg *pagelist,
4878 struct buffinfo seg_buffs[])
4879 {
4880 int i;
4881
4882 strcpy (page->name, "");
4883 page->mode = PAGE_MODE_NONE;
4884 page->res_unit = RESUNIT_NONE;
4885 page->hres = 0.0;
4886 page->vres = 0.0;
4887 page->width = 0.0;
4888 page->length = 0.0;
4889 page->hmargin = 0.0;
4890 page->vmargin = 0.0;
4891 page->rows = 0;
4892 page->cols = 0;
4893 page->orient = ORIENTATION_NONE;
4894
4895 for (i = 0; i < MAX_SECTIONS; i++)
4896 {
4897 pagelist[i].x1 = (uint32)0;
4898 pagelist[i].x2 = (uint32)0;
4899 pagelist[i].y1 = (uint32)0;
4900 pagelist[i].y2 = (uint32)0;
4901 pagelist[i].buffsize = (uint32)0;
4902 pagelist[i].position = 0;
4903 pagelist[i].total = 0;
4904 }
4905
4906 for (i = 0; i < MAX_OUTBUFFS; i++)
4907 {
4908 seg_buffs[i].size = 0;
4909 seg_buffs[i].buffer = NULL;
4910 }
4911 }
4912
4913 static void
4914 initImageData (struct image_data *image)
4915 {
4916 image->xres = 0.0;
4917 image->yres = 0.0;
4918 image->width = 0;
4919 image->length = 0;
4920 image->res_unit = RESUNIT_NONE;
4921 image->bps = 0;
4922 image->spp = 0;
4923 image->planar = 0;
4924 image->photometric = 0;
4925 image->orientation = 0;
4926 image->compression = COMPRESSION_NONE;
4927 image->adjustments = 0;
4928 }
4929
4930 static void
4931 initCropMasks (struct crop_mask *cps)
4932 {
4933 int i;
4934
4935 cps->crop_mode = CROP_NONE;
4936 cps->res_unit = RESUNIT_NONE;
4937 cps->edge_ref = EDGE_TOP;
4938 cps->width = 0;
4939 cps->length = 0;
4940 for (i = 0; i < 4; i++)
4941 cps->margins[i] = 0.0;
4942 cps->bufftotal = (uint32)0;
4943 cps->combined_width = (uint32)0;
4944 cps->combined_length = (uint32)0;
4945 cps->rotation = (uint16)0;
4946 cps->photometric = INVERT_DATA_AND_TAG;
4947 cps->mirror = (uint16)0;
4948 cps->invert = (uint16)0;
4949 cps->zones = (uint32)0;
4950 cps->regions = (uint32)0;
4951 for (i = 0; i < MAX_REGIONS; i++)
4952 {
4953 cps->corners[i].X1 = 0.0;
4954 cps->corners[i].X2 = 0.0;
4955 cps->corners[i].Y1 = 0.0;
4956 cps->corners[i].Y2 = 0.0;
4957 cps->regionlist[i].x1 = 0;
4958 cps->regionlist[i].x2 = 0;
4959 cps->regionlist[i].y1 = 0;
4960 cps->regionlist[i].y2 = 0;
4961 cps->regionlist[i].width = 0;
4962 cps->regionlist[i].length = 0;
4963 cps->regionlist[i].buffsize = 0;
4964 cps->regionlist[i].buffptr = NULL;
4965 cps->zonelist[i].position = 0;
4966 cps->zonelist[i].total = 0;
4967 }
4968 cps->exp_mode = ONE_FILE_COMPOSITE;
4969 cps->img_mode = COMPOSITE_IMAGES;
4970 }
4971
4972 static void initDumpOptions(struct dump_opts *dump)
4973 {
4974 dump->debug = 0;
4975 dump->format = DUMP_NONE;
4976 dump->level = 1;
4977 sprintf (dump->mode, "w");
4978 memset (dump->infilename, '\0', PATH_MAX + 1);
4979 memset (dump->outfilename, '\0',PATH_MAX + 1);
4980 dump->infile = NULL;
4981 dump->outfile = NULL;
4982 }
4983
4984 /* Compute pixel offsets into the image for margins and fixed regions */
4985 static int
4986 computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image,
4987 struct offset *off)
4988 {
4989 double scale;
4990 float xres, yres;
4991 /* Values for these offsets are in pixels from start of image, not bytes,
4992 * and are indexed from zero to width - 1 or length - 1 */
4993 uint32 tmargin, bmargin, lmargin, rmargin;
4994 uint32 startx, endx; /* offsets of first and last columns to extract */
4995 uint32 starty, endy; /* offsets of first and last row to extract */
4996 uint32 width, length, crop_width, crop_length;
4997 uint32 i, max_width, max_length, zwidth, zlength, buffsize;
4998 uint32 x1, x2, y1, y2;
4999
5000 if (image->res_unit != RESUNIT_INCH && image->res_unit != RESUNIT_CENTIMETER)
5001 {
5002 xres = 1.0;
5003 yres = 1.0;
5004 }
5005 else
5006 {
5007 if (((image->xres == 0) || (image->yres == 0)) &&
5008 (crop->res_unit != RESUNIT_NONE) &&
5009 ((crop->crop_mode & CROP_REGIONS) || (crop->crop_mode & CROP_MARGINS) ||
5010 (crop->crop_mode & CROP_LENGTH) || (crop->crop_mode & CROP_WIDTH)))
5011 {
5012 TIFFError("computeInputPixelOffsets", "Cannot compute margins or fixed size sections without image resolution");
5013 TIFFError("computeInputPixelOffsets", "Specify units in pixels and try again");
5014 return (-1);
5015 }
5016 xres = image->xres;
5017 yres = image->yres;
5018 }
5019
5020 /* Translate user units to image units */
5021 scale = 1.0;
5022 switch (crop->res_unit) {
5023 case RESUNIT_CENTIMETER:
5024 if (image->res_unit == RESUNIT_INCH)
5025 scale = 1.0/2.54;
5026 break;
5027 case RESUNIT_INCH:
5028 if (image->res_unit == RESUNIT_CENTIMETER)
5029 scale = 2.54;
5030 break;
5031 case RESUNIT_NONE: /* Dimensions in pixels */
5032 default:
5033 break;
5034 }
5035
5036 if (crop->crop_mode & CROP_REGIONS)
5037 {
5038 max_width = max_length = 0;
5039 for (i = 0; i < crop->regions; i++)
5040 {
5041 if ((crop->res_unit == RESUNIT_INCH) || (crop->res_unit == RESUNIT_CENTIMETER))
5042 {
5043 x1 = (uint32) (crop->corners[i].X1 * scale * xres);
5044 x2 = (uint32) (crop->corners[i].X2 * scale * xres);
5045 y1 = (uint32) (crop->corners[i].Y1 * scale * yres);
5046 y2 = (uint32) (crop->corners[i].Y2 * scale * yres);
5047 }
5048 else
5049 {
5050 x1 = (uint32) (crop->corners[i].X1);
5051 x2 = (uint32) (crop->corners[i].X2);
5052 y1 = (uint32) (crop->corners[i].Y1);
5053 y2 = (uint32) (crop->corners[i].Y2);
5054 }
5055 if (x1 < 1)
5056 crop->regionlist[i].x1 = 0;
5057 else
5058 crop->regionlist[i].x1 = (uint32) (x1 - 1);
5059
5060 if (x2 > image->width - 1)
5061 crop->regionlist[i].x2 = image->width - 1;
5062 else
5063 crop->regionlist[i].x2 = (uint32) (x2 - 1);
5064 zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1;
5065
5066 if (y1 < 1)
5067 crop->regionlist[i].y1 = 0;
5068 else
5069 crop->regionlist[i].y1 = (uint32) (y1 - 1);
5070
5071 if (y2 > image->length - 1)
5072 crop->regionlist[i].y2 = image->length - 1;
5073 else
5074 crop->regionlist[i].y2 = (uint32) (y2 - 1);
5075
5076 zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
5077
5078 if (zwidth > max_width)
5079 max_width = zwidth;
5080 if (zlength > max_length)
5081 max_length = zlength;
5082
5083 buffsize = (uint32)
5084 (((zwidth * image->bps * image->spp + 7 ) / 8) * (zlength + 1));
5085
5086 crop->regionlist[i].buffsize = buffsize;
5087 crop->bufftotal += buffsize;
5088 if (crop->img_mode == COMPOSITE_IMAGES)
5089 {
5090 switch (crop->edge_ref)
5091 {
5092 case EDGE_LEFT:
5093 case EDGE_RIGHT:
5094 crop->combined_length = zlength;
5095 crop->combined_width += zwidth;
5096 break;
5097 case EDGE_BOTTOM:
5098 case EDGE_TOP: /* width from left, length from top */
5099 default:
5100 crop->combined_width = zwidth;
5101 crop->combined_length += zlength;
5102 break;
5103 }
5104 }
5105 }
5106 return (0);
5107 }
5108
5109 /* Convert crop margins into offsets into image
5110 * Margins are expressed as pixel rows and columns, not bytes
5111 */
5112 if (crop->crop_mode & CROP_MARGINS)
5113 {
5114 if (crop->res_unit != RESUNIT_INCH && crop->res_unit != RESUNIT_CENTIMETER)
5115 { /* User has specified pixels as reference unit */
5116 tmargin = (uint32)(crop->margins[0]);
5117 lmargin = (uint32)(crop->margins[1]);
5118 bmargin = (uint32)(crop->margins[2]);
5119 rmargin = (uint32)(crop->margins[3]);
5120 }
5121 else
5122 { /* inches or centimeters specified */
5123 tmargin = (uint32)(crop->margins[0] * scale * yres);
5124 lmargin = (uint32)(crop->margins[1] * scale * xres);
5125 bmargin = (uint32)(crop->margins[2] * scale * yres);
5126 rmargin = (uint32)(crop->margins[3] * scale * xres);
5127 }
5128
5129 if ((lmargin + rmargin) > image->width)
5130 {
5131 TIFFError("computeInputPixelOffsets", "Combined left and right margins exceed image width");
5132 lmargin = (uint32) 0;
5133 rmargin = (uint32) 0;
5134 return (-1);
5135 }
5136 if ((tmargin + bmargin) > image->length)
5137 {
5138 TIFFError("computeInputPixelOffsets", "Combined top and bottom margins exceed image length");
5139 tmargin = (uint32) 0;
5140 bmargin = (uint32) 0;
5141 return (-1);
5142 }
5143 }
5144 else
5145 { /* no margins requested */
5146 tmargin = (uint32) 0;
5147 lmargin = (uint32) 0;
5148 bmargin = (uint32) 0;
5149 rmargin = (uint32) 0;
5150 }
5151
5152 /* Width, height, and margins are expressed as pixel offsets into image */
5153 if (crop->res_unit != RESUNIT_INCH && crop->res_unit != RESUNIT_CENTIMETER)
5154 {
5155 if (crop->crop_mode & CROP_WIDTH)
5156 width = (uint32)crop->width;
5157 else
5158 width = image->width - lmargin - rmargin;
5159
5160 if (crop->crop_mode & CROP_LENGTH)
5161 length = (uint32)crop->length;
5162 else
5163 length = image->length - tmargin - bmargin;
5164 }
5165 else
5166 {
5167 if (crop->crop_mode & CROP_WIDTH)
5168 width = (uint32)(crop->width * scale * image->xres);
5169 else
5170 width = image->width - lmargin - rmargin;
5171
5172 if (crop->crop_mode & CROP_LENGTH)
5173 length = (uint32)(crop->length * scale * image->yres);
5174 else
5175 length = image->length - tmargin - bmargin;
5176 }
5177
5178 off->tmargin = tmargin;
5179 off->bmargin = bmargin;
5180 off->lmargin = lmargin;
5181 off->rmargin = rmargin;
5182
5183 /* Calculate regions defined by margins, width, and length.
5184 * Coordinates expressed as 0 to imagewidth - 1, imagelength - 1,
5185 * since they are used to compute offsets into buffers */
5186 switch (crop->edge_ref) {
5187 case EDGE_BOTTOM:
5188 startx = lmargin;
5189 if ((startx + width) >= (image->width - rmargin))
5190 endx = image->width - rmargin - 1;
5191 else
5192 endx = startx + width - 1;
5193
5194 endy = image->length - bmargin - 1;
5195 if ((endy - length) <= tmargin)
5196 starty = tmargin;
5197 else
5198 starty = endy - length + 1;
5199 break;
5200 case EDGE_RIGHT:
5201 endx = image->width - rmargin - 1;
5202 if ((endx - width) <= lmargin)
5203 startx = lmargin;
5204 else
5205 startx = endx - width + 1;
5206
5207 starty = tmargin;
5208 if ((starty + length) >= (image->length - bmargin))
5209 endy = image->length - bmargin - 1;
5210 else
5211 endy = starty + length - 1;
5212 break;
5213 case EDGE_TOP: /* width from left, length from top */
5214 case EDGE_LEFT:
5215 default:
5216 startx = lmargin;
5217 if ((startx + width) >= (image->width - rmargin))
5218 endx = image->width - rmargin - 1;
5219 else
5220 endx = startx + width - 1;
5221
5222 starty = tmargin;
5223 if ((starty + length) >= (image->length - bmargin))
5224 endy = image->length - bmargin - 1;
5225 else
5226 endy = starty + length - 1;
5227 break;
5228 }
5229 off->startx = startx;
5230 off->starty = starty;
5231 off->endx = endx;
5232 off->endy = endy;
5233
5234 crop_width = endx - startx + 1;
5235 crop_length = endy - starty + 1;
5236
5237 if (crop_width <= 0)
5238 {
5239 TIFFError("computeInputPixelOffsets",
5240 "Invalid left/right margins and /or image crop width requested");
5241 return (-1);
5242 }
5243 if (crop_width > image->width)
5244 crop_width = image->width;
5245
5246 if (crop_length <= 0)
5247 {
5248 TIFFError("computeInputPixelOffsets",
5249 "Invalid top/bottom margins and /or image crop length requested");
5250 return (-1);
5251 }
5252 if (crop_length > image->length)
5253 crop_length = image->length;
5254
5255 off->crop_width = crop_width;
5256 off->crop_length = crop_length;
5257
5258 return (0);
5259 } /* end computeInputPixelOffsets */
5260
5261 /*
5262 * Translate crop options into pixel offsets for one or more regions of the image.
5263 * Options are applied in this order: margins, specific width and length, zones,
5264 * but all are optional. Margins are relative to each edge. Width, length and
5265 * zones are relative to the specified reference edge. Zones are expressed as
5266 * X:Y where X is the ordinal value in a set of Y equal sized portions. eg.
5267 * 2:3 would indicate the middle third of the region qualified by margins and
5268 * any explicit width and length specified. Regions are specified by coordinates
5269 * of the top left and lower right corners with range 1 to width or height.
5270 */
5271
5272 static int
5273 getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opts *dump)
5274 {
5275 struct offset offsets;
5276 int i;
5277 int32 test;
5278 uint32 seg, total, need_buff = 0;
5279 uint32 buffsize;
5280 uint32 zwidth, zlength;
5281
5282 memset(&offsets, '\0', sizeof(struct offset));
5283 crop->bufftotal = 0;
5284 crop->combined_width = (uint32)0;
5285 crop->combined_length = (uint32)0;
5286 crop->selections = 0;
5287
5288 /* Compute pixel offsets if margins or fixed width or length specified */
5289 if ((crop->crop_mode & CROP_MARGINS) ||
5290 (crop->crop_mode & CROP_REGIONS) ||
5291 (crop->crop_mode & CROP_LENGTH) ||
5292 (crop->crop_mode & CROP_WIDTH))
5293 {
5294 if (computeInputPixelOffsets(crop, image, &offsets))
5295 {
5296 TIFFError ("getCropOffsets", "Unable to compute crop margins");
5297 return (-1);
5298 }
5299 need_buff = TRUE;
5300 crop->selections = crop->regions;
5301 /* Regions are only calculated from top and left edges with no margins */
5302 if (crop->crop_mode & CROP_REGIONS)
5303 return (0);
5304 }
5305 else
5306 { /* cropped area is the full image */
5307 offsets.tmargin = 0;
5308 offsets.lmargin = 0;
5309 offsets.bmargin = 0;
5310 offsets.rmargin = 0;
5311 offsets.crop_width = image->width;
5312 offsets.crop_length = image->length;
5313 offsets.startx = 0;
5314 offsets.endx = image->width - 1;
5315 offsets.starty = 0;
5316 offsets.endy = image->length - 1;
5317 need_buff = FALSE;
5318 }
5319
5320 if (dump->outfile != NULL)
5321 {
5322 dump_info (dump->outfile, dump->format, "", "Margins: Top: %d Left: %d Bottom: %d Right: %d",
5323 offsets.tmargin, offsets.lmargin, offsets.bmargin, offsets.rmargin);
5324 dump_info (dump->outfile, dump->format, "", "Crop region within margins: Adjusted Width: %6d Length: %6d",
5325 offsets.crop_width, offsets.crop_length);
5326 }
5327
5328 if (!(crop->crop_mode & CROP_ZONES)) /* no crop zones requested */
5329 {
5330 if (need_buff == FALSE) /* No margins or fixed width or length areas */
5331 {
5332 crop->selections = 0;
5333 crop->combined_width = image->width;
5334 crop->combined_length = image->length;
5335 return (0);
5336 }
5337 else
5338 {
5339 /* Use one region for margins and fixed width or length areas
5340 * even though it was not formally declared as a region.
5341 */
5342 crop->selections = 1;
5343 crop->zones = 1;
5344 crop->zonelist[0].total = 1;
5345 crop->zonelist[0].position = 1;
5346 }
5347 }
5348 else
5349 crop->selections = crop->zones;
5350
5351 for (i = 0; i < crop->zones; i++)
5352 {
5353 seg = crop->zonelist[i].position;
5354 total = crop->zonelist[i].total;
5355
5356 switch (crop->edge_ref)
5357 {
5358 case EDGE_LEFT: /* zones from left to right, length from top */
5359 zlength = offsets.crop_length;
5360 crop->regionlist[i].y1 = offsets.starty;
5361 crop->regionlist[i].y2 = offsets.endy;
5362
5363 crop->regionlist[i].x1 = offsets.startx +
5364 (uint32)(offsets.crop_width * 1.0 * (seg - 1) / total);
5365 test = (int32)offsets.startx +
5366 (int32)(offsets.crop_width * 1.0 * seg / total);
5367 if (test < 1 )
5368 crop->regionlist[i].x2 = 0;
5369 else
5370 {
5371 if (test > (int32)(image->width - 1))
5372 crop->regionlist[i].x2 = image->width - 1;
5373 else
5374 crop->regionlist[i].x2 = test - 1;
5375 }
5376 zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1;
5377
5378 /* This is passed to extractCropZone or extractCompositeZones */
5379 crop->combined_length = (uint32)zlength;
5380 if (crop->exp_mode == COMPOSITE_IMAGES)
5381 crop->combined_width += (uint32)zwidth;
5382 else
5383 crop->combined_width = (uint32)zwidth;
5384 break;
5385 case EDGE_BOTTOM: /* width from left, zones from bottom to top */
5386 zwidth = offsets.crop_width;
5387 crop->regionlist[i].x1 = offsets.startx;
5388 crop->regionlist[i].x2 = offsets.endx;
5389
5390 test = offsets.endy - (uint32)(offsets.crop_length * 1.0 * seg / total);
5391 if (test < 1 )
5392 crop->regionlist[i].y1 = 0;
5393 else
5394 crop->regionlist[i].y1 = test + 1;
5395
5396 test = offsets.endy - (offsets.crop_length * 1.0 * (seg - 1) / total);
5397 if (test < 1 )
5398 crop->regionlist[i].y2 = 0;
5399 else
5400 {
5401 if (test > (int32)(image->length - 1))
5402 crop->regionlist[i].y2 = image->length - 1;
5403 else
5404 crop->regionlist[i].y2 = test;
5405 }
5406 zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
5407
5408 /* This is passed to extractCropZone or extractCompositeZones */
5409 if (crop->exp_mode == COMPOSITE_IMAGES)
5410 crop->combined_length += (uint32)zlength;
5411 else
5412 crop->combined_length = (uint32)zlength;
5413 crop->combined_width = (uint32)zwidth;
5414 break;
5415 case EDGE_RIGHT: /* zones from right to left, length from top */
5416 zlength = offsets.crop_length;
5417 crop->regionlist[i].y1 = offsets.starty;
5418 crop->regionlist[i].y2 = offsets.endy;
5419
5420 crop->regionlist[i].x1 = offsets.startx +
5421 (uint32)(offsets.crop_width * (total - seg) * 1.0 / total);
5422 test = offsets.startx +
5423 (offsets.crop_width * (total - seg + 1) * 1.0 / total);
5424 if (test < 1 )
5425 crop->regionlist[i].x2 = 0;
5426 else
5427 {
5428 if (test > (int32)(image->width - 1))
5429 crop->regionlist[i].x2 = image->width - 1;
5430 else
5431 crop->regionlist[i].x2 = test - 1;
5432 }
5433 zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1;
5434
5435 /* This is passed to extractCropZone or extractCompositeZones */
5436 crop->combined_length = (uint32)zlength;
5437 if (crop->exp_mode == COMPOSITE_IMAGES)
5438 crop->combined_width += (uint32)zwidth;
5439 else
5440 crop->combined_width = (uint32)zwidth;
5441 break;
5442 case EDGE_TOP: /* width from left, zones from top to bottom */
5443 default:
5444 zwidth = offsets.crop_width;
5445 crop->regionlist[i].x1 = offsets.startx;
5446 crop->regionlist[i].x2 = offsets.endx;
5447
5448 crop->regionlist[i].y1 = offsets.starty + (uint32)(offsets.crop_length * 1.0 * (seg - 1) / total);
5449 test = offsets.starty + (uint32)(offsets.crop_length * 1.0 * seg / total);
5450 if (test < 1 )
5451 crop->regionlist[i].y2 = 0;
5452 else
5453 {
5454 if (test > (int32)(image->length - 1))
5455 crop->regionlist[i].y2 = image->length - 1;
5456 else
5457 crop->regionlist[i].y2 = test - 1;
5458 }
5459 zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
5460
5461 /* This is passed to extractCropZone or extractCompositeZones */
5462 if (crop->exp_mode == COMPOSITE_IMAGES)
5463 crop->combined_length += (uint32)zlength;
5464 else
5465 crop->combined_length = (uint32)zlength;
5466 crop->combined_width = (uint32)zwidth;
5467 break;
5468 } /* end switch statement */
5469
5470 buffsize = (uint32)
5471 ((((zwidth * image->bps * image->spp) + 7 ) / 8) * (zlength + 1));
5472 crop->regionlist[i].width = (uint32) zwidth;
5473 crop->regionlist[i].length = (uint32) zlength;
5474 crop->regionlist[i].buffsize = buffsize;
5475 crop->bufftotal += buffsize;
5476
5477
5478 if (dump->outfile != NULL)
5479 dump_info (dump->outfile, dump->format, "", "Zone %d, width: %4d, length: %4d, x1: %4d x2: %4d y1: %4d y2: %4d",
5480 i + 1, (uint32)zwidth, (uint32)zlength,
5481 crop->regionlist[i].x1, crop->regionlist[i].x2,
5482 crop->regionlist[i].y1, crop->regionlist[i].y2);
5483 }
5484
5485 return (0);
5486 } /* end getCropOffsets */
5487
5488
5489 static int
5490 computeOutputPixelOffsets (struct crop_mask *crop, struct image_data *image,
5491 struct pagedef *page, struct pageseg *sections,
5492 struct dump_opts* dump)
5493 {
5494 double scale;
5495 double pwidth, plength; /* Output page width and length in user units*/
5496 uint32 iwidth, ilength; /* Input image width and length in pixels*/
5497 uint32 owidth, olength; /* Output image width and length in pixels*/
5498 uint32 orows, ocols; /* rows and cols for output */
5499 uint32 hmargin, vmargin; /* Horizontal and vertical margins */
5500 uint32 x1, x2, y1, y2, line_bytes;
5501 unsigned int orientation;
5502 uint32 i, j, k;
5503
5504 scale = 1.0;
5505 if (page->res_unit == RESUNIT_NONE)
5506 page->res_unit = image->res_unit;
5507
5508 switch (image->res_unit) {
5509 case RESUNIT_CENTIMETER:
5510 if (page->res_unit == RESUNIT_INCH)
5511 scale = 1.0/2.54;
5512 break;
5513 case RESUNIT_INCH:
5514 if (page->res_unit == RESUNIT_CENTIMETER)
5515 scale = 2.54;
5516 break;
5517 case RESUNIT_NONE: /* Dimensions in pixels */
5518 default:
5519 break;
5520 }
5521
5522 /* get width, height, resolutions of input image selection */
5523 if (crop->combined_width > 0)
5524 iwidth = crop->combined_width;
5525 else
5526 iwidth = image->width;
5527 if (crop->combined_length > 0)
5528 ilength = crop->combined_length;
5529 else
5530 ilength = image->length;
5531
5532 if (page->hres <= 1.0)
5533 page->hres = image->xres;
5534 if (page->vres <= 1.0)
5535 page->vres = image->yres;
5536
5537 if ((page->hres < 1.0) || (page->vres < 1.0))
5538 {
5539 TIFFError("computeOutputPixelOffsets",
5540 "Invalid horizontal or vertical resolution specified or read from input image");
5541 return (1);
5542 }
5543
5544 /* If no page sizes are being specified, we just use the input image size to
5545 * calculate maximum margins that can be taken from image.
5546 */
5547 if (page->width <= 0)
5548 pwidth = iwidth;
5549 else
5550 pwidth = page->width;
5551
5552 if (page->length <= 0)
5553 plength = ilength;
5554 else
5555 plength = page->length;
5556
5557 if (dump->debug)
5558 {
5559 TIFFError("", "Page size: %s, Vres: %3.2f, Hres: %3.2f, "
5560 "Hmargin: %3.2f, Vmargin: %3.2f",
5561 page->name, page->vres, page->hres,
5562 page->hmargin, page->vmargin);
5563 TIFFError("", "Res_unit: %d, Scale: %3.2f, Page width: %3.2f, length: %3.2f",
5564 page->res_unit, scale, pwidth, plength);
5565 }
5566
5567 /* compute margins at specified unit and resolution */
5568 if (page->mode & PAGE_MODE_MARGINS)
5569 {
5570 if (page->res_unit == RESUNIT_INCH || page->res_unit == RESUNIT_CENTIMETER)
5571 { /* inches or centimeters specified */
5572 hmargin = (uint32)(page->hmargin * scale * page->hres * ((image->bps + 7)/ 8));
5573 vmargin = (uint32)(page->vmargin * scale * page->vres * ((image->bps + 7)/ 8));
5574 }
5575 else
5576 { /* Otherwise user has specified pixels as reference unit */
5577 hmargin = (uint32)(page->hmargin * scale * ((image->bps + 7)/ 8));
5578 vmargin = (uint32)(page->vmargin * scale * ((image->bps + 7)/ 8));
5579 }
5580
5581 if ((hmargin * 2.0) > (pwidth * page->hres))
5582 {
5583 TIFFError("computeOutputPixelOffsets",
5584 "Combined left and right margins exceed page width");
5585 hmargin = (uint32) 0;
5586 return (-1);
5587 }
5588 if ((vmargin * 2.0) > (plength * page->vres))
5589 {
5590 TIFFError("computeOutputPixelOffsets",
5591 "Combined top and bottom margins exceed page length");
5592 vmargin = (uint32) 0;
5593 return (-1);
5594 }
5595 }
5596 else
5597 {
5598 hmargin = 0;
5599 vmargin = 0;
5600 }
5601
5602 if (page->mode & PAGE_MODE_ROWSCOLS )
5603 {
5604 /* Maybe someday but not for now */
5605 if (page->mode & PAGE_MODE_MARGINS)
5606 TIFFError("computeOutputPixelOffsets",
5607 "Output margins cannot be specified with rows and columns");
5608
5609 owidth = TIFFhowmany(iwidth, page->cols);
5610 olength = TIFFhowmany(ilength, page->rows);
5611 }
5612 else
5613 {
5614 if (page->mode & PAGE_MODE_PAPERSIZE )
5615 {
5616 owidth = (uint32)((pwidth * page->hres) - (hmargin * 2));
5617 olength = (uint32)((plength * page->vres) - (vmargin * 2));
5618 }
5619 else
5620 {
5621 owidth = (uint32)(iwidth - (hmargin * 2 * page->hres));
5622 olength = (uint32)(ilength - (vmargin * 2 * page->vres));
5623 }
5624 }
5625
5626 if (owidth > iwidth)
5627 owidth = iwidth;
5628 if (olength > ilength)
5629 olength = ilength;
5630
5631 /* Compute the number of pages required for Portrait or Landscape */
5632 switch (page->orient)
5633 {
5634 case ORIENTATION_NONE:
5635 case ORIENTATION_PORTRAIT:
5636 ocols = TIFFhowmany(iwidth, owidth);
5637 orows = TIFFhowmany(ilength, olength);
5638 orientation = ORIENTATION_PORTRAIT;
5639 break;
5640
5641 case ORIENTATION_LANDSCAPE:
5642 ocols = TIFFhowmany(iwidth, olength);
5643 orows = TIFFhowmany(ilength, owidth);
5644 x1 = olength;
5645 olength = owidth;
5646 owidth = x1;
5647 orientation = ORIENTATION_LANDSCAPE;
5648 break;
5649
5650 case ORIENTATION_AUTO:
5651 default:
5652 x1 = TIFFhowmany(iwidth, owidth);
5653 x2 = TIFFhowmany(ilength, olength);
5654 y1 = TIFFhowmany(iwidth, olength);
5655 y2 = TIFFhowmany(ilength, owidth);
5656
5657 if ( (x1 * x2) < (y1 * y2))
5658 { /* Portrait */
5659 ocols = x1;
5660 orows = x2;
5661 orientation = ORIENTATION_PORTRAIT;
5662 }
5663 else
5664 { /* Landscape */
5665 ocols = y1;
5666 orows = y2;
5667 x1 = olength;
5668 olength = owidth;
5669 owidth = x1;
5670 orientation = ORIENTATION_LANDSCAPE;
5671 }
5672 }
5673
5674 if (ocols < 1)
5675 ocols = 1;
5676 if (orows < 1)
5677 orows = 1;
5678
5679 /* If user did not specify rows and cols, set them from calcuation */
5680 if (page->rows < 1)
5681 page->rows = orows;
5682 if (page->cols < 1)
5683 page->cols = ocols;
5684
5685 line_bytes = TIFFhowmany8(owidth * image->bps) * image->spp;
5686
5687 if ((page->rows * page->cols) > MAX_SECTIONS)
5688 {
5689 TIFFError("computeOutputPixelOffsets",
5690 "Rows and Columns exceed maximum sections\nIncrease resolution or reduce sections");
5691 return (-1);
5692 }
5693
5694 /* build the list of offsets for each output section */
5695 for (k = 0, i = 0 && k <= MAX_SECTIONS; i < orows; i++)
5696 {
5697 y1 = (uint32)(olength * i);
5698 y2 = (uint32)(olength * (i + 1) - 1);
5699 if (y2 >= ilength)
5700 y2 = ilength - 1;
5701 for (j = 0; j < ocols; j++, k++)
5702 {
5703 x1 = (uint32)(owidth * j);
5704 x2 = (uint32)(owidth * (j + 1) - 1);
5705 if (x2 >= iwidth)
5706 x2 = iwidth - 1;
5707 sections[k].x1 = x1;
5708 sections[k].x2 = x2;
5709 sections[k].y1 = y1;
5710 sections[k].y2 = y2;
5711 sections[k].buffsize = line_bytes * olength;
5712 sections[k].position = k + 1;
5713 sections[k].total = orows * ocols;
5714 }
5715 }
5716 return (0);
5717 } /* end computeOutputPixelOffsets */
5718
5719 static int
5720 loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned char **read_ptr)
5721 {
5722 uint32 i;
5723 float xres = 0.0, yres = 0.0;
5724 uint16 nstrips = 0, ntiles = 0, planar = 0;
5725 uint16 bps = 0, spp = 0, res_unit = 0;
5726 uint16 orientation = 0;
5727 uint16 input_compression = 0, input_photometric = 0;
5728 uint16 subsampling_horiz, subsampling_vert;
5729 uint32 width = 0, length = 0;
5730 uint32 stsize = 0, tlsize = 0, buffsize = 0, scanlinesize = 0;
5731 uint32 tw = 0, tl = 0; /* Tile width and length */
5732 uint32 tile_rowsize = 0;
5733 unsigned char *read_buff = NULL;
5734 unsigned char *new_buff = NULL;
5735 int readunit = 0;
5736 static uint32 prev_readsize = 0;
5737
5738 TIFFGetFieldDefaulted(in, TIFFTAG_BITSPERSAMPLE, &bps);
5739 TIFFGetFieldDefaulted(in, TIFFTAG_SAMPLESPERPIXEL, &spp);
5740 TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &planar);
5741 TIFFGetFieldDefaulted(in, TIFFTAG_ORIENTATION, &orientation);
5742 if (! TIFFGetFieldDefaulted(in, TIFFTAG_PHOTOMETRIC, &input_photometric))
5743 TIFFError("loadImage","Image lacks Photometric interpreation tag");
5744 if (! TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &width))
5745 TIFFError("loadimage","Image lacks image width tag");
5746 if(! TIFFGetField(in, TIFFTAG_IMAGELENGTH, &length))
5747 TIFFError("loadimage","Image lacks image length tag");
5748 TIFFGetFieldDefaulted(in, TIFFTAG_XRESOLUTION, &xres);
5749 TIFFGetFieldDefaulted(in, TIFFTAG_YRESOLUTION, &yres);
5750 if (!TIFFGetFieldDefaulted(in, TIFFTAG_RESOLUTIONUNIT, &res_unit))
5751 res_unit = RESUNIT_INCH;
5752 if (!TIFFGetField(in, TIFFTAG_COMPRESSION, &input_compression))
5753 input_compression = COMPRESSION_NONE;
5754
5755 #ifdef DEBUG2
5756 char compressionid[16];
5757
5758 switch (input_compression)
5759 {
5760 case COMPRESSION_NONE: /* 1 dump mode */
5761 strcpy (compressionid, "None/dump");
5762 break;
5763 case COMPRESSION_CCITTRLE: /* 2 CCITT modified Huffman RLE */
5764 strcpy (compressionid, "Huffman RLE");
5765 break;
5766 case COMPRESSION_CCITTFAX3: /* 3 CCITT Group 3 fax encoding */
5767 strcpy (compressionid, "Group3 Fax");
5768 break;
5769 case COMPRESSION_CCITTFAX4: /* 4 CCITT Group 4 fax encoding */
5770 strcpy (compressionid, "Group4 Fax");
5771 break;
5772 case COMPRESSION_LZW: /* 5 Lempel-Ziv & Welch */
5773 strcpy (compressionid, "LZW");
5774 break;
5775 case COMPRESSION_OJPEG: /* 6 !6.0 JPEG */
5776 strcpy (compressionid, "Old Jpeg");
5777 break;
5778 case COMPRESSION_JPEG: /* 7 %JPEG DCT compression */
5779 strcpy (compressionid, "New Jpeg");
5780 break;
5781 case COMPRESSION_NEXT: /* 32766 NeXT 2-bit RLE */
5782 strcpy (compressionid, "Next RLE");
5783 break;
5784 case COMPRESSION_CCITTRLEW: /* 32771 #1 w/ word alignment */
5785 strcpy (compressionid, "CITTRLEW");
5786 break;
5787 case COMPRESSION_PACKBITS: /* 32773 Macintosh RLE */
5788 strcpy (compressionid, "Mac Packbits");
5789 break;
5790 case COMPRESSION_THUNDERSCAN: /* 32809 ThunderScan RLE */
5791 strcpy (compressionid, "Thunderscan");
5792 break;
5793 case COMPRESSION_IT8CTPAD: /* 32895 IT8 CT w/padding */
5794 strcpy (compressionid, "IT8 padded");
5795 break;
5796 case COMPRESSION_IT8LW: /* 32896 IT8 Linework RLE */
5797 strcpy (compressionid, "IT8 RLE");
5798 break;
5799 case COMPRESSION_IT8MP: /* 32897 IT8 Monochrome picture */
5800 strcpy (compressionid, "IT8 mono");
5801 break;
5802 case COMPRESSION_IT8BL: /* 32898 IT8 Binary line art */
5803 strcpy (compressionid, "IT8 lineart");
5804 break;
5805 case COMPRESSION_PIXARFILM: /* 32908 Pixar companded 10bit LZW */
5806 strcpy (compressionid, "Pixar 10 bit");
5807 break;
5808 case COMPRESSION_PIXARLOG: /* 32909 Pixar companded 11bit ZIP */
5809 strcpy (compressionid, "Pixar 11bit");
5810 break;
5811 case COMPRESSION_DEFLATE: /* 32946 Deflate compression */
5812 strcpy (compressionid, "Deflate");
5813 break;
5814 case COMPRESSION_ADOBE_DEFLATE: /* 8 Deflate compression */
5815 strcpy (compressionid, "Adobe deflate");
5816 break;
5817 default:
5818 strcpy (compressionid, "None/unknown");
5819 break;
5820 }
5821 TIFFError("loadImage", "Input compression %s", compressionid);
5822 #endif
5823
5824 scanlinesize = TIFFScanlineSize(in);
5825 image->bps = bps;
5826 image->spp = spp;
5827 image->planar = planar;
5828 image->width = width;
5829 image->length = length;
5830 image->xres = xres;
5831 image->yres = yres;
5832 image->res_unit = res_unit;
5833 image->compression = input_compression;
5834 image->photometric = input_photometric;
5835 #ifdef DEBUG2
5836 char photometricid[12];
5837
5838 switch (input_photometric)
5839 {
5840 case PHOTOMETRIC_MINISWHITE:
5841 strcpy (photometricid, "MinIsWhite");
5842 break;
5843 case PHOTOMETRIC_MINISBLACK:
5844 strcpy (photometricid, "MinIsBlack");
5845 break;
5846 case PHOTOMETRIC_RGB:
5847 strcpy (photometricid, "RGB");
5848 break;
5849 case PHOTOMETRIC_PALETTE:
5850 strcpy (photometricid, "Palette");
5851 break;
5852 case PHOTOMETRIC_MASK:
5853 strcpy (photometricid, "Mask");
5854 break;
5855 case PHOTOMETRIC_SEPARATED:
5856 strcpy (photometricid, "Separated");
5857 break;
5858 case PHOTOMETRIC_YCBCR:
5859 strcpy (photometricid, "YCBCR");
5860 break;
5861 case PHOTOMETRIC_CIELAB:
5862 strcpy (photometricid, "CIELab");
5863 break;
5864 case PHOTOMETRIC_ICCLAB:
5865 strcpy (photometricid, "ICCLab");
5866 break;
5867 case PHOTOMETRIC_ITULAB:
5868 strcpy (photometricid, "ITULab");
5869 break;
5870 case PHOTOMETRIC_LOGL:
5871 strcpy (photometricid, "LogL");
5872 break;
5873 case PHOTOMETRIC_LOGLUV:
5874 strcpy (photometricid, "LOGLuv");
5875 break;
5876 default:
5877 strcpy (photometricid, "Unknown");
5878 break;
5879 }
5880 TIFFError("loadImage", "Input photometric interpretation %s", photometricid);
5881
5882 #endif
5883 image->orientation = orientation;
5884 switch (orientation)
5885 {
5886 case 0:
5887 case ORIENTATION_TOPLEFT:
5888 image->adjustments = 0;
5889 break;
5890 case ORIENTATION_TOPRIGHT:
5891 image->adjustments = MIRROR_HORIZ;
5892 break;
5893 case ORIENTATION_BOTRIGHT:
5894 image->adjustments = ROTATECW_180;
5895 break;
5896 case ORIENTATION_BOTLEFT:
5897 image->adjustments = MIRROR_VERT;
5898 break;
5899 case ORIENTATION_LEFTTOP:
5900 image->adjustments = MIRROR_VERT | ROTATECW_90;
5901 break;
5902 case ORIENTATION_RIGHTTOP:
5903 image->adjustments = ROTATECW_90;
5904 break;
5905 case ORIENTATION_RIGHTBOT:
5906 image->adjustments = MIRROR_VERT | ROTATECW_270;
5907 break;
5908 case ORIENTATION_LEFTBOT:
5909 image->adjustments = ROTATECW_270;
5910 break;
5911 default:
5912 image->adjustments = 0;
5913 image->orientation = ORIENTATION_TOPLEFT;
5914 }
5915
5916 if ((bps == 0) || (spp == 0))
5917 {
5918 TIFFError("loadImage", "Invalid samples per pixel (%d) or bits per sample (%d)",
5919 spp, bps);
5920 return (-1);
5921 }
5922
5923 if (TIFFIsTiled(in))
5924 {
5925 readunit = TILE;
5926 tlsize = TIFFTileSize(in);
5927 ntiles = TIFFNumberOfTiles(in);
5928 TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
5929 TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
5930
5931 tile_rowsize = TIFFTileRowSize(in);
5932 buffsize = tlsize * ntiles;
5933
5934
5935 if (buffsize < (uint32)(ntiles * tl * tile_rowsize))
5936 {
5937 buffsize = ntiles * tl * tile_rowsize;
5938 #ifdef DEBUG2
5939 TIFFError("loadImage",
5940 "Tilesize %u is too small, using ntiles * tilelength * tilerowsize %lu",
5941 tlsize, (unsigned long)buffsize);
5942 #endif
5943 }
5944
5945 if (dump->infile != NULL)
5946 dump_info (dump->infile, dump->format, "",
5947 "Tilesize: %u, Number of Tiles: %u, Tile row size: %u",
5948 tlsize, ntiles, tile_rowsize);
5949 }
5950 else
5951 {
5952 readunit = STRIP;
5953 TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
5954 stsize = TIFFStripSize(in);
5955 nstrips = TIFFNumberOfStrips(in);
5956 buffsize = stsize * nstrips;
5957
5958 if (buffsize < (uint32) (((length * width * spp * bps) + 7) / 8))
5959 {
5960 buffsize = ((length * width * spp * bps) + 7) / 8;
5961 #ifdef DEBUG2
5962 TIFFError("loadImage",
5963 "Stripsize %u is too small, using imagelength * width * spp * bps / 8 = %lu",
5964 stsize, (unsigned long)buffsize);
5965 #endif
5966 }
5967
5968 if (dump->infile != NULL)
5969 dump_info (dump->infile, dump->format, "",
5970 "Stripsize: %u, Number of Strips: %u, Rows per Strip: %u, Scanline size: %u",
5971 stsize, nstrips, rowsperstrip, scanlinesize);
5972 }
5973
5974 if (input_compression == COMPRESSION_JPEG)
5975 { /* Force conversion to RGB */
5976 jpegcolormode = JPEGCOLORMODE_RGB;
5977 TIFFSetField(in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
5978 }
5979 /* The clause up to the read statement is taken from Tom Lane's tiffcp patch */
5980 else
5981 { /* Otherwise, can't handle subsampled input */
5982 if (input_photometric == PHOTOMETRIC_YCBCR)
5983 {
5984 TIFFGetFieldDefaulted(in, TIFFTAG_YCBCRSUBSAMPLING,
5985 &subsampling_horiz, &subsampling_vert);
5986 if (subsampling_horiz != 1 || subsampling_vert != 1)
5987 {
5988 TIFFError("loadImage",
5989 "Can't copy/convert subsampled image with subsampling %d horiz %d vert",
5990 subsampling_horiz, subsampling_vert);
5991 return (-1);
5992 }
5993 }
5994 }
5995
5996 read_buff = *read_ptr;
5997 if (!read_buff)
5998 read_buff = (unsigned char *)_TIFFmalloc(buffsize);
5999 else
6000 {
6001 if (prev_readsize < buffsize)
6002 {
6003 new_buff = _TIFFrealloc(read_buff, buffsize);
6004 if (!new_buff)
6005 {
6006 free (read_buff);
6007 read_buff = (unsigned char *)_TIFFmalloc(buffsize);
6008 }
6009 else
6010 read_buff = new_buff;
6011 }
6012 }
6013
6014 if (!read_buff)
6015 {
6016 TIFFError("loadImage", "Unable to allocate/reallocate read buffer");
6017 return (-1);
6018 }
6019
6020 prev_readsize = buffsize;
6021 *read_ptr = read_buff;
6022
6023 /* N.B. The read functions used copy separate plane data into a buffer as interleaved
6024 * samples rather than separate planes so the same logic works to extract regions
6025 * regardless of the way the data are organized in the input file.
6026 */
6027 switch (readunit) {
6028 case STRIP:
6029 if (planar == PLANARCONFIG_CONTIG)
6030 {
6031 if (!(readContigStripsIntoBuffer(in, read_buff)))
6032 {
6033 TIFFError("loadImage", "Unable to read contiguous strips into buffer");
6034 return (-1);
6035 }
6036 }
6037 else
6038 {
6039 if (!(readSeparateStripsIntoBuffer(in, read_buff, length, width, spp, dump)))
6040 {
6041 TIFFError("loadImage", "Unable to read separate strips into buffer");
6042 return (-1);
6043 }
6044 }
6045 break;
6046
6047 case TILE:
6048 if (planar == PLANARCONFIG_CONTIG)
6049 {
6050 if (!(readContigTilesIntoBuffer(in, read_buff, length, width, tw, tl, spp, bps)))
6051 {
6052 TIFFError("loadImage", "Unable to read contiguous tiles into buffer");
6053 return (-1);
6054 }
6055 }
6056 else
6057 {
6058 if (!(readSeparateTilesIntoBuffer(in, read_buff, length, width, tw, tl, spp, bps)))
6059 {
6060 TIFFError("loadImage", "Unable to read separate tiles into buffer");
6061 return (-1);
6062 }
6063 }
6064 break;
6065 default: TIFFError("loadImage", "Unsupported image file format");
6066 return (-1);
6067 break;
6068 }
6069 if ((dump->infile != NULL) && (dump->level == 2))
6070 {
6071 dump_info (dump->infile, dump->format, "loadImage",
6072 "Image width %d, length %d, Raw image data, %4d bytes",
6073 width, length, buffsize);
6074 dump_info (dump->infile, dump->format, "",
6075 "Bits per sample %d, Samples per pixel %d", bps, spp);
6076
6077 for (i = 0; i < length; i++)
6078 dump_buffer(dump->infile, dump->format, 1, scanlinesize,
6079 i, read_buff + (i * scanlinesize));
6080 }
6081 return (0);
6082 } /* end loadImage */
6083
6084 static int correct_orientation(struct image_data *image, unsigned char **work_buff_ptr)
6085 {
6086 uint16 mirror, rotation;
6087 unsigned char *work_buff;
6088
6089 work_buff = *work_buff_ptr;
6090 if ((image == NULL) || (work_buff == NULL))
6091 {
6092 TIFFError ("correct_orientatin", "Invalid image or buffer pointer");
6093 return (-1);
6094 }
6095
6096 if ((image->adjustments & MIRROR_HORIZ) || (image->adjustments & MIRROR_VERT))
6097 {
6098 mirror = (uint16)(image->adjustments & MIRROR_BOTH);
6099 if (mirrorImage(image->spp, image->bps, mirror,
6100 image->width, image->length, work_buff))
6101 {
6102 TIFFError ("correct_orientation", "Unable to mirror image");
6103 return (-1);
6104 }
6105 }
6106
6107 if (image->adjustments & ROTATE_ANY)
6108 {
6109 if (image->adjustments & ROTATECW_90)
6110 rotation = (uint16) 90;
6111 else
6112 if (image->adjustments & ROTATECW_180)
6113 rotation = (uint16) 180;
6114 else
6115 if (image->adjustments & ROTATECW_270)
6116 rotation = (uint16) 270;
6117 else
6118 {
6119 TIFFError ("correct_orientation", "Invalid rotation value: %d",
6120 image->adjustments & ROTATE_ANY);
6121 return (-1);
6122 }
6123
6124 if (rotateImage(rotation, image, &image->width, &image->length, work_buff_ptr))
6125 {
6126 TIFFError ("correct_orientation", "Unable to rotate image");
6127 return (-1);
6128 }
6129 image->orientation = ORIENTATION_TOPLEFT;
6130 }
6131
6132 return (0);
6133 } /* end correct_orientation */
6134
6135
6136 /* Extract multiple zones from an image and combine into a single composite image */
6137 static int
6138 extractCompositeRegions(struct image_data *image, struct crop_mask *crop,
6139 unsigned char *read_buff, unsigned char *crop_buff)
6140 {
6141 int shift_width, bytes_per_sample, bytes_per_pixel;
6142 uint32 i, trailing_bits, prev_trailing_bits;
6143 uint32 row, first_row, last_row, first_col, last_col;
6144 uint32 src_rowsize, dst_rowsize, src_offset, dst_offset;
6145 uint32 crop_width, crop_length, img_width, img_length;
6146 uint32 prev_length, prev_width, composite_width;
6147 uint16 bps, spp;
6148 uint8 *src, *dst;
6149 tsample_t count, sample = 0; /* Update to extract one or more samples */
6150
6151 img_width = image->width;
6152 img_length = image->length;
6153 bps = image->bps;
6154 spp = image->spp;
6155 count = spp;
6156
6157 bytes_per_sample = (bps + 7) / 8;
6158 bytes_per_pixel = ((bps * spp) + 7) / 8;
6159 if ((bps % 8) == 0)
6160 shift_width = 0;
6161 else
6162 {
6163 if (bytes_per_pixel < (bytes_per_sample + 1))
6164 shift_width = bytes_per_pixel;
6165 else
6166 shift_width = bytes_per_sample + 1;
6167 }
6168 src = read_buff;
6169 dst = crop_buff;
6170
6171 /* These are setup for adding additional sections */
6172 prev_width = prev_length = 0;
6173 prev_trailing_bits = trailing_bits = 0;
6174 composite_width = crop->combined_width;
6175 crop->combined_width = 0;
6176 crop->combined_length = 0;
6177
6178 for (i = 0; i < crop->selections; i++)
6179 {
6180 /* rows, columns, width, length are expressed in pixels */
6181 first_row = crop->regionlist[i].y1;
6182 last_row = crop->regionlist[i].y2;
6183 first_col = crop->regionlist[i].x1;
6184 last_col = crop->regionlist[i].x2;
6185
6186 crop_width = last_col - first_col + 1;
6187 crop_length = last_row - first_row + 1;
6188
6189 /* These should not be needed for composite images */
6190 crop->regionlist[i].width = crop_width;
6191 crop->regionlist[i].length = crop_length;
6192 crop->regionlist[i].buffptr = crop_buff;
6193
6194 src_rowsize = ((img_width * bps * spp) + 7) / 8;
6195 dst_rowsize = (((crop_width * bps * count) + 7) / 8);
6196
6197 switch (crop->edge_ref)
6198 {
6199 default:
6200 case EDGE_TOP:
6201 case EDGE_BOTTOM:
6202 if ((i > 0) && (crop_width != crop->regionlist[i - 1].width))
6203 {
6204 TIFFError ("extractCompositeRegions",
6205 "Only equal width regions can be combined for -E top or bottom");
6206 return (1);
6207 }
6208
6209 crop->combined_width = crop_width;
6210 crop->combined_length += crop_length;
6211
6212 for (row = first_row; row <= last_row; row++)
6213 {
6214 src_offset = row * src_rowsize;
6215 dst_offset = (row - first_row) * dst_rowsize;
6216 src = read_buff + src_offset;
6217 dst = crop_buff + dst_offset + (prev_length * dst_rowsize);
6218 switch (shift_width)
6219 {
6220 case 0: if (extractContigSamplesBytes (src, dst, img_width, sample,
6221 spp, bps, count, first_col,
6222 last_col + 1))
6223 {
6224 TIFFError("extractCompositeRegions",
6225 "Unable to extract row %d", row);
6226 return (1);
6227 }
6228 break;
6229 case 1: if (bps == 1)
6230 {
6231 if (extractContigSamplesShifted8bits (src, dst, img_width,
6232 sample, spp, bps, count,
6233 first_col, last_col + 1,
6234 prev_trailing_bits))
6235 {
6236 TIFFError("extractCompositeRegions",
6237 "Unable to extract row %d", row);
6238 return (1);
6239 }
6240 break;
6241 }
6242 else
6243 if (extractContigSamplesShifted16bits (src, dst, img_width,
6244 sample, spp, bps, count,
6245 first_col, last_col + 1,
6246 prev_trailing_bits))
6247 {
6248 TIFFError("extractCompositeRegions",
6249 "Unable to extract row %d", row);
6250 return (1);
6251 }
6252 break;
6253 case 2: if (extractContigSamplesShifted24bits (src, dst, img_width,
6254 sample, spp, bps, count,
6255 first_col, last_col + 1,
6256 prev_trailing_bits))
6257 {
6258 TIFFError("extractCompositeRegions",
6259 "Unable to extract row %d", row);
6260 return (1);
6261 }
6262 break;
6263 case 3:
6264 case 4:
6265 case 5: if (extractContigSamplesShifted32bits (src, dst, img_width,
6266 sample, spp, bps, count,
6267 first_col, last_col + 1,
6268 prev_trailing_bits))
6269 {
6270 TIFFError("extractCompositeRegions",
6271 "Unable to extract row %d", row);
6272 return (1);
6273 }
6274 break;
6275 default: TIFFError("extractCompositeRegions", "Unsupported bit depth %d", bps);
6276 return (1);
6277 }
6278 }
6279 prev_length += crop_length;
6280 break;
6281 case EDGE_LEFT: /* splice the pieces of each row together, side by side */
6282 case EDGE_RIGHT:
6283 if ((i > 0) && (crop_length != crop->regionlist[i - 1].length))
6284 {
6285 TIFFError ("extractCompositeRegions",
6286 "Only equal length regions can be combined for -E left or right");
6287 return (1);
6288 }
6289 crop->combined_width += crop_width;
6290 crop->combined_length = crop_length;
6291 dst_rowsize = (((composite_width * bps * count) + 7) / 8);
6292 trailing_bits = (crop_width * bps * count) % 8;
6293 for (row = first_row; row <= last_row; row++)
6294 {
6295 src_offset = row * src_rowsize;
6296 dst_offset = (row - first_row) * dst_rowsize;
6297 src = read_buff + src_offset;
6298 dst = crop_buff + dst_offset + prev_width;
6299
6300 switch (shift_width)
6301 {
6302 case 0: if (extractContigSamplesBytes (src, dst, img_width,
6303 sample, spp, bps, count,
6304 first_col, last_col + 1))
6305 {
6306 TIFFError("extractCompositeRegions",
6307 "Unable to extract row %d", row);
6308 return (1);
6309 }
6310 break;
6311 case 1: if (bps == 1)
6312 {
6313 if (extractContigSamplesShifted8bits (src, dst, img_width,
6314 sample, spp, bps, count,
6315 first_col, last_col + 1,
6316 prev_trailing_bits))
6317 {
6318 TIFFError("extractCompositeRegions",
6319 "Unable to extract row %d", row);
6320 return (1);
6321 }
6322 break;
6323 }
6324 else
6325 if (extractContigSamplesShifted16bits (src, dst, img_width,
6326 sample, spp, bps, count,
6327 first_col, last_col + 1,
6328 prev_trailing_bits))
6329 {
6330 TIFFError("extractCompositeRegions",
6331 "Unable to extract row %d", row);
6332 return (1);
6333 }
6334 break;
6335 case 2: if (extractContigSamplesShifted24bits (src, dst, img_width,
6336 sample, spp, bps, count,
6337 first_col, last_col + 1,
6338 prev_trailing_bits))
6339 {
6340 TIFFError("extractCompositeRegions",
6341 "Unable to extract row %d", row);
6342 return (1);
6343 }
6344 break;
6345 case 3:
6346 case 4:
6347 case 5: if (extractContigSamplesShifted32bits (src, dst, img_width,
6348 sample, spp, bps, count,
6349 first_col, last_col + 1,
6350 prev_trailing_bits))
6351 {
6352 TIFFError("extractCompositeRegions",
6353 "Unable to extract row %d", row);
6354 return (1);
6355 }
6356 break;
6357 default: TIFFError("extractCompositeRegions", "Unsupported bit depth %d", bps);
6358 return (1);
6359 }
6360 }
6361 prev_width += (crop_width * bps * count) / 8;
6362 prev_trailing_bits += trailing_bits;
6363 if (prev_trailing_bits > 7)
6364 prev_trailing_bits-= 8;
6365 break;
6366 }
6367 }
6368 if (crop->combined_width != composite_width)
6369 TIFFError("combineSeparateRegions","Combined width does not match composite width");
6370
6371 return (0);
6372 } /* end extractCompositeRegions */
6373
6374 /* Copy a single region of input buffer to an output buffer.
6375 * The read functions used copy separate plane data into a buffer
6376 * as interleaved samples rather than separate planes so the same
6377 * logic works to extract regions regardless of the way the data
6378 * are organized in the input file. This function can be used to
6379 * extract one or more samples from the input image by updating the
6380 * parameters for starting sample and number of samples to copy in the
6381 * fifth and eighth arguments of the call to extractContigSamples.
6382 * They would be passed as new elements of the crop_mask struct.
6383 */
6384
6385 static int
6386 extractSeparateRegion(struct image_data *image, struct crop_mask *crop,
6387 unsigned char *read_buff, unsigned char *crop_buff,
6388 int region)
6389 {
6390 int shift_width, prev_trailing_bits = 0;
6391 uint32 bytes_per_sample, bytes_per_pixel;
6392 uint32 src_rowsize, dst_rowsize;
6393 uint32 row, first_row, last_row, first_col, last_col;
6394 uint32 src_offset, dst_offset;
6395 uint32 crop_width, crop_length, img_width, img_length;
6396 uint16 bps, spp;
6397 uint8 *src, *dst;
6398 tsample_t count, sample = 0; /* Update to extract more or more samples */
6399
6400 img_width = image->width;
6401 img_length = image->length;
6402 bps = image->bps;
6403 spp = image->spp;
6404 count = spp;
6405
6406 bytes_per_sample = (bps + 7) / 8;
6407 bytes_per_pixel = ((bps * spp) + 7) / 8;
6408 if ((bps % 8) == 0)
6409 shift_width = 0; /* Byte aligned data only */
6410 else
6411 {
6412 if (bytes_per_pixel < (bytes_per_sample + 1))
6413 shift_width = bytes_per_pixel;
6414 else
6415 shift_width = bytes_per_sample + 1;
6416 }
6417
6418 /* rows, columns, width, length are expressed in pixels */
6419 first_row = crop->regionlist[region].y1;
6420 last_row = crop->regionlist[region].y2;
6421 first_col = crop->regionlist[region].x1;
6422 last_col = crop->regionlist[region].x2;
6423
6424 crop_width = last_col - first_col + 1;
6425 crop_length = last_row - first_row + 1;
6426
6427 crop->regionlist[region].width = crop_width;
6428 crop->regionlist[region].length = crop_length;
6429 crop->regionlist[region].buffptr = crop_buff;
6430
6431 src = read_buff;
6432 dst = crop_buff;
6433 src_rowsize = ((img_width * bps * spp) + 7) / 8;
6434 dst_rowsize = (((crop_width * bps * spp) + 7) / 8);
6435
6436 for (row = first_row; row <= last_row; row++)
6437 {
6438 src_offset = row * src_rowsize;
6439 dst_offset = (row - first_row) * dst_rowsize;
6440 src = read_buff + src_offset;
6441 dst = crop_buff + dst_offset;
6442
6443 switch (shift_width)
6444 {
6445 case 0: if (extractContigSamplesBytes (src, dst, img_width, sample,
6446 spp, bps, count, first_col,
6447 last_col + 1))
6448 {
6449 TIFFError("extractSeparateRegion",
6450 "Unable to extract row %d", row);
6451 return (1);
6452 }
6453 break;
6454 case 1: if (bps == 1)
6455 {
6456 if (extractContigSamplesShifted8bits (src, dst, img_width,
6457 sample, spp, bps, count,
6458 first_col, last_col + 1,
6459 prev_trailing_bits))
6460 {
6461 TIFFError("extractSeparateRegion",
6462 "Unable to extract row %d", row);
6463 return (1);
6464 }
6465 break;
6466 }
6467 else
6468 if (extractContigSamplesShifted16bits (src, dst, img_width,
6469 sample, spp, bps, count,
6470 first_col, last_col + 1,
6471 prev_trailing_bits))
6472 {
6473 TIFFError("extractSeparateRegion",
6474 "Unable to extract row %d", row);
6475 return (1);
6476 }
6477 break;
6478 case 2: if (extractContigSamplesShifted24bits (src, dst, img_width,
6479 sample, spp, bps, count,
6480 first_col, last_col + 1,
6481 prev_trailing_bits))
6482 {
6483 TIFFError("extractSeparateRegion",
6484 "Unable to extract row %d", row);
6485 return (1);
6486 }
6487 break;
6488 case 3:
6489 case 4:
6490 case 5: if (extractContigSamplesShifted32bits (src, dst, img_width,
6491 sample, spp, bps, count,
6492 first_col, last_col + 1,
6493 prev_trailing_bits))
6494 {
6495 TIFFError("extractSeparateRegion",
6496 "Unable to extract row %d", row);
6497 return (1);
6498 }
6499 break;
6500 default: TIFFError("extractSeparateRegion", "Unsupported bit depth %d", bps);
6501 return (1);
6502 }
6503 }
6504
6505 return (0);
6506 } /* end extractSeparateRegion */
6507
6508 static int
6509 extractImageSection(struct image_data *image, struct pageseg *section,
6510 unsigned char *src_buff, unsigned char *sect_buff)
6511 {
6512 unsigned char bytebuff1, bytebuff2;
6513 unsigned char *src, *dst;
6514
6515 uint32 img_width, img_length, img_rowsize;
6516 uint32 j, shift1, shift2, trailing_bits;
6517 uint32 row, first_row, last_row, first_col, last_col;
6518 uint32 src_offset, dst_offset, row_offset, col_offset;
6519 uint32 offset1, offset2, full_bytes;
6520 uint32 sect_width, sect_length;
6521 uint16 bps, spp;
6522
6523 #ifdef DEVELMODE
6524 int k;
6525 unsigned char bitset;
6526 static char *bitarray = NULL;
6527 #endif
6528
6529 img_width = image->width;
6530 img_length = image->length;
6531 bps = image->bps;
6532 spp = image->spp;
6533
6534 src = src_buff;
6535 dst = sect_buff;
6536 src_offset = 0;
6537 dst_offset = 0;
6538
6539 #ifdef DEVELMODE
6540 if (bitarray == NULL)
6541 {
6542 if ((bitarray = (char *)malloc(img_width)) == NULL)
6543 {
6544 TIFFError ("", "DEBUG: Unable to allocate debugging bitarray");
6545 return (-1);
6546 }
6547 }
6548 #endif
6549
6550 /* rows, columns, width, length are expressed in pixels */
6551 first_row = section->y1;
6552 last_row = section->y2;
6553 first_col = section->x1;
6554 last_col = section->x2;
6555
6556 sect_width = last_col - first_col + 1;
6557 sect_length = last_row - first_row + 1;
6558 img_rowsize = ((img_width * bps + 7) / 8) * spp;
6559 full_bytes = (sect_width * spp * bps) / 8; /* number of COMPLETE bytes per row in section */
6560 trailing_bits = (sect_width * bps) % 8;
6561
6562 #ifdef DEVELMODE
6563 TIFFError ("", "First row: %d, last row: %d, First col: %d, last col: %d\n",
6564 first_row, last_row, first_col, last_col);
6565 TIFFError ("", "Image width: %d, Image length: %d, bps: %d, spp: %d\n",
6566 img_width, img_length, bps, spp);
6567 TIFFError ("", "Sect width: %d, Sect length: %d, full bytes: %d trailing bits %d\n",
6568 sect_width, sect_length, full_bytes, trailing_bits);
6569 #endif
6570
6571 if ((bps % 8) == 0)
6572 {
6573 col_offset = first_col * spp * bps / 8;
6574 for (row = first_row; row <= last_row; row++)
6575 {
6576 /* row_offset = row * img_width * spp * bps / 8; */
6577 row_offset = row * img_rowsize;
6578 src_offset = row_offset + col_offset;
6579
6580 #ifdef DEVELMODE
6581 TIFFError ("", "Src offset: %8d, Dst offset: %8d", src_offset, dst_offset);
6582 #endif
6583 _TIFFmemcpy (sect_buff + dst_offset, src_buff + src_offset, full_bytes);
6584 dst_offset += full_bytes;
6585 }
6586 }
6587 else
6588 { /* bps != 8 */
6589 shift1 = spp * ((first_col * bps) % 8);
6590 shift2 = spp * ((last_col * bps) % 8);
6591 for (row = first_row; row <= last_row; row++)
6592 {
6593 /* pull out the first byte */
6594 row_offset = row * img_rowsize;
6595 offset1 = row_offset + (first_col * bps / 8);
6596 offset2 = row_offset + (last_col * bps / 8);
6597
6598 #ifdef DEVELMODE
6599 for (j = 0, k = 7; j < 8; j++, k--)
6600 {
6601 bitset = *(src_buff + offset1) & (((unsigned char)1 << k)) ? 1 : 0;
6602 sprintf(&bitarray[j], (bitset) ? "1" : "0");
6603 }
6604 sprintf(&bitarray[8], " ");
6605 sprintf(&bitarray[9], " ");
6606 for (j = 10, k = 7; j < 18; j++, k--)
6607 {
6608 bitset = *(src_buff + offset2) & (((unsigned char)1 << k)) ? 1 : 0;
6609 sprintf(&bitarray[j], (bitset) ? "1" : "0");
6610 }
6611 bitarray[18] = '\0';
6612 TIFFError ("", "Row: %3d Offset1: %d, Shift1: %d, Offset2: %d, Shift2: %d\n",
6613 row, offset1, shift1, offset2, shift2);
6614 #endif
6615
6616 bytebuff1 = bytebuff2 = 0;
6617 if (shift1 == 0) /* the region is byte and sample alligned */
6618 {
6619 _TIFFmemcpy (sect_buff + dst_offset, src_buff + offset1, full_bytes);
6620
6621 #ifdef DEVELMODE
6622 TIFFError ("", " Alligned data src offset1: %8d, Dst offset: %8d\n", offset1, dst_offset);
6623 sprintf(&bitarray[18], "\n");
6624 sprintf(&bitarray[19], "\t");
6625 for (j = 20, k = 7; j < 28; j++, k--)
6626 {
6627 bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
6628 sprintf(&bitarray[j], (bitset) ? "1" : "0");
6629 }
6630 bitarray[28] = ' ';
6631 bitarray[29] = ' ';
6632 #endif
6633 dst_offset += full_bytes;
6634
6635 if (trailing_bits != 0)
6636 {
6637 bytebuff2 = src_buff[offset2] & ((unsigned char)255 << (7 - shift2));
6638 sect_buff[dst_offset] = bytebuff2;
6639 #ifdef DEVELMODE
6640 TIFFError ("", " Trailing bits src offset: %8d, Dst offset: %8d\n",
6641 offset2, dst_offset);
6642 for (j = 30, k = 7; j < 38; j++, k--)
6643 {
6644 bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
6645 sprintf(&bitarray[j], (bitset) ? "1" : "0");
6646 }
6647 bitarray[38] = '\0';
6648 TIFFError ("", "\tFirst and last bytes before and after masking:\n\t%s\n\n", bitarray);
6649 #endif
6650 dst_offset++;
6651 }
6652 }
6653 else /* each destination byte will have to be built from two source bytes*/
6654 {
6655 #ifdef DEVELMODE
6656 TIFFError ("", " Unalligned data src offset: %8d, Dst offset: %8d\n", offset1 , dst_offset);
6657 #endif
6658 for (j = 0; j <= full_bytes; j++)
6659 {
6660 bytebuff1 = src_buff[offset1 + j] & ((unsigned char)255 >> shift1);
6661 bytebuff2 = src_buff[offset1 + j + 1] & ((unsigned char)255 << (7 - shift1));
6662 sect_buff[dst_offset + j] = (bytebuff1 << shift1) | (bytebuff2 >> (8 - shift1));
6663 }
6664 #ifdef DEVELMODE
6665 sprintf(&bitarray[18], "\n");
6666 sprintf(&bitarray[19], "\t");
6667 for (j = 20, k = 7; j < 28; j++, k--)
6668 {
6669 bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
6670 sprintf(&bitarray[j], (bitset) ? "1" : "0");
6671 }
6672 bitarray[28] = ' ';
6673 bitarray[29] = ' ';
6674 #endif
6675 dst_offset += full_bytes;
6676
6677 if (trailing_bits != 0)
6678 {
6679 #ifdef DEVELMODE
6680 TIFFError ("", " Trailing bits src offset: %8d, Dst offset: %8d\n", offset1 + full_bytes, dst_offset);
6681 #endif
6682 if (shift2 > shift1)
6683 {
6684 bytebuff1 = src_buff[offset1 + full_bytes] & ((unsigned char)255 << (7 - shift2));
6685 bytebuff2 = bytebuff1 & ((unsigned char)255 << shift1);
6686 sect_buff[dst_offset] = bytebuff2;
6687 #ifdef DEVELMODE
6688 TIFFError ("", " Shift2 > Shift1\n");
6689 #endif
6690 }
6691 else
6692 {
6693 if (shift2 < shift1)
6694 {
6695 bytebuff2 = ((unsigned char)255 << (shift1 - shift2 - 1));
6696 sect_buff[dst_offset] &= bytebuff2;
6697 #ifdef DEVELMODE
6698 TIFFError ("", " Shift2 < Shift1\n");
6699 #endif
6700 }
6701 #ifdef DEVELMODE
6702 else
6703 TIFFError ("", " Shift2 == Shift1\n");
6704 #endif
6705 }
6706 }
6707 #ifdef DEVELMODE
6708 sprintf(&bitarray[28], " ");
6709 sprintf(&bitarray[29], " ");
6710 for (j = 30, k = 7; j < 38; j++, k--)
6711 {
6712 bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
6713 sprintf(&bitarray[j], (bitset) ? "1" : "0");
6714 }
6715 bitarray[38] = '\0';
6716 TIFFError ("", "\tFirst and last bytes before and after masking:\n\t%s\n\n", bitarray);
6717 #endif
6718 dst_offset++;
6719 }
6720 }
6721 }
6722
6723 return (0);
6724 } /* end extractImageSection */
6725
6726 static int
6727 writeSelections(TIFF *in, TIFF **out, struct crop_mask *crop,
6728 struct image_data *image, struct dump_opts *dump,
6729 struct buffinfo seg_buffs[], char *mp, char *filename,
6730 unsigned int *page, unsigned int total_pages)
6731 {
6732 int i, page_count;
6733 int autoindex = 0;
6734 unsigned char *crop_buff = NULL;
6735
6736 /* Where we open a new file depends on the export mode */
6737 switch (crop->exp_mode)
6738 {
6739 case ONE_FILE_COMPOSITE: /* Regions combined into single image */
6740 autoindex = 0;
6741 crop_buff = seg_buffs[0].buffer;
6742 if (update_output_file (out, mp, autoindex, filename, page))
6743 return (1);
6744 page_count = total_pages;
6745 if (writeCroppedImage(in, *out, image, dump,
6746 crop->combined_width,
6747 crop->combined_length,
6748 crop_buff, *page, total_pages))
6749 {
6750 TIFFError("writeRegions", "Unable to write new image");
6751 return (-1);
6752 }
6753 break;
6754 case ONE_FILE_SEPARATED: /* Regions as separated images */
6755 autoindex = 0;
6756 if (update_output_file (out, mp, autoindex, filename, page))
6757 return (1);
6758 page_count = crop->selections * total_pages;
6759 for (i = 0; i < crop->selections; i++)
6760 {
6761 crop_buff = seg_buffs[i].buffer;
6762 if (writeCroppedImage(in, *out, image, dump,
6763 crop->regionlist[i].width,
6764 crop->regionlist[i].length,
6765 crop_buff, *page, page_count))
6766 {
6767 TIFFError("writeRegions", "Unable to write new image");
6768 return (-1);
6769 }
6770 }
6771 break;
6772 case FILE_PER_IMAGE_COMPOSITE: /* Regions as composite image */
6773 autoindex = 1;
6774 if (update_output_file (out, mp, autoindex, filename, page))
6775 return (1);
6776
6777 crop_buff = seg_buffs[0].buffer;
6778 if (writeCroppedImage(in, *out, image, dump,
6779 crop->combined_width,
6780 crop->combined_length,
6781 crop_buff, *page, total_pages))
6782 {
6783 TIFFError("writeRegions", "Unable to write new image");
6784 return (-1);
6785 }
6786 break;
6787 case FILE_PER_IMAGE_SEPARATED: /* Regions as separated images */
6788 autoindex = 1;
6789 page_count = crop->selections;
6790 if (update_output_file (out, mp, autoindex, filename, page))
6791 return (1);
6792
6793 for (i = 0; i < crop->selections; i++)
6794 {
6795 crop_buff = seg_buffs[i].buffer;
6796 /* Write the current region to the current file */
6797 if (writeCroppedImage(in, *out, image, dump,
6798 crop->regionlist[i].width,
6799 crop->regionlist[i].length,
6800 crop_buff, *page, page_count))
6801 {
6802 TIFFError("writeRegions", "Unable to write new image");
6803 return (-1);
6804 }
6805 }
6806 break;
6807 case FILE_PER_SELECTION:
6808 autoindex = 1;
6809 page_count = 1;
6810 for (i = 0; i < crop->selections; i++)
6811 {
6812 if (update_output_file (out, mp, autoindex, filename, page))
6813 return (1);
6814
6815 crop_buff = seg_buffs[i].buffer;
6816 /* Write the current region to the current file */
6817 if (writeCroppedImage(in, *out, image, dump,
6818 crop->regionlist[i].width,
6819 crop->regionlist[i].length,
6820 crop_buff, *page, page_count))
6821 {
6822 TIFFError("writeRegions", "Unable to write new image");
6823 return (-1);
6824 }
6825 }
6826 break;
6827 default: return (1);
6828 }
6829
6830 return (0);
6831 } /* end writeRegions */
6832
6833 static int
6834 writeImageSections(TIFF *in, TIFF *out, struct image_data *image,
6835 struct pagedef *page, struct pageseg *sections,
6836 struct dump_opts * dump, unsigned char *src_buff,
6837 unsigned char **sect_buff_ptr)
6838 {
6839 double hres, vres;
6840 uint32 i, k, width, length, sectsize;
6841 unsigned char *sect_buff = *sect_buff_ptr;
6842
6843 hres = page->hres;
6844 vres = page->vres;
6845
6846 k = page->cols * page->rows;
6847 if ((k < 1) || (k > MAX_SECTIONS))
6848 {
6849 TIFFError("writeImageSections",
6850 "%d Rows and Columns exceed maximum sections\nIncrease resolution or reduce sections", k);
6851 return (-1);
6852 }
6853
6854 for (i = 0; i < k; i++)
6855 {
6856 width = sections[i].x2 - sections[i].x1 + 1;
6857 length = sections[i].y2 - sections[i].y1 + 1;
6858 sectsize = (uint32)
6859 ceil((width * image->bps + 7) / (double)8) * image->spp * length;
6860 /* allocate a buffer if we don't have one already */
6861 if (createImageSection(sectsize, sect_buff_ptr))
6862 {
6863 TIFFError("writeImageSections", "Unable to allocate section buffer");
6864 exit (-1);
6865 }
6866 sect_buff = *sect_buff_ptr;
6867
6868 if (extractImageSection (image, &sections[i], src_buff, sect_buff))
6869 {
6870 TIFFError("writeImageSections", "Unable to extract image sections");
6871 exit (-1);
6872 }
6873
6874 /* call the write routine here instead of outside the loop */
6875 if (writeSingleSection(in, out, image, dump, width, length, hres, vres, sect_buff))
6876 {
6877 TIFFError("writeImageSections", "Unable to write image section");
6878 exit (-1);
6879 }
6880 }
6881
6882 return (0);
6883 } /* end writeImageSections */
6884
6885 /* Code in this function is heavily indebted to code in tiffcp
6886 * with modifications by Richard Nolde to handle orientation correctly.
6887 * It will have to be updated significantly if support is added to
6888 * extract one or more samples from original image since the
6889 * original code assumes we are always copying all samples.
6890 */
6891 static int
6892 writeSingleSection(TIFF *in, TIFF *out, struct image_data *image,
6893 struct dump_opts *dump, uint32 width, uint32 length,
6894 double hres, double vres,
6895 unsigned char *sect_buff)
6896 {
6897 uint16 bps, spp;
6898 uint16 input_compression, input_photometric;
6899 uint16 input_planar;
6900 struct cpTag* p;
6901
6902 /* Calling this seems to reset the compression mode on the TIFF *in file.
6903 TIFFGetField(in, TIFFTAG_JPEGCOLORMODE, &input_jpeg_colormode);
6904 */
6905 input_compression = image->compression;
6906 input_photometric = image->photometric;
6907
6908 spp = image->spp;
6909 bps = image->bps;
6910 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
6911 TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
6912 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bps);
6913 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
6914
6915 #ifdef DEBUG2
6916 TIFFError("writeSingleSection", "Input compression: %s",
6917 (input_compression == COMPRESSION_OJPEG) ? "Old Jpeg" :
6918 ((input_compression == COMPRESSION_JPEG) ? "New Jpeg" : "Non Jpeg"));
6919 #endif
6920 /* This is the global variable compression which is set
6921 * if the user has specified a command line option for
6922 * a compression option. Should be passed around in one
6923 * of the parameters instead of as a global. If no user
6924 * option specified it will still be (uint16) -1. */
6925 if (compression != (uint16)-1)
6926 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
6927 else
6928 { /* OJPEG is no longer supported for writing so upgrade to JPEG */
6929 if (input_compression == COMPRESSION_OJPEG)
6930 {
6931 compression = COMPRESSION_JPEG;
6932 jpegcolormode = JPEGCOLORMODE_RAW;
6933 TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
6934 }
6935 else /* Use the compression from the input file */
6936 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
6937 }
6938
6939 if (compression == COMPRESSION_JPEG)
6940 {
6941 if ((input_photometric == PHOTOMETRIC_PALETTE) || /* color map indexed */
6942 (input_photometric == PHOTOMETRIC_MASK)) /* holdout mask */
6943 {
6944 TIFFError ("writeSingleSection",
6945 "JPEG compression cannot be used with %s image data",
6946 (input_photometric == PHOTOMETRIC_PALETTE) ?
6947 "palette" : "mask");
6948 return (-1);
6949 }
6950 if ((input_photometric == PHOTOMETRIC_RGB) &&
6951 (jpegcolormode == JPEGCOLORMODE_RGB))
6952 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
6953 else
6954 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
6955 }
6956 else
6957 {
6958 if (compression == COMPRESSION_SGILOG || compression == COMPRESSION_SGILOG24)
6959 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, spp == 1 ?
6960 PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
6961 else
6962 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, image->photometric);
6963 }
6964
6965 #ifdef DEBUG2
6966 TIFFError("writeSingleSection", "Input photometric: %s",
6967 (input_photometric == PHOTOMETRIC_RGB) ? "RGB" :
6968 ((input_photometric == PHOTOMETRIC_YCBCR) ? "YCbCr" : "Not RGB or YCbCr"));
6969 #endif
6970
6971 if (((input_photometric == PHOTOMETRIC_LOGL) ||
6972 (input_photometric == PHOTOMETRIC_LOGLUV)) &&
6973 ((compression != COMPRESSION_SGILOG) &&
6974 (compression != COMPRESSION_SGILOG24)))
6975 {
6976 TIFFError("writeSingleSection",
6977 "LogL and LogLuv source data require SGI_LOG or SGI_LOG24 compression");
6978 return (-1);
6979 }
6980
6981 if (fillorder != 0)
6982 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
6983 else
6984 CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
6985
6986 /* The loadimage function reads input orientation and sets
6987 * image->orientation. The correct_image_orientation function
6988 * applies the required rotation and mirror operations to
6989 * present the data in TOPLEFT orientation and updates
6990 * image->orientation if any transforms are performed,
6991 * as per EXIF standard.
6992 */
6993 TIFFSetField(out, TIFFTAG_ORIENTATION, image->orientation);
6994
6995 /*
6996 * Choose tiles/strip for the output image according to
6997 * the command line arguments (-tiles, -strips) and the
6998 * structure of the input image.
6999 */
7000 if (outtiled == -1)
7001 outtiled = TIFFIsTiled(in);
7002 if (outtiled) {
7003 /*
7004 * Setup output file's tile width&height. If either
7005 * is not specified, use either the value from the
7006 * input image or, if nothing is defined, use the
7007 * library default.
7008 */
7009 if (tilewidth == (uint32) 0)
7010 TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
7011 if (tilelength == (uint32) 0)
7012 TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
7013
7014 if (tilewidth == 0 || tilelength == 0)
7015 TIFFDefaultTileSize(out, &tilewidth, &tilelength);
7016 TIFFDefaultTileSize(out, &tilewidth, &tilelength);
7017 TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
7018 TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
7019 } else {
7020 /*
7021 * RowsPerStrip is left unspecified: use either the
7022 * value from the input image or, if nothing is defined,
7023 * use the library default.
7024 */
7025 if (rowsperstrip == (uint32) 0)
7026 {
7027 if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
7028 rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
7029 if (compression != COMPRESSION_JPEG)
7030 {
7031 if (rowsperstrip > length)
7032 rowsperstrip = length;
7033 }
7034 }
7035 else
7036 if (rowsperstrip == (uint32) -1)
7037 rowsperstrip = length;
7038 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
7039 }
7040
7041 TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &input_planar);
7042 if (config != (uint16) -1)
7043 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
7044 else
7045 CopyField(TIFFTAG_PLANARCONFIG, config);
7046 if (spp <= 4)
7047 CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
7048 CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
7049
7050 /* SMinSampleValue & SMaxSampleValue */
7051 switch (compression) {
7052 /* These are references to GLOBAL variables set by defaults
7053 * and /or the compression flag
7054 */
7055 case COMPRESSION_JPEG:
7056 if (((bps % 8) == 0) || ((bps % 12) == 0))
7057 {
7058 TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
7059 TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
7060 }
7061 else
7062 {
7063 TIFFError("writeSingleSection",
7064 "JPEG compression requires 8 or 12 bits per sample");
7065 return (-1);
7066 }
7067 break;
7068 case COMPRESSION_LZW:
7069 case COMPRESSION_ADOBE_DEFLATE:
7070 case COMPRESSION_DEFLATE:
7071 if (predictor != (uint16)-1)
7072 TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
7073 else
7074 CopyField(TIFFTAG_PREDICTOR, predictor);
7075 break;
7076 case COMPRESSION_CCITTFAX3:
7077 case COMPRESSION_CCITTFAX4:
7078 if (compression == COMPRESSION_CCITTFAX3) {
7079 if (g3opts != (uint32) -1)
7080 TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
7081 else
7082 CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
7083 } else
7084 CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
7085 CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
7086 CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
7087 CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
7088 CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
7089 CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
7090 CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
7091 break;
7092 }
7093 { uint32 len32;
7094 void** data;
7095 if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
7096 TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
7097 }
7098 { uint16 ninks;
7099 const char* inknames;
7100 if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
7101 TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
7102 if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
7103 int inknameslen = strlen(inknames) + 1;
7104 const char* cp = inknames;
7105 while (ninks > 1) {
7106 cp = strchr(cp, '\0');
7107 if (cp) {
7108 cp++;
7109 inknameslen += (strlen(cp) + 1);
7110 }
7111 ninks--;
7112 }
7113 TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
7114 }
7115 }
7116 }
7117 {
7118 unsigned short pg0, pg1;
7119 if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
7120 if (pageNum < 0) /* only one input file */
7121 TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
7122 else
7123 TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
7124 }
7125 }
7126
7127 for (p = tags; p < &tags[NTAGS]; p++)
7128 CopyTag(p->tag, p->count, p->type);
7129
7130 /* Update these since they are overwritten from input res by loop above */
7131 TIFFSetField(out, TIFFTAG_XRESOLUTION, (float)hres);
7132 TIFFSetField(out, TIFFTAG_YRESOLUTION, (float)vres);
7133
7134 /* Compute the tile or strip dimensions and write to disk */
7135 if (outtiled)
7136 {
7137 if (config == PLANARCONFIG_CONTIG)
7138 writeBufferToContigTiles (out, sect_buff, length, width, spp, dump);
7139 else
7140 writeBufferToSeparateTiles (out, sect_buff, length, width, spp, dump);
7141 }
7142 else
7143 {
7144 if (config == PLANARCONFIG_CONTIG)
7145 writeBufferToContigStrips (out, sect_buff, length);
7146 else
7147 writeBufferToSeparateStrips(out, sect_buff, length, width, spp, dump);
7148 }
7149
7150 if (!TIFFWriteDirectory(out))
7151 {
7152 TIFFClose(out);
7153 return (-1);
7154 }
7155
7156 return (0);
7157 } /* end writeSingleSection */
7158
7159
7160 /* Create a buffer to write one section at a time */
7161 static int
7162 createImageSection(uint32 sectsize, unsigned char **sect_buff_ptr)
7163 {
7164 unsigned char *sect_buff = NULL;
7165 unsigned char *new_buff = NULL;
7166 static uint32 prev_sectsize = 0;
7167
7168 sect_buff = *sect_buff_ptr;
7169
7170 if (!sect_buff)
7171 {
7172 sect_buff = (unsigned char *)_TIFFmalloc(sectsize);
7173 *sect_buff_ptr = sect_buff;
7174 _TIFFmemset(sect_buff, 0, sectsize);
7175 }
7176 else
7177 {
7178 if (prev_sectsize < sectsize)
7179 {
7180 new_buff = _TIFFrealloc(sect_buff, sectsize);
7181 if (!new_buff)
7182 {
7183 free (sect_buff);
7184 sect_buff = (unsigned char *)_TIFFmalloc(sectsize);
7185 }
7186 else
7187 sect_buff = new_buff;
7188
7189 _TIFFmemset(sect_buff, 0, sectsize);
7190 }
7191 }
7192
7193 if (!sect_buff)
7194 {
7195 TIFFError("createImageSection", "Unable to allocate/reallocate section buffer");
7196 return (-1);
7197 }
7198 prev_sectsize = sectsize;
7199 *sect_buff_ptr = sect_buff;
7200
7201 return (0);
7202 } /* end createImageSection */
7203
7204
7205 /* Process selections defined by regions, zones, margins, or fixed sized areas */
7206 static int
7207 processCropSelections(struct image_data *image, struct crop_mask *crop,
7208 unsigned char **read_buff_ptr, struct buffinfo seg_buffs[])
7209 {
7210 int i;
7211 uint32 width, length, total_width, total_length;
7212 tsize_t cropsize;
7213 unsigned char *crop_buff = NULL;
7214 unsigned char *read_buff = NULL;
7215 unsigned char *next_buff = NULL;
7216 tsize_t prev_cropsize = 0;
7217
7218 read_buff = *read_buff_ptr;
7219
7220 if (crop->img_mode == COMPOSITE_IMAGES)
7221 {
7222 cropsize = crop->bufftotal;
7223 crop_buff = seg_buffs[0].buffer;
7224 if (!crop_buff)
7225 crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
7226 else
7227 {
7228 prev_cropsize = seg_buffs[0].size;
7229 if (prev_cropsize < cropsize)
7230 {
7231 next_buff = _TIFFrealloc(crop_buff, cropsize);
7232 if (! next_buff)
7233 {
7234 _TIFFfree (crop_buff);
7235 crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
7236 }
7237 else
7238 crop_buff = next_buff;
7239 }
7240 }
7241
7242 if (!crop_buff)
7243 {
7244 TIFFError("processCropSelections", "Unable to allocate/reallocate crop buffer");
7245 return (-1);
7246 }
7247
7248 _TIFFmemset(crop_buff, 0, cropsize);
7249 seg_buffs[0].buffer = crop_buff;
7250 seg_buffs[0].size = cropsize;
7251
7252 /* Checks for matching width or length as required */
7253 if (extractCompositeRegions(image, crop, read_buff, crop_buff) != 0)
7254 return (1);
7255
7256 if (crop->crop_mode & CROP_INVERT)
7257 {
7258 switch (crop->photometric)
7259 {
7260 /* Just change the interpretation */
7261 case PHOTOMETRIC_MINISWHITE:
7262 case PHOTOMETRIC_MINISBLACK:
7263 image->photometric = crop->photometric;
7264 break;
7265 case INVERT_DATA_ONLY:
7266 case INVERT_DATA_AND_TAG:
7267 if (invertImage(image->photometric, image->spp, image->bps,
7268 crop->combined_width, crop->combined_length, crop_buff))
7269 {
7270 TIFFError("processCropSelections",
7271 "Failed to invert colorspace for composite regions");
7272 return (-1);
7273 }
7274 if (crop->photometric == INVERT_DATA_AND_TAG)
7275 {
7276 switch (image->photometric)
7277 {
7278 case PHOTOMETRIC_MINISWHITE:
7279 image->photometric = PHOTOMETRIC_MINISBLACK;
7280 break;
7281 case PHOTOMETRIC_MINISBLACK:
7282 image->photometric = PHOTOMETRIC_MINISWHITE;
7283 break;
7284 default:
7285 break;
7286 }
7287 }
7288 break;
7289 default: break;
7290 }
7291 }
7292
7293 /* Mirror and Rotate will not work with multiple regions unless they are the same width */
7294 if (crop->crop_mode & CROP_MIRROR)
7295 {
7296 if (mirrorImage(image->spp, image->bps, crop->mirror,
7297 crop->combined_width, crop->combined_length, crop_buff))
7298 {
7299 TIFFError("processCropSelections", "Failed to mirror composite regions %s",
7300 (crop->rotation == MIRROR_HORIZ) ? "horizontally" : "vertically");
7301 return (-1);
7302 }
7303 }
7304
7305 if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
7306 {
7307 if (rotateImage(crop->rotation, image, &crop->combined_width,
7308 &crop->combined_length, &crop_buff))
7309 {
7310 TIFFError("processCropSelections",
7311 "Failed to rotate composite regions by %d degrees", crop->rotation);
7312 return (-1);
7313 }
7314 seg_buffs[0].buffer = crop_buff;
7315 seg_buffs[0].size = (((crop->combined_width * image->bps + 7 ) / 8)
7316 * image->spp) * crop->combined_length;
7317 }
7318 }
7319 else /* Separated Images */
7320 {
7321 total_width = total_length = 0;
7322 for (i = 0; i < crop->selections; i++)
7323 {
7324 cropsize = crop->bufftotal;
7325 crop_buff = seg_buffs[i].buffer;
7326 if (!crop_buff)
7327 crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
7328 else
7329 {
7330 prev_cropsize = seg_buffs[0].size;
7331 if (prev_cropsize < cropsize)
7332 {
7333 next_buff = _TIFFrealloc(crop_buff, cropsize);
7334 if (! next_buff)
7335 {
7336 _TIFFfree (crop_buff);
7337 crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
7338 }
7339 else
7340 crop_buff = next_buff;
7341 }
7342 }
7343
7344 if (!crop_buff)
7345 {
7346 TIFFError("processCropSelections", "Unable to allocate/reallocate crop buffer");
7347 return (-1);
7348 }
7349
7350 _TIFFmemset(crop_buff, 0, cropsize);
7351 seg_buffs[i].buffer = crop_buff;
7352 seg_buffs[i].size = cropsize;
7353
7354 if (extractSeparateRegion(image, crop, read_buff, crop_buff, i))
7355 {
7356 TIFFError("processCropSelections", "Unable to extract cropped region %d from image", i);
7357 return (-1);
7358 }
7359
7360 width = crop->regionlist[i].width;
7361 length = crop->regionlist[i].length;
7362
7363 if (crop->crop_mode & CROP_INVERT)
7364 {
7365 switch (crop->photometric)
7366 {
7367 /* Just change the interpretation */
7368 case PHOTOMETRIC_MINISWHITE:
7369 case PHOTOMETRIC_MINISBLACK:
7370 image->photometric = crop->photometric;
7371 break;
7372 case INVERT_DATA_ONLY:
7373 case INVERT_DATA_AND_TAG:
7374 if (invertImage(image->photometric, image->spp, image->bps,
7375 width, length, crop_buff))
7376 {
7377 TIFFError("processCropSelections",
7378 "Failed to invert colorspace for region");
7379 return (-1);
7380 }
7381 if (crop->photometric == INVERT_DATA_AND_TAG)
7382 {
7383 switch (image->photometric)
7384 {
7385 case PHOTOMETRIC_MINISWHITE:
7386 image->photometric = PHOTOMETRIC_MINISBLACK;
7387 break;
7388 case PHOTOMETRIC_MINISBLACK:
7389 image->photometric = PHOTOMETRIC_MINISWHITE;
7390 break;
7391 default:
7392 break;
7393 }
7394 }
7395 break;
7396 default: break;
7397 }
7398 }
7399
7400 if (crop->crop_mode & CROP_MIRROR)
7401 {
7402 if (mirrorImage(image->spp, image->bps, crop->mirror,
7403 width, length, crop_buff))
7404 {
7405 TIFFError("processCropSelections", "Failed to mirror crop region %s",
7406 (crop->rotation == MIRROR_HORIZ) ? "horizontally" : "vertically");
7407 return (-1);
7408 }
7409 }
7410
7411 if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
7412 {
7413 if (rotateImage(crop->rotation, image, &crop->regionlist[i].width,
7414 &crop->regionlist[i].length, &crop_buff))
7415 {
7416 TIFFError("processCropSelections",
7417 "Failed to rotate crop region by %d degrees", crop->rotation);
7418 return (-1);
7419 }
7420 total_width += crop->regionlist[i].width;
7421 total_length += crop->regionlist[i].length;
7422 crop->combined_width = total_width;
7423 crop->combined_length = total_length;
7424 seg_buffs[i].buffer = crop_buff;
7425 seg_buffs[i].size = (((crop->regionlist[i].width * image->bps + 7 ) / 8)
7426 * image->spp) * crop->regionlist[i].length;
7427 }
7428 }
7429 }
7430 return (0);
7431 } /* end processCropSelections */
7432
7433 /* Copy the crop section of the data from the current image into a buffer
7434 * and adjust the IFD values to reflect the new size. If no cropping is
7435 * required, use the origial read buffer as the crop buffer.
7436 *
7437 * There is quite a bit of redundancy between this routine and the more
7438 * specialized processCropSelections, but this provides
7439 * the most optimized path when no Zones or Regions are required.
7440 */
7441 static int
7442 createCroppedImage(struct image_data *image, struct crop_mask *crop,
7443 unsigned char **read_buff_ptr, unsigned char **crop_buff_ptr)
7444 {
7445 tsize_t cropsize;
7446 unsigned char *read_buff = NULL;
7447 unsigned char *crop_buff = NULL;
7448 unsigned char *new_buff = NULL;
7449 static tsize_t prev_cropsize = 0;
7450
7451 read_buff = *read_buff_ptr;
7452
7453 /* process full image, no crop buffer needed */
7454 crop_buff = read_buff;
7455 *crop_buff_ptr = read_buff;
7456 crop->combined_width = image->width;
7457 crop->combined_length = image->length;
7458
7459 cropsize = crop->bufftotal;
7460 crop_buff = *crop_buff_ptr;
7461 if (!crop_buff)
7462 {
7463 crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
7464 *crop_buff_ptr = crop_buff;
7465 _TIFFmemset(crop_buff, 0, cropsize);
7466 prev_cropsize = cropsize;
7467 }
7468 else
7469 {
7470 if (prev_cropsize < cropsize)
7471 {
7472 new_buff = _TIFFrealloc(crop_buff, cropsize);
7473 if (!new_buff)
7474 {
7475 free (crop_buff);
7476 crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
7477 }
7478 else
7479 crop_buff = new_buff;
7480 _TIFFmemset(crop_buff, 0, cropsize);
7481 }
7482 }
7483
7484 if (!crop_buff)
7485 {
7486 TIFFError("createCroppedImage", "Unable to allocate/reallocate crop buffer");
7487 return (-1);
7488 }
7489 *crop_buff_ptr = crop_buff;
7490
7491 if (crop->crop_mode & CROP_INVERT)
7492 {
7493 switch (crop->photometric)
7494 {
7495 /* Just change the interpretation */
7496 case PHOTOMETRIC_MINISWHITE:
7497 case PHOTOMETRIC_MINISBLACK:
7498 image->photometric = crop->photometric;
7499 break;
7500 case INVERT_DATA_ONLY:
7501 case INVERT_DATA_AND_TAG:
7502 if (invertImage(image->photometric, image->spp, image->bps,
7503 crop->combined_width, crop->combined_length, crop_buff))
7504 {
7505 TIFFError("createCroppedImage",
7506 "Failed to invert colorspace for image or cropped selection");
7507 return (-1);
7508 }
7509 if (crop->photometric == INVERT_DATA_AND_TAG)
7510 {
7511 switch (image->photometric)
7512 {
7513 case PHOTOMETRIC_MINISWHITE:
7514 image->photometric = PHOTOMETRIC_MINISBLACK;
7515 break;
7516 case PHOTOMETRIC_MINISBLACK:
7517 image->photometric = PHOTOMETRIC_MINISWHITE;
7518 break;
7519 default:
7520 break;
7521 }
7522 }
7523 break;
7524 default: break;
7525 }
7526 }
7527
7528 if (crop->crop_mode & CROP_MIRROR)
7529 {
7530 if (mirrorImage(image->spp, image->bps, crop->mirror,
7531 crop->combined_width, crop->combined_length, crop_buff))
7532 {
7533 TIFFError("createCroppedImage", "Failed to mirror image or cropped selection %s",
7534 (crop->rotation == MIRROR_HORIZ) ? "horizontally" : "vertically");
7535 return (-1);
7536 }
7537 }
7538
7539 if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
7540 {
7541 if (rotateImage(crop->rotation, image, &crop->combined_width,
7542 &crop->combined_length, crop_buff_ptr))
7543 {
7544 TIFFError("createCroppedImage",
7545 "Failed to rotate image or cropped selection by %d degrees", crop->rotation);
7546 return (-1);
7547 }
7548 }
7549
7550 if (crop_buff == read_buff) /* we used the read buffer for the crop buffer */
7551 *read_buff_ptr = NULL; /* so we don't try to free it later */
7552
7553 return (0);
7554 } /* end createCroppedImage */
7555
7556
7557 /* Code in this function is heavily indebted to code in tiffcp
7558 * with modifications by Richard Nolde to handle orientation correctly.
7559 * It will have to be updated significantly if support is added to
7560 * extract one or more samples from original image since the
7561 * original code assumes we are always copying all samples.
7562 * Use of global variables for config, compression and others
7563 * should be replaced by addition to the crop_mask struct (which
7564 * will be renamed to proc_opts indicating that is controlls
7565 * user supplied processing options, not just cropping) and
7566 * then passed in as an argument.
7567 */
7568 static int
7569 writeCroppedImage(TIFF *in, TIFF *out, struct image_data *image,
7570 struct dump_opts *dump, uint32 width, uint32 length,
7571 unsigned char *crop_buff, int pagenum, int total_pages)
7572 {
7573 uint16 bps, spp;
7574 uint16 input_compression, input_photometric;
7575 uint16 input_planar;
7576 struct cpTag* p;
7577
7578 input_compression = image->compression;
7579 input_photometric = image->photometric;
7580 spp = image->spp;
7581 bps = image->bps;
7582
7583 TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
7584 TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
7585 TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bps);
7586 TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
7587
7588 #ifdef DEBUG2
7589 TIFFError("writeCroppedImage", "Input compression: %s",
7590 (input_compression == COMPRESSION_OJPEG) ? "Old Jpeg" :
7591 ((input_compression == COMPRESSION_JPEG) ? "New Jpeg" : "Non Jpeg"));
7592 #endif
7593
7594 if (compression != (uint16)-1)
7595 TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
7596 else
7597 {
7598 if (input_compression == COMPRESSION_OJPEG)
7599 {
7600 compression = COMPRESSION_JPEG;
7601 jpegcolormode = JPEGCOLORMODE_RAW;
7602 TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
7603 }
7604 else
7605 CopyField(TIFFTAG_COMPRESSION, compression);
7606 }
7607
7608 if (compression == COMPRESSION_JPEG)
7609 {
7610 if ((input_photometric == PHOTOMETRIC_PALETTE) || /* color map indexed */
7611 (input_photometric == PHOTOMETRIC_MASK)) /* $holdout mask */
7612 {
7613 TIFFError ("writeCroppedImage",
7614 "JPEG compression cannot be used with %s image data",
7615 (input_photometric == PHOTOMETRIC_PALETTE) ?
7616 "palette" : "mask");
7617 return (-1);
7618 }
7619 if ((input_photometric == PHOTOMETRIC_RGB) &&
7620 (jpegcolormode == JPEGCOLORMODE_RGB))
7621 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
7622 else
7623 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
7624 }
7625 else
7626 {
7627 if (compression == COMPRESSION_SGILOG || compression == COMPRESSION_SGILOG24)
7628 {
7629 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, spp == 1 ?
7630 PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
7631 }
7632 else
7633 {
7634 if (input_compression == COMPRESSION_SGILOG ||
7635 input_compression == COMPRESSION_SGILOG24)
7636 {
7637 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, spp == 1 ?
7638 PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
7639 }
7640 else
7641 TIFFSetField(out, TIFFTAG_PHOTOMETRIC, image->photometric);
7642 }
7643 }
7644
7645 if (((input_photometric == PHOTOMETRIC_LOGL) ||
7646 (input_photometric == PHOTOMETRIC_LOGLUV)) &&
7647 ((compression != COMPRESSION_SGILOG) &&
7648 (compression != COMPRESSION_SGILOG24)))
7649 {
7650 TIFFError("writeCroppedImage",
7651 "LogL and LogLuv source data require SGI_LOG or SGI_LOG24 compression");
7652 return (-1);
7653 }
7654
7655 if (fillorder != 0)
7656 TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
7657 else
7658 CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
7659
7660 /* The loadimage function reads input orientation and sets
7661 * image->orientation. The correct_image_orientation function
7662 * applies the required rotation and mirror operations to
7663 * present the data in TOPLEFT orientation and updates
7664 * image->orientation if any transforms are performed,
7665 * as per EXIF standard.
7666 */
7667 TIFFSetField(out, TIFFTAG_ORIENTATION, image->orientation);
7668
7669 /*
7670 * Choose tiles/strip for the output image according to
7671 * the command line arguments (-tiles, -strips) and the
7672 * structure of the input image.
7673 */
7674 if (outtiled == -1)
7675 outtiled = TIFFIsTiled(in);
7676 if (outtiled) {
7677 /*
7678 * Setup output file's tile width&height. If either
7679 * is not specified, use either the value from the
7680 * input image or, if nothing is defined, use the
7681 * library default.
7682 */
7683 if (tilewidth == (uint32) 0)
7684 TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
7685 if (tilelength == (uint32) 0)
7686 TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
7687
7688 if (tilewidth == 0 || tilelength == 0)
7689 TIFFDefaultTileSize(out, &tilewidth, &tilelength);
7690 TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
7691 TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
7692 } else {
7693 /*
7694 * RowsPerStrip is left unspecified: use either the
7695 * value from the input image or, if nothing is defined,
7696 * use the library default.
7697 */
7698 if (rowsperstrip == (uint32) 0)
7699 {
7700 if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
7701 rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
7702 if (compression != COMPRESSION_JPEG)
7703 {
7704 if (rowsperstrip > length)
7705 rowsperstrip = length;
7706 }
7707 }
7708 else
7709 if (rowsperstrip == (uint32) -1)
7710 rowsperstrip = length;
7711 TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
7712 }
7713
7714 TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &input_planar);
7715 if (config != (uint16) -1)
7716 TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
7717 else
7718 CopyField(TIFFTAG_PLANARCONFIG, config);
7719 if (spp <= 4)
7720 CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
7721 CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
7722
7723 /* SMinSampleValue & SMaxSampleValue */
7724 switch (compression) {
7725 case COMPRESSION_JPEG:
7726 if (((bps % 8) == 0) || ((bps % 12) == 0))
7727 {
7728 TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
7729 TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
7730 }
7731 else
7732 {
7733 TIFFError("writeCroppedImage",
7734 "JPEG compression requires 8 or 12 bits per sample");
7735 return (-1);
7736 }
7737 break;
7738 case COMPRESSION_LZW:
7739 case COMPRESSION_ADOBE_DEFLATE:
7740 case COMPRESSION_DEFLATE:
7741 if (predictor != (uint16)-1)
7742 TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
7743 else
7744 CopyField(TIFFTAG_PREDICTOR, predictor);
7745 break;
7746 case COMPRESSION_CCITTFAX3:
7747 case COMPRESSION_CCITTFAX4:
7748 if (bps != 1)
7749 {
7750 TIFFError("writeCroppedImage",
7751 "Group 3/4 compression is not usable with bps > 1");
7752 return (-1);
7753 }
7754 if (compression == COMPRESSION_CCITTFAX3) {
7755 if (g3opts != (uint32) -1)
7756 TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
7757 else
7758 CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
7759 } else
7760 CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
7761 CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
7762 CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
7763 CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
7764 CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
7765 CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
7766 CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
7767 break;
7768 case COMPRESSION_NONE:
7769 break;
7770 default: break;
7771 }
7772 { uint32 len32;
7773 void** data;
7774 if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
7775 TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
7776 }
7777 { uint16 ninks;
7778 const char* inknames;
7779 if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
7780 TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
7781 if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
7782 int inknameslen = strlen(inknames) + 1;
7783 const char* cp = inknames;
7784 while (ninks > 1) {
7785 cp = strchr(cp, '\0');
7786 if (cp) {
7787 cp++;
7788 inknameslen += (strlen(cp) + 1);
7789 }
7790 ninks--;
7791 }
7792 TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
7793 }
7794 }
7795 }
7796 {
7797 unsigned short pg0, pg1;
7798 if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
7799 TIFFSetField(out, TIFFTAG_PAGENUMBER, pagenum, total_pages);
7800 }
7801 }
7802
7803 for (p = tags; p < &tags[NTAGS]; p++)
7804 CopyTag(p->tag, p->count, p->type);
7805
7806 /* Compute the tile or strip dimensions and write to disk */
7807 if (outtiled)
7808 {
7809 if (config == PLANARCONFIG_CONTIG)
7810 {
7811 if (writeBufferToContigTiles (out, crop_buff, length, width, spp, dump))
7812 TIFFError("","Unable to write contiguous tile data for page %d", pagenum);
7813 }
7814 else
7815 {
7816 if (writeBufferToSeparateTiles (out, crop_buff, length, width, spp, dump))
7817 TIFFError("","Unable to write separate tile data for page %d", pagenum);
7818 }
7819 }
7820 else
7821 {
7822 if (config == PLANARCONFIG_CONTIG)
7823 {
7824 if (writeBufferToContigStrips (out, crop_buff, length))
7825 TIFFError("","Unable to write contiguous strip data for page %d", pagenum);
7826 }
7827 else
7828 {
7829 if (writeBufferToSeparateStrips(out, crop_buff, length, width, spp, dump))
7830 TIFFError("","Unable to write separate strip data for page %d", pagenum);
7831 }
7832 }
7833
7834 if (!TIFFWriteDirectory(out))
7835 {
7836 TIFFError("","Failed to write IFD for page number %d", pagenum);
7837 TIFFClose(out);
7838 return (-1);
7839 }
7840
7841 return (0);
7842 } /* end writeCroppedImage */
7843
7844 static int
7845 rotateContigSamples8bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width,
7846 uint32 length, uint32 col, uint8 *src, uint8 *dst)
7847 {
7848 int ready_bits = 0;
7849 uint32 src_byte = 0, src_bit = 0;
7850 uint32 row, rowsize = 0, bit_offset = 0;
7851 uint8 matchbits = 0, maskbits = 0;
7852 uint8 buff1 = 0, buff2 = 0;
7853 uint8 *next;
7854 tsample_t sample;
7855
7856 if ((src == NULL) || (dst == NULL))
7857 {
7858 TIFFError("rotateContigSamples8bits","Invalid src or destination buffer");
7859 return (1);
7860 }
7861
7862 rowsize = ((bps * spp * width) + 7) / 8;
7863 ready_bits = 0;
7864 maskbits = (uint8)-1 >> ( 8 - bps);
7865 buff1 = buff2 = 0;
7866
7867 for (row = 0; row < length ; row++)
7868 {
7869 bit_offset = col * bps * spp;
7870 for (sample = 0; sample < spp; sample++)
7871 {
7872 if (sample == 0)
7873 {
7874 src_byte = bit_offset / 8;
7875 src_bit = bit_offset % 8;
7876 }
7877 else
7878 {
7879 src_byte = (bit_offset + (sample * bps)) / 8;
7880 src_bit = (bit_offset + (sample * bps)) % 8;
7881 }
7882
7883 switch (rotation)
7884 {
7885 case 90: next = src + src_byte - (row * rowsize);
7886 break;
7887 case 270: next = src + src_byte + (row * rowsize);
7888 break;
7889 default: TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
7890 return (1);
7891 }
7892 matchbits = maskbits << (8 - src_bit - bps);
7893 buff1 = ((*next) & matchbits) << (src_bit);
7894
7895 /* If we have a full buffer's worth, write it out */
7896 if (ready_bits >= 8)
7897 {
7898 *dst++ = buff2;
7899 buff2 = buff1;
7900 ready_bits -= 8;
7901 }
7902 else
7903 {
7904 buff2 = (buff2 | (buff1 >> ready_bits));
7905 }
7906 ready_bits += bps;
7907 }
7908 }
7909
7910 if (ready_bits > 0)
7911 {
7912 buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
7913 *dst++ = buff1;
7914 }
7915
7916 return (0);
7917 } /* end rotateContigSamples8bits */
7918
7919
7920 static int
7921 rotateContigSamples16bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width,
7922 uint32 length, uint32 col, uint8 *src, uint8 *dst)
7923 {
7924 int ready_bits = 0;
7925 uint32 row, rowsize, bit_offset;
7926 uint32 src_byte = 0, src_bit = 0;
7927 uint16 matchbits = 0, maskbits = 0;
7928 uint16 buff1 = 0, buff2 = 0;
7929 uint8 bytebuff = 0;
7930 uint8 *next;
7931 tsample_t sample;
7932
7933 if ((src == NULL) || (dst == NULL))
7934 {
7935 TIFFError("rotateContigSamples16bits","Invalid src or destination buffer");
7936 return (1);
7937 }
7938
7939 rowsize = ((bps * spp * width) + 7) / 8;
7940 ready_bits = 0;
7941 maskbits = (uint16)-1 >> (16 - bps);
7942 buff1 = buff2 = 0;
7943 for (row = 0; row < length; row++)
7944 {
7945 bit_offset = col * bps * spp;
7946 for (sample = 0; sample < spp; sample++)
7947 {
7948 if (sample == 0)
7949 {
7950 src_byte = bit_offset / 8;
7951 src_bit = bit_offset % 8;
7952 }
7953 else
7954 {
7955 src_byte = (bit_offset + (sample * bps)) / 8;
7956 src_bit = (bit_offset + (sample * bps)) % 8;
7957 }
7958
7959 switch (rotation)
7960 {
7961 case 90: next = src + src_byte - (row * rowsize);
7962 break;
7963 case 270: next = src + src_byte + (row * rowsize);
7964 break;
7965 default: TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
7966 return (1);
7967 }
7968 matchbits = maskbits << (16 - src_bit - bps);
7969 if (little_endian)
7970 buff1 = (next[0] << 8) | next[1];
7971 else
7972 buff1 = (next[1] << 8) | next[0];
7973
7974 buff1 = (buff1 & matchbits) << (src_bit);
7975
7976 /* If we have a full buffer's worth, write it out */
7977 if (ready_bits >= 8)
7978 {
7979 bytebuff = (buff2 >> 8);
7980 *dst++ = bytebuff;
7981 ready_bits -= 8;
7982 /* shift in new bits */
7983 buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
7984 }
7985 else
7986 { /* add another bps bits to the buffer */
7987 bytebuff = 0;
7988 buff2 = (buff2 | (buff1 >> ready_bits));
7989 }
7990 ready_bits += bps;
7991 }
7992 }
7993
7994 if (ready_bits > 0)
7995 {
7996 bytebuff = (buff2 >> 8);
7997 *dst++ = bytebuff;
7998 }
7999
8000 return (0);
8001 } /* end rotateContigSamples16bits */
8002
8003 static int
8004 rotateContigSamples24bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width,
8005 uint32 length, uint32 col, uint8 *src, uint8 *dst)
8006 {
8007 int ready_bits = 0;
8008 uint32 row, rowsize, bit_offset;
8009 uint32 src_byte = 0, src_bit = 0;
8010 uint32 matchbits = 0, maskbits = 0;
8011 uint32 buff1 = 0, buff2 = 0;
8012 uint8 bytebuff1 = 0, bytebuff2 = 0;
8013 uint8 *next;
8014 tsample_t sample;
8015
8016
8017 if ((src == NULL) || (dst == NULL))
8018 {
8019 TIFFError("rotateContigSamples24bits","Invalid src or destination buffer");
8020 return (1);
8021 }
8022
8023 rowsize = ((bps * spp * width) + 7) / 8;
8024 ready_bits = 0;
8025 maskbits = (uint32)-1 >> (32 - bps);
8026 buff1 = buff2 = 0;
8027 for (row = 0; row < length; row++)
8028 {
8029 bit_offset = col * bps * spp;
8030 for (sample = 0; sample < spp; sample++)
8031 {
8032 if (sample == 0)
8033 {
8034 src_byte = bit_offset / 8;
8035 src_bit = bit_offset % 8;
8036 }
8037 else
8038 {
8039 src_byte = (bit_offset + (sample * bps)) / 8;
8040 src_bit = (bit_offset + (sample * bps)) % 8;
8041 }
8042
8043 switch (rotation)
8044 {
8045 case 90: next = src + src_byte - (row * rowsize);
8046 break;
8047 case 270: next = src + src_byte + (row * rowsize);
8048 break;
8049 default: TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
8050 return (1);
8051 }
8052 matchbits = maskbits << (32 - src_bit - bps);
8053 if (little_endian)
8054 buff1 = (next[0] << 24) | (next[1] << 16) | (next[2] << 8) | next[3];
8055 else
8056 buff1 = (next[3] << 24) | (next[2] << 16) | (next[1] << 8) | next[0];
8057 buff1 = (buff1 & matchbits) << (src_bit);
8058
8059 /* If we have a full buffer's worth, write it out */
8060 if (ready_bits >= 16)
8061 {
8062 bytebuff1 = (buff2 >> 24);
8063 *dst++ = bytebuff1;
8064 bytebuff2 = (buff2 >> 16);
8065 *dst++ = bytebuff2;
8066 ready_bits -= 16;
8067
8068 /* shift in new bits */
8069 buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
8070 }
8071 else
8072 { /* add another bps bits to the buffer */
8073 bytebuff1 = bytebuff2 = 0;
8074 buff2 = (buff2 | (buff1 >> ready_bits));
8075 }
8076 ready_bits += bps;
8077 }
8078 }
8079
8080 /* catch any trailing bits at the end of the line */
8081 while (ready_bits > 0)
8082 {
8083 bytebuff1 = (buff2 >> 24);
8084 *dst++ = bytebuff1;
8085
8086 buff2 = (buff2 << 8);
8087 bytebuff2 = bytebuff1;
8088 ready_bits -= 8;
8089 }
8090
8091 return (0);
8092 } /* end rotateContigSamples24bits */
8093
8094 static int
8095 rotateContigSamples32bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width,
8096 uint32 length, uint32 col, uint8 *src, uint8 *dst)
8097 {
8098 int ready_bits = 0, shift_width = 0;
8099 int bytes_per_sample, bytes_per_pixel;
8100 uint32 row, rowsize, bit_offset;
8101 uint32 src_byte, src_bit;
8102 uint32 longbuff1 = 0, longbuff2 = 0;
8103 uint64 maskbits = 0, matchbits = 0;
8104 uint64 buff1 = 0, buff2 = 0, buff3 = 0;
8105 uint8 bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
8106 uint8 *next;
8107 tsample_t sample;
8108
8109
8110 if ((src == NULL) || (dst == NULL))
8111 {
8112 TIFFError("rotateContigSamples24bits","Invalid src or destination buffer");
8113 return (1);
8114 }
8115
8116 bytes_per_sample = (bps + 7) / 8;
8117 bytes_per_pixel = ((bps * spp) + 7) / 8;
8118 if (bytes_per_pixel < (bytes_per_sample + 1))
8119 shift_width = bytes_per_pixel;
8120 else
8121 shift_width = bytes_per_sample + 1;
8122
8123 rowsize = ((bps * spp * width) + 7) / 8;
8124 ready_bits = 0;
8125 maskbits = (uint64)-1 >> (64 - bps);
8126 buff1 = buff2 = 0;
8127 for (row = 0; row < length; row++)
8128 {
8129 bit_offset = col * bps * spp;
8130 for (sample = 0; sample < spp; sample++)
8131 {
8132 if (sample == 0)
8133 {
8134 src_byte = bit_offset / 8;
8135 src_bit = bit_offset % 8;
8136 }
8137 else
8138 {
8139 src_byte = (bit_offset + (sample * bps)) / 8;
8140 src_bit = (bit_offset + (sample * bps)) % 8;
8141 }
8142
8143 switch (rotation)
8144 {
8145 case 90: next = src + src_byte - (row * rowsize);
8146 break;
8147 case 270: next = src + src_byte + (row * rowsize);
8148 break;
8149 default: TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
8150 return (1);
8151 }
8152 matchbits = maskbits << (64 - src_bit - bps);
8153 if (little_endian)
8154 {
8155 longbuff1 = (next[0] << 24) | (next[1] << 16) | (next[2] << 8) | next[3];
8156 longbuff2 = longbuff1;
8157 }
8158 else
8159 {
8160 longbuff1 = (next[3] << 24) | (next[2] << 16) | (next[1] << 8) | next[0];
8161 longbuff2 = longbuff1;
8162 }
8163
8164 buff3 = ((uint64)longbuff1 << 32) | longbuff2;
8165 buff1 = (buff3 & matchbits) << (src_bit);
8166
8167 if (ready_bits < 32)
8168 { /* add another bps bits to the buffer */
8169 bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
8170 buff2 = (buff2 | (buff1 >> ready_bits));
8171 }
8172 else /* If we have a full buffer's worth, write it out */
8173 {
8174 bytebuff1 = (buff2 >> 56);
8175 *dst++ = bytebuff1;
8176 bytebuff2 = (buff2 >> 48);
8177 *dst++ = bytebuff2;
8178 bytebuff3 = (buff2 >> 40);
8179 *dst++ = bytebuff3;
8180 bytebuff4 = (buff2 >> 32);
8181 *dst++ = bytebuff4;
8182 ready_bits -= 32;
8183
8184 /* shift in new bits */
8185 buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
8186 }
8187 ready_bits += bps;
8188 }
8189 }
8190 while (ready_bits > 0)
8191 {
8192 bytebuff1 = (buff2 >> 56);
8193 *dst++ = bytebuff1;
8194 buff2 = (buff2 << 8);
8195 ready_bits -= 8;
8196 }
8197
8198 return (0);
8199 } /* end rotateContigSamples32bits */
8200
8201
8202 /* Rotate an image by a multiple of 90 degrees clockwise */
8203 static int
8204 rotateImage(uint16 rotation, struct image_data *image, uint32 *img_width,
8205 uint32 *img_length, unsigned char **ibuff_ptr)
8206 {
8207 int shift_width;
8208 uint32 bytes_per_pixel, bytes_per_sample;
8209 uint32 row, rowsize, src_offset, dst_offset;
8210 uint32 i, col, width, length;
8211 uint32 colsize, buffsize, col_offset, pix_offset;
8212 unsigned char *ibuff;
8213 unsigned char *src;
8214 unsigned char *dst;
8215 uint16 spp, bps;
8216 float res_temp;
8217 unsigned char *rbuff = NULL;
8218
8219 width = *img_width;
8220 length = *img_length;
8221 spp = image->spp;
8222 bps = image->bps;
8223
8224 rowsize = ((bps * spp * width) + 7) / 8;
8225 colsize = ((bps * spp * length) + 7) / 8;
8226 if ((colsize * width) > (rowsize * length))
8227 buffsize = (colsize + 1) * width;
8228 else
8229 buffsize = (rowsize + 1) * length;
8230
8231 bytes_per_sample = (bps + 7) / 8;
8232 bytes_per_pixel = ((bps * spp) + 7) / 8;
8233 if (bytes_per_pixel < (bytes_per_sample + 1))
8234 shift_width = bytes_per_pixel;
8235 else
8236 shift_width = bytes_per_sample + 1;
8237
8238 switch (rotation)
8239 {
8240 case 0:
8241 case 360: return (0);
8242 case 90:
8243 case 180:
8244 case 270: break;
8245 default: TIFFError("rotateImage", "Invalid rotation angle %d", rotation);
8246 return (-1);
8247 }
8248
8249 if (!(rbuff = (unsigned char *)_TIFFmalloc(buffsize)))
8250 {
8251 TIFFError("rotateImage", "Unable to allocate rotation buffer of %1u bytes", buffsize);
8252 return (-1);
8253 }
8254 _TIFFmemset(rbuff, '\0', buffsize);
8255
8256 ibuff = *ibuff_ptr;
8257 switch (rotation)
8258 {
8259 case 180: if ((bps % 8) == 0) /* byte alligned data */
8260 {
8261 src = ibuff;
8262 pix_offset = (spp * bps) / 8;
8263 for (row = 0; row < length; row++)
8264 {
8265 dst_offset = (length - row - 1) * rowsize;
8266 for (col = 0; col < width; col++)
8267 {
8268 col_offset = (width - col - 1) * pix_offset;
8269 dst = rbuff + dst_offset + col_offset;
8270
8271 for (i = 0; i < bytes_per_pixel; i++)
8272 *dst++ = *src++;
8273 }
8274 }
8275 }
8276 else
8277 { /* non 8 bit per sample data */
8278 for (row = 0; row < length; row++)
8279 {
8280 src_offset = row * rowsize;
8281 dst_offset = (length - row - 1) * rowsize;
8282 src = ibuff + src_offset;
8283 dst = rbuff + dst_offset;
8284 switch (shift_width)
8285 {
8286 case 1: if (bps == 1)
8287 {
8288 if (reverseSamples8bits(spp, bps, width, src, dst))
8289 {
8290 _TIFFfree(rbuff);
8291 return (-1);
8292 }
8293 break;
8294 }
8295 if (reverseSamples16bits(spp, bps, width, src, dst))
8296 {
8297 _TIFFfree(rbuff);
8298 return (-1);
8299 }
8300 break;
8301 case 2: if (reverseSamples24bits(spp, bps, width, src, dst))
8302 {
8303 _TIFFfree(rbuff);
8304 return (-1);
8305 }
8306 break;
8307 case 3:
8308 case 4:
8309 case 5: if (reverseSamples32bits(spp, bps, width, src, dst))
8310 {
8311 _TIFFfree(rbuff);
8312 return (-1);
8313 }
8314 break;
8315 default: TIFFError("rotateImage","Unsupported bit depth %d", bps);
8316 _TIFFfree(rbuff);
8317 return (-1);
8318 }
8319 }
8320 }
8321 _TIFFfree(ibuff);
8322 *(ibuff_ptr) = rbuff;
8323 break;
8324
8325 case 90: if ((bps % 8) == 0) /* byte aligned data */
8326 {
8327 for (col = 0; col < width; col++)
8328 {
8329 src_offset = ((length - 1) * rowsize) + (col * bytes_per_pixel);
8330 dst_offset = col * colsize;
8331 src = ibuff + src_offset;
8332 dst = rbuff + dst_offset;
8333 for (row = length; row > 0; row--)
8334 {
8335 for (i = 0; i < bytes_per_pixel; i++)
8336 *dst++ = *(src + i);
8337 src -= rowsize;
8338 }
8339 }
8340 }
8341 else
8342 { /* non 8 bit per sample data */
8343 for (col = 0; col < width; col++)
8344 {
8345 src_offset = (length - 1) * rowsize;
8346 dst_offset = col * colsize;
8347 src = ibuff + src_offset;
8348 dst = rbuff + dst_offset;
8349 switch (shift_width)
8350 {
8351 case 1: if (bps == 1)
8352 {
8353 if (rotateContigSamples8bits(rotation, spp, bps, width,
8354 length, col, src, dst))
8355 {
8356 _TIFFfree(rbuff);
8357 return (-1);
8358 }
8359 break;
8360 }
8361 if (rotateContigSamples16bits(rotation, spp, bps, width,
8362 length, col, src, dst))
8363 {
8364 _TIFFfree(rbuff);
8365 return (-1);
8366 }
8367 break;
8368 case 2: if (rotateContigSamples24bits(rotation, spp, bps, width,
8369 length, col, src, dst))
8370 {
8371 _TIFFfree(rbuff);
8372 return (-1);
8373 }
8374 break;
8375 case 3:
8376 case 4:
8377 case 5: if (rotateContigSamples32bits(rotation, spp, bps, width,
8378 length, col, src, dst))
8379 {
8380 _TIFFfree(rbuff);
8381 return (-1);
8382 }
8383 break;
8384 default: TIFFError("rotateImage","Unsupported bit depth %d", bps);
8385 _TIFFfree(rbuff);
8386 return (-1);
8387 }
8388 }
8389 }
8390 _TIFFfree(ibuff);
8391 *(ibuff_ptr) = rbuff;
8392
8393 *img_width = length;
8394 *img_length = width;
8395 image->width = length;
8396 image->length = width;
8397 res_temp = image->xres;
8398 image->xres = image->yres;
8399 image->yres = res_temp;
8400 break;
8401
8402 case 270: if ((bps % 8) == 0) /* byte aligned data */
8403 {
8404 for (col = 0; col < width; col++)
8405 {
8406 src_offset = col * bytes_per_pixel;
8407 dst_offset = (width - col - 1) * colsize;
8408 src = ibuff + src_offset;
8409 dst = rbuff + dst_offset;
8410 for (row = length; row > 0; row--)
8411 {
8412 for (i = 0; i < bytes_per_pixel; i++)
8413 *dst++ = *(src + i);
8414 src += rowsize;
8415 }
8416 }
8417 }
8418 else
8419 { /* non 8 bit per sample data */
8420 for (col = 0; col < width; col++)
8421 {
8422 src_offset = 0;
8423 dst_offset = (width - col - 1) * colsize;
8424 src = ibuff + src_offset;
8425 dst = rbuff + dst_offset;
8426 switch (shift_width)
8427 {
8428 case 1: if (bps == 1)
8429 {
8430 if (rotateContigSamples8bits(rotation, spp, bps, width,
8431 length, col, src, dst))
8432 {
8433 _TIFFfree(rbuff);
8434 return (-1);
8435 }
8436 break;
8437 }
8438 if (rotateContigSamples16bits(rotation, spp, bps, width,
8439 length, col, src, dst))
8440 {
8441 _TIFFfree(rbuff);
8442 return (-1);
8443 }
8444 break;
8445 case 2: if (rotateContigSamples24bits(rotation, spp, bps, width,
8446 length, col, src, dst))
8447 {
8448 _TIFFfree(rbuff);
8449 return (-1);
8450 }
8451 break;
8452 case 3:
8453 case 4:
8454 case 5: if (rotateContigSamples32bits(rotation, spp, bps, width,
8455 length, col, src, dst))
8456 {
8457 _TIFFfree(rbuff);
8458 return (-1);
8459 }
8460 break;
8461 default: TIFFError("rotateImage","Unsupported bit depth %d", bps);
8462 _TIFFfree(rbuff);
8463 return (-1);
8464 }
8465 }
8466 }
8467 _TIFFfree(ibuff);
8468 *(ibuff_ptr) = rbuff;
8469
8470 *img_width = length;
8471 *img_length = width;
8472 image->width = length;
8473 image->length = width;
8474 res_temp = image->xres;
8475 image->xres = image->yres;
8476 image->yres = res_temp;
8477 break;
8478 default:
8479 break;
8480 }
8481
8482 return (0);
8483 } /* end rotateImage */
8484
8485 static int
8486 reverseSamples8bits (uint16 spp, uint16 bps, uint32 width,
8487 uint8 *ibuff, uint8 *obuff)
8488 {
8489 int ready_bits = 0;
8490 uint32 col;
8491 uint32 src_byte, src_bit;
8492 uint32 bit_offset = 0;
8493 uint8 match_bits = 0, mask_bits = 0;
8494 uint8 buff1 = 0, buff2 = 0;
8495 unsigned char *src;
8496 unsigned char *dst;
8497 tsample_t sample;
8498
8499 if ((ibuff == NULL) || (obuff == NULL))
8500 {
8501 TIFFError("reverseSamples8bits","Invalid image or work buffer");
8502 return (1);
8503 }
8504
8505 ready_bits = 0;
8506 mask_bits = (uint8)-1 >> ( 8 - bps);
8507 dst = obuff;
8508 for (col = width; col > 0; col--)
8509 {
8510 /* Compute src byte(s) and bits within byte(s) */
8511 bit_offset = (col - 1) * bps * spp;
8512 for (sample = 0; sample < spp; sample++)
8513 {
8514 if (sample == 0)
8515 {
8516 src_byte = bit_offset / 8;
8517 src_bit = bit_offset % 8;
8518 }
8519 else
8520 {
8521 src_byte = (bit_offset + (sample * bps)) / 8;
8522 src_bit = (bit_offset + (sample * bps)) % 8;
8523 }
8524
8525 src = ibuff + src_byte;
8526 match_bits = mask_bits << (8 - src_bit - bps);
8527 buff1 = ((*src) & match_bits) << (src_bit);
8528
8529 if (ready_bits < 8)
8530 buff2 = (buff2 | (buff1 >> ready_bits));
8531 else /* If we have a full buffer's worth, write it out */
8532 {
8533 *dst++ = buff2;
8534 buff2 = buff1;
8535 ready_bits -= 8;
8536 }
8537 ready_bits += bps;
8538 }
8539 }
8540 if (ready_bits > 0)
8541 {
8542 buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
8543 *dst++ = buff1;
8544 }
8545
8546 return (0);
8547 } /* end reverseSamples8bits */
8548
8549
8550 static int
8551 reverseSamples16bits (uint16 spp, uint16 bps, uint32 width,
8552 uint8 *ibuff, uint8 *obuff)
8553 {
8554 int ready_bits = 0;
8555 uint32 col;
8556 uint32 src_byte = 0, high_bit = 0;
8557 uint32 bit_offset = 0;
8558 uint16 match_bits = 0, mask_bits = 0;
8559 uint16 buff1 = 0, buff2 = 0;
8560 uint8 bytebuff = 0;
8561 unsigned char *src;
8562 unsigned char *dst;
8563 tsample_t sample;
8564
8565 if ((ibuff == NULL) || (obuff == NULL))
8566 {
8567 TIFFError("reverseSample16bits","Invalid image or work buffer");
8568 return (1);
8569 }
8570
8571 ready_bits = 0;
8572 mask_bits = (uint16)-1 >> (16 - bps);
8573 dst = obuff;
8574 for (col = width; col > 0; col--)
8575 {
8576 /* Compute src byte(s) and bits within byte(s) */
8577 bit_offset = (col - 1) * bps * spp;
8578 for (sample = 0; sample < spp; sample++)
8579 {
8580 if (sample == 0)
8581 {
8582 src_byte = bit_offset / 8;
8583 high_bit = bit_offset % 8;
8584 }
8585 else
8586 {
8587 src_byte = (bit_offset + (sample * bps)) / 8;
8588 high_bit = (bit_offset + (sample * bps)) % 8;
8589 }
8590
8591 src = ibuff + src_byte;
8592 match_bits = mask_bits << (16 - high_bit - bps);
8593 if (little_endian)
8594 buff1 = (src[0] << 8) | src[1];
8595 else
8596 buff1 = (src[1] << 8) | src[0];
8597 buff1 = (buff1 & match_bits) << (high_bit);
8598
8599 if (ready_bits < 8)
8600 { /* add another bps bits to the buffer */
8601 bytebuff = 0;
8602 buff2 = (buff2 | (buff1 >> ready_bits));
8603 }
8604 else /* If we have a full buffer's worth, write it out */
8605 {
8606 bytebuff = (buff2 >> 8);
8607 *dst++ = bytebuff;
8608 ready_bits -= 8;
8609 /* shift in new bits */
8610 buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
8611 }
8612 ready_bits += bps;
8613 }
8614 }
8615
8616 if (ready_bits > 0)
8617 {
8618 bytebuff = (buff2 >> 8);
8619 *dst++ = bytebuff;
8620 }
8621
8622 return (0);
8623 } /* end reverseSamples16bits */
8624
8625 static int
8626 reverseSamples24bits (uint16 spp, uint16 bps, uint32 width,
8627 uint8 *ibuff, uint8 *obuff)
8628 {
8629 int ready_bits = 0;
8630 uint32 col;
8631 uint32 src_byte = 0, high_bit = 0;
8632 uint32 bit_offset = 0;
8633 uint32 match_bits = 0, mask_bits = 0;
8634 uint32 buff1 = 0, buff2 = 0;
8635 uint8 bytebuff1 = 0, bytebuff2 = 0;
8636 unsigned char *src;
8637 unsigned char *dst;
8638 tsample_t sample;
8639
8640 if ((ibuff == NULL) || (obuff == NULL))
8641 {
8642 TIFFError("reverseSamples24bits","Invalid image or work buffer");
8643 return (1);
8644 }
8645
8646 ready_bits = 0;
8647 mask_bits = (uint32)-1 >> (32 - bps);
8648 dst = obuff;
8649 for (col = width; col > 0; col--)
8650 {
8651 /* Compute src byte(s) and bits within byte(s) */
8652 bit_offset = (col - 1) * bps * spp;
8653 for (sample = 0; sample < spp; sample++)
8654 {
8655 if (sample == 0)
8656 {
8657 src_byte = bit_offset / 8;
8658 high_bit = bit_offset % 8;
8659 }
8660 else
8661 {
8662 src_byte = (bit_offset + (sample * bps)) / 8;
8663 high_bit = (bit_offset + (sample * bps)) % 8;
8664 }
8665
8666 src = ibuff + src_byte;
8667 match_bits = mask_bits << (32 - high_bit - bps);
8668 if (little_endian)
8669 buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
8670 else
8671 buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
8672 buff1 = (buff1 & match_bits) << (high_bit);
8673
8674 if (ready_bits < 16)
8675 { /* add another bps bits to the buffer */
8676 bytebuff1 = bytebuff2 = 0;
8677 buff2 = (buff2 | (buff1 >> ready_bits));
8678 }
8679 else /* If we have a full buffer's worth, write it out */
8680 {
8681 bytebuff1 = (buff2 >> 24);
8682 *dst++ = bytebuff1;
8683 bytebuff2 = (buff2 >> 16);
8684 *dst++ = bytebuff2;
8685 ready_bits -= 16;
8686
8687 /* shift in new bits */
8688 buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
8689 }
8690 ready_bits += bps;
8691 }
8692 }
8693
8694 /* catch any trailing bits at the end of the line */
8695 while (ready_bits > 0)
8696 {
8697 bytebuff1 = (buff2 >> 24);
8698 *dst++ = bytebuff1;
8699
8700 buff2 = (buff2 << 8);
8701 bytebuff2 = bytebuff1;
8702 ready_bits -= 8;
8703 }
8704
8705 return (0);
8706 } /* end reverseSamples24bits */
8707
8708
8709 static int
8710 reverseSamples32bits (uint16 spp, uint16 bps, uint32 width,
8711 uint8 *ibuff, uint8 *obuff)
8712 {
8713 int ready_bits = 0, shift_width = 0;
8714 int bytes_per_sample, bytes_per_pixel;
8715 uint32 bit_offset;
8716 uint32 src_byte = 0, high_bit = 0;
8717 uint32 col;
8718 uint32 longbuff1 = 0, longbuff2 = 0;
8719 uint64 mask_bits = 0, match_bits = 0;
8720 uint64 buff1 = 0, buff2 = 0, buff3 = 0;
8721 uint8 bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
8722 unsigned char *src;
8723 unsigned char *dst;
8724 tsample_t sample;
8725
8726 if ((ibuff == NULL) || (obuff == NULL))
8727 {
8728 TIFFError("reverseSamples32bits","Invalid image or work buffer");
8729 return (1);
8730 }
8731
8732 ready_bits = 0;
8733 mask_bits = (uint64)-1 >> (64 - bps);
8734 dst = obuff;
8735
8736 bytes_per_sample = (bps + 7) / 8;
8737 bytes_per_pixel = ((bps * spp) + 7) / 8;
8738 if (bytes_per_pixel < (bytes_per_sample + 1))
8739 shift_width = bytes_per_pixel;
8740 else
8741 shift_width = bytes_per_sample + 1;
8742
8743 for (col = width; col > 0; col--)
8744 {
8745 /* Compute src byte(s) and bits within byte(s) */
8746 bit_offset = (col - 1) * bps * spp;
8747 for (sample = 0; sample < spp; sample++)
8748 {
8749 if (sample == 0)
8750 {
8751 src_byte = bit_offset / 8;
8752 high_bit = bit_offset % 8;
8753 }
8754 else
8755 {
8756 src_byte = (bit_offset + (sample * bps)) / 8;
8757 high_bit = (bit_offset + (sample * bps)) % 8;
8758 }
8759
8760 src = ibuff + src_byte;
8761 match_bits = mask_bits << (64 - high_bit - bps);
8762 if (little_endian)
8763 {
8764 longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
8765 longbuff2 = longbuff1;
8766 }
8767 else
8768 {
8769 longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
8770 longbuff2 = longbuff1;
8771 }
8772 buff3 = ((uint64)longbuff1 << 32) | longbuff2;
8773 buff1 = (buff3 & match_bits) << (high_bit);
8774
8775 if (ready_bits < 32)
8776 { /* add another bps bits to the buffer */
8777 bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
8778 buff2 = (buff2 | (buff1 >> ready_bits));
8779 }
8780 else /* If we have a full buffer's worth, write it out */
8781 {
8782 bytebuff1 = (buff2 >> 56);
8783 *dst++ = bytebuff1;
8784 bytebuff2 = (buff2 >> 48);
8785 *dst++ = bytebuff2;
8786 bytebuff3 = (buff2 >> 40);
8787 *dst++ = bytebuff3;
8788 bytebuff4 = (buff2 >> 32);
8789 *dst++ = bytebuff4;
8790 ready_bits -= 32;
8791
8792 /* shift in new bits */
8793 buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
8794 }
8795 ready_bits += bps;
8796 }
8797 }
8798 while (ready_bits > 0)
8799 {
8800 bytebuff1 = (buff2 >> 56);
8801 *dst++ = bytebuff1;
8802 buff2 = (buff2 << 8);
8803 ready_bits -= 8;
8804 }
8805
8806 return (0);
8807 } /* end reverseSamples32bits */
8808
8809 static int
8810 reverseSamplesBytes (uint16 spp, uint16 bps, uint32 width,
8811 uint8 *src, uint8 *dst)
8812 {
8813 int i;
8814 uint32 col, bytes_per_pixel, col_offset;
8815 uint8 bytebuff1;
8816 unsigned char swapbuff[32];
8817
8818 if ((src == NULL) || (dst == NULL))
8819 {
8820 TIFFError("reverseSamplesBytes","Invalid input or output buffer");
8821 return (1);
8822 }
8823
8824 bytes_per_pixel = ((bps * spp) + 7) / 8;
8825 switch (bps / 8)
8826 {
8827 case 8: /* Use memcpy for multiple bytes per sample data */
8828 case 4:
8829 case 3:
8830 case 2: for (col = 0; col < (width / 2); col++)
8831 {
8832 col_offset = col * bytes_per_pixel;
8833 _TIFFmemcpy (swapbuff, src + col_offset, bytes_per_pixel);
8834 _TIFFmemcpy (src + col_offset, dst - col_offset - bytes_per_pixel, bytes_per_pixel);
8835 _TIFFmemcpy (dst - col_offset - bytes_per_pixel, swapbuff, bytes_per_pixel);
8836 }
8837 break;
8838 case 1: /* Use byte copy only for single byte per sample data */
8839 for (col = 0; col < (width / 2); col++)
8840 {
8841 for (i = 0; i < spp; i++)
8842 {
8843 bytebuff1 = *src;
8844 *src++ = *(dst - spp + i);
8845 *(dst - spp + i) = bytebuff1;
8846 }
8847 dst -= spp;
8848 }
8849 break;
8850 default: TIFFError("reverseSamplesBytes","Unsupported bit depth %d", bps);
8851 return (1);
8852 }
8853 return (0);
8854 } /* end reverseSamplesBytes */
8855
8856
8857 /* Mirror an image horizontally or vertically */
8858 static int
8859 mirrorImage(uint16 spp, uint16 bps, uint16 mirror, uint32 width, uint32 length, unsigned char *ibuff)
8860 {
8861 int shift_width;
8862 uint32 bytes_per_pixel, bytes_per_sample;
8863 uint32 row, rowsize, row_offset;
8864 unsigned char *line_buff = NULL;
8865 unsigned char *src;
8866 unsigned char *dst;
8867
8868 src = ibuff;
8869 rowsize = ((width * bps * spp) + 7) / 8;
8870 switch (mirror)
8871 {
8872 case MIRROR_BOTH:
8873 case MIRROR_VERT:
8874 line_buff = (unsigned char *)_TIFFmalloc(rowsize);
8875 if (line_buff == NULL)
8876 {
8877 TIFFError ("mirrorImage", "Unable to allocate mirror line buffer of %1u bytes", rowsize);
8878 return (-1);
8879 }
8880
8881 dst = ibuff + (rowsize * (length - 1));
8882 for (row = 0; row < length / 2; row++)
8883 {
8884 _TIFFmemcpy(line_buff, src, rowsize);
8885 _TIFFmemcpy(src, dst, rowsize);
8886 _TIFFmemcpy(dst, line_buff, rowsize);
8887 src += (rowsize);
8888 dst -= (rowsize);
8889 }
8890 if (line_buff)
8891 _TIFFfree(line_buff);
8892 if (mirror == MIRROR_VERT)
8893 break;
8894 case MIRROR_HORIZ :
8895 if ((bps % 8) == 0) /* byte alligned data */
8896 {
8897 for (row = 0; row < length; row++)
8898 {
8899 row_offset = row * rowsize;
8900 src = ibuff + row_offset;
8901 dst = ibuff + row_offset + rowsize;
8902 if (reverseSamplesBytes(spp, bps, width, src, dst))
8903 {
8904 return (-1);
8905 }
8906 }
8907 }
8908 else
8909 { /* non 8 bit per sample data */
8910 if (!(line_buff = (unsigned char *)_TIFFmalloc(rowsize + 1)))
8911 {
8912 TIFFError("mirrorImage", "Unable to allocate mirror line buffer");
8913 return (-1);
8914 }
8915 bytes_per_sample = (bps + 7) / 8;
8916 bytes_per_pixel = ((bps * spp) + 7) / 8;
8917 if (bytes_per_pixel < (bytes_per_sample + 1))
8918 shift_width = bytes_per_pixel;
8919 else
8920 shift_width = bytes_per_sample + 1;
8921
8922 for (row = 0; row < length; row++)
8923 {
8924 row_offset = row * rowsize;
8925 src = ibuff + row_offset;
8926 _TIFFmemset (line_buff, '\0', rowsize);
8927 switch (shift_width)
8928 {
8929 case 1: if (reverseSamples16bits(spp, bps, width, src, line_buff))
8930 {
8931 _TIFFfree(line_buff);
8932 return (-1);
8933 }
8934 _TIFFmemcpy (src, line_buff, rowsize);
8935 break;
8936 case 2: if (reverseSamples24bits(spp, bps, width, src, line_buff))
8937 {
8938 _TIFFfree(line_buff);
8939 return (-1);
8940 }
8941 _TIFFmemcpy (src, line_buff, rowsize);
8942 break;
8943 case 3:
8944 case 4:
8945 case 5: if (reverseSamples32bits(spp, bps, width, src, line_buff))
8946 {
8947 _TIFFfree(line_buff);
8948 return (-1);
8949 }
8950 _TIFFmemcpy (src, line_buff, rowsize);
8951 break;
8952 default: TIFFError("mirrorImage","Unsupported bit depth %d", bps);
8953 _TIFFfree(line_buff);
8954 return (-1);
8955 }
8956 }
8957 if (line_buff)
8958 _TIFFfree(line_buff);
8959 }
8960 break;
8961
8962 default: TIFFError ("mirrorImage", "Invalid mirror axis %d", mirror);
8963 return (-1);
8964 break;
8965 }
8966
8967 return (0);
8968 }
8969
8970 /* Invert the light and dark values for a bilevel or grayscale image */
8971 static int
8972 invertImage(uint16 photometric, uint16 spp, uint16 bps, uint32 width, uint32 length, unsigned char *work_buff)
8973 {
8974 uint32 row, col;
8975 unsigned char bytebuff1, bytebuff2, bytebuff3, bytebuff4;
8976 unsigned char *src;
8977 uint16 *src_uint16;
8978 uint32 *src_uint32;
8979
8980 if (spp != 1)
8981 {
8982 TIFFError("invertImage", "Image inversion not supported for more than one sample per pixel");
8983 return (-1);
8984 }
8985
8986 if (photometric != PHOTOMETRIC_MINISWHITE && photometric != PHOTOMETRIC_MINISBLACK)
8987 {
8988 TIFFError("invertImage", "Only black and white and grayscale images can be inverted");
8989 return (-1);
8990 }
8991
8992 src = work_buff;
8993 if (src == NULL)
8994 {
8995 TIFFError ("invertImage", "Invalid crop buffer passed to invertImage");
8996 return (-1);
8997 }
8998
8999 switch (bps)
9000 {
9001 case 32: src_uint32 = (uint32 *)src;
9002 for (row = 0; row < length; row++)
9003 for (col = 0; col < width; col++)
9004 {
9005 *src_uint32 = (uint32)0xFFFFFFFF - *src_uint32;
9006 src_uint32++;
9007 }
9008 break;
9009 case 16: src_uint16 = (uint16 *)src;
9010 for (row = 0; row < length; row++)
9011 for (col = 0; col < width; col++)
9012 {
9013 *src_uint16 = (uint16)0xFFFF - *src_uint16;
9014 src_uint16++;
9015 }
9016 break;
9017 case 8: for (row = 0; row < length; row++)
9018 for (col = 0; col < width; col++)
9019 {
9020 *src = (uint8)255 - *src;
9021 src++;
9022 }
9023 break;
9024 case 4: for (row = 0; row < length; row++)
9025 for (col = 0; col < width; col++)
9026 {
9027 bytebuff1 = 16 - (uint8)(*src & 240 >> 4);
9028 bytebuff2 = 16 - (*src & 15);
9029 *src = bytebuff1 << 4 & bytebuff2;
9030 src++;
9031 }
9032 break;
9033 case 2: for (row = 0; row < length; row++)
9034 for (col = 0; col < width; col++)
9035 {
9036 bytebuff1 = 4 - (uint8)(*src & 192 >> 6);
9037 bytebuff2 = 4 - (uint8)(*src & 48 >> 4);
9038 bytebuff3 = 4 - (uint8)(*src & 12 >> 2);
9039 bytebuff4 = 4 - (uint8)(*src & 3);
9040 *src = (bytebuff1 << 6) || (bytebuff2 << 4) || (bytebuff3 << 2) || bytebuff4;
9041 src++;
9042 }
9043 break;
9044 case 1: for (row = 0; row < length; row++)
9045 for (col = 0; col < width; col += 8 /(spp * bps))
9046 {
9047 *src = ~(*src);
9048 src++;
9049 }
9050 break;
9051 default: TIFFError("invertImage", "Unsupported bit depth %d", bps);
9052 return (-1);
9053 }
9054
9055 return (0);
9056 }
9057
9058 /* vim: set ts=8 sts=8 sw=8 noet: */
9059 /*
9060 * Local Variables:
9061 * mode: c
9062 * c-basic-offset: 8
9063 * fill-column: 78
9064 * End:
9065 */