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