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