]> git.saurik.com Git - wxWidgets.git/blame - src/tiff/tools/tiffcrop.c
Fit the generic preferences editor dialog to its pages size initially.
[wxWidgets.git] / src / tiff / tools / tiffcrop.c
CommitLineData
80ed523f
VZ
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
110static char tiffcrop_version_id[] = "2.4";
111static 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
134extern 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 */
219struct 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
238struct buffinfo {
239 uint32 size; /* size of this buffer */
240 unsigned char *buffer; /* address of the allocated buffer */
241};
242
243struct zone {
244 int position; /* ordinal of segment to be extracted */
245 int total; /* total equal sized divisions of crop area */
246 };
247
248struct 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
258struct 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
265struct 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 */
280struct 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
329struct 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 */
339struct 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 */
392struct 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 */
408struct 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
423struct 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 */
435static int outtiled = -1;
436static uint32 tilewidth = 0;
437static uint32 tilelength = 0;
438
439static uint16 config = 0;
440static uint16 compression = 0;
441static uint16 predictor = 0;
442static uint16 fillorder = 0;
443static uint32 rowsperstrip = 0;
444static uint32 g3opts = 0;
445static int ignore = FALSE; /* if true, ignore read errors */
446static uint32 defg3opts = (uint32) -1;
447static int quality = 100; /* JPEG quality */
448/* static int jpegcolormode = -1; was JPEGCOLORMODE_RGB; */
449static int jpegcolormode = JPEGCOLORMODE_RGB;
450static uint16 defcompression = (uint16) -1;
451static uint16 defpredictor = (uint16) -1;
452static int pageNum = 0;
453static int little_endian = 1;
454
455/* Functions adapted from tiffcp with additions or significant modifications */
456static int readContigStripsIntoBuffer (TIFF*, uint8*);
457static int readSeparateStripsIntoBuffer (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
458static int readContigTilesIntoBuffer (TIFF*, uint8*, uint32, uint32, uint32, uint32, tsample_t, uint16);
459static int readSeparateTilesIntoBuffer (TIFF*, uint8*, uint32, uint32, uint32, uint32, tsample_t, uint16);
460static int writeBufferToContigStrips (TIFF*, uint8*, uint32);
461static int writeBufferToContigTiles (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
462static int writeBufferToSeparateStrips (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
463static int writeBufferToSeparateTiles (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
464static int extractContigSamplesToBuffer (uint8 *, uint8 *, uint32, uint32, tsample_t,
465 uint16, uint16, struct dump_opts *);
466static int processCompressOptions(char*);
467static void usage(void);
468
469/* All other functions by Richard Nolde, not found in tiffcp */
470static void initImageData (struct image_data *);
471static void initCropMasks (struct crop_mask *);
472static void initPageSetup (struct pagedef *, struct pageseg *, struct buffinfo []);
473static void initDumpOptions(struct dump_opts *);
474
475/* Command line and file naming functions */
476void 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 *);
481static int update_output_file (TIFF **, char *, int, char *, unsigned int *);
482
483
484/* * High level functions for whole image manipulation */
485static int get_page_geometry (char *, struct pagedef*);
486static int computeInputPixelOffsets(struct crop_mask *, struct image_data *,
487 struct offset *);
488static int computeOutputPixelOffsets (struct crop_mask *, struct image_data *,
489 struct pagedef *, struct pageseg *,
490 struct dump_opts *);
491static int loadImage(TIFF *, struct image_data *, struct dump_opts *, unsigned char **);
492static int correct_orientation(struct image_data *, unsigned char **);
493static int getCropOffsets(struct image_data *, struct crop_mask *, struct dump_opts *);
494static int processCropSelections(struct image_data *, struct crop_mask *,
495 unsigned char **, struct buffinfo []);
496static 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 */
501static int createImageSection(uint32, unsigned char **);
502static int extractImageSection(struct image_data *, struct pageseg *,
503 unsigned char *, unsigned char *);
504static int writeSingleSection(TIFF *, TIFF *, struct image_data *,
505 struct dump_opts *, uint32, uint32,
506 double, double, unsigned char *);
507static 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 */
512static int createCroppedImage(struct image_data *, struct crop_mask *,
513 unsigned char **, unsigned char **);
514static 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 */
519static int rotateContigSamples8bits(uint16, uint16, uint16, uint32,
520 uint32, uint32, uint8 *, uint8 *);
521static int rotateContigSamples16bits(uint16, uint16, uint16, uint32,
522 uint32, uint32, uint8 *, uint8 *);
523static int rotateContigSamples24bits(uint16, uint16, uint16, uint32,
524 uint32, uint32, uint8 *, uint8 *);
525static int rotateContigSamples32bits(uint16, uint16, uint16, uint32,
526 uint32, uint32, uint8 *, uint8 *);
527static int rotateImage(uint16, struct image_data *, uint32 *, uint32 *,
528 unsigned char **);
529static int mirrorImage(uint16, uint16, uint16, uint32, uint32,
530 unsigned char *);
531static int invertImage(uint16, uint16, uint16, uint32, uint32,
532 unsigned char *);
533
534/* Functions to reverse the sequence of samples in a scanline */
535static int reverseSamples8bits (uint16, uint16, uint32, uint8 *, uint8 *);
536static int reverseSamples16bits (uint16, uint16, uint32, uint8 *, uint8 *);
537static int reverseSamples24bits (uint16, uint16, uint32, uint8 *, uint8 *);
538static int reverseSamples32bits (uint16, uint16, uint32, uint8 *, uint8 *);
539static int reverseSamplesBytes (uint16, uint16, uint32, uint8 *, uint8 *);
540
541/* Functions for manipulating individual samples in an image */
542static int extractSeparateRegion(struct image_data *, struct crop_mask *,
543 unsigned char *, unsigned char *, int);
544static int extractCompositeRegions(struct image_data *, struct crop_mask *,
545 unsigned char *, unsigned char *);
546static int extractContigSamples8bits (uint8 *, uint8 *, uint32,
547 tsample_t, uint16, uint16,
548 tsample_t, uint32, uint32);
549static int extractContigSamples16bits (uint8 *, uint8 *, uint32,
550 tsample_t, uint16, uint16,
551 tsample_t, uint32, uint32);
552static int extractContigSamples24bits (uint8 *, uint8 *, uint32,
553 tsample_t, uint16, uint16,
554 tsample_t, uint32, uint32);
555static int extractContigSamples32bits (uint8 *, uint8 *, uint32,
556 tsample_t, uint16, uint16,
557 tsample_t, uint32, uint32);
558static int extractContigSamplesBytes (uint8 *, uint8 *, uint32,
559 tsample_t, uint16, uint16,
560 tsample_t, uint32, uint32);
561static int extractContigSamplesShifted8bits (uint8 *, uint8 *, uint32,
562 tsample_t, uint16, uint16,
563 tsample_t, uint32, uint32,
564 int);
565static int extractContigSamplesShifted16bits (uint8 *, uint8 *, uint32,
566 tsample_t, uint16, uint16,
567 tsample_t, uint32, uint32,
568 int);
569static int extractContigSamplesShifted24bits (uint8 *, uint8 *, uint32,
570 tsample_t, uint16, uint16,
571 tsample_t, uint32, uint32,
572 int);
573static int extractContigSamplesShifted32bits (uint8 *, uint8 *, uint32,
574 tsample_t, uint16, uint16,
575 tsample_t, uint32, uint32,
576 int);
577static 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 */
582static int combineSeparateSamples8bits (uint8 *[], uint8 *, uint32, uint32,
583 uint16, uint16, FILE *, int, int);
584static int combineSeparateSamples16bits (uint8 *[], uint8 *, uint32, uint32,
585 uint16, uint16, FILE *, int, int);
586static int combineSeparateSamples24bits (uint8 *[], uint8 *, uint32, uint32,
587 uint16, uint16, FILE *, int, int);
588static int combineSeparateSamples32bits (uint8 *[], uint8 *, uint32, uint32,
589 uint16, uint16, FILE *, int, int);
590static int combineSeparateSamplesBytes (unsigned char *[], unsigned char *,
591 uint32, uint32, tsample_t, uint16,
592 FILE *, int, int);
593
594static int combineSeparateTileSamples8bits (uint8 *[], uint8 *, uint32, uint32,
595 uint32, uint32, uint16, uint16,
596 FILE *, int, int);
597static int combineSeparateTileSamples16bits (uint8 *[], uint8 *, uint32, uint32,
598 uint32, uint32, uint16, uint16,
599 FILE *, int, int);
600static int combineSeparateTileSamples24bits (uint8 *[], uint8 *, uint32, uint32,
601 uint32, uint32, uint16, uint16,
602 FILE *, int, int);
603static int combineSeparateTileSamples32bits (uint8 *[], uint8 *, uint32, uint32,
604 uint32, uint32, uint16, uint16,
605 FILE *, int, int);
606static int combineSeparateTileSamplesBytes (unsigned char *[], unsigned char *,
607 uint32, uint32, uint32, uint32,
608 tsample_t, uint16, FILE *, int, int);
609
610/* Dump functions for debugging */
611static void dump_info (FILE *, int, char *, char *, ...);
612static int dump_data (FILE *, int, char *, unsigned char *, uint32);
613static int dump_byte (FILE *, int, char *, unsigned char);
614static int dump_short (FILE *, int, char *, uint16);
615static int dump_long (FILE *, int, char *, uint32);
616static int dump_wide (FILE *, int, char *, uint64);
617static 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
623static 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" ",
755NULL
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 */
763static 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
951static 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
1098static 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 */
1129static int
1130writeBufferToSeparateStrips (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 */
1194static 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 */
1269static 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
1332static void
1333processG3Options(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
1352static int
1353processCompressOptions(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
1412static void
1413usage(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
1432static void
1433cpTag(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
1487static 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. */
1531void 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 */
2037static int
2038update_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
2103int
2104main(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 */
2404static 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
2444static 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
2479static 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
2516static 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
2552static 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
2589static 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
2601static 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
2636static int
2637extractContigSamplesBytes (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
2702static int
2703extractContigSamples8bits (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
2779static int
2780extractContigSamples16bits (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
2868static int
2869extractContigSamples24bits (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
2961static int
2962extractContigSamples32bits (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
3066static int
3067extractContigSamplesShifted8bits (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
3146static int
3147extractContigSamplesShifted16bits (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
3236static int
3237extractContigSamplesShifted24bits (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
3334static int
3335extractContigSamplesShifted32bits (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
3442static int
3443extractContigSamplesToBuffer(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
3518static int
3519extractContigSamplesToTileBuffer(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
3595static 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
3625static int
3626combineSeparateSamplesBytes (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
3683static int
3684combineSeparateSamples8bits (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
3783static int
3784combineSeparateSamples16bits (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
3893static int
3894combineSeparateSamples24bits (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
4017static int
4018combineSeparateSamples32bits (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
4148static int
4149combineSeparateTileSamplesBytes (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
4209static int
4210combineSeparateTileSamples8bits (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
4308static int
4309combineSeparateTileSamples16bits (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
4417static int
4418combineSeparateTileSamples24bits (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
4541static int
4542combineSeparateTileSamples32bits (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
4674static 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
4852static int
4853get_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
4877static void
4878initPageSetup (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
4914static void
4915initImageData (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
4931static void
4932initCropMasks (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
4973static 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 */
4986static int
4987computeInputPixelOffsets(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
5273static int
5274getCropOffsets(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
5490static int
5491computeOutputPixelOffsets (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
5720static int
5721loadImage(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
6085static 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 */
6138static int
6139extractCompositeRegions(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
6386static int
6387extractSeparateRegion(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
6509static int
6510extractImageSection(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
6727static int
6728writeSelections(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
6834static int
6835writeImageSections(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 */
6892static int
6893writeSingleSection(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 */
7162static int
7163createImageSection(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 */
7207static int
7208processCropSelections(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 */
7442static int
7443createCroppedImage(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 */
7569static int
7570writeCroppedImage(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
7845static int
7846rotateContigSamples8bits(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
7921static int
7922rotateContigSamples16bits(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
8004static int
8005rotateContigSamples24bits(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
8095static int
8096rotateContigSamples32bits(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 */
8204static int
8205rotateImage(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
8486static int
8487reverseSamples8bits (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
8551static int
8552reverseSamples16bits (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
8626static int
8627reverseSamples24bits (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
8710static int
8711reverseSamples32bits (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
8810static int
8811reverseSamplesBytes (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 */
8859static int
8860mirrorImage(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 */
8972static int
8973invertImage(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 */