roentgen b75cab
/* $Id: tiffcrop.c,v 1.20 2010-12-14 02:03:24 faxguy Exp $ */
roentgen b75cab
roentgen b75cab
/* tiffcrop.c -- a port of tiffcp.c extended to include manipulations of
roentgen b75cab
 * the image data through additional options listed below
roentgen b75cab
 *
roentgen b75cab
 * Original code:
roentgen b75cab
 * Copyright (c) 1988-1997 Sam Leffler
roentgen b75cab
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
roentgen b75cab
 * Additions (c) Richard Nolde 2006-2010 
roentgen b75cab
 *
roentgen b75cab
 * Permission to use, copy, modify, distribute, and sell this software and 
roentgen b75cab
 * its documentation for any purpose is hereby granted without fee, provided
roentgen b75cab
 * that (i) the above copyright notices and this permission notice appear in
roentgen b75cab
 * all copies of the software and related documentation, and (ii) the names of
roentgen b75cab
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
roentgen b75cab
 * publicity relating to the software without the specific, prior written
roentgen b75cab
 * permission of Sam Leffler and Silicon Graphics.
roentgen b75cab
 * 
roentgen b75cab
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
roentgen b75cab
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
roentgen b75cab
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
roentgen b75cab
 * 
roentgen b75cab
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS OR ANY OTHER COPYRIGHT  
roentgen b75cab
 * HOLDERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL 
roentgen b75cab
 * DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
roentgen b75cab
 * DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND 
roentgen b75cab
 * ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
roentgen b75cab
 * OR PERFORMANCE OF THIS SOFTWARE.
roentgen b75cab
 *
roentgen b75cab
 * Some portions of the current code are derived from tiffcp, primarly in 
roentgen b75cab
 * the areas of lowlevel reading and writing of TAGS, scanlines and tiles though
roentgen b75cab
 * some of the original functions have been extended to support arbitrary bit
roentgen b75cab
 * depths. These functions are presented at the top of this file.
roentgen b75cab
 *
roentgen b75cab
 * Add support for the options below to extract sections of image(s) 
roentgen b75cab
 * and to modify the whole image or selected portions of each image by
roentgen b75cab
 * rotations, mirroring, and colorscale/colormap inversion of selected
roentgen b75cab
 * types of TIFF images when appropriate. Some color model dependent 
roentgen b75cab
 * functions are restricted to bilevel or 8 bit per sample data.
roentgen b75cab
 * See the man page for the full explanations.
roentgen b75cab
 *
roentgen b75cab
 * New Options: 
roentgen b75cab
 * -h             Display the syntax guide.
roentgen b75cab
 * -v             Report the version and last build date for tiffcrop and libtiff.
roentgen b75cab
 * -z x1,y1,x2,y2:x3,y3,x4,y4:..xN,yN,xN + 1, yN + 1 
roentgen b75cab
 *                Specify a series of coordinates to define rectangular
roentgen b75cab
 *                regions by the top left and lower right corners.
roentgen b75cab
 * -e c|d|i|m|s   export mode for images and selections from input images
roentgen b75cab
 *   combined     All images and selections are written to a single file (default)
roentgen b75cab
 *                with multiple selections from one image combined into a single image
roentgen b75cab
 *   divided      All images and selections are written to a single file
roentgen b75cab
 *                with each selection from one image written to a new image
roentgen b75cab
 *   image        Each input image is written to a new file (numeric filename sequence)
roentgen b75cab
 *                with multiple selections from the image combined into one image
roentgen b75cab
 *   multiple     Each input image is written to a new file (numeric filename sequence)
roentgen b75cab
 *                with each selection from the image written to a new image
roentgen b75cab
 *   separated    Individual selections from each image are written to separate files
roentgen b75cab
 * -U units       [in, cm, px ] inches, centimeters or pixels
roentgen b75cab
 * -H #           Set horizontal resolution of output images to #
roentgen b75cab
 * -V #           Set vertical resolution of output images to #
roentgen b75cab
 * -J #           Horizontal margin of output page to # expressed in current
roentgen b75cab
 *                units when sectioning image into columns x rows 
roentgen b75cab
 *                using the -S cols:rows option.
roentgen b75cab
 * -K #           Vertical margin of output page to # expressed in current
roentgen b75cab
 *                units when sectioning image into columns x rows
roentgen b75cab
 *                using the -S cols:rows option.
roentgen b75cab
 * -X #           Horizontal dimension of region to extract expressed in current
roentgen b75cab
 *                units
roentgen b75cab
 * -Y #           Vertical dimension of region to extract expressed in current
roentgen b75cab
 *                units
roentgen b75cab
 * -O orient      Orientation for output image, portrait, landscape, auto
roentgen b75cab
 * -P page        Page size for output image segments, eg letter, legal, tabloid,
roentgen b75cab
 *                etc.
roentgen b75cab
 * -S cols:rows   Divide the image into equal sized segments using cols across
roentgen b75cab
 *                and rows down
roentgen b75cab
 * -E t|l|r|b     Edge to use as origin
roentgen b75cab
 * -m #,#,#,#     Margins from edges for selection: top, left, bottom, right
roentgen b75cab
 *                (commas separated)
roentgen b75cab
 * -Z #:#,#:#     Zones of the image designated as zone X of Y, 
roentgen b75cab
 *                eg 1:3 would be first of three equal portions measured
roentgen b75cab
 *                from reference edge
roentgen b75cab
 * -N odd|even|#,#-#,#|last 
roentgen b75cab
 *                Select sequences and/or ranges of images within file
roentgen b75cab
 *                to process. The words odd or even may be used to specify
roentgen b75cab
 *                all odd or even numbered images the word last may be used
roentgen b75cab
 *                in place of a number in the sequence to indicate the final
roentgen b75cab
 *                image in the file without knowing how many images there are.
roentgen b75cab
 * -R #           Rotate image or crop selection by 90,180,or 270 degrees
roentgen b75cab
 *                clockwise  
roentgen b75cab
 * -F h|v         Flip (mirror) image or crop selection horizontally
roentgen b75cab
 *                or vertically 
roentgen b75cab
 * -I [black|white|data|both]
roentgen b75cab
 *                Invert color space, eg dark to light for bilevel and grayscale images
roentgen b75cab
 *                If argument is white or black, set the PHOTOMETRIC_INTERPRETATION 
roentgen b75cab
 *                tag to MinIsBlack or MinIsWhite without altering the image data
roentgen b75cab
 *                If the argument is data or both, the image data are modified:
roentgen b75cab
 *                both inverts the data and the PHOTOMETRIC_INTERPRETATION tag,
roentgen b75cab
 *                data inverts the data but not the PHOTOMETRIC_INTERPRETATION tag
roentgen b75cab
 * -D input:<filename1>,output:<filename2>,format:<raw|txt>,level:N,debug:N
roentgen b75cab
 *                Dump raw data for input and/or output images to individual files
roentgen b75cab
 *                in raw (binary) format or text (ASCII) representing binary data
roentgen b75cab
 *                as strings of 1s and 0s. The filename arguments are used as stems
roentgen b75cab
 *                from which individual files are created for each image. Text format
roentgen b75cab
 *                includes annotations for image parameters and scanline info. Level
roentgen b75cab
 *                selects which functions dump data, with higher numbers selecting
roentgen b75cab
 *                lower level, scanline level routines. Debug reports a limited set
roentgen b75cab
 *                of messages to monitor progess without enabling dump logs.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static   char tiffcrop_version_id[] = "2.4";
roentgen b75cab
static   char tiffcrop_rev_date[] = "12-13-2010";
roentgen b75cab
roentgen b75cab
#include "tif_config.h"
roentgen b75cab
#include "tiffiop.h"
roentgen b75cab
roentgen b75cab
#include <stdio.h>
roentgen b75cab
#include <stdlib.h>
roentgen b75cab
#include <string.h>
roentgen b75cab
#include <math.h>
roentgen b75cab
#include <ctype.h>
roentgen b75cab
#include <limits.h>
roentgen b75cab
#include <sys/stat.h>
roentgen b75cab
#include <assert.h>
roentgen b75cab
roentgen b75cab
#ifdef HAVE_UNISTD_H
roentgen b75cab
# include <unistd.h>
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#ifdef HAVE_STDINT_H
roentgen b75cab
# include <stdint.h>
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#ifndef HAVE_GETOPT
roentgen b75cab
extern int getopt(int, char**, char*);
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#ifdef NEED_LIBPORT
roentgen b75cab
# include "libport.h"
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#include "tiffio.h"
roentgen b75cab
roentgen b75cab
#if defined(VMS)
roentgen b75cab
# define unlink delete
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#ifndef PATH_MAX
roentgen b75cab
#define PATH_MAX 1024
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#ifndef streq
roentgen b75cab
#define	streq(a,b)	(strcmp((a),(b)) == 0)
roentgen b75cab
#endif
roentgen b75cab
#define	strneq(a,b,n)	(strncmp((a),(b),(n)) == 0)
roentgen b75cab
roentgen b75cab
#define	TRUE	1
roentgen b75cab
#define	FALSE	0
roentgen b75cab
roentgen b75cab
#ifndef TIFFhowmany
roentgen b75cab
#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
roentgen b75cab
#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Definitions and data structures required to support cropping and image
roentgen b75cab
 * manipulations.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
#define EDGE_TOP      1
roentgen b75cab
#define EDGE_LEFT     2
roentgen b75cab
#define EDGE_BOTTOM   3
roentgen b75cab
#define EDGE_RIGHT    4
roentgen b75cab
#define EDGE_CENTER   5
roentgen b75cab
roentgen b75cab
#define MIRROR_HORIZ  1
roentgen b75cab
#define MIRROR_VERT   2
roentgen b75cab
#define MIRROR_BOTH   3
roentgen b75cab
#define ROTATECW_90   8
roentgen b75cab
#define ROTATECW_180 16
roentgen b75cab
#define ROTATECW_270 32
roentgen b75cab
#define ROTATE_ANY ROTATECW_90 || ROTATECW_180 || ROTATECW_270 
roentgen b75cab
roentgen b75cab
#define CROP_NONE     0
roentgen b75cab
#define CROP_MARGINS  1
roentgen b75cab
#define CROP_WIDTH    2
roentgen b75cab
#define CROP_LENGTH   4
roentgen b75cab
#define CROP_ZONES    8
roentgen b75cab
#define CROP_REGIONS 16
roentgen b75cab
#define CROP_ROTATE  32
roentgen b75cab
#define CROP_MIRROR  64
roentgen b75cab
#define CROP_INVERT 128
roentgen b75cab
roentgen b75cab
/* Modes for writing out images and selections */
roentgen b75cab
#define ONE_FILE_COMPOSITE       0 /* One file, sections combined sections */
roentgen b75cab
#define ONE_FILE_SEPARATED       1 /* One file, sections to new IFDs */
roentgen b75cab
#define FILE_PER_IMAGE_COMPOSITE 2 /* One file per image, combined sections */
roentgen b75cab
#define FILE_PER_IMAGE_SEPARATED 3 /* One file per input image */
roentgen b75cab
#define FILE_PER_SELECTION       4 /* One file per selection */
roentgen b75cab
roentgen b75cab
#define COMPOSITE_IMAGES         0 /* Selections combined into one image */  
roentgen b75cab
#define SEPARATED_IMAGES         1 /* Selections saved to separate images */
roentgen b75cab
roentgen b75cab
#define STRIP    1
roentgen b75cab
#define TILE     2
roentgen b75cab
roentgen b75cab
#define MAX_REGIONS   8  /* number of regions to extract from a single page */
roentgen b75cab
#define MAX_OUTBUFFS  8  /* must match larger of zones or regions */
roentgen b75cab
#define MAX_SECTIONS 32  /* number of sections per page to write to output */
roentgen b75cab
#define MAX_IMAGES 2048  /* number of images in descrete list, not in the file */
roentgen b75cab
#define MAX_SAMPLES   8  /* maximum number of samples per pixel supported */
roentgen b75cab
#define MAX_BITS_PER_SAMPLE 64 /* maximum bit depth supported */
roentgen b75cab
#define MAX_EXPORT_PAGES 999999  /* maximum number of export pages per file */
roentgen b75cab
roentgen b75cab
#define DUMP_NONE   0
roentgen b75cab
#define DUMP_TEXT   1
roentgen b75cab
#define DUMP_RAW    2
roentgen b75cab
roentgen b75cab
/* Offsets into buffer for margins and fixed width and length segments */
roentgen b75cab
struct offset {
roentgen b75cab
  uint32  tmargin;
roentgen b75cab
  uint32  lmargin;
roentgen b75cab
  uint32  bmargin;
roentgen b75cab
  uint32  rmargin;
roentgen b75cab
  uint32  crop_width;
roentgen b75cab
  uint32  crop_length;
roentgen b75cab
  uint32  startx;
roentgen b75cab
  uint32  endx;
roentgen b75cab
  uint32  starty;
roentgen b75cab
  uint32  endy;
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
/* Description of a zone within the image. Position 1 of 3 zones would be 
roentgen b75cab
 * the first third of the image. These are computed after margins and 
roentgen b75cab
 * width/length requests are applied so that you can extract multiple 
roentgen b75cab
 * zones from within a larger region for OCR or barcode recognition.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
struct  buffinfo {
roentgen b75cab
  uint32 size;           /* size of this buffer */
roentgen b75cab
  unsigned char *buffer; /* address of the allocated buffer */
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
struct  zone {
roentgen b75cab
  int   position;  /* ordinal of segment to be extracted */
roentgen b75cab
  int   total;     /* total equal sized divisions of crop area */
roentgen b75cab
  };
roentgen b75cab
roentgen b75cab
struct  pageseg {
roentgen b75cab
  uint32 x1;        /* index of left edge */
roentgen b75cab
  uint32 x2;        /* index of right edge */
roentgen b75cab
  uint32 y1;        /* index of top edge */
roentgen b75cab
  uint32 y2;        /* index of bottom edge */
roentgen b75cab
  int    position;  /* ordinal of segment to be extracted */
roentgen b75cab
  int    total;     /* total equal sized divisions of crop area */
roentgen b75cab
  uint32 buffsize;  /* size of buffer needed to hold the cropped zone */
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
struct  coordpairs {
roentgen b75cab
  double X1;        /* index of left edge in current units */
roentgen b75cab
  double X2;        /* index of right edge in current units */
roentgen b75cab
  double Y1;        /* index of top edge in current units */
roentgen b75cab
  double Y2;        /* index of bottom edge in current units */
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
struct  region {
roentgen b75cab
  uint32 x1;        /* pixel offset of left edge */
roentgen b75cab
  uint32 x2;        /* pixel offset of right edge */
roentgen b75cab
  uint32 y1;        /* pixel offset of top edge */
roentgen b75cab
  uint32 y2;        /* picel offset of bottom edge */
roentgen b75cab
  uint32 width;     /* width in pixels */
roentgen b75cab
  uint32 length;    /* length in pixels */
roentgen b75cab
  uint32 buffsize;  /* size of buffer needed to hold the cropped region */
roentgen b75cab
  unsigned char *buffptr; /* address of start of the region */
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
/* Cropping parameters from command line and image data 
roentgen b75cab
 * Note: This should be renamed to proc_opts and expanded to include all current globals
roentgen b75cab
 * if possible, but each function that accesses global variables will have to be redone.
roentgen b75cab
 */
roentgen b75cab
struct crop_mask {
roentgen b75cab
  double width;           /* Selection width for master crop region in requested units */
roentgen b75cab
  double length;          /* Selection length for master crop region in requesed units */
roentgen b75cab
  double margins[4];      /* Top, left, bottom, right margins */
roentgen b75cab
  float  xres;            /* Horizontal resolution read from image*/
roentgen b75cab
  float  yres;            /* Vertical resolution read from image */
roentgen b75cab
  uint32 combined_width;  /* Width of combined cropped zones */
roentgen b75cab
  uint32 combined_length; /* Length of combined cropped zones */
roentgen b75cab
  uint32 bufftotal;       /* Size of buffer needed to hold all the cropped region */
roentgen b75cab
  uint16 img_mode;        /* Composite or separate images created from zones or regions */
roentgen b75cab
  uint16 exp_mode;        /* Export input images or selections to one or more files */
roentgen b75cab
  uint16 crop_mode;       /* Crop options to be applied */
roentgen b75cab
  uint16 res_unit;        /* Resolution unit for margins and selections */
roentgen b75cab
  uint16 edge_ref;        /* Reference edge for sections extraction and combination */
roentgen b75cab
  uint16 rotation;        /* Clockwise rotation of the extracted region or image */
roentgen b75cab
  uint16 mirror;          /* Mirror extracted region or image horizontally or vertically */
roentgen b75cab
  uint16 invert;          /* Invert the color map of image or region */
roentgen b75cab
  uint16 photometric;     /* Status of photometric interpretation for inverted image */
roentgen b75cab
  uint16 selections;      /* Number of regions or zones selected */
roentgen b75cab
  uint16 regions;         /* Number of regions delimited by corner coordinates */
roentgen b75cab
  struct region regionlist[MAX_REGIONS]; /* Regions within page or master crop region */
roentgen b75cab
  uint16 zones;           /* Number of zones delimited by Ordinal:Total requested */
roentgen b75cab
  struct zone zonelist[MAX_REGIONS]; /* Zones indices to define a region */
roentgen b75cab
  struct coordpairs corners[MAX_REGIONS]; /* Coordinates of upper left and lower right corner */
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
#define MAX_PAPERNAMES 49
roentgen b75cab
#define MAX_PAPERNAME_LENGTH 15
roentgen b75cab
#define DEFAULT_RESUNIT      RESUNIT_INCH
roentgen b75cab
#define DEFAULT_PAGE_HEIGHT   14.0
roentgen b75cab
#define DEFAULT_PAGE_WIDTH     8.5
roentgen b75cab
#define DEFAULT_RESOLUTION   300
roentgen b75cab
#define DEFAULT_PAPER_SIZE  "legal"
roentgen b75cab
roentgen b75cab
#define ORIENTATION_NONE       0
roentgen b75cab
#define ORIENTATION_PORTRAIT   1
roentgen b75cab
#define ORIENTATION_LANDSCAPE  2
roentgen b75cab
#define ORIENTATION_SEASCAPE   4
roentgen b75cab
#define ORIENTATION_AUTO      16
roentgen b75cab
roentgen b75cab
#define PAGE_MODE_NONE         0
roentgen b75cab
#define PAGE_MODE_RESOLUTION   1
roentgen b75cab
#define PAGE_MODE_PAPERSIZE    2
roentgen b75cab
#define PAGE_MODE_MARGINS      4
roentgen b75cab
#define PAGE_MODE_ROWSCOLS     8
roentgen b75cab
roentgen b75cab
#define INVERT_DATA_ONLY      10
roentgen b75cab
#define INVERT_DATA_AND_TAG   11
roentgen b75cab
roentgen b75cab
struct paperdef {
roentgen b75cab
  char   name[MAX_PAPERNAME_LENGTH];
roentgen b75cab
  double width;
roentgen b75cab
  double length;
roentgen b75cab
  double asratio;
roentgen b75cab
  };
roentgen b75cab
roentgen b75cab
/* European page sizes corrected from update sent by 
roentgen b75cab
 * thomas . jarosch @ intra2net . com on 5/7/2010
roentgen b75cab
 * Paper Size       Width   Length  Aspect Ratio */
roentgen b75cab
struct paperdef PaperTable[MAX_PAPERNAMES] = {
roentgen b75cab
  {"default",         8.500,  14.000,  0.607},
roentgen b75cab
  {"pa4",             8.264,  11.000,  0.751},
roentgen b75cab
  {"letter",          8.500,  11.000,  0.773},
roentgen b75cab
  {"legal",           8.500,  14.000,  0.607},
roentgen b75cab
  {"half-letter",     8.500,   5.514,  1.542},
roentgen b75cab
  {"executive",       7.264,  10.528,  0.690},
roentgen b75cab
  {"tabloid",        11.000,  17.000,  0.647},
roentgen b75cab
  {"11x17",          11.000,  17.000,  0.647},
roentgen b75cab
  {"ledger",         17.000,  11.000,  1.545},
roentgen b75cab
  {"archa",           9.000,  12.000,  0.750},
roentgen b75cab
  {"archb",          12.000,  18.000,  0.667},
roentgen b75cab
  {"archc",          18.000,  24.000,  0.750},
roentgen b75cab
  {"archd",          24.000,  36.000,  0.667},
roentgen b75cab
  {"arche",          36.000,  48.000,  0.750},
roentgen b75cab
  {"csheet",         17.000,  22.000,  0.773},
roentgen b75cab
  {"dsheet",         22.000,  34.000,  0.647},
roentgen b75cab
  {"esheet",         34.000,  44.000,  0.773},
roentgen b75cab
  {"superb",         11.708,  17.042,  0.687},
roentgen b75cab
  {"commercial",      4.139,   9.528,  0.434},
roentgen b75cab
  {"monarch",         3.889,   7.528,  0.517},
roentgen b75cab
  {"envelope-dl",     4.333,   8.681,  0.499},
roentgen b75cab
  {"envelope-c5",     6.389,   9.028,  0.708},
roentgen b75cab
  {"europostcard",    4.139,   5.833,  0.710},
roentgen b75cab
  {"a0",             33.110,  46.811,  0.707},
roentgen b75cab
  {"a1",             23.386,  33.110,  0.706},
roentgen b75cab
  {"a2",             16.535,  23.386,  0.707},
roentgen b75cab
  {"a3",             11.693,  16.535,  0.707},
roentgen b75cab
  {"a4",              8.268,  11.693,  0.707},
roentgen b75cab
  {"a5",              5.827,   8.268,  0.705},
roentgen b75cab
  {"a6",              4.134,   5.827,  0.709},
roentgen b75cab
  {"a7",              2.913,   4.134,  0.705},
roentgen b75cab
  {"a8",              2.047,   2.913,  0.703},
roentgen b75cab
  {"a9",              1.457,   2.047,  0.712},
roentgen b75cab
  {"a10",             1.024,   1.457,  0.703},
roentgen b75cab
  {"b0",             39.370,  55.669,  0.707},
roentgen b75cab
  {"b1",             27.835,  39.370,  0.707},
roentgen b75cab
  {"b2",             19.685,  27.835,  0.707},
roentgen b75cab
  {"b3",             13.898,  19.685,  0.706},
roentgen b75cab
  {"b4",              9.843,  13.898,  0.708},
roentgen b75cab
  {"b5",              6.929,   9.843,  0.704},
roentgen b75cab
  {"b6",              4.921,   6.929,  0.710},
roentgen b75cab
  {"c0",             36.102,  51.063,  0.707},
roentgen b75cab
  {"c1",             25.512,  36.102,  0.707},
roentgen b75cab
  {"c2",             18.031,  25.512,  0.707},
roentgen b75cab
  {"c3",             12.756,  18.031,  0.707},
roentgen b75cab
  {"c4",              9.016,  12.756,  0.707},
roentgen b75cab
  {"c5",              6.378,   9.016,  0.707},
roentgen b75cab
  {"c6",              4.488,   6.378,  0.704},
roentgen b75cab
  {"",                0.000,   0.000,  1.000}
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
/* Structure to define input image parameters */
roentgen b75cab
struct image_data {
roentgen b75cab
  float  xres;
roentgen b75cab
  float  yres;
roentgen b75cab
  uint32 width;
roentgen b75cab
  uint32 length;
roentgen b75cab
  uint16 res_unit;
roentgen b75cab
  uint16 bps;
roentgen b75cab
  uint16 spp;
roentgen b75cab
  uint16 planar;
roentgen b75cab
  uint16 photometric;
roentgen b75cab
  uint16 orientation;
roentgen b75cab
  uint16 compression;
roentgen b75cab
  uint16 adjustments;
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
/* Structure to define the output image modifiers */
roentgen b75cab
struct pagedef {
roentgen b75cab
  char          name[16];
roentgen b75cab
  double        width;    /* width in pixels */
roentgen b75cab
  double        length;   /* length in pixels */
roentgen b75cab
  double        hmargin;  /* margins to subtract from width of sections */
roentgen b75cab
  double        vmargin;  /* margins to subtract from height of sections */
roentgen b75cab
  double        hres;     /* horizontal resolution for output */
roentgen b75cab
  double        vres;     /* vertical resolution for output */
roentgen b75cab
  uint32        mode;     /* bitmask of modifiers to page format */
roentgen b75cab
  uint16        res_unit; /* resolution unit for output image */
roentgen b75cab
  unsigned int  rows;     /* number of section rows */
roentgen b75cab
  unsigned int  cols;     /* number of section cols */
roentgen b75cab
  unsigned int  orient;   /* portrait, landscape, seascape, auto */
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
struct dump_opts {
roentgen b75cab
  int  debug;
roentgen b75cab
  int  format;
roentgen b75cab
  int  level;
roentgen b75cab
  char mode[4];
roentgen b75cab
  char infilename[PATH_MAX + 1];
roentgen b75cab
  char outfilename[PATH_MAX + 1];
roentgen b75cab
  FILE *infile;
roentgen b75cab
  FILE *outfile;
roentgen b75cab
  };
roentgen b75cab
roentgen b75cab
/* globals */
roentgen b75cab
static int    outtiled = -1;
roentgen b75cab
static uint32 tilewidth = 0;
roentgen b75cab
static uint32 tilelength = 0;
roentgen b75cab
roentgen b75cab
static uint16 config = 0;
roentgen b75cab
static uint16 compression = 0;
roentgen b75cab
static uint16 predictor = 0;
roentgen b75cab
static uint16 fillorder = 0;
roentgen b75cab
static uint32 rowsperstrip = 0;
roentgen b75cab
static uint32 g3opts = 0;
roentgen b75cab
static int    ignore = FALSE;		/* if true, ignore read errors */
roentgen b75cab
static uint32 defg3opts = (uint32) -1;
roentgen b75cab
static int    quality = 100;		/* JPEG quality */
roentgen b75cab
/* static int    jpegcolormode = -1;        was JPEGCOLORMODE_RGB;  */
roentgen b75cab
static int    jpegcolormode = JPEGCOLORMODE_RGB;
roentgen b75cab
static uint16 defcompression = (uint16) -1;
roentgen b75cab
static uint16 defpredictor = (uint16) -1;
roentgen b75cab
static int    pageNum = 0;
roentgen b75cab
static int    little_endian = 1;
roentgen b75cab
roentgen b75cab
/* Functions adapted from tiffcp with additions or significant modifications */
roentgen b75cab
static int  readContigStripsIntoBuffer   (TIFF*, uint8*);
roentgen b75cab
static int  readSeparateStripsIntoBuffer (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
roentgen b75cab
static int  readContigTilesIntoBuffer    (TIFF*, uint8*, uint32, uint32, uint32, uint32, tsample_t, uint16);
roentgen b75cab
static int  readSeparateTilesIntoBuffer  (TIFF*, uint8*, uint32, uint32, uint32, uint32, tsample_t, uint16);
roentgen b75cab
static int  writeBufferToContigStrips    (TIFF*, uint8*, uint32);
roentgen b75cab
static int  writeBufferToContigTiles     (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
roentgen b75cab
static int  writeBufferToSeparateStrips  (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
roentgen b75cab
static int  writeBufferToSeparateTiles   (TIFF*, uint8*, uint32, uint32, tsample_t, struct dump_opts *);
roentgen b75cab
static int  extractContigSamplesToBuffer (uint8 *, uint8 *, uint32, uint32, tsample_t, 
roentgen b75cab
                                         uint16, uint16, struct dump_opts *);
roentgen b75cab
static int processCompressOptions(char*);
roentgen b75cab
static void usage(void);
roentgen b75cab
roentgen b75cab
/* All other functions by Richard Nolde,  not found in tiffcp */
roentgen b75cab
static void initImageData (struct image_data *);
roentgen b75cab
static void initCropMasks (struct crop_mask *);
roentgen b75cab
static void initPageSetup (struct pagedef *, struct pageseg *, struct buffinfo []);
roentgen b75cab
static void initDumpOptions(struct dump_opts *);
roentgen b75cab
roentgen b75cab
/* Command line and file naming functions */
roentgen b75cab
void  process_command_opts (int, char *[], char *, char *, uint32 *,
roentgen b75cab
	                    uint16 *, uint16 *, uint32 *, uint32 *, uint32 *,
roentgen b75cab
		            struct crop_mask *, struct pagedef *, 
roentgen b75cab
                            struct dump_opts *, 
roentgen b75cab
                            unsigned int *, unsigned int *);
roentgen b75cab
static  int update_output_file (TIFF **, char *, int, char *, unsigned int *);
roentgen b75cab
roentgen b75cab
roentgen b75cab
/*  * High level functions for whole image manipulation */
roentgen b75cab
static int  get_page_geometry (char *, struct pagedef*);
roentgen b75cab
static int  computeInputPixelOffsets(struct crop_mask *, struct image_data *, 
roentgen b75cab
                                     struct offset *);
roentgen b75cab
static int  computeOutputPixelOffsets (struct crop_mask *, struct image_data *,
roentgen b75cab
				       struct pagedef *, struct pageseg *,
roentgen b75cab
                                       struct dump_opts *);
roentgen b75cab
static int  loadImage(TIFF *, struct image_data *, struct dump_opts *, unsigned char **);
roentgen b75cab
static int  correct_orientation(struct image_data *, unsigned char **);
roentgen b75cab
static int  getCropOffsets(struct image_data *, struct crop_mask *, struct dump_opts *);
roentgen b75cab
static int  processCropSelections(struct image_data *, struct crop_mask *, 
roentgen b75cab
                                  unsigned char **, struct buffinfo []);
roentgen b75cab
static int  writeSelections(TIFF *, TIFF **, struct crop_mask *, struct image_data *,
roentgen b75cab
                            struct dump_opts *, struct buffinfo [],
roentgen b75cab
                            char *, char *, unsigned int*, unsigned int);
roentgen b75cab
roentgen b75cab
/* Section functions */
roentgen b75cab
static int  createImageSection(uint32, unsigned char **);
roentgen b75cab
static int  extractImageSection(struct image_data *, struct pageseg *, 
roentgen b75cab
                                unsigned char *, unsigned char *);
roentgen b75cab
static int  writeSingleSection(TIFF *, TIFF *, struct image_data *,
roentgen b75cab
                               struct dump_opts *, uint32, uint32,
roentgen b75cab
			       double, double, unsigned char *);
roentgen b75cab
static int  writeImageSections(TIFF *, TIFF *, struct image_data *,
roentgen b75cab
                               struct pagedef *, struct pageseg *, 
roentgen b75cab
                               struct dump_opts *, unsigned char *, 
roentgen b75cab
                               unsigned char **);
roentgen b75cab
/* Whole image functions */
roentgen b75cab
static int  createCroppedImage(struct image_data *, struct crop_mask *, 
roentgen b75cab
                               unsigned char **, unsigned char **);
roentgen b75cab
static int  writeCroppedImage(TIFF *, TIFF *, struct image_data *image,
roentgen b75cab
                              struct dump_opts * dump,
roentgen b75cab
                              uint32, uint32, unsigned char *, int, int);
roentgen b75cab
roentgen b75cab
/* Image manipulation functions */
roentgen b75cab
static int rotateContigSamples8bits(uint16, uint16, uint16, uint32, 
roentgen b75cab
                                    uint32,   uint32, uint8 *, uint8 *);
roentgen b75cab
static int rotateContigSamples16bits(uint16, uint16, uint16, uint32, 
roentgen b75cab
                                     uint32,   uint32, uint8 *, uint8 *);
roentgen b75cab
static int rotateContigSamples24bits(uint16, uint16, uint16, uint32, 
roentgen b75cab
                                     uint32,   uint32, uint8 *, uint8 *);
roentgen b75cab
static int rotateContigSamples32bits(uint16, uint16, uint16, uint32, 
roentgen b75cab
                                     uint32,   uint32, uint8 *, uint8 *);
roentgen b75cab
static int rotateImage(uint16, struct image_data *, uint32 *, uint32 *,
roentgen b75cab
 		       unsigned char **);
roentgen b75cab
static int mirrorImage(uint16, uint16, uint16, uint32, uint32,
roentgen b75cab
		       unsigned char *);
roentgen b75cab
static int invertImage(uint16, uint16, uint16, uint32, uint32,
roentgen b75cab
		       unsigned char *);
roentgen b75cab
roentgen b75cab
/* Functions to reverse the sequence of samples in a scanline */
roentgen b75cab
static int reverseSamples8bits  (uint16, uint16, uint32, uint8 *, uint8 *);
roentgen b75cab
static int reverseSamples16bits (uint16, uint16, uint32, uint8 *, uint8 *);
roentgen b75cab
static int reverseSamples24bits (uint16, uint16, uint32, uint8 *, uint8 *);
roentgen b75cab
static int reverseSamples32bits (uint16, uint16, uint32, uint8 *, uint8 *);
roentgen b75cab
static int reverseSamplesBytes  (uint16, uint16, uint32, uint8 *, uint8 *);
roentgen b75cab
roentgen b75cab
/* Functions for manipulating individual samples in an image */
roentgen b75cab
static int extractSeparateRegion(struct image_data *, struct crop_mask *,
roentgen b75cab
		 		 unsigned char *, unsigned char *, int);
roentgen b75cab
static int extractCompositeRegions(struct image_data *,  struct crop_mask *,
roentgen b75cab
				   unsigned char *, unsigned char *);
roentgen b75cab
static int extractContigSamples8bits (uint8 *, uint8 *, uint32,
roentgen b75cab
 	                             tsample_t, uint16, uint16, 
roentgen b75cab
                                     tsample_t, uint32, uint32);
roentgen b75cab
static int extractContigSamples16bits (uint8 *, uint8 *, uint32,
roentgen b75cab
 	                              tsample_t, uint16, uint16, 
roentgen b75cab
                                      tsample_t, uint32, uint32);
roentgen b75cab
static int extractContigSamples24bits (uint8 *, uint8 *, uint32,
roentgen b75cab
 	                              tsample_t, uint16, uint16, 
roentgen b75cab
                                      tsample_t, uint32, uint32);
roentgen b75cab
static int extractContigSamples32bits (uint8 *, uint8 *, uint32,
roentgen b75cab
	                              tsample_t, uint16, uint16, 
roentgen b75cab
                                      tsample_t, uint32, uint32);
roentgen b75cab
static int extractContigSamplesBytes (uint8 *, uint8 *, uint32, 
roentgen b75cab
                                      tsample_t, uint16, uint16, 
roentgen b75cab
				      tsample_t, uint32, uint32);
roentgen b75cab
static int extractContigSamplesShifted8bits (uint8 *, uint8 *, uint32,
roentgen b75cab
 	                                     tsample_t, uint16, uint16,
roentgen b75cab
                                             tsample_t, uint32, uint32,
roentgen b75cab
                                             int);
roentgen b75cab
static int extractContigSamplesShifted16bits (uint8 *, uint8 *, uint32,
roentgen b75cab
 	                                      tsample_t, uint16, uint16, 
roentgen b75cab
				              tsample_t, uint32, uint32,
roentgen b75cab
                                              int);
roentgen b75cab
static int extractContigSamplesShifted24bits (uint8 *, uint8 *, uint32,
roentgen b75cab
 	                                      tsample_t, uint16, uint16, 
roentgen b75cab
				              tsample_t, uint32, uint32,
roentgen b75cab
                                              int);
roentgen b75cab
static int extractContigSamplesShifted32bits (uint8 *, uint8 *, uint32,
roentgen b75cab
	                                      tsample_t, uint16, uint16, 
roentgen b75cab
				              tsample_t, uint32, uint32,
roentgen b75cab
                                              int);
roentgen b75cab
static int extractContigSamplesToTileBuffer(uint8 *, uint8 *, uint32, uint32,
roentgen b75cab
  	                                    uint32, uint32, tsample_t, uint16,
roentgen b75cab
					    uint16, uint16, struct dump_opts *);
roentgen b75cab
roentgen b75cab
/* Functions to combine separate planes into interleaved planes */
roentgen b75cab
static int combineSeparateSamples8bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                        uint16, uint16, FILE *, int, int);
roentgen b75cab
static int combineSeparateSamples16bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                         uint16, uint16, FILE *, int, int);
roentgen b75cab
static int combineSeparateSamples24bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                         uint16, uint16, FILE *, int, int);
roentgen b75cab
static int combineSeparateSamples32bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                         uint16, uint16, FILE *, int, int);
roentgen b75cab
static int combineSeparateSamplesBytes (unsigned char *[], unsigned char *,
roentgen b75cab
					uint32, uint32, tsample_t, uint16,
roentgen b75cab
                                        FILE *, int, int);
roentgen b75cab
roentgen b75cab
static int combineSeparateTileSamples8bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                            uint32, uint32, uint16, uint16, 
roentgen b75cab
                                            FILE *, int, int);
roentgen b75cab
static int combineSeparateTileSamples16bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                             uint32, uint32, uint16, uint16,
roentgen b75cab
                                             FILE *, int, int);
roentgen b75cab
static int combineSeparateTileSamples24bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                             uint32, uint32, uint16, uint16,
roentgen b75cab
                                             FILE *, int, int);
roentgen b75cab
static int combineSeparateTileSamples32bits (uint8 *[], uint8 *, uint32, uint32,
roentgen b75cab
                                             uint32, uint32, uint16, uint16,
roentgen b75cab
                                             FILE *, int, int);
roentgen b75cab
static int combineSeparateTileSamplesBytes (unsigned char *[], unsigned char *,
roentgen b75cab
			  		    uint32, uint32, uint32, uint32, 
roentgen b75cab
                                            tsample_t, uint16, FILE *, int, int);
roentgen b75cab
roentgen b75cab
/* Dump functions for debugging */
roentgen b75cab
static void dump_info  (FILE *, int, char *, char *, ...);
roentgen b75cab
static int  dump_data  (FILE *, int, char *, unsigned char *, uint32);
roentgen b75cab
static int  dump_byte  (FILE *, int, char *, unsigned char);
roentgen b75cab
static int  dump_short (FILE *, int, char *, uint16);
roentgen b75cab
static int  dump_long  (FILE *, int, char *, uint32);
roentgen b75cab
static int  dump_wide  (FILE *, int, char *, uint64);
roentgen b75cab
static int  dump_buffer (FILE *, int, uint32, uint32, uint32, unsigned char *);
roentgen b75cab
roentgen b75cab
/* End function declarations */
roentgen b75cab
/* Functions derived in whole or in part from tiffcp */
roentgen b75cab
/* The following functions are taken largely intact from tiffcp */
roentgen b75cab
roentgen b75cab
static   char* usage_info[] = {
roentgen b75cab
"usage: tiffcrop [options] source1 ... sourceN  destination",
roentgen b75cab
"where options are:",
roentgen b75cab
" -h		Print this syntax listing",
roentgen b75cab
" -v		Print tiffcrop version identifier and last revision date",
roentgen b75cab
" ",
roentgen b75cab
" -a		Append to output instead of overwriting",
roentgen b75cab
" -d offset	Set initial directory offset, counting first image as one, not zero",
roentgen b75cab
" -p contig	Pack samples contiguously (e.g. RGBRGB...)",
roentgen b75cab
" -p separate	Store samples separately (e.g. RRR...GGG...BBB...)",
roentgen b75cab
" -s		Write output in strips",
roentgen b75cab
" -t		Write output in tiles",
roentgen b75cab
" -i		Ignore read errors",
roentgen b75cab
" ",
roentgen b75cab
" -r #		Make each strip have no more than # rows",
roentgen b75cab
" -w #		Set output tile width (pixels)",
roentgen b75cab
" -l #		Set output tile length (pixels)",
roentgen b75cab
" ",
roentgen b75cab
" -f lsb2msb	Force lsb-to-msb FillOrder for output",
roentgen b75cab
" -f msb2lsb	Force msb-to-lsb FillOrder for output",
roentgen b75cab
"",
roentgen b75cab
" -c lzw[:opts]	 Compress output with Lempel-Ziv & Welch encoding",
roentgen b75cab
" -c zip[:opts]	 Compress output with deflate encoding",
roentgen b75cab
" -c jpeg[:opts] Compress output with JPEG encoding",
roentgen b75cab
" -c packbits	 Compress output with packbits encoding",
roentgen b75cab
" -c g3[:opts]	 Compress output with CCITT Group 3 encoding",
roentgen b75cab
" -c g4		 Compress output with CCITT Group 4 encoding",
roentgen b75cab
" -c none	 Use no compression algorithm on output",
roentgen b75cab
" ",
roentgen b75cab
"Group 3 options:",
roentgen b75cab
" 1d		Use default CCITT Group 3 1D-encoding",
roentgen b75cab
" 2d		Use optional CCITT Group 3 2D-encoding",
roentgen b75cab
" fill		Byte-align EOL codes",
roentgen b75cab
"For example, -c g3:2d:fill to get G3-2D-encoded data with byte-aligned EOLs",
roentgen b75cab
" ",
roentgen b75cab
"JPEG options:",
roentgen b75cab
" #		Set compression quality level (0-100, default 100)",
roentgen b75cab
" raw		Output color image as raw YCbCr",
roentgen b75cab
" rgb		Output color image as RGB",
roentgen b75cab
"For example, -c jpeg:rgb:50 to get JPEG-encoded RGB data with 50% comp. quality",
roentgen b75cab
" ",
roentgen b75cab
"LZW and deflate options:",
roentgen b75cab
" #		Set predictor value",
roentgen b75cab
"For example, -c lzw:2 to get LZW-encoded data with horizontal differencing",
roentgen b75cab
" ",
roentgen b75cab
"Page and selection options:",
roentgen b75cab
" -N odd|even|#,#-#,#|last         sequences and ranges of images within file to process",
roentgen b75cab
"             The words odd or even may be used to specify all odd or even numbered images.",
roentgen b75cab
"             The word last may be used in place of a number in the sequence to indicate.",
roentgen b75cab
"             The final image in the file without knowing how many images there are.",
roentgen b75cab
"             Numbers are counted from one even though TIFF IFDs are counted from zero.",
roentgen b75cab
" ",
roentgen b75cab
" -E t|l|r|b  edge to use as origin for width and length of crop region",
roentgen b75cab
" -U units    [in, cm, px ] inches, centimeters or pixels",
roentgen b75cab
" ",
roentgen b75cab
" -m #,#,#,#  margins from edges for selection: top, left, bottom, right separated by commas",
roentgen b75cab
" -X #        horizontal dimension of region to extract expressed in current units",
roentgen b75cab
" -Y #        vertical dimension of region to extract expressed in current units",
roentgen b75cab
" -Z #:#,#:#  zones of the image designated as position X of Y,",
roentgen b75cab
"             eg 1:3 would be first of three equal portions measured from reference edge",
roentgen b75cab
" -z x1,y1,x2,y2:...:xN,yN,xN+1,yN+1",
roentgen b75cab
"             regions of the image designated by upper left and lower right coordinates",
roentgen b75cab
"",
roentgen b75cab
"Export grouping options:",
roentgen b75cab
" -e c|d|i|m|s    export mode for images and selections from input images.",
roentgen b75cab
"                 When exporting a composite image from multiple zones or regions",
roentgen b75cab
"                 (combined and image modes), the selections must have equal sizes",
roentgen b75cab
"                 for the axis perpendicular to the edge specified with -E.",
roentgen b75cab
"    c|combined   All images and selections are written to a single file (default).",
roentgen b75cab
"                 with multiple selections from one image combined into a single image.",
roentgen b75cab
"    d|divided    All images and selections are written to a single file",
roentgen b75cab
"                 with each selection from one image written to a new image.",
roentgen b75cab
"    i|image      Each input image is written to a new file (numeric filename sequence)",
roentgen b75cab
"                 with multiple selections from the image combined into one image.",
roentgen b75cab
"    m|multiple   Each input image is written to a new file (numeric filename sequence)",
roentgen b75cab
"                 with each selection from the image written to a new image.",
roentgen b75cab
"    s|separated  Individual selections from each image are written to separate files.",
roentgen b75cab
"",
roentgen b75cab
"Output options:",
roentgen b75cab
" -H #        Set horizontal resolution of output images to #",
roentgen b75cab
" -V #        Set vertical resolution of output images to #",
roentgen b75cab
" -J #        Set horizontal margin of output page to # expressed in current units",
roentgen b75cab
"             when sectioning image into columns x rows using the -S cols:rows option",
roentgen b75cab
" -K #        Set verticalal margin of output page to # expressed in current units",
roentgen b75cab
"             when sectioning image into columns x rows using the -S cols:rows option",
roentgen b75cab
" ",
roentgen b75cab
" -O orient    orientation for output image, portrait, landscape, auto",
roentgen b75cab
" -P page      page size for output image segments, eg letter, legal, tabloid, etc",
roentgen b75cab
"              use #.#x#.# to specify a custom page size in the currently defined units",
roentgen b75cab
"              where #.# represents the width and length",        
roentgen b75cab
" -S cols:rows Divide the image into equal sized segments using cols across and rows down.",
roentgen b75cab
" ",
roentgen b75cab
" -F hor|vert|both",
roentgen b75cab
"             flip (mirror) image or region horizontally, vertically, or both",
roentgen b75cab
" -R #        [90,180,or 270] degrees clockwise rotation of image or extracted region",
roentgen b75cab
" -I [black|white|data|both]",
roentgen b75cab
"             invert color space, eg dark to light for bilevel and grayscale images",
roentgen b75cab
"             If argument is white or black, set the PHOTOMETRIC_INTERPRETATION ",
roentgen b75cab
"             tag to MinIsBlack or MinIsWhite without altering the image data",
roentgen b75cab
"             If the argument is data or both, the image data are modified:",
roentgen b75cab
"             both inverts the data and the PHOTOMETRIC_INTERPRETATION tag,",
roentgen b75cab
"             data inverts the data but not the PHOTOMETRIC_INTERPRETATION tag",
roentgen b75cab
" ",
roentgen b75cab
"-D opt1:value1,opt2:value2,opt3:value3:opt4:value4",
roentgen b75cab
"             Debug/dump program progress and/or data to non-TIFF files.",
roentgen b75cab
"             Options include the following and must be joined as a comma",
roentgen b75cab
"             separate list. The use of this option is generally limited to",
roentgen b75cab
"             program debugging and development of future options.",
roentgen b75cab
" ",
roentgen b75cab
"   debug:N   Display limited program progress indicators where larger N",
roentgen b75cab
"             increase the level of detail. Note: Tiffcrop may be compiled with",
roentgen b75cab
"             -DDEVELMODE to enable additional very low level debug reporting.",
roentgen b75cab
"",
roentgen b75cab
"   Format:txt|raw  Format any logged data as ASCII text or raw binary ",
roentgen b75cab
"             values. ASCII text dumps include strings of ones and zeroes",
roentgen b75cab
"             representing the binary values in the image data plus identifying headers.",
roentgen b75cab
" ",
roentgen b75cab
"   level:N   Specify the level of detail presented in the dump files.",
roentgen b75cab
"             This can vary from dumps of the entire input or output image data to dumps",
roentgen b75cab
"             of data processed by specific functions. Current range of levels is 1 to 3.",
roentgen b75cab
" ",
roentgen b75cab
"   input:full-path-to-directory/input-dumpname",
roentgen b75cab
" ",
roentgen b75cab
"   output:full-path-to-directory/output-dumpnaem",
roentgen b75cab
" ",
roentgen b75cab
"             When dump files are being written, each image will be written to a separate",
roentgen b75cab
"             file with the name built by adding a numeric sequence value to the dumpname",
roentgen b75cab
"             and an extension of .txt for ASCII dumps or .bin for binary dumps.",
roentgen b75cab
" ",
roentgen b75cab
"             The four debug/dump options are independent, though it makes little sense to",
roentgen b75cab
"             specify a dump file without specifying a detail level.",
roentgen b75cab
" ",
roentgen b75cab
NULL
roentgen b75cab
};
roentgen b75cab
roentgen b75cab
/* This function could be modified to pass starting sample offset 
roentgen b75cab
 * and number of samples as args to select fewer than spp
roentgen b75cab
 * from input image. These would then be passed to individual 
roentgen b75cab
 * extractContigSampleXX routines.
roentgen b75cab
 */
roentgen b75cab
static int readContigTilesIntoBuffer (TIFF* in, uint8* buf, 
roentgen b75cab
                                      uint32 imagelength, 
roentgen b75cab
                                      uint32 imagewidth, 
roentgen b75cab
                                      uint32 tw, uint32 tl,
roentgen b75cab
                                      tsample_t spp, uint16 bps)
roentgen b75cab
  {
roentgen b75cab
  int status = 1;
roentgen b75cab
  tsample_t sample = 0;
roentgen b75cab
  tsample_t count = spp; 
roentgen b75cab
  uint32 row, col, trow;
roentgen b75cab
  uint32 nrow, ncol;
roentgen b75cab
  uint32 dst_rowsize, shift_width;
roentgen b75cab
  uint32 bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32 trailing_bits, prev_trailing_bits;
roentgen b75cab
  uint32 tile_rowsize  = TIFFTileRowSize(in);
roentgen b75cab
  uint32 src_offset, dst_offset;
roentgen b75cab
  uint32 row_offset, col_offset;
roentgen b75cab
  uint8 *bufp = (uint8*) buf;
roentgen b75cab
  unsigned char *src = NULL;
roentgen b75cab
  unsigned char *dst = NULL;
roentgen b75cab
  tsize_t tbytes = 0, tile_buffsize = 0;
roentgen b75cab
  tsize_t tilesize = TIFFTileSize(in);
roentgen b75cab
  unsigned char *tilebuf = NULL;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
roentgen b75cab
  if ((bps % 8) == 0)
roentgen b75cab
    shift_width = 0;
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
      shift_width = bytes_per_pixel;
roentgen b75cab
    else
roentgen b75cab
      shift_width = bytes_per_sample + 1;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  tile_buffsize = tilesize;
roentgen b75cab
roentgen b75cab
  if (tilesize < (tsize_t)(tl * tile_rowsize))
roentgen b75cab
    {
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
    TIFFError("readContigTilesIntoBuffer",
roentgen b75cab
	      "Tilesize %lu is too small, using alternate calculation %u",
roentgen b75cab
              tilesize, tl * tile_rowsize);
roentgen b75cab
#endif
roentgen b75cab
    tile_buffsize = tl * tile_rowsize;
roentgen b75cab
    } 
roentgen b75cab
roentgen b75cab
  tilebuf = _TIFFmalloc(tile_buffsize);
roentgen b75cab
  if (tilebuf == 0)
roentgen b75cab
    return 0;
roentgen b75cab
roentgen b75cab
  dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;  
roentgen b75cab
  for (row = 0; row < imagelength; row += tl)
roentgen b75cab
    {
roentgen b75cab
    nrow = (row + tl > imagelength) ? imagelength - row : tl;
roentgen b75cab
    for (col = 0; col < imagewidth; col += tw)
roentgen b75cab
      {
roentgen b75cab
      tbytes = TIFFReadTile(in, tilebuf, col, row, 0, 0);
roentgen b75cab
      if (tbytes < tilesize  && !ignore)
roentgen b75cab
        {
roentgen b75cab
	TIFFError(TIFFFileName(in),
roentgen b75cab
		  "Error, can't read tile at row %lu col %lu, Read %lu bytes of %lu",
roentgen b75cab
		  (unsigned long) col, (unsigned long) row, (unsigned long)tbytes,
roentgen b75cab
                  (unsigned long)tilesize);
roentgen b75cab
		  status = 0;
roentgen b75cab
                  _TIFFfree(tilebuf);
roentgen b75cab
		  return status;
roentgen b75cab
	}
roentgen b75cab
      
roentgen b75cab
      row_offset = row * dst_rowsize;
roentgen b75cab
      col_offset = ((col * bps * spp) + 7)/ 8;
roentgen b75cab
      bufp = buf + row_offset + col_offset;
roentgen b75cab
roentgen b75cab
      if (col + tw > imagewidth)
roentgen b75cab
	ncol = imagewidth - col;
roentgen b75cab
      else
roentgen b75cab
        ncol = tw;
roentgen b75cab
roentgen b75cab
      /* Each tile scanline will start on a byte boundary but it
roentgen b75cab
       * has to be merged into the scanline for the entire
roentgen b75cab
       * image buffer and the previous segment may not have
roentgen b75cab
       * ended on a byte boundary
roentgen b75cab
       */
roentgen b75cab
      /* Optimization for common bit depths, all samples */
roentgen b75cab
      if (((bps % 8) == 0) && (count == spp))
roentgen b75cab
        {
roentgen b75cab
	for (trow = 0; trow < nrow; trow++)
roentgen b75cab
          {
roentgen b75cab
	  src_offset = trow * tile_rowsize;
roentgen b75cab
	  _TIFFmemcpy (bufp, tilebuf + src_offset, (ncol * spp * bps) / 8);
roentgen b75cab
          bufp += (imagewidth * bps * spp) / 8;
roentgen b75cab
	  }
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	/* Bit depths not a multiple of 8 and/or extract fewer than spp samples */
roentgen b75cab
        prev_trailing_bits = trailing_bits = 0;
roentgen b75cab
        trailing_bits = (ncol * bps * spp) % 8;
roentgen b75cab
roentgen b75cab
	/*	for (trow = 0; tl < nrow; trow++) */
roentgen b75cab
	for (trow = 0; trow < nrow; trow++)
roentgen b75cab
          {
roentgen b75cab
	  src_offset = trow * tile_rowsize;
roentgen b75cab
          src = tilebuf + src_offset;
roentgen b75cab
	  dst_offset = (row + trow) * dst_rowsize;
roentgen b75cab
          dst = buf + dst_offset + col_offset;
roentgen b75cab
          switch (shift_width)
roentgen b75cab
            {
roentgen b75cab
            case 0: if (extractContigSamplesBytes (src, dst, ncol, sample,
roentgen b75cab
                                                   spp, bps, count, 0, ncol))
roentgen b75cab
                      {
roentgen b75cab
		      TIFFError("readContigTilesIntoBuffer",
roentgen b75cab
                                "Unable to extract row %d from tile %lu", 
roentgen b75cab
				row, (unsigned long)TIFFCurrentTile(in));
roentgen b75cab
		      return 1;
roentgen b75cab
		      }
roentgen b75cab
		    break;
roentgen b75cab
            case 1: if (bps == 1)
roentgen b75cab
                      { 
roentgen b75cab
                      if (extractContigSamplesShifted8bits (src, dst, ncol,
roentgen b75cab
                                                            sample, spp,
roentgen b75cab
                                                            bps, count,
roentgen b75cab
                                                            0, ncol,
roentgen b75cab
                                                            prev_trailing_bits))
roentgen b75cab
                        {
roentgen b75cab
		        TIFFError("readContigTilesIntoBuffer",
roentgen b75cab
                                  "Unable to extract row %d from tile %lu", 
roentgen b75cab
				  row, (unsigned long)TIFFCurrentTile(in));
roentgen b75cab
		        return 1;
roentgen b75cab
		        }
roentgen b75cab
		      break;
roentgen b75cab
		      }
roentgen b75cab
                    else
roentgen b75cab
                      if (extractContigSamplesShifted16bits (src, dst, ncol,
roentgen b75cab
                                                             sample, spp,
roentgen b75cab
                                                             bps, count,
roentgen b75cab
                                                             0, ncol,
roentgen b75cab
                                                             prev_trailing_bits))
roentgen b75cab
                        {
roentgen b75cab
		        TIFFError("readContigTilesIntoBuffer",
roentgen b75cab
                                  "Unable to extract row %d from tile %lu", 
roentgen b75cab
			  	  row, (unsigned long)TIFFCurrentTile(in));
roentgen b75cab
		        return 1;
roentgen b75cab
		        }
roentgen b75cab
	            break;
roentgen b75cab
            case 2: if (extractContigSamplesShifted24bits (src, dst, ncol,
roentgen b75cab
                                                           sample, spp,
roentgen b75cab
                                                           bps, count,
roentgen b75cab
                                                           0, ncol,
roentgen b75cab
                                                           prev_trailing_bits))
roentgen b75cab
                      {
roentgen b75cab
		      TIFFError("readContigTilesIntoBuffer",
roentgen b75cab
                                "Unable to extract row %d from tile %lu", 
roentgen b75cab
		  	        row, (unsigned long)TIFFCurrentTile(in));
roentgen b75cab
		      return 1;
roentgen b75cab
		      }
roentgen b75cab
		    break;
roentgen b75cab
            case 3:
roentgen b75cab
            case 4:
roentgen b75cab
            case 5: if (extractContigSamplesShifted32bits (src, dst, ncol,
roentgen b75cab
                                                           sample, spp,
roentgen b75cab
                                                           bps, count,
roentgen b75cab
                                                           0, ncol,
roentgen b75cab
                                                           prev_trailing_bits))
roentgen b75cab
                      {
roentgen b75cab
		      TIFFError("readContigTilesIntoBuffer",
roentgen b75cab
                                "Unable to extract row %d from tile %lu", 
roentgen b75cab
			        row, (unsigned long)TIFFCurrentTile(in));
roentgen b75cab
		      return 1;
roentgen b75cab
		      }
roentgen b75cab
		    break;
roentgen b75cab
            default: TIFFError("readContigTilesIntoBuffer", "Unsupported bit depth %d", bps);
roentgen b75cab
		     return 1;
roentgen b75cab
	    }
roentgen b75cab
          }
roentgen b75cab
        prev_trailing_bits += trailing_bits;
roentgen b75cab
        if (prev_trailing_bits > 7)
roentgen b75cab
	  prev_trailing_bits-= 8;
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  _TIFFfree(tilebuf);
roentgen b75cab
  return status;
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int  readSeparateTilesIntoBuffer (TIFF* in, uint8 *obuf, 
roentgen b75cab
					 uint32 imagelength, uint32 imagewidth, 
roentgen b75cab
                                         uint32 tw, uint32 tl,
roentgen b75cab
                                         uint16 spp, uint16 bps)
roentgen b75cab
  {
roentgen b75cab
  int     i, status = 1, sample;
roentgen b75cab
  int     shift_width, bytes_per_pixel;
roentgen b75cab
  uint16  bytes_per_sample;
roentgen b75cab
  uint32  row, col;     /* Current row and col of image */
roentgen b75cab
  uint32  nrow, ncol;   /* Number of rows and cols in current tile */
roentgen b75cab
  uint32  row_offset, col_offset; /* Output buffer offsets */
roentgen b75cab
  tsize_t tbytes = 0, tilesize = TIFFTileSize(in);
roentgen b75cab
  tsample_t s;
roentgen b75cab
  uint8*  bufp = (uint8*)obuf;
roentgen b75cab
  unsigned char *srcbuffs[MAX_SAMPLES];
roentgen b75cab
  unsigned char *tbuff = NULL;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8;
roentgen b75cab
roentgen b75cab
  for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
roentgen b75cab
    {
roentgen b75cab
    srcbuffs[sample] = NULL;
roentgen b75cab
    tbuff = (unsigned char *)_TIFFmalloc(tilesize + 8);
roentgen b75cab
    if (!tbuff)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("readSeparateTilesIntoBuffer", 
roentgen b75cab
                 "Unable to allocate tile read buffer for sample %d", sample);
roentgen b75cab
      for (i = 0; i < sample; i++)
roentgen b75cab
        _TIFFfree (srcbuffs[i]);
roentgen b75cab
      return 0;
roentgen b75cab
      }
roentgen b75cab
    srcbuffs[sample] = tbuff;
roentgen b75cab
    } 
roentgen b75cab
  /* Each tile contains only the data for a single plane
roentgen b75cab
   * arranged in scanlines of tw * bytes_per_sample bytes.
roentgen b75cab
   */
roentgen b75cab
  for (row = 0; row < imagelength; row += tl)
roentgen b75cab
    {
roentgen b75cab
    nrow = (row + tl > imagelength) ? imagelength - row : tl;
roentgen b75cab
    for (col = 0; col < imagewidth; col += tw)
roentgen b75cab
      {
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {  /* Read each plane of a tile set into srcbuffs[s] */
roentgen b75cab
	tbytes = TIFFReadTile(in, srcbuffs[s], col, row, 0, s);
roentgen b75cab
        if (tbytes < 0  && !ignore)
roentgen b75cab
          {
roentgen b75cab
	  TIFFError(TIFFFileName(in),
roentgen b75cab
                 "Error, can't read tile for row %lu col %lu, "
roentgen b75cab
		 "sample %lu",
roentgen b75cab
		 (unsigned long) col, (unsigned long) row,
roentgen b75cab
		 (unsigned long) s);
roentgen b75cab
		 status = 0;
roentgen b75cab
          for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
roentgen b75cab
            {
roentgen b75cab
            tbuff = srcbuffs[sample];
roentgen b75cab
            if (tbuff != NULL)
roentgen b75cab
              _TIFFfree(tbuff);
roentgen b75cab
            }
roentgen b75cab
          return status;
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
     /* Tiles on the right edge may be padded out to tw 
roentgen b75cab
      * which must be a multiple of 16.
roentgen b75cab
      * Ncol represents the visible (non padding) portion.  
roentgen b75cab
      */
roentgen b75cab
      if (col + tw > imagewidth)
roentgen b75cab
        ncol = imagewidth - col;
roentgen b75cab
      else
roentgen b75cab
        ncol = tw;
roentgen b75cab
roentgen b75cab
      row_offset = row * (((imagewidth * spp * bps) + 7) / 8);
roentgen b75cab
      col_offset = ((col * spp * bps) + 7) / 8;
roentgen b75cab
      bufp = obuf + row_offset + col_offset;
roentgen b75cab
roentgen b75cab
      if ((bps % 8) == 0)
roentgen b75cab
        {
roentgen b75cab
        if (combineSeparateTileSamplesBytes(srcbuffs, bufp, ncol, nrow, imagewidth,
roentgen b75cab
					    tw, spp, bps, NULL, 0, 0))
roentgen b75cab
	  {
roentgen b75cab
          status = 0;
roentgen b75cab
          break;
roentgen b75cab
      	  }
roentgen b75cab
	}
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
        if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
          shift_width = bytes_per_pixel;
roentgen b75cab
        else
roentgen b75cab
          shift_width = bytes_per_sample + 1;
roentgen b75cab
roentgen b75cab
        switch (shift_width)
roentgen b75cab
          {
roentgen b75cab
          case 1: if (combineSeparateTileSamples8bits (srcbuffs, bufp, ncol, nrow,
roentgen b75cab
                                                       imagewidth, tw, spp, bps, 
roentgen b75cab
						       NULL, 0, 0))
roentgen b75cab
	            {
roentgen b75cab
                    status = 0;
roentgen b75cab
                    break;
roentgen b75cab
      	            }
roentgen b75cab
	          break;
roentgen b75cab
          case 2: if (combineSeparateTileSamples16bits (srcbuffs, bufp, ncol, nrow,
roentgen b75cab
                                                       imagewidth, tw, spp, bps, 
roentgen b75cab
						       NULL, 0, 0))
roentgen b75cab
	            {
roentgen b75cab
                    status = 0;
roentgen b75cab
                    break;
roentgen b75cab
		    }
roentgen b75cab
	          break;
roentgen b75cab
          case 3: if (combineSeparateTileSamples24bits (srcbuffs, bufp, ncol, nrow,
roentgen b75cab
                                                       imagewidth, tw, spp, bps, 
roentgen b75cab
						       NULL, 0, 0))
roentgen b75cab
	            {
roentgen b75cab
                    status = 0;
roentgen b75cab
                    break;
roentgen b75cab
       	            }
roentgen b75cab
                  break;
roentgen b75cab
          case 4: 
roentgen b75cab
          case 5:
roentgen b75cab
          case 6:
roentgen b75cab
          case 7:
roentgen b75cab
          case 8: if (combineSeparateTileSamples32bits (srcbuffs, bufp, ncol, nrow,
roentgen b75cab
                                                       imagewidth, tw, spp, bps, 
roentgen b75cab
						       NULL, 0, 0))
roentgen b75cab
	            {
roentgen b75cab
                    status = 0;
roentgen b75cab
                    break;
roentgen b75cab
		    }
roentgen b75cab
	          break;
roentgen b75cab
          default: TIFFError ("readSeparateTilesIntoBuffer", "Unsupported bit depth: %d", bps);
roentgen b75cab
                  status = 0;
roentgen b75cab
                  break;
roentgen b75cab
          }
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  for (sample = 0; (sample < spp) && (sample < MAX_SAMPLES); sample++)
roentgen b75cab
    {
roentgen b75cab
    tbuff = srcbuffs[sample];
roentgen b75cab
    if (tbuff != NULL)
roentgen b75cab
      _TIFFfree(tbuff);
roentgen b75cab
    }
roentgen b75cab
 
roentgen b75cab
  return status;
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int writeBufferToContigStrips(TIFF* out, uint8* buf, uint32 imagelength)
roentgen b75cab
  {
roentgen b75cab
  uint32 row, nrows, rowsperstrip;
roentgen b75cab
  tstrip_t strip = 0;
roentgen b75cab
  tsize_t stripsize;
roentgen b75cab
roentgen b75cab
  TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
roentgen b75cab
  for (row = 0; row < imagelength; row += rowsperstrip)
roentgen b75cab
    {
roentgen b75cab
    nrows = (row + rowsperstrip > imagelength) ?
roentgen b75cab
	     imagelength - row : rowsperstrip;
roentgen b75cab
    stripsize = TIFFVStripSize(out, nrows);
roentgen b75cab
    if (TIFFWriteEncodedStrip(out, strip++, buf, stripsize) < 0)
roentgen b75cab
      {
roentgen b75cab
      TIFFError(TIFFFileName(out), "Error, can't write strip %u", strip - 1);
roentgen b75cab
      return 1;
roentgen b75cab
      }
roentgen b75cab
    buf += stripsize;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return 0;
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
/* Abandon plans to modify code so that plannar orientation separate images
roentgen b75cab
 * do not have all samples for each channel written before all samples
roentgen b75cab
 * for the next channel have been abandoned.
roentgen b75cab
 * Libtiff internals seem to depend on all data for a given sample
roentgen b75cab
 * being contiguous within a strip or tile when PLANAR_CONFIG is 
roentgen b75cab
 * separate. All strips or tiles of a given plane are written
roentgen b75cab
 * before any strips or tiles of a different plane are stored.
roentgen b75cab
 */
roentgen b75cab
static int 
roentgen b75cab
writeBufferToSeparateStrips (TIFF* out, uint8* buf, 
roentgen b75cab
			     uint32 length, uint32 width, uint16 spp,
roentgen b75cab
			     struct dump_opts *dump)
roentgen b75cab
  {
roentgen b75cab
  uint8   *src;
roentgen b75cab
  uint16   bps;
roentgen b75cab
  uint32   row, nrows, rowsize, rowsperstrip;
roentgen b75cab
  uint32   bytes_per_sample;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  tstrip_t strip = 0;
roentgen b75cab
  tsize_t  stripsize = TIFFStripSize(out);
roentgen b75cab
  tsize_t  rowstripsize,  scanlinesize = TIFFScanlineSize(out);
roentgen b75cab
  tsize_t  total_bytes = 0;
roentgen b75cab
  tdata_t  obuf;
roentgen b75cab
roentgen b75cab
  (void) TIFFGetFieldDefaulted(out, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
roentgen b75cab
  (void) TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8;
roentgen b75cab
  rowsize = ((bps * spp * width) + 7) / 8; /* source has interleaved samples */
roentgen b75cab
  rowstripsize = rowsperstrip * bytes_per_sample * (width + 1); 
roentgen b75cab
roentgen b75cab
  obuf = _TIFFmalloc (rowstripsize);
roentgen b75cab
  if (obuf == NULL)
roentgen b75cab
    return 1;
roentgen b75cab
  
roentgen b75cab
  for (s = 0; s < spp; s++)
roentgen b75cab
    {
roentgen b75cab
    for (row = 0; row < length; row += rowsperstrip)
roentgen b75cab
      {
roentgen b75cab
      nrows = (row + rowsperstrip > length) ? length - row : rowsperstrip;
roentgen b75cab
roentgen b75cab
      stripsize = TIFFVStripSize(out, nrows);
roentgen b75cab
      src = buf + (row * rowsize);
roentgen b75cab
      total_bytes += stripsize;
roentgen b75cab
      memset (obuf, '\0', rowstripsize);
roentgen b75cab
      if (extractContigSamplesToBuffer(obuf, src, nrows, width, s, spp, bps, dump))
roentgen b75cab
        {
roentgen b75cab
        _TIFFfree(obuf);
roentgen b75cab
        return 1;
roentgen b75cab
	}
roentgen b75cab
      if ((dump->outfile != NULL) && (dump->level == 1))
roentgen b75cab
        {
roentgen b75cab
        dump_info(dump->outfile, dump->format,"", 
roentgen b75cab
                  "Sample %2d, Strip: %2d, bytes: %4d, Row %4d, bytes: %4d, Input offset: %6d", 
roentgen b75cab
                  s + 1, strip + 1, stripsize, row + 1, scanlinesize, src - buf);
roentgen b75cab
        dump_buffer(dump->outfile, dump->format, nrows, scanlinesize, row, obuf);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
      if (TIFFWriteEncodedStrip(out, strip++, obuf, stripsize) < 0)
roentgen b75cab
        {
roentgen b75cab
	TIFFError(TIFFFileName(out), "Error, can't write strip %u", strip - 1);
roentgen b75cab
	_TIFFfree(obuf);
roentgen b75cab
	return 1;
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    }      
roentgen b75cab
roentgen b75cab
  _TIFFfree(obuf);
roentgen b75cab
  return 0;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/* Extract all planes from contiguous buffer into a single tile buffer 
roentgen b75cab
 * to be written out as a tile.
roentgen b75cab
 */
roentgen b75cab
static int writeBufferToContigTiles (TIFF* out, uint8* buf, uint32 imagelength,
roentgen b75cab
				       uint32 imagewidth, tsample_t spp, 
roentgen b75cab
                                       struct dump_opts* dump)
roentgen b75cab
  {
roentgen b75cab
  uint16 bps;
roentgen b75cab
  uint32 tl, tw;
roentgen b75cab
  uint32 row, col, nrow, ncol;
roentgen b75cab
  uint32 src_rowsize, col_offset;
roentgen b75cab
  uint32 tile_rowsize  = TIFFTileRowSize(out);
roentgen b75cab
  uint8* bufp = (uint8*) buf;
roentgen b75cab
  tsize_t tile_buffsize = 0;
roentgen b75cab
  tsize_t tilesize = TIFFTileSize(out);
roentgen b75cab
  unsigned char *tilebuf = NULL;
roentgen b75cab
roentgen b75cab
  TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
roentgen b75cab
  TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
roentgen b75cab
  TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
roentgen b75cab
roentgen b75cab
  tile_buffsize = tilesize;
roentgen b75cab
  if (tilesize < (tsize_t)(tl * tile_rowsize))
roentgen b75cab
    {
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
    TIFFError("writeBufferToContigTiles",
roentgen b75cab
	      "Tilesize %lu is too small, using alternate calculation %u",
roentgen b75cab
              tilesize, tl * tile_rowsize);
roentgen b75cab
#endif
roentgen b75cab
    tile_buffsize = tl * tile_rowsize;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  tilebuf = _TIFFmalloc(tile_buffsize);
roentgen b75cab
  if (tilebuf == 0)
roentgen b75cab
    return 1;
roentgen b75cab
roentgen b75cab
  src_rowsize = ((imagewidth * spp * bps) + 7) / 8;
roentgen b75cab
  for (row = 0; row < imagelength; row += tl)
roentgen b75cab
    {
roentgen b75cab
    nrow = (row + tl > imagelength) ? imagelength - row : tl;
roentgen b75cab
    for (col = 0; col < imagewidth; col += tw)
roentgen b75cab
      {
roentgen b75cab
      /* Calculate visible portion of tile. */
roentgen b75cab
      if (col + tw > imagewidth)
roentgen b75cab
	ncol = imagewidth - col;
roentgen b75cab
      else
roentgen b75cab
        ncol = tw;
roentgen b75cab
roentgen b75cab
      col_offset = (((col * bps * spp) + 7) / 8);
roentgen b75cab
      bufp = buf + (row * src_rowsize) + col_offset;
roentgen b75cab
      if (extractContigSamplesToTileBuffer(tilebuf, bufp, nrow, ncol, imagewidth,
roentgen b75cab
					   tw, 0, spp, spp, bps, dump) > 0)
roentgen b75cab
        {
roentgen b75cab
	TIFFError("writeBufferToContigTiles", 
roentgen b75cab
                  "Unable to extract data to tile for row %lu, col %lu",
roentgen b75cab
                  (unsigned long) row, (unsigned long)col);
roentgen b75cab
	_TIFFfree(tilebuf);
roentgen b75cab
	return 1;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (TIFFWriteTile(out, tilebuf, col, row, 0, 0) < 0)
roentgen b75cab
        {
roentgen b75cab
	TIFFError("writeBufferToContigTiles",
roentgen b75cab
	          "Cannot write tile at %lu %lu",
roentgen b75cab
	          (unsigned long) col, (unsigned long) row);
roentgen b75cab
	 _TIFFfree(tilebuf);
roentgen b75cab
	return 1;
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  _TIFFfree(tilebuf);
roentgen b75cab
roentgen b75cab
  return 0;
roentgen b75cab
  } /* end writeBufferToContigTiles */
roentgen b75cab
roentgen b75cab
/* Extract each plane from contiguous buffer into a single tile buffer 
roentgen b75cab
 * to be written out as a tile.
roentgen b75cab
 */
roentgen b75cab
static int writeBufferToSeparateTiles (TIFF* out, uint8* buf, uint32 imagelength,
roentgen b75cab
				       uint32 imagewidth, tsample_t spp, 
roentgen b75cab
                                       struct dump_opts * dump)
roentgen b75cab
  {
roentgen b75cab
  tdata_t obuf = _TIFFmalloc(TIFFTileSize(out));
roentgen b75cab
  uint32 tl, tw;
roentgen b75cab
  uint32 row, col, nrow, ncol;
roentgen b75cab
  uint32 src_rowsize, col_offset;
roentgen b75cab
  uint16 bps;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  uint8* bufp = (uint8*) buf;
roentgen b75cab
roentgen b75cab
  if (obuf == NULL)
roentgen b75cab
    return 1;
roentgen b75cab
roentgen b75cab
  TIFFGetField(out, TIFFTAG_TILELENGTH, &tl);
roentgen b75cab
  TIFFGetField(out, TIFFTAG_TILEWIDTH, &tw);
roentgen b75cab
  TIFFGetField(out, TIFFTAG_BITSPERSAMPLE, &bps);
roentgen b75cab
  src_rowsize = ((imagewidth * spp * bps) + 7) / 8;
roentgen b75cab
         
roentgen b75cab
  for (row = 0; row < imagelength; row += tl)
roentgen b75cab
    {
roentgen b75cab
    nrow = (row + tl > imagelength) ? imagelength - row : tl;
roentgen b75cab
    for (col = 0; col < imagewidth; col += tw)
roentgen b75cab
      {
roentgen b75cab
      /* Calculate visible portion of tile. */
roentgen b75cab
      if (col + tw > imagewidth)
roentgen b75cab
	ncol = imagewidth - col;
roentgen b75cab
      else
roentgen b75cab
        ncol = tw;
roentgen b75cab
roentgen b75cab
      col_offset = (((col * bps * spp) + 7) / 8);
roentgen b75cab
      bufp = buf + (row * src_rowsize) + col_offset;
roentgen b75cab
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	if (extractContigSamplesToTileBuffer(obuf, bufp, nrow, ncol, imagewidth,
roentgen b75cab
					     tw, s, 1, spp, bps, dump) > 0)
roentgen b75cab
          {
roentgen b75cab
	  TIFFError("writeBufferToSeparateTiles", 
roentgen b75cab
                    "Unable to extract data to tile for row %lu, col %lu sample %d",
roentgen b75cab
                    (unsigned long) row, (unsigned long)col, (int)s);
roentgen b75cab
	  _TIFFfree(obuf);
roentgen b75cab
	  return 1;
roentgen b75cab
          }
roentgen b75cab
roentgen b75cab
	if (TIFFWriteTile(out, obuf, col, row, 0, s) < 0)
roentgen b75cab
          {
roentgen b75cab
	   TIFFError("writeBufferToseparateTiles",
roentgen b75cab
	             "Cannot write tile at %lu %lu sample %lu",
roentgen b75cab
	             (unsigned long) col, (unsigned long) row,
roentgen b75cab
	             (unsigned long) s);
roentgen b75cab
	   _TIFFfree(obuf);
roentgen b75cab
	   return 1;
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  _TIFFfree(obuf);
roentgen b75cab
roentgen b75cab
  return 0;
roentgen b75cab
  } /* end writeBufferToSeparateTiles */
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
processG3Options(char* cp)
roentgen b75cab
{
roentgen b75cab
	if( (cp = strchr(cp, ':')) ) {
roentgen b75cab
		if (defg3opts == (uint32) -1)
roentgen b75cab
			defg3opts = 0;
roentgen b75cab
		do {
roentgen b75cab
			cp++;
roentgen b75cab
			if (strneq(cp, "1d", 2))
roentgen b75cab
				defg3opts &= ~GROUP3OPT_2DENCODING;
roentgen b75cab
			else if (strneq(cp, "2d", 2))
roentgen b75cab
				defg3opts |= GROUP3OPT_2DENCODING;
roentgen b75cab
			else if (strneq(cp, "fill", 4))
roentgen b75cab
				defg3opts |= GROUP3OPT_FILLBITS;
roentgen b75cab
			else
roentgen b75cab
				usage();
roentgen b75cab
		} while( (cp = strchr(cp, ':')) );
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
processCompressOptions(char* opt)
roentgen b75cab
  {
roentgen b75cab
  char* cp = NULL;
roentgen b75cab
roentgen b75cab
  if (strneq(opt, "none",4))
roentgen b75cab
    {
roentgen b75cab
    defcompression = COMPRESSION_NONE;
roentgen b75cab
    }
roentgen b75cab
  else if (streq(opt, "packbits"))
roentgen b75cab
    {
roentgen b75cab
    defcompression = COMPRESSION_PACKBITS;
roentgen b75cab
    }
roentgen b75cab
  else if (strneq(opt, "jpeg", 4))
roentgen b75cab
    {
roentgen b75cab
    cp = strchr(opt, ':');
roentgen b75cab
    defcompression = COMPRESSION_JPEG;
roentgen b75cab
roentgen b75cab
    while (cp)
roentgen b75cab
      {
roentgen b75cab
      if (isdigit((int)cp[1]))
roentgen b75cab
	quality = atoi(cp + 1);
roentgen b75cab
      else if (strneq(cp + 1, "raw", 3 ))
roentgen b75cab
	jpegcolormode = JPEGCOLORMODE_RAW;
roentgen b75cab
      else if (strneq(cp + 1, "rgb", 3 ))
roentgen b75cab
	jpegcolormode = JPEGCOLORMODE_RGB;
roentgen b75cab
      else
roentgen b75cab
	usage();
roentgen b75cab
      cp = strchr(cp + 1, ':');
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  else if (strneq(opt, "g3", 2))
roentgen b75cab
    {
roentgen b75cab
    processG3Options(opt);
roentgen b75cab
    defcompression = COMPRESSION_CCITTFAX3;
roentgen b75cab
    }
roentgen b75cab
  else if (streq(opt, "g4"))
roentgen b75cab
    {
roentgen b75cab
    defcompression = COMPRESSION_CCITTFAX4;
roentgen b75cab
    }
roentgen b75cab
  else if (strneq(opt, "lzw", 3))
roentgen b75cab
    {
roentgen b75cab
    cp = strchr(opt, ':');
roentgen b75cab
    if (cp)
roentgen b75cab
      defpredictor = atoi(cp+1);
roentgen b75cab
    defcompression = COMPRESSION_LZW;
roentgen b75cab
    }
roentgen b75cab
  else if (strneq(opt, "zip", 3))
roentgen b75cab
    {
roentgen b75cab
    cp = strchr(opt, ':');
roentgen b75cab
    if (cp)
roentgen b75cab
      defpredictor = atoi(cp+1);
roentgen b75cab
    defcompression = COMPRESSION_ADOBE_DEFLATE;
roentgen b75cab
   }
roentgen b75cab
  else
roentgen b75cab
    return (0);
roentgen b75cab
roentgen b75cab
  return (1);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
usage(void)
roentgen b75cab
  {
roentgen b75cab
  int i;
roentgen b75cab
roentgen b75cab
  fprintf(stderr, "\n%s\n", TIFFGetVersion());
roentgen b75cab
  for (i = 0; usage_info[i] != NULL; i++)
roentgen b75cab
    fprintf(stderr, "%s\n", usage_info[i]);
roentgen b75cab
  exit(-1);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
#define	CopyField(tag, v) \
roentgen b75cab
    if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v)
roentgen b75cab
#define	CopyField2(tag, v1, v2) \
roentgen b75cab
    if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2)
roentgen b75cab
#define	CopyField3(tag, v1, v2, v3) \
roentgen b75cab
    if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3)
roentgen b75cab
#define	CopyField4(tag, v1, v2, v3, v4) \
roentgen b75cab
    if (TIFFGetField(in, tag, &v1, &v2, &v3, &v4)) TIFFSetField(out, tag, v1, v2, v3, v4)
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
cpTag(TIFF* in, TIFF* out, uint16 tag, uint16 count, TIFFDataType type)
roentgen b75cab
{
roentgen b75cab
	switch (type) {
roentgen b75cab
	case TIFF_SHORT:
roentgen b75cab
		if (count == 1) {
roentgen b75cab
			uint16 shortv;
roentgen b75cab
			CopyField(tag, shortv);
roentgen b75cab
		} else if (count == 2) {
roentgen b75cab
			uint16 shortv1, shortv2;
roentgen b75cab
			CopyField2(tag, shortv1, shortv2);
roentgen b75cab
		} else if (count == 4) {
roentgen b75cab
			uint16 *tr, *tg, *tb, *ta;
roentgen b75cab
			CopyField4(tag, tr, tg, tb, ta);
roentgen b75cab
		} else if (count == (uint16) -1) {
roentgen b75cab
			uint16 shortv1;
roentgen b75cab
			uint16* shortav;
roentgen b75cab
			CopyField2(tag, shortv1, shortav);
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFF_LONG:
roentgen b75cab
		{ uint32 longv;
roentgen b75cab
		  CopyField(tag, longv);
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFF_RATIONAL:
roentgen b75cab
		if (count == 1) {
roentgen b75cab
			float floatv;
roentgen b75cab
			CopyField(tag, floatv);
roentgen b75cab
		} else if (count == (uint16) -1) {
roentgen b75cab
			float* floatav;
roentgen b75cab
			CopyField(tag, floatav);
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFF_ASCII:
roentgen b75cab
		{ char* stringv;
roentgen b75cab
		  CopyField(tag, stringv);
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
	case TIFF_DOUBLE:
roentgen b75cab
		if (count == 1) {
roentgen b75cab
			double doublev;
roentgen b75cab
			CopyField(tag, doublev);
roentgen b75cab
		} else if (count == (uint16) -1) {
roentgen b75cab
			double* doubleav;
roentgen b75cab
			CopyField(tag, doubleav);
roentgen b75cab
		}
roentgen b75cab
		break;
roentgen b75cab
          default:
roentgen b75cab
                TIFFError(TIFFFileName(in),
roentgen b75cab
                          "Data type %d is not supported, tag %d skipped",
roentgen b75cab
                          tag, type);
roentgen b75cab
	}
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static struct cpTag {
roentgen b75cab
	uint16	tag;
roentgen b75cab
	uint16	count;
roentgen b75cab
	TIFFDataType type;
roentgen b75cab
} tags[] = {
roentgen b75cab
	{ TIFFTAG_SUBFILETYPE,		1, TIFF_LONG },
roentgen b75cab
	{ TIFFTAG_THRESHHOLDING,	1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_DOCUMENTNAME,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_IMAGEDESCRIPTION,	1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_MAKE,			1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_MODEL,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_MINSAMPLEVALUE,	1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_MAXSAMPLEVALUE,	1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_XRESOLUTION,		1, TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_YRESOLUTION,		1, TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_PAGENAME,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_XPOSITION,		1, TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_YPOSITION,		1, TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_RESOLUTIONUNIT,	1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_SOFTWARE,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_DATETIME,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_ARTIST,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_HOSTCOMPUTER,		1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_WHITEPOINT,		(uint16) -1, TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_PRIMARYCHROMATICITIES,(uint16) -1,TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_HALFTONEHINTS,	2, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_INKSET,		1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_DOTRANGE,		2, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_TARGETPRINTER,	1, TIFF_ASCII },
roentgen b75cab
	{ TIFFTAG_SAMPLEFORMAT,		1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_YCBCRCOEFFICIENTS,	(uint16) -1,TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_YCBCRSUBSAMPLING,	2, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_YCBCRPOSITIONING,	1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_REFERENCEBLACKWHITE,	(uint16) -1,TIFF_RATIONAL },
roentgen b75cab
	{ TIFFTAG_EXTRASAMPLES,		(uint16) -1, TIFF_SHORT },
roentgen b75cab
	{ TIFFTAG_SMINSAMPLEVALUE,	1, TIFF_DOUBLE },
roentgen b75cab
	{ TIFFTAG_SMAXSAMPLEVALUE,	1, TIFF_DOUBLE },
roentgen b75cab
	{ TIFFTAG_STONITS,		1, TIFF_DOUBLE },
roentgen b75cab
};
roentgen b75cab
#define	NTAGS	(sizeof (tags) / sizeof (tags[0]))
roentgen b75cab
roentgen b75cab
#define	CopyTag(tag, count, type)	cpTag(in, out, tag, count, type)
roentgen b75cab
roentgen b75cab
/* Functions written by Richard Nolde, with exceptions noted. */
roentgen b75cab
void  process_command_opts (int argc, char *argv[], char *mp, char *mode, uint32 *dirnum,
roentgen b75cab
	                    uint16 *defconfig, uint16 *deffillorder, uint32 *deftilewidth,
roentgen b75cab
                            uint32 *deftilelength, uint32 *defrowsperstrip,
roentgen b75cab
		            struct crop_mask *crop_data, struct pagedef *page, 
roentgen b75cab
                            struct dump_opts *dump,
roentgen b75cab
                            unsigned int     *imagelist, unsigned int   *image_count )
roentgen b75cab
    {
roentgen b75cab
    int   c, good_args = 0;
roentgen b75cab
    char *opt_offset   = NULL;    /* Position in string of value sought */
roentgen b75cab
    char *opt_ptr      = NULL;    /* Pointer to next token in option set */
roentgen b75cab
    char *sep          = NULL;    /* Pointer to a token separator */
roentgen b75cab
    unsigned int  i, j, start, end;
roentgen b75cab
    extern int   optind;
roentgen b75cab
    extern char* optarg;
roentgen b75cab
roentgen b75cab
    *mp++ = 'w';
roentgen b75cab
    *mp = '\0';
roentgen b75cab
    while ((c = getopt(argc, argv,
roentgen b75cab
       "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)
roentgen b75cab
      {
roentgen b75cab
    good_args++;
roentgen b75cab
    switch (c) {
roentgen b75cab
      case 'a': mode[0] = 'a';	/* append to output */
roentgen b75cab
		break;
roentgen b75cab
      case 'c':	if (!processCompressOptions(optarg)) /* compression scheme */
roentgen b75cab
		  {
roentgen b75cab
		  TIFFError ("Unknown compression option", "%s", optarg);
roentgen b75cab
                  TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                  exit (-1);
roentgen b75cab
                  }
roentgen b75cab
		break;
roentgen b75cab
      case 'd':	start = strtoul(optarg, NULL, 0); /* initial IFD offset */
roentgen b75cab
	        if (start == 0)
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError ("","Directory offset must be greater than zero");
roentgen b75cab
		  TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                  exit (-1);
roentgen b75cab
		  }
roentgen b75cab
	        *dirnum = start - 1;
roentgen b75cab
		break;
roentgen b75cab
      case 'e': switch (tolower(optarg[0])) /* image export modes*/
roentgen b75cab
                  {
roentgen b75cab
		  case 'c': crop_data->exp_mode = ONE_FILE_COMPOSITE;
roentgen b75cab
 		            crop_data->img_mode = COMPOSITE_IMAGES;
roentgen b75cab
		            break; /* Composite */
roentgen b75cab
		  case 'd': crop_data->exp_mode = ONE_FILE_SEPARATED;
roentgen b75cab
 		            crop_data->img_mode = SEPARATED_IMAGES;
roentgen b75cab
		            break; /* Divided */
roentgen b75cab
		  case 'i': crop_data->exp_mode = FILE_PER_IMAGE_COMPOSITE;
roentgen b75cab
 		            crop_data->img_mode = COMPOSITE_IMAGES;
roentgen b75cab
		            break; /* Image */
roentgen b75cab
		  case 'm': crop_data->exp_mode = FILE_PER_IMAGE_SEPARATED;
roentgen b75cab
 		            crop_data->img_mode = SEPARATED_IMAGES;
roentgen b75cab
		            break; /* Multiple */
roentgen b75cab
		  case 's': crop_data->exp_mode = FILE_PER_SELECTION;
roentgen b75cab
 		            crop_data->img_mode = SEPARATED_IMAGES;
roentgen b75cab
		            break; /* Sections */
roentgen b75cab
		  default:  TIFFError ("Unknown export mode","%s", optarg);
roentgen b75cab
                            TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                            exit (-1);
roentgen b75cab
                  }
roentgen b75cab
	        break;
roentgen b75cab
      case 'f':	if (streq(optarg, "lsb2msb"))	   /* fill order */
roentgen b75cab
		  *deffillorder = FILLORDER_LSB2MSB;
roentgen b75cab
		else if (streq(optarg, "msb2lsb"))
roentgen b75cab
		  *deffillorder = FILLORDER_MSB2LSB;
roentgen b75cab
		else
roentgen b75cab
		  {
roentgen b75cab
		  TIFFError ("Unknown fill order", "%s", optarg);
roentgen b75cab
                  TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                  exit (-1);
roentgen b75cab
                  }
roentgen b75cab
		break;
roentgen b75cab
      case 'h':	usage();
roentgen b75cab
		break;
roentgen b75cab
      case 'i':	ignore = TRUE;		/* ignore errors */
roentgen b75cab
		break;
roentgen b75cab
      case 'l':	outtiled = TRUE;	 /* tile length */
roentgen b75cab
		*deftilelength = atoi(optarg);
roentgen b75cab
		break;
roentgen b75cab
      case 'p': /* planar configuration */
roentgen b75cab
		if (streq(optarg, "separate"))
roentgen b75cab
		  *defconfig = PLANARCONFIG_SEPARATE;
roentgen b75cab
		else if (streq(optarg, "contig"))
roentgen b75cab
		  *defconfig = PLANARCONFIG_CONTIG;
roentgen b75cab
		else
roentgen b75cab
		  {
roentgen b75cab
		  TIFFError ("Unkown planar configuration", "%s", optarg);
roentgen b75cab
                  TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                  exit (-1);
roentgen b75cab
                  }
roentgen b75cab
		break;
roentgen b75cab
      case 'r':	/* rows/strip */
roentgen b75cab
		*defrowsperstrip = atol(optarg);
roentgen b75cab
		break;
roentgen b75cab
      case 's':	/* generate stripped output */
roentgen b75cab
		outtiled = FALSE;
roentgen b75cab
		break;
roentgen b75cab
      case 't':	/* generate tiled output */
roentgen b75cab
		outtiled = TRUE;
roentgen b75cab
		break;
roentgen b75cab
      case 'v': TIFFError("Library Release", "%s", TIFFGetVersion());
roentgen b75cab
                TIFFError ("Tiffcrop version", "%s, last updated: %s", 
roentgen b75cab
			   tiffcrop_version_id, tiffcrop_rev_date);
roentgen b75cab
 	        TIFFError ("Tiffcp code", "Copyright (c) 1988-1997 Sam Leffler");
roentgen b75cab
		TIFFError ("           ", "Copyright (c) 1991-1997 Silicon Graphics, Inc");
roentgen b75cab
                TIFFError ("Tiffcrop additions", "Copyright (c) 2007-2010 Richard Nolde");
roentgen b75cab
	        exit (0);
roentgen b75cab
		break;
roentgen b75cab
      case 'w':	/* tile width */
roentgen b75cab
		outtiled = TRUE;
roentgen b75cab
		*deftilewidth = atoi(optarg);
roentgen b75cab
		break;
roentgen b75cab
      case 'z': /* regions of an image specified as x1,y1,x2,y2:x3,y3,x4,y4 etc */
roentgen b75cab
	        crop_data->crop_mode |= CROP_REGIONS;
roentgen b75cab
		for (i = 0, opt_ptr = strtok (optarg, ":");
roentgen b75cab
                   ((opt_ptr != NULL) &&  (i < MAX_REGIONS));
roentgen b75cab
                    (opt_ptr = strtok (NULL, ":")), i++)
roentgen b75cab
                    {
roentgen b75cab
		    crop_data->regions++;
roentgen b75cab
                    if (sscanf(opt_ptr, "%lf,%lf,%lf,%lf",
roentgen b75cab
			       &crop_data->corners[i].X1, &crop_data->corners[i].Y1,
roentgen b75cab
			       &crop_data->corners[i].X2, &crop_data->corners[i].Y2) != 4)
roentgen b75cab
                      {
roentgen b75cab
                      TIFFError ("Unable to parse coordinates for region", "%d %s", i, optarg);
roentgen b75cab
		      TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                      exit (-1);
roentgen b75cab
		      }
roentgen b75cab
                    }
roentgen b75cab
                /*  check for remaining elements over MAX_REGIONS */
roentgen b75cab
                if ((opt_ptr != NULL) && (i >= MAX_REGIONS))
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError ("Region list exceeds limit of", "%d regions %s", MAX_REGIONS, optarg);
roentgen b75cab
		  TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                  exit (-1);;
roentgen b75cab
                  }
roentgen b75cab
		break;
roentgen b75cab
      /* options for file open modes */
roentgen b75cab
      case 'B': *mp++ = 'b'; *mp = '\0';
roentgen b75cab
		break;
roentgen b75cab
      case 'L': *mp++ = 'l'; *mp = '\0';
roentgen b75cab
		break;
roentgen b75cab
      case 'M': *mp++ = 'm'; *mp = '\0';
roentgen b75cab
		break;
roentgen b75cab
      case 'C': *mp++ = 'c'; *mp = '\0';
roentgen b75cab
		break;
roentgen b75cab
      /* options for Debugging / data dump */
roentgen b75cab
      case 'D': for (i = 0, opt_ptr = strtok (optarg, ",");
roentgen b75cab
                    (opt_ptr != NULL);
roentgen b75cab
                    (opt_ptr = strtok (NULL, ",")), i++)
roentgen b75cab
                    {
roentgen b75cab
		    opt_offset = strpbrk(opt_ptr, ":=");
roentgen b75cab
                    if (opt_offset == NULL)
roentgen b75cab
                      {
roentgen b75cab
                      TIFFError("Invalid dump option", "%s", optarg);
roentgen b75cab
                      TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                      exit (-1);
roentgen b75cab
		      }
roentgen b75cab
                      
roentgen b75cab
                    *opt_offset = '\0';
roentgen b75cab
                    /* convert option to lowercase */
roentgen b75cab
                    end = strlen (opt_ptr);
roentgen b75cab
                    for (i = 0; i < end; i++)
roentgen b75cab
                      *(opt_ptr + i) = tolower(*(opt_ptr + i));
roentgen b75cab
                    /* Look for dump format specification */
roentgen b75cab
                    if (strncmp(opt_ptr, "for", 3) == 0)
roentgen b75cab
                      {
roentgen b75cab
		      /* convert value to lowercase */
roentgen b75cab
                      end = strlen (opt_offset + 1);
roentgen b75cab
                      for (i = 1; i <= end; i++)
roentgen b75cab
                        *(opt_offset + i) = tolower(*(opt_offset + i));
roentgen b75cab
                      /* check dump format value */
roentgen b75cab
		      if (strncmp (opt_offset + 1, "txt", 3) == 0)
roentgen b75cab
                        {
roentgen b75cab
                        dump->format = DUMP_TEXT;
roentgen b75cab
                        strcpy (dump->mode, "w");
roentgen b75cab
                        }
roentgen b75cab
                      else
roentgen b75cab
                        {
roentgen b75cab
		        if (strncmp(opt_offset + 1, "raw", 3) == 0)
roentgen b75cab
                          {
roentgen b75cab
                          dump->format = DUMP_RAW;
roentgen b75cab
                          strcpy (dump->mode, "wb");
roentgen b75cab
                          }
roentgen b75cab
                        else
roentgen b75cab
                          {
roentgen b75cab
                          TIFFError("parse_command_opts", "Unknown dump format %s", opt_offset + 1);
roentgen b75cab
                          TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                          exit (-1);
roentgen b75cab
		          }
roentgen b75cab
			}
roentgen b75cab
                      }
roentgen b75cab
		    else
roentgen b75cab
                      { /* Look for dump level specification */
roentgen b75cab
                      if (strncmp (opt_ptr, "lev", 3) == 0)
roentgen b75cab
                        dump->level = atoi(opt_offset + 1);
roentgen b75cab
                        /* Look for input data dump file name */
roentgen b75cab
                      if (strncmp (opt_ptr, "in", 2) == 0)
roentgen b75cab
		        {
roentgen b75cab
                        strncpy (dump->infilename, opt_offset + 1, PATH_MAX - 20);
roentgen b75cab
                        dump->infilename[PATH_MAX - 20] = '\0';
roentgen b75cab
                        }
roentgen b75cab
                        /* Look for output data dump file name */
roentgen b75cab
                      if (strncmp (opt_ptr, "out", 3) == 0)
roentgen b75cab
			{
roentgen b75cab
                        strncpy (dump->outfilename, opt_offset + 1, PATH_MAX - 20);
roentgen b75cab
                        dump->outfilename[PATH_MAX - 20] = '\0';
roentgen b75cab
                        }
roentgen b75cab
                      if (strncmp (opt_ptr, "deb", 3) == 0)
roentgen b75cab
			dump->debug = atoi(opt_offset + 1);
roentgen b75cab
		      }
roentgen b75cab
                    }
roentgen b75cab
	        if ((strlen(dump->infilename)) || (strlen(dump->outfilename)))
roentgen b75cab
                  {
roentgen b75cab
		  if (dump->level == 1)
roentgen b75cab
                    TIFFError("","Defaulting to dump level 1, no data.");
roentgen b75cab
	          if (dump->format == DUMP_NONE)
roentgen b75cab
                    {
roentgen b75cab
		    TIFFError("", "You must specify a dump format for dump files");
roentgen b75cab
		    TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
		    exit (-1);
roentgen b75cab
		    }
roentgen b75cab
                  }
roentgen b75cab
	        break;
roentgen b75cab
roentgen b75cab
      /* image manipulation routine options */
roentgen b75cab
      case 'm': /* margins to exclude from selection, uppercase M was already used */
roentgen b75cab
		/* order of values must be TOP, LEFT, BOTTOM, RIGHT */
roentgen b75cab
		crop_data->crop_mode |= CROP_MARGINS;
roentgen b75cab
                for (i = 0, opt_ptr = strtok (optarg, ",:");
roentgen b75cab
                    ((opt_ptr != NULL) &&  (i < 4));
roentgen b75cab
                     (opt_ptr = strtok (NULL, ",:")), i++)
roentgen b75cab
                    {
roentgen b75cab
		    crop_data->margins[i] = atof(opt_ptr);
roentgen b75cab
                    }
roentgen b75cab
		break;
roentgen b75cab
      case 'E':	/* edge reference */
roentgen b75cab
		switch (tolower(optarg[0]))
roentgen b75cab
                  {
roentgen b75cab
		  case 't': crop_data->edge_ref = EDGE_TOP;
roentgen b75cab
                            break;
roentgen b75cab
                  case 'b': crop_data->edge_ref = EDGE_BOTTOM;
roentgen b75cab
                             break;
roentgen b75cab
                  case 'l': crop_data->edge_ref = EDGE_LEFT;
roentgen b75cab
                            break;
roentgen b75cab
                  case 'r': crop_data->edge_ref = EDGE_RIGHT;
roentgen b75cab
                            break;
roentgen b75cab
		  default:  TIFFError ("Edge reference must be top, bottom, left, or right", "%s", optarg);
roentgen b75cab
			    TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                            exit (-1);
roentgen b75cab
		  }
roentgen b75cab
		break;
roentgen b75cab
      case 'F': /* flip eg mirror image or cropped segment, M was already used */
roentgen b75cab
		crop_data->crop_mode |= CROP_MIRROR;
roentgen b75cab
		switch (tolower(optarg[0]))
roentgen b75cab
                  {
roentgen b75cab
		  case  'h': crop_data->mirror = MIRROR_HORIZ;
roentgen b75cab
                             break;
roentgen b75cab
                  case  'v': crop_data->mirror = MIRROR_VERT;
roentgen b75cab
                             break;
roentgen b75cab
                  case  'b': crop_data->mirror = MIRROR_BOTH;
roentgen b75cab
                             break;
roentgen b75cab
		  default:   TIFFError ("Flip mode must be horiz, vert, or both", "%s", optarg);
roentgen b75cab
			     TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                             exit (-1);
roentgen b75cab
		  }
roentgen b75cab
		break;
roentgen b75cab
      case 'H': /* set horizontal resolution to new value */
roentgen b75cab
		page->hres = atof (optarg);
roentgen b75cab
                page->mode |= PAGE_MODE_RESOLUTION;
roentgen b75cab
		break;
roentgen b75cab
      case 'I': /* invert the color space, eg black to white */
roentgen b75cab
		crop_data->crop_mode |= CROP_INVERT;
roentgen b75cab
                /* The PHOTOMETIC_INTERPRETATION tag may be updated */
roentgen b75cab
                if (streq(optarg, "black"))
roentgen b75cab
                  {
roentgen b75cab
		  crop_data->photometric = PHOTOMETRIC_MINISBLACK;
roentgen b75cab
		  continue;
roentgen b75cab
                  }
roentgen b75cab
                if (streq(optarg, "white"))
roentgen b75cab
                  {
roentgen b75cab
		  crop_data->photometric = PHOTOMETRIC_MINISWHITE;
roentgen b75cab
                  continue;
roentgen b75cab
                  }
roentgen b75cab
                if (streq(optarg, "data")) 
roentgen b75cab
                  {
roentgen b75cab
		  crop_data->photometric = INVERT_DATA_ONLY;
roentgen b75cab
                  continue;
roentgen b75cab
                  }
roentgen b75cab
                if (streq(optarg, "both"))
roentgen b75cab
                  {
roentgen b75cab
		  crop_data->photometric = INVERT_DATA_AND_TAG;
roentgen b75cab
                  continue;
roentgen b75cab
                  }
roentgen b75cab
roentgen b75cab
		TIFFError("Missing or unknown option for inverting PHOTOMETRIC_INTERPRETATION", "%s", optarg);
roentgen b75cab
		TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                exit (-1);
roentgen b75cab
		break;
roentgen b75cab
      case 'J': /* horizontal margin for sectioned ouput pages */ 
roentgen b75cab
		page->hmargin = atof(optarg);
roentgen b75cab
                page->mode |= PAGE_MODE_MARGINS;
roentgen b75cab
		break;
roentgen b75cab
      case 'K': /* vertical margin for sectioned ouput pages*/ 
roentgen b75cab
                page->vmargin = atof(optarg);
roentgen b75cab
                page->mode |= PAGE_MODE_MARGINS;
roentgen b75cab
		break;
roentgen b75cab
      case 'N':	/* list of images to process */
roentgen b75cab
                for (i = 0, opt_ptr = strtok (optarg, ",");
roentgen b75cab
                    ((opt_ptr != NULL) &&  (i < MAX_IMAGES));
roentgen b75cab
                     (opt_ptr = strtok (NULL, ",")))
roentgen b75cab
                     { /* We do not know how many images are in file yet 
roentgen b75cab
			* so we build a list to include the maximum allowed
roentgen b75cab
                        * and follow it until we hit the end of the file.
roentgen b75cab
                        * Image count is not accurate for odd, even, last
roentgen b75cab
                        * so page numbers won't be valid either.
roentgen b75cab
                        */
roentgen b75cab
		     if (streq(opt_ptr, "odd"))
roentgen b75cab
                       {
roentgen b75cab
		       for (j = 1; j <= MAX_IMAGES; j += 2)
roentgen b75cab
			 imagelist[i++] = j;
roentgen b75cab
                       *image_count = (MAX_IMAGES - 1) / 2;
roentgen b75cab
                       break;
roentgen b75cab
		       }
roentgen b75cab
		     else
roentgen b75cab
                       {
roentgen b75cab
		       if (streq(opt_ptr, "even"))
roentgen b75cab
                         {
roentgen b75cab
			 for (j = 2; j <= MAX_IMAGES; j += 2)
roentgen b75cab
			   imagelist[i++] = j;
roentgen b75cab
                         *image_count = MAX_IMAGES / 2;
roentgen b75cab
                         break;
roentgen b75cab
			 }
roentgen b75cab
		       else
roentgen b75cab
                         {
roentgen b75cab
			 if (streq(opt_ptr, "last"))
roentgen b75cab
			   imagelist[i++] = MAX_IMAGES;
roentgen b75cab
			 else  /* single value between commas */
roentgen b75cab
			   {
roentgen b75cab
			   sep = strpbrk(opt_ptr, ":-");
roentgen b75cab
			   if (!sep)
roentgen b75cab
			     imagelist[i++] = atoi(opt_ptr);
roentgen b75cab
                           else
roentgen b75cab
                             {
roentgen b75cab
			     *sep = '\0';
roentgen b75cab
                             start = atoi (opt_ptr);
roentgen b75cab
                             if (!strcmp((sep + 1), "last"))
roentgen b75cab
			       end = MAX_IMAGES;
roentgen b75cab
                             else
roentgen b75cab
                               end = atoi (sep + 1);
roentgen b75cab
                             for (j = start; j <= end && j - start + i < MAX_IMAGES; j++)
roentgen b75cab
			       imagelist[i++] = j;
roentgen b75cab
			     }
roentgen b75cab
			   }
roentgen b75cab
			 }
roentgen b75cab
		      }
roentgen b75cab
		    }
roentgen b75cab
                *image_count = i;
roentgen b75cab
		break;
roentgen b75cab
      case 'O': /* page orientation */ 
roentgen b75cab
		switch (tolower(optarg[0]))
roentgen b75cab
                  {
roentgen b75cab
		  case  'a': page->orient = ORIENTATION_AUTO;
roentgen b75cab
                             break;
roentgen b75cab
		  case  'p': page->orient = ORIENTATION_PORTRAIT;
roentgen b75cab
                             break;
roentgen b75cab
		  case  'l': page->orient = ORIENTATION_LANDSCAPE;
roentgen b75cab
                             break;
roentgen b75cab
		  default:  TIFFError ("Orientation must be portrait, landscape, or auto.", "%s", optarg);
roentgen b75cab
			    TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                            exit (-1);
roentgen b75cab
		  }
roentgen b75cab
		break;
roentgen b75cab
      case 'P': /* page size selection */ 
roentgen b75cab
	        if (sscanf(optarg, "%lfx%lf", &page->width, &page->length) == 2)
roentgen b75cab
                  {
roentgen b75cab
                  strcpy (page->name, "Custom"); 
roentgen b75cab
                  page->mode |= PAGE_MODE_PAPERSIZE;
roentgen b75cab
                  break;
roentgen b75cab
                  }
roentgen b75cab
                if (get_page_geometry (optarg, page))
roentgen b75cab
                  {
roentgen b75cab
		  if (!strcmp(optarg, "list"))
roentgen b75cab
                    {
roentgen b75cab
		    TIFFError("", "Name            Width   Length (in inches)");
roentgen b75cab
                    for (i = 0; i < MAX_PAPERNAMES - 1; i++)
roentgen b75cab
                      TIFFError ("", "%-15.15s %5.2f   %5.2f", 
roentgen b75cab
			       PaperTable[i].name, PaperTable[i].width, 
roentgen b75cab
                               PaperTable[i].length);
roentgen b75cab
		    exit (-1);                   
roentgen b75cab
                    }
roentgen b75cab
     
roentgen b75cab
		  TIFFError ("Invalid paper size", "%s", optarg);
roentgen b75cab
                  TIFFError ("", "Select one of:");
roentgen b75cab
		  TIFFError("", "Name            Width   Length (in inches)");
roentgen b75cab
                  for (i = 0; i < MAX_PAPERNAMES - 1; i++)
roentgen b75cab
                    TIFFError ("", "%-15.15s %5.2f   %5.2f", 
roentgen b75cab
			       PaperTable[i].name, PaperTable[i].width, 
roentgen b75cab
                               PaperTable[i].length);
roentgen b75cab
		  exit (-1);
roentgen b75cab
		  }
roentgen b75cab
		else
roentgen b75cab
                  {
roentgen b75cab
                  page->mode |= PAGE_MODE_PAPERSIZE;
roentgen b75cab
		  }
roentgen b75cab
		break;
roentgen b75cab
      case 'R': /* rotate image or cropped segment */
roentgen b75cab
		crop_data->crop_mode |= CROP_ROTATE;
roentgen b75cab
		switch (strtoul(optarg, NULL, 0))
roentgen b75cab
                  {
roentgen b75cab
		  case  90:  crop_data->rotation = (uint16)90;
roentgen b75cab
                             break;
roentgen b75cab
                  case  180: crop_data->rotation = (uint16)180;
roentgen b75cab
                             break;
roentgen b75cab
                  case  270: crop_data->rotation = (uint16)270;
roentgen b75cab
                             break;
roentgen b75cab
		  default:   TIFFError ("Rotation must be 90, 180, or 270 degrees clockwise", "%s", optarg);
roentgen b75cab
			     TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                             exit (-1);
roentgen b75cab
		  }
roentgen b75cab
		break;
roentgen b75cab
      case 'S':	/* subdivide into Cols:Rows sections, eg 3:2 would be 3 across and 2 down */
roentgen b75cab
		sep = strpbrk(optarg, ",:");
roentgen b75cab
		if (sep)
roentgen b75cab
                  {
roentgen b75cab
                  *sep = '\0';
roentgen b75cab
                  page->cols = atoi(optarg);
roentgen b75cab
                  page->rows = atoi(sep +1);
roentgen b75cab
		  }
roentgen b75cab
                else
roentgen b75cab
                  {
roentgen b75cab
                  page->cols = atoi(optarg);
roentgen b75cab
                  page->rows = atoi(optarg);
roentgen b75cab
		  }
roentgen b75cab
                if ((page->cols * page->rows) > MAX_SECTIONS)
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError ("Limit for subdivisions, ie rows x columns, exceeded", "%d", MAX_SECTIONS);
roentgen b75cab
		  exit (-1);
roentgen b75cab
                  }
roentgen b75cab
                page->mode |= PAGE_MODE_ROWSCOLS;
roentgen b75cab
		break;
roentgen b75cab
      case 'U':	/* units for measurements and offsets */
roentgen b75cab
		if (streq(optarg, "in"))
roentgen b75cab
                  {
roentgen b75cab
		  crop_data->res_unit = RESUNIT_INCH;
roentgen b75cab
		  page->res_unit = RESUNIT_INCH;
roentgen b75cab
		  }
roentgen b75cab
		else if (streq(optarg, "cm"))
roentgen b75cab
		  {
roentgen b75cab
		  crop_data->res_unit = RESUNIT_CENTIMETER;
roentgen b75cab
		  page->res_unit = RESUNIT_CENTIMETER;
roentgen b75cab
		  }
roentgen b75cab
		else if (streq(optarg, "px"))
roentgen b75cab
		  {
roentgen b75cab
		  crop_data->res_unit = RESUNIT_NONE;
roentgen b75cab
		  page->res_unit = RESUNIT_NONE;
roentgen b75cab
		  }
roentgen b75cab
		else
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError ("Illegal unit of measure","%s", optarg);
roentgen b75cab
		  TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                  exit (-1);
roentgen b75cab
		  }
roentgen b75cab
		break;
roentgen b75cab
      case 'V': /* set vertical resolution to new value */
roentgen b75cab
		page->vres = atof (optarg);
roentgen b75cab
                page->mode |= PAGE_MODE_RESOLUTION;
roentgen b75cab
		break;
roentgen b75cab
      case 'X':	/* selection width */
roentgen b75cab
		crop_data->crop_mode |= CROP_WIDTH;
roentgen b75cab
		crop_data->width = atof(optarg);
roentgen b75cab
		break;
roentgen b75cab
      case 'Y':	/* selection length */
roentgen b75cab
		crop_data->crop_mode |= CROP_LENGTH;
roentgen b75cab
		crop_data->length = atof(optarg);
roentgen b75cab
		break;
roentgen b75cab
      case 'Z': /* zones of an image X:Y read as zone X of Y */
roentgen b75cab
		crop_data->crop_mode |= CROP_ZONES;
roentgen b75cab
		for (i = 0, opt_ptr = strtok (optarg, ",");
roentgen b75cab
                   ((opt_ptr != NULL) &&  (i < MAX_REGIONS));
roentgen b75cab
                    (opt_ptr = strtok (NULL, ",")), i++)
roentgen b75cab
                    {
roentgen b75cab
		    crop_data->zones++;
roentgen b75cab
		    opt_offset = strchr(opt_ptr, ':');
roentgen b75cab
                    *opt_offset = '\0';
roentgen b75cab
                    crop_data->zonelist[i].position = atoi(opt_ptr);
roentgen b75cab
                    crop_data->zonelist[i].total    = atoi(opt_offset + 1);
roentgen b75cab
                    }
roentgen b75cab
                /*  check for remaining elements over MAX_REGIONS */
roentgen b75cab
                if ((opt_ptr != NULL) && (i >= MAX_REGIONS))
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError("Zone list exceeds region limit", "%d",  MAX_REGIONS);
roentgen b75cab
		  exit (-1);
roentgen b75cab
                  }
roentgen b75cab
		break;
roentgen b75cab
    case '?':	TIFFError ("For valid options type", "tiffcrop -h");
roentgen b75cab
                exit (-1);
roentgen b75cab
		/*NOTREACHED*/
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  }  /* end process_command_opts */
roentgen b75cab
roentgen b75cab
/* Start a new output file if one has not been previously opened or
roentgen b75cab
 * autoindex is set to non-zero. Update page and file counters
roentgen b75cab
 * so TIFFTAG PAGENUM will be correct in image.
roentgen b75cab
 */
roentgen b75cab
static int 
roentgen b75cab
update_output_file (TIFF **tiffout, char *mode, int autoindex,
roentgen b75cab
                    char *outname, unsigned int *page)
roentgen b75cab
  {
roentgen b75cab
  static int findex = 0;    /* file sequence indicator */
roentgen b75cab
  char  *sep;
roentgen b75cab
  char   filenum[16];
roentgen b75cab
  char   export_ext[16];
roentgen b75cab
  char   exportname[PATH_MAX];
roentgen b75cab
roentgen b75cab
  if (autoindex && (*tiffout != NULL))
roentgen b75cab
    {   
roentgen b75cab
    /* Close any export file that was previously opened */
roentgen b75cab
    TIFFClose (*tiffout);
roentgen b75cab
    *tiffout = NULL;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  strcpy (export_ext, ".tiff");
roentgen b75cab
  memset (exportname, '\0', PATH_MAX);
roentgen b75cab
roentgen b75cab
  /* Leave room for page number portion of the new filename */
roentgen b75cab
  strncpy (exportname, outname, PATH_MAX - 16);
roentgen b75cab
  if (*tiffout == NULL)   /* This is a new export file */
roentgen b75cab
    {
roentgen b75cab
    if (autoindex)
roentgen b75cab
      { /* create a new filename for each export */
roentgen b75cab
      findex++;
roentgen b75cab
      if ((sep = strstr(exportname, ".tif")) || (sep = strstr(exportname, ".TIF")))
roentgen b75cab
        {
roentgen b75cab
        strncpy (export_ext, sep, 5);
roentgen b75cab
        *sep = '\0';
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        strncpy (export_ext, ".tiff", 5);
roentgen b75cab
      export_ext[5] = '\0';
roentgen b75cab
roentgen b75cab
      /* MAX_EXPORT_PAGES limited to 6 digits to prevent string overflow of pathname */
roentgen b75cab
      if (findex > MAX_EXPORT_PAGES)
roentgen b75cab
	{
roentgen b75cab
	TIFFError("update_output_file", "Maximum of %d pages per file exceeded", MAX_EXPORT_PAGES);
roentgen b75cab
        return 1;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      sprintf (filenum, "-%03d%s", findex, export_ext);
roentgen b75cab
      filenum[14] = '\0';
roentgen b75cab
      strncat (exportname, filenum, 15);
roentgen b75cab
      }
roentgen b75cab
    exportname[PATH_MAX - 1] = '\0';
roentgen b75cab
roentgen b75cab
    *tiffout = TIFFOpen(exportname, mode);
roentgen b75cab
    if (*tiffout == NULL)
roentgen b75cab
      {
roentgen b75cab
      TIFFError("update_output_file", "Unable to open output file %s", exportname);
roentgen b75cab
      return 1;
roentgen b75cab
      }
roentgen b75cab
    *page = 0; 
roentgen b75cab
roentgen b75cab
    return 0;
roentgen b75cab
    }
roentgen b75cab
  else 
roentgen b75cab
    (*page)++;
roentgen b75cab
roentgen b75cab
  return 0;
roentgen b75cab
  } /* end update_output_file */
roentgen b75cab
roentgen b75cab
roentgen b75cab
int
roentgen b75cab
main(int argc, char* argv[])
roentgen b75cab
  {
roentgen b75cab
  extern int optind;
roentgen b75cab
  uint16 defconfig = (uint16) -1;
roentgen b75cab
  uint16 deffillorder = 0;
roentgen b75cab
  uint32 deftilewidth = (uint32) 0;
roentgen b75cab
  uint32 deftilelength = (uint32) 0;
roentgen b75cab
  uint32 defrowsperstrip = (uint32) 0;
roentgen b75cab
  uint32 dirnum = 0;
roentgen b75cab
roentgen b75cab
  TIFF *in = NULL;
roentgen b75cab
  TIFF *out = NULL;
roentgen b75cab
  char  mode[10];
roentgen b75cab
  char *mp = mode;
roentgen b75cab
roentgen b75cab
  /** RJN additions **/
roentgen b75cab
  struct image_data image;     /* Image parameters for one image */
roentgen b75cab
  struct crop_mask  crop;      /* Cropping parameters for all images */
roentgen b75cab
  struct pagedef    page;      /* Page definition for output pages */
roentgen b75cab
  struct pageseg    sections[MAX_SECTIONS];  /* Sections of one output page */
roentgen b75cab
  struct buffinfo   seg_buffs[MAX_SECTIONS]; /* Segment buffer sizes and pointers */
roentgen b75cab
  struct dump_opts  dump;                  /* Data dump options */
roentgen b75cab
  unsigned char *read_buff    = NULL;      /* Input image data buffer */
roentgen b75cab
  unsigned char *crop_buff    = NULL;      /* Crop area buffer */
roentgen b75cab
  unsigned char *sect_buff    = NULL;      /* Image section buffer */
roentgen b75cab
  unsigned char *sect_src     = NULL;      /* Image section buffer pointer */
roentgen b75cab
  unsigned int  imagelist[MAX_IMAGES + 1]; /* individually specified images */
roentgen b75cab
  unsigned int  image_count  = 0;
roentgen b75cab
  unsigned int  dump_images  = 0;
roentgen b75cab
  unsigned int  next_image   = 0;
roentgen b75cab
  unsigned int  next_page    = 0;
roentgen b75cab
  unsigned int  total_pages  = 0;
roentgen b75cab
  unsigned int  total_images = 0;
roentgen b75cab
  unsigned int  end_of_input = FALSE;
roentgen b75cab
  int    seg, length;
roentgen b75cab
  char   temp_filename[PATH_MAX + 1];
roentgen b75cab
roentgen b75cab
  little_endian = *((unsigned char *)&little_endian) & '1';
roentgen b75cab
roentgen b75cab
  initImageData(&image);
roentgen b75cab
  initCropMasks(&crop);
roentgen b75cab
  initPageSetup(&page, sections, seg_buffs);
roentgen b75cab
  initDumpOptions(&dump);
roentgen b75cab
roentgen b75cab
  process_command_opts (argc, argv, mp, mode, &dirnum, &defconfig, 
roentgen b75cab
                        &deffillorder, &deftilewidth, &deftilelength, &defrowsperstrip,
roentgen b75cab
	                &crop, &page, &dump, imagelist, &image_count);
roentgen b75cab
roentgen b75cab
  if (argc - optind < 2)
roentgen b75cab
    usage();
roentgen b75cab
roentgen b75cab
  if ((argc - optind) == 2)
roentgen b75cab
    pageNum = -1;
roentgen b75cab
  else
roentgen b75cab
    total_images = 0;
roentgen b75cab
  /* read multiple input files and write to output file(s) */
roentgen b75cab
  while (optind < argc - 1)
roentgen b75cab
    {
roentgen b75cab
    in = TIFFOpen (argv[optind], "r");
roentgen b75cab
    if (in == NULL)
roentgen b75cab
      return (-3);
roentgen b75cab
roentgen b75cab
    /* If only one input file is specified, we can use directory count */
roentgen b75cab
    total_images = TIFFNumberOfDirectories(in); 
roentgen b75cab
    if (image_count == 0)
roentgen b75cab
      {
roentgen b75cab
      dirnum = 0;
roentgen b75cab
      total_pages = total_images; /* Only valid with single input file */
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      dirnum = (tdir_t)(imagelist[next_image] - 1);
roentgen b75cab
      next_image++;
roentgen b75cab
roentgen b75cab
      /* Total pages only valid for enumerated list of pages not derived
roentgen b75cab
       * using odd, even, or last keywords.
roentgen b75cab
       */
roentgen b75cab
      if (image_count >  total_images)
roentgen b75cab
	image_count = total_images;
roentgen b75cab
      
roentgen b75cab
      total_pages = image_count;
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    /* MAX_IMAGES is used for special case "last" in selection list */
roentgen b75cab
    if (dirnum == (MAX_IMAGES - 1))
roentgen b75cab
      dirnum = total_images - 1;
roentgen b75cab
roentgen b75cab
    if (dirnum > (total_images))
roentgen b75cab
      {
roentgen b75cab
      TIFFError (TIFFFileName(in), 
roentgen b75cab
      "Invalid image number %d, File contains only %d images", 
roentgen b75cab
		 (int)dirnum + 1, total_images);
roentgen b75cab
      if (out != NULL)
roentgen b75cab
        (void) TIFFClose(out);
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if (dirnum != 0 && !TIFFSetDirectory(in, (tdir_t)dirnum))
roentgen b75cab
      {
roentgen b75cab
      TIFFError(TIFFFileName(in),"Error, setting subdirectory at %d", dirnum);
roentgen b75cab
      if (out != NULL)
roentgen b75cab
        (void) TIFFClose(out);
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    end_of_input = FALSE;
roentgen b75cab
    while (end_of_input == FALSE)
roentgen b75cab
      {
roentgen b75cab
      config = defconfig;
roentgen b75cab
      compression = defcompression;
roentgen b75cab
      predictor = defpredictor;
roentgen b75cab
      fillorder = deffillorder;
roentgen b75cab
      rowsperstrip = defrowsperstrip;
roentgen b75cab
      tilewidth = deftilewidth;
roentgen b75cab
      tilelength = deftilelength;
roentgen b75cab
      g3opts = defg3opts;
roentgen b75cab
roentgen b75cab
      if (dump.format != DUMP_NONE)
roentgen b75cab
        {
roentgen b75cab
        /* manage input and/or output dump files here */
roentgen b75cab
	dump_images++;
roentgen b75cab
        length = strlen(dump.infilename);
roentgen b75cab
        if (length > 0)
roentgen b75cab
          {
roentgen b75cab
          if (dump.infile != NULL)
roentgen b75cab
            fclose (dump.infile);
roentgen b75cab
roentgen b75cab
          /* dump.infilename is guaranteed to be NUL termimated and have 20 bytes 
roentgen b75cab
             fewer than PATH_MAX */ 
roentgen b75cab
          memset (temp_filename, '\0', PATH_MAX + 1);              
roentgen b75cab
          sprintf (temp_filename, "%s-read-%03d.%s", dump.infilename, dump_images,
roentgen b75cab
                  (dump.format == DUMP_TEXT) ? "txt" : "raw");
roentgen b75cab
          if ((dump.infile = fopen(temp_filename, dump.mode)) == NULL)
roentgen b75cab
            {
roentgen b75cab
	    TIFFError ("Unable to open dump file for writing", "%s", temp_filename);
roentgen b75cab
	    exit (-1);
roentgen b75cab
            }
roentgen b75cab
          dump_info(dump.infile, dump.format, "Reading image","%d from %s", 
roentgen b75cab
                    dump_images, TIFFFileName(in));
roentgen b75cab
          } 
roentgen b75cab
        length = strlen(dump.outfilename);
roentgen b75cab
        if (length > 0)
roentgen b75cab
          {
roentgen b75cab
          if (dump.outfile != NULL)
roentgen b75cab
            fclose (dump.outfile);
roentgen b75cab
roentgen b75cab
          /* dump.outfilename is guaranteed to be NUL termimated and have 20 bytes 
roentgen b75cab
             fewer than PATH_MAX */ 
roentgen b75cab
          memset (temp_filename, '\0', PATH_MAX + 1);              
roentgen b75cab
          sprintf (temp_filename, "%s-write-%03d.%s", dump.outfilename, dump_images,
roentgen b75cab
                  (dump.format == DUMP_TEXT) ? "txt" : "raw");
roentgen b75cab
          if ((dump.outfile = fopen(temp_filename, dump.mode)) == NULL)
roentgen b75cab
            {
roentgen b75cab
	      TIFFError ("Unable to open dump file for writing", "%s", temp_filename);
roentgen b75cab
	    exit (-1);
roentgen b75cab
            }
roentgen b75cab
          dump_info(dump.outfile, dump.format, "Writing image","%d from %s", 
roentgen b75cab
                    dump_images, TIFFFileName(in));
roentgen b75cab
          } 
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (dump.debug)
roentgen b75cab
         TIFFError("main", "Reading image %4d of %4d total pages.", dirnum + 1, total_pages);
roentgen b75cab
roentgen b75cab
      if (loadImage(in, &image, &dump, &read_buff))
roentgen b75cab
        {
roentgen b75cab
        TIFFError("main", "Unable to load source image");
roentgen b75cab
        exit (-1);
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      /* Correct the image orientation if it was not ORIENTATION_TOPLEFT.
roentgen b75cab
       */
roentgen b75cab
      if (image.adjustments != 0)
roentgen b75cab
        {
roentgen b75cab
	if (correct_orientation(&image, &read_buff))
roentgen b75cab
	    TIFFError("main", "Unable to correct image orientation");
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (getCropOffsets(&image, &crop, &dump))
roentgen b75cab
        {
roentgen b75cab
        TIFFError("main", "Unable to define crop regions");
roentgen b75cab
        exit (-1);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
      if (crop.selections > 0)
roentgen b75cab
        {
roentgen b75cab
        if (processCropSelections(&image, &crop, &read_buff, seg_buffs))
roentgen b75cab
          {
roentgen b75cab
          TIFFError("main", "Unable to process image selections");
roentgen b75cab
          exit (-1);
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      else  /* Single image segment without zones or regions */
roentgen b75cab
        {
roentgen b75cab
        if (createCroppedImage(&image, &crop, &read_buff, &crop_buff))
roentgen b75cab
          {
roentgen b75cab
          TIFFError("main", "Unable to create output image");
roentgen b75cab
          exit (-1);
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      if (page.mode == PAGE_MODE_NONE)
roentgen b75cab
        {  /* Whole image or sections not based on output page size */
roentgen b75cab
        if (crop.selections > 0)
roentgen b75cab
          {
roentgen b75cab
	  writeSelections(in, &out, &crop, &image, &dump, seg_buffs,
roentgen b75cab
                          mp, argv[argc - 1], &next_page, total_pages);
roentgen b75cab
          }
roentgen b75cab
	else  /* One file all images and sections */
roentgen b75cab
          {
roentgen b75cab
	  if (update_output_file (&out, mp, crop.exp_mode, argv[argc - 1],
roentgen b75cab
                                  &next_page))
roentgen b75cab
             exit (1);
roentgen b75cab
          if (writeCroppedImage(in, out, &image, &dump,crop.combined_width, 
roentgen b75cab
                                crop.combined_length, crop_buff, next_page, total_pages))
roentgen b75cab
            {
roentgen b75cab
             TIFFError("main", "Unable to write new image");
roentgen b75cab
             exit (-1);
roentgen b75cab
	    }
roentgen b75cab
          }
roentgen b75cab
	}
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	/* If we used a crop buffer, our data is there, otherwise it is
roentgen b75cab
         * in the read_buffer
roentgen b75cab
         */
roentgen b75cab
	if (crop_buff != NULL)  
roentgen b75cab
	  sect_src = crop_buff;
roentgen b75cab
        else
roentgen b75cab
          sect_src = read_buff;
roentgen b75cab
        /* Break input image into pages or rows and columns */
roentgen b75cab
        if (computeOutputPixelOffsets(&crop, &image, &page, sections, &dump))
roentgen b75cab
          {
roentgen b75cab
          TIFFError("main", "Unable to compute output section data");
roentgen b75cab
          exit (-1);
roentgen b75cab
	  }
roentgen b75cab
        /* If there are multiple files on the command line, the final one is assumed 
roentgen b75cab
         * to be the output filename into which the images are written.
roentgen b75cab
         */
roentgen b75cab
	if (update_output_file (&out, mp, crop.exp_mode, argv[argc - 1], &next_page))
roentgen b75cab
          exit (1);
roentgen b75cab
roentgen b75cab
	if (writeImageSections(in, out, &image, &page, sections, &dump, sect_src, &sect_buff))
roentgen b75cab
          {
roentgen b75cab
          TIFFError("main", "Unable to write image sections");
roentgen b75cab
          exit (-1);
roentgen b75cab
	  }
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      /* No image list specified, just read the next image */
roentgen b75cab
      if (image_count == 0)
roentgen b75cab
        dirnum++;
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	dirnum = (tdir_t)(imagelist[next_image] - 1);
roentgen b75cab
        next_image++;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (dirnum == MAX_IMAGES - 1)
roentgen b75cab
        dirnum = TIFFNumberOfDirectories(in) - 1;
roentgen b75cab
roentgen b75cab
      if (!TIFFSetDirectory(in, (tdir_t)dirnum))
roentgen b75cab
        end_of_input = TRUE;
roentgen b75cab
      }
roentgen b75cab
    TIFFClose(in);
roentgen b75cab
    optind++;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* If we did not use the read buffer as the crop buffer */
roentgen b75cab
  if (read_buff)
roentgen b75cab
    _TIFFfree(read_buff);
roentgen b75cab
roentgen b75cab
  if (crop_buff)
roentgen b75cab
    _TIFFfree(crop_buff);
roentgen b75cab
roentgen b75cab
  if (sect_buff)
roentgen b75cab
    _TIFFfree(sect_buff);
roentgen b75cab
roentgen b75cab
   /* Clean up any segment buffers used for zones or regions */
roentgen b75cab
  for (seg = 0; seg < crop.selections; seg++)
roentgen b75cab
    _TIFFfree (seg_buffs[seg].buffer);
roentgen b75cab
roentgen b75cab
  if (dump.format != DUMP_NONE)
roentgen b75cab
    {
roentgen b75cab
    if (dump.infile != NULL)
roentgen b75cab
     fclose (dump.infile);
roentgen b75cab
roentgen b75cab
    if (dump.outfile != NULL)
roentgen b75cab
      {
roentgen b75cab
      dump_info (dump.outfile, dump.format, "", "Completed run for %s", TIFFFileName(out));
roentgen b75cab
      fclose (dump.outfile);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  TIFFClose(out);
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end main */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Debugging functions */
roentgen b75cab
static int dump_data (FILE *dumpfile, int format, char *dump_tag, unsigned char *data, uint32 count)
roentgen b75cab
  {
roentgen b75cab
  int j, k;
roentgen b75cab
  uint32 i;
roentgen b75cab
  char  dump_array[10];
roentgen b75cab
  unsigned char bitset;
roentgen b75cab
roentgen b75cab
  if (dumpfile == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("", "Invalid FILE pointer for dump file");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (format == DUMP_TEXT)
roentgen b75cab
    {
roentgen b75cab
    fprintf (dumpfile," %s  ", dump_tag);
roentgen b75cab
    for (i = 0; i < count; i++)
roentgen b75cab
      {
roentgen b75cab
      for (j = 0, k = 7; j < 8; j++, k--)
roentgen b75cab
        {
roentgen b75cab
	bitset = (*(data + i)) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
        sprintf(&dump_array[j], (bitset) ? "1" : "0");
roentgen b75cab
        }
roentgen b75cab
      dump_array[8] = '\0';
roentgen b75cab
      fprintf (dumpfile," %s", dump_array);
roentgen b75cab
      }
roentgen b75cab
    fprintf (dumpfile,"\n");
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if ((fwrite (data, 1, count, dumpfile)) != count)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("", "Unable to write binary data to dump file");
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int dump_byte (FILE *dumpfile, int format, char *dump_tag, unsigned char data)
roentgen b75cab
  {
roentgen b75cab
  int j, k;
roentgen b75cab
  char  dump_array[10];
roentgen b75cab
  unsigned char bitset;
roentgen b75cab
roentgen b75cab
  if (dumpfile == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("", "Invalid FILE pointer for dump file");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (format == DUMP_TEXT)
roentgen b75cab
    {
roentgen b75cab
    fprintf (dumpfile," %s  ", dump_tag);
roentgen b75cab
    for (j = 0, k = 7; j < 8; j++, k--)
roentgen b75cab
      {
roentgen b75cab
      bitset = data & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
      sprintf(&dump_array[j], (bitset) ? "1" : "0");
roentgen b75cab
      }
roentgen b75cab
    dump_array[8] = '\0';
roentgen b75cab
    fprintf (dumpfile," %s\n", dump_array);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if ((fwrite (&data, 1, 1, dumpfile)) != 1)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("", "Unable to write binary data to dump file");
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int dump_short (FILE *dumpfile, int format, char *dump_tag, uint16 data)
roentgen b75cab
  {
roentgen b75cab
  int j, k;
roentgen b75cab
  char  dump_array[20];
roentgen b75cab
  unsigned char bitset;
roentgen b75cab
roentgen b75cab
  if (dumpfile == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("", "Invalid FILE pointer for dump file");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (format == DUMP_TEXT)
roentgen b75cab
    {
roentgen b75cab
    fprintf (dumpfile," %s  ", dump_tag);
roentgen b75cab
    for (j = 0, k = 15; k >= 0; j++, k--)
roentgen b75cab
      {
roentgen b75cab
      bitset = data & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
      sprintf(&dump_array[j], (bitset) ? "1" : "0");
roentgen b75cab
      if ((k % 8) == 0)
roentgen b75cab
          sprintf(&dump_array[++j], " ");
roentgen b75cab
      }
roentgen b75cab
    dump_array[17] = '\0';
roentgen b75cab
    fprintf (dumpfile," %s\n", dump_array);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if ((fwrite (&data, 2, 1, dumpfile)) != 2)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("", "Unable to write binary data to dump file");
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int dump_long (FILE *dumpfile, int format, char *dump_tag, uint32 data)
roentgen b75cab
  {
roentgen b75cab
  int j, k;
roentgen b75cab
  char  dump_array[40];
roentgen b75cab
  unsigned char bitset;
roentgen b75cab
roentgen b75cab
  if (dumpfile == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("", "Invalid FILE pointer for dump file");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (format == DUMP_TEXT)
roentgen b75cab
    {
roentgen b75cab
    fprintf (dumpfile," %s  ", dump_tag);
roentgen b75cab
    for (j = 0, k = 31; k >= 0; j++, k--)
roentgen b75cab
      {
roentgen b75cab
      bitset = data & (((uint32)1 << k)) ? 1 : 0;
roentgen b75cab
      sprintf(&dump_array[j], (bitset) ? "1" : "0");
roentgen b75cab
      if ((k % 8) == 0)
roentgen b75cab
          sprintf(&dump_array[++j], " ");
roentgen b75cab
      }
roentgen b75cab
    dump_array[35] = '\0';
roentgen b75cab
    fprintf (dumpfile," %s\n", dump_array);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if ((fwrite (&data, 4, 1, dumpfile)) != 4)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("", "Unable to write binary data to dump file");
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int dump_wide (FILE *dumpfile, int format, char *dump_tag, uint64 data)
roentgen b75cab
  {
roentgen b75cab
  int j, k;
roentgen b75cab
  char  dump_array[80];
roentgen b75cab
  unsigned char bitset;
roentgen b75cab
roentgen b75cab
  if (dumpfile == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("", "Invalid FILE pointer for dump file");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (format == DUMP_TEXT)
roentgen b75cab
    {
roentgen b75cab
    fprintf (dumpfile," %s  ", dump_tag);
roentgen b75cab
    for (j = 0, k = 63; k >= 0; j++, k--)
roentgen b75cab
      {
roentgen b75cab
      bitset = data & (((uint64)1 << k)) ? 1 : 0;
roentgen b75cab
      sprintf(&dump_array[j], (bitset) ? "1" : "0");
roentgen b75cab
      if ((k % 8) == 0)
roentgen b75cab
          sprintf(&dump_array[++j], " ");
roentgen b75cab
      }
roentgen b75cab
    dump_array[71] = '\0';
roentgen b75cab
    fprintf (dumpfile," %s\n", dump_array);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if ((fwrite (&data, 8, 1, dumpfile)) != 8)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("", "Unable to write binary data to dump file");
roentgen b75cab
      return (1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static void dump_info(FILE *dumpfile, int format, char *prefix, char *msg, ...)
roentgen b75cab
  {
roentgen b75cab
  if (format == DUMP_TEXT)
roentgen b75cab
    {
roentgen b75cab
    va_list ap;
roentgen b75cab
    va_start(ap, msg);
roentgen b75cab
    fprintf(dumpfile, "%s ", prefix);
roentgen b75cab
    vfprintf(dumpfile, msg, ap);
roentgen b75cab
    fprintf(dumpfile, "\n");
roentgen b75cab
    }
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static int dump_buffer (FILE* dumpfile, int format, uint32 rows, uint32 width, 
roentgen b75cab
                 uint32 row, unsigned char *buff)
roentgen b75cab
  {
roentgen b75cab
  int j, k;
roentgen b75cab
  uint32 i;
roentgen b75cab
  unsigned char * dump_ptr;
roentgen b75cab
roentgen b75cab
  if (dumpfile == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("", "Invalid FILE pointer for dump file");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  for (i = 0; i < rows; i++)
roentgen b75cab
    {
roentgen b75cab
    dump_ptr = buff + (i * width);
roentgen b75cab
    if (format == DUMP_TEXT)
roentgen b75cab
      dump_info (dumpfile, format, "", 
roentgen b75cab
                 "Row %4d, %d bytes at offset %d",
roentgen b75cab
	         row + i + 1, width, row * width);
roentgen b75cab
     
roentgen b75cab
    for (j = 0, k = width; k >= 10; j += 10, k -= 10, dump_ptr += 10)
roentgen b75cab
      dump_data (dumpfile, format, "", dump_ptr, 10);
roentgen b75cab
    if (k > 0)
roentgen b75cab
      dump_data (dumpfile, format, "", dump_ptr, k);
roentgen b75cab
    }
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
/* Extract one or more samples from an interleaved buffer. If count == 1,
roentgen b75cab
 * only the sample plane indicated by sample will be extracted.  If count > 1, 
roentgen b75cab
 * count samples beginning at sample will be extracted. Portions of a 
roentgen b75cab
 * scanline can be extracted by specifying a start and end value.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static int 
roentgen b75cab
extractContigSamplesBytes (uint8 *in, uint8 *out, uint32 cols, 
roentgen b75cab
                           tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
                           tsample_t count, uint32 start, uint32 end)
roentgen b75cab
  {
roentgen b75cab
  int i, bytes_per_sample, sindex;
roentgen b75cab
  uint32 col, dst_rowsize, bit_offset;
roentgen b75cab
  uint32 src_byte, src_bit;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamplesBytes","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesBytes", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesBytes", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  dst_rowsize = (bps * (end - start) * count) / 8;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  /* Optimize case for copying all samples */
roentgen b75cab
  if (count == spp)
roentgen b75cab
    {
roentgen b75cab
    src = in + (start * spp * bytes_per_sample);
roentgen b75cab
    _TIFFmemcpy (dst, src, dst_rowsize);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    for (col = start; col < end; col++)
roentgen b75cab
      {
roentgen b75cab
      for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
        {
roentgen b75cab
        bit_offset = col * bps * spp;
roentgen b75cab
        if (sindex == 0)
roentgen b75cab
          {
roentgen b75cab
          src_byte = bit_offset / 8;
roentgen b75cab
          src_bit  = bit_offset % 8;
roentgen b75cab
          }
roentgen b75cab
        else
roentgen b75cab
          {
roentgen b75cab
          src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
          src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
          }
roentgen b75cab
        src = in + src_byte;
roentgen b75cab
        for (i = 0; i < bytes_per_sample; i++)
roentgen b75cab
            *dst++ = *src++;
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesBytes */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamples8bits (uint8 *in, uint8 *out, uint32 cols,
roentgen b75cab
                           tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
                           tsample_t count, uint32 start, uint32 end)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint8  maskbits = 0, matchbits = 0;
roentgen b75cab
  uint8  buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamples8bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples8bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples8bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint8)-1 >> ( 8 - bps);
roentgen b75cab
  buff1 = buff2 = 0;
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (8 - src_bit - bps); 
roentgen b75cab
      buff1 = ((*src) & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      /* If we have a full buffer's worth, write it out */
roentgen b75cab
      if (ready_bits >= 8)
roentgen b75cab
        {
roentgen b75cab
        *dst++ = buff2;
roentgen b75cab
        buff2 = buff1;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
roentgen b75cab
    *dst++ = buff1;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamples8bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamples16bits (uint8 *in, uint8 *out, uint32 cols, 
roentgen b75cab
                            tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
                            tsample_t count, uint32 start, uint32 end)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint16 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint16 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamples16bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples16bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples16bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits = (uint16)-1 >> (16 - bps);
roentgen b75cab
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (16 - src_bit - bps); 
roentgen b75cab
roentgen b75cab
      if (little_endian)
roentgen b75cab
        buff1 = (src[0] << 8) | src[1];
roentgen b75cab
      else
roentgen b75cab
        buff1 = (src[1] << 8) | src[0];
roentgen b75cab
roentgen b75cab
      buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
      if (ready_bits < 8) /* add another bps bits to the buffer */
roentgen b75cab
        { 
roentgen b75cab
        bytebuff = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff = (buff2 >> 8);
roentgen b75cab
        *dst++ = bytebuff;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* catch any trailing bits at the end of the line */
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff = (buff2 >> 8);
roentgen b75cab
    *dst++ = bytebuff;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamples16bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamples24bits (uint8 *in, uint8 *out, uint32 cols,
roentgen b75cab
 	                    tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
                            tsample_t count, uint32 start, uint32 end)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint32 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint32 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((in == NULL) || (out == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamples24bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples24bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples24bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint32)-1 >> ( 32 - bps);
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (32 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
	buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
      else
roentgen b75cab
	buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
      buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 16) /* add another bps bits to the buffer */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = bytebuff2 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 24);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 16);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        ready_bits -= 16;
roentgen b75cab
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* catch any trailing bits at the end of the line */
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 24);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    bytebuff2 = bytebuff1;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    } 
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamples24bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamples32bits (uint8 *in, uint8 *out, uint32 cols,
roentgen b75cab
                            tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
 			    tsample_t count, uint32 start, uint32 end)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0, shift_width = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint32 longbuff1 = 0, longbuff2 = 0;
roentgen b75cab
  uint64 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint64 buff1 = 0, buff2 = 0, buff3 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((in == NULL) || (out == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamples32bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples32bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamples32bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  shift_width = ((bps + 7) / 8) + 1; 
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint64)-1 >> ( 64 - bps);
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (64 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (src[0] << 24) | (src[1] << 16)  | (src[2] << 8) | src[3];
roentgen b75cab
	longbuff2 = longbuff1;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
	longbuff2 = longbuff1;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
      buff3 = ((uint64)longbuff1 << 32) | longbuff2;
roentgen b75cab
      buff1 = (buff3 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      /* If we have a full buffer's worth, write it out */
roentgen b75cab
      if (ready_bits >= 32)
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 56);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 48);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        bytebuff3 = (buff2 >> 40);
roentgen b75cab
        *dst++ = bytebuff3;
roentgen b75cab
        bytebuff4 = (buff2 >> 32);
roentgen b75cab
        *dst++ = bytebuff4;
roentgen b75cab
        ready_bits -= 32;
roentgen b75cab
                    
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 56);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamples32bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamplesShifted8bits (uint8 *in, uint8 *out, uint32 cols,
roentgen b75cab
                                  tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
			          tsample_t count, uint32 start, uint32 end,
roentgen b75cab
 	                          int shift)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint8  maskbits = 0, matchbits = 0;
roentgen b75cab
  uint8  buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamplesShifted8bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted8bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted8bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = shift;
roentgen b75cab
  maskbits =  (uint8)-1 >> ( 8 - bps);
roentgen b75cab
  buff1 = buff2 = 0;
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (8 - src_bit - bps); 
roentgen b75cab
      buff1 = ((*src) & matchbits) << (src_bit);
roentgen b75cab
      if ((col == start) && (sindex == sample))
roentgen b75cab
        buff2 = *src & ((uint8)-1) << (shift);
roentgen b75cab
roentgen b75cab
      /* If we have a full buffer's worth, write it out */
roentgen b75cab
      if (ready_bits >= 8)
roentgen b75cab
        {
roentgen b75cab
        *dst++ |= buff2;
roentgen b75cab
        buff2 = buff1;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
	buff2 = buff2 | (buff1 >> ready_bits);
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
roentgen b75cab
    *dst++ = buff1;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesShifted8bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamplesShifted16bits (uint8 *in, uint8 *out, uint32 cols, 
roentgen b75cab
                                   tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
  			           tsample_t count, uint32 start, uint32 end,
roentgen b75cab
 	                           int shift)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint16 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint16 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
  
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamplesShifted16bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted16bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted16bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = shift;
roentgen b75cab
  maskbits = (uint16)-1 >> (16 - bps);
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (16 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        buff1 = (src[0] << 8) | src[1];
roentgen b75cab
      else
roentgen b75cab
        buff1 = (src[1] << 8) | src[0];
roentgen b75cab
roentgen b75cab
      if ((col == start) && (sindex == sample))
roentgen b75cab
        buff2 = buff1 & ((uint16)-1) << (8 - shift);
roentgen b75cab
roentgen b75cab
      buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 8) /* add another bps bits to the buffer */
roentgen b75cab
        buff2 = buff2 | (buff1 >> ready_bits);
roentgen b75cab
      else  /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff = (buff2 >> 8);
roentgen b75cab
        *dst++ = bytebuff;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* catch any trailing bits at the end of the line */
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff = (buff2 >> 8);
roentgen b75cab
    *dst++ = bytebuff;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesShifted16bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamplesShifted24bits (uint8 *in, uint8 *out, uint32 cols,
roentgen b75cab
 	                           tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
                                   tsample_t count, uint32 start, uint32 end,
roentgen b75cab
	                           int shift)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint32 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint32 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((in == NULL) || (out == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamplesShifted24bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted24bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted24bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = shift;
roentgen b75cab
  maskbits =  (uint32)-1 >> ( 32 - bps);
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (32 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
	buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
      else
roentgen b75cab
	buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
roentgen b75cab
      if ((col == start) && (sindex == sample))
roentgen b75cab
        buff2 = buff1 & ((uint32)-1) << (16 - shift);
roentgen b75cab
roentgen b75cab
      buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 16)  /* add another bps bits to the buffer */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = bytebuff2 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 24);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 16);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        ready_bits -= 16;
roentgen b75cab
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* catch any trailing bits at the end of the line */
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 24);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    bytebuff2 = bytebuff1;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
   
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesShifted24bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamplesShifted32bits (uint8 *in, uint8 *out, uint32 cols,
roentgen b75cab
                                   tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
 			           tsample_t count, uint32 start, uint32 end,
roentgen b75cab
	                           int shift)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, sindex = 0, shift_width = 0;
roentgen b75cab
  uint32 col, src_byte, src_bit, bit_offset;
roentgen b75cab
  uint32 longbuff1 = 0, longbuff2 = 0;
roentgen b75cab
  uint64 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint64 buff1 = 0, buff2 = 0, buff3 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
roentgen b75cab
  uint8 *src = in;
roentgen b75cab
  uint8 *dst = out;
roentgen b75cab
roentgen b75cab
  if ((in == NULL) || (out == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("extractContigSamplesShifted32bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
roentgen b75cab
  if ((start > end) || (start > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted32bits", 
roentgen b75cab
               "Invalid start column value %d ignored", start);
roentgen b75cab
    start = 0;
roentgen b75cab
    }
roentgen b75cab
  if ((end == 0) || (end > cols))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("extractContigSamplesShifted32bits", 
roentgen b75cab
               "Invalid end column value %d ignored", end);
roentgen b75cab
    end = cols;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  shift_width = ((bps + 7) / 8) + 1; 
roentgen b75cab
  ready_bits = shift;
roentgen b75cab
  maskbits =  (uint64)-1 >> ( 64 - bps);
roentgen b75cab
  for (col = start; col < end; col++)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sindex = sample; (sindex < spp) && (sindex < (sample + count)); sindex++)
roentgen b75cab
      {
roentgen b75cab
      if (sindex == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sindex * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sindex * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = in + src_byte;
roentgen b75cab
      matchbits = maskbits << (64 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
	longbuff2 = longbuff1;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
	longbuff2 = longbuff1;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
      buff3 = ((uint64)longbuff1 << 32) | longbuff2;
roentgen b75cab
      if ((col == start) && (sindex == sample))
roentgen b75cab
        buff2 = buff3 & ((uint64)-1) << (32 - shift);
roentgen b75cab
roentgen b75cab
      buff1 = (buff3 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 32)
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else  /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 56);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 48);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        bytebuff3 = (buff2 >> 40);
roentgen b75cab
        *dst++ = bytebuff3;
roentgen b75cab
        bytebuff4 = (buff2 >> 32);
roentgen b75cab
        *dst++ = bytebuff4;
roentgen b75cab
        ready_bits -= 32;
roentgen b75cab
                    
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 56);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesShifted32bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamplesToBuffer(uint8 *out, uint8 *in, uint32 rows, uint32 cols,
roentgen b75cab
  	                     tsample_t sample, uint16 spp, uint16 bps, 
roentgen b75cab
                             struct dump_opts *dump)
roentgen b75cab
  {
roentgen b75cab
  int    shift_width, bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32 src_rowsize, src_offset, row, first_col = 0;
roentgen b75cab
  uint32 dst_rowsize, dst_offset;
roentgen b75cab
  tsample_t count = 1;
roentgen b75cab
  uint8 *src, *dst;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if ((bps % 8) == 0)
roentgen b75cab
    shift_width = 0;
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
      shift_width = bytes_per_pixel;
roentgen b75cab
    else
roentgen b75cab
      shift_width = bytes_per_sample + 1;
roentgen b75cab
    }
roentgen b75cab
  src_rowsize = ((bps * spp * cols) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * cols) + 7) / 8;
roentgen b75cab
roentgen b75cab
  if ((dump->outfile != NULL) && (dump->level == 4))
roentgen b75cab
    {
roentgen b75cab
    dump_info  (dump->outfile, dump->format, "extractContigSamplesToBuffer", 
roentgen b75cab
                "Sample %d, %d rows", sample + 1, rows + 1);
roentgen b75cab
    }
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    dst_offset = row * dst_rowsize;
roentgen b75cab
    src = in + src_offset;
roentgen b75cab
    dst = out + dst_offset;
roentgen b75cab
roentgen b75cab
    /* pack the data into the scanline */
roentgen b75cab
    switch (shift_width)
roentgen b75cab
      {  
roentgen b75cab
      case 0: if (extractContigSamplesBytes (src, dst, cols, sample,
roentgen b75cab
                                             spp, bps,  count, first_col, cols))  
roentgen b75cab
                return (1);
roentgen b75cab
 	      break;
roentgen b75cab
      case 1: if (bps == 1)
roentgen b75cab
                {
roentgen b75cab
                if (extractContigSamples8bits (src, dst, cols, sample,
roentgen b75cab
                                               spp, bps, count, first_col, cols))
roentgen b75cab
	          return (1);
roentgen b75cab
	        break;
roentgen b75cab
		}
roentgen b75cab
	      else
roentgen b75cab
                 if (extractContigSamples16bits (src, dst, cols, sample,
roentgen b75cab
                                                 spp, bps, count, first_col, cols))
roentgen b75cab
	         return (1);
roentgen b75cab
	      break;
roentgen b75cab
      case 2: if (extractContigSamples24bits (src, dst, cols, sample,
roentgen b75cab
                                              spp, bps,  count, first_col, cols))
roentgen b75cab
	         return (1);
roentgen b75cab
	      break;
roentgen b75cab
      case 3:
roentgen b75cab
      case 4: 
roentgen b75cab
      case 5: if (extractContigSamples32bits (src, dst, cols, sample,
roentgen b75cab
                                              spp, bps,  count, first_col, cols))
roentgen b75cab
	         return (1);
roentgen b75cab
	      break;
roentgen b75cab
      default: TIFFError ("extractContigSamplesToBuffer", "Unsupported bit depth: %d", bps);
roentgen b75cab
	       return (1);
roentgen b75cab
      }
roentgen b75cab
    if ((dump->outfile != NULL) && (dump->level == 4))
roentgen b75cab
      dump_buffer(dump->outfile, dump->format, 1, dst_rowsize, row, dst);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesToBuffer */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractContigSamplesToTileBuffer(uint8 *out, uint8 *in, uint32 rows, uint32 cols,
roentgen b75cab
  	                         uint32 imagewidth, uint32 tilewidth, tsample_t sample,
roentgen b75cab
				 uint16 count, uint16 spp, uint16 bps, struct dump_opts *dump)
roentgen b75cab
  {
roentgen b75cab
  int    shift_width, bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32 src_rowsize, src_offset, row;
roentgen b75cab
  uint32 dst_rowsize, dst_offset;
roentgen b75cab
  uint8 *src, *dst;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if ((bps % 8) == 0)
roentgen b75cab
    shift_width = 0;
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
      shift_width = bytes_per_pixel;
roentgen b75cab
    else
roentgen b75cab
      shift_width = bytes_per_sample + 1;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((dump->outfile != NULL) && (dump->level == 4))
roentgen b75cab
    {
roentgen b75cab
    dump_info  (dump->outfile, dump->format, "extractContigSamplesToTileBuffer", 
roentgen b75cab
                "Sample %d, %d rows", sample + 1, rows + 1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * spp * imagewidth) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * tilewidth * count) + 7) / 8;
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    dst_offset = row * dst_rowsize;
roentgen b75cab
    src = in + src_offset;
roentgen b75cab
    dst = out + dst_offset;
roentgen b75cab
roentgen b75cab
    /* pack the data into the scanline */
roentgen b75cab
    switch (shift_width)
roentgen b75cab
      {  
roentgen b75cab
      case 0: if (extractContigSamplesBytes (src, dst, cols, sample,
roentgen b75cab
                                             spp, bps,  count, 0, cols))  
roentgen b75cab
                return (1);
roentgen b75cab
 	      break;
roentgen b75cab
      case 1: if (bps == 1)
roentgen b75cab
                {
roentgen b75cab
                if (extractContigSamples8bits (src, dst, cols, sample,
roentgen b75cab
                                               spp, bps, count, 0, cols))
roentgen b75cab
	          return (1);
roentgen b75cab
	        break;
roentgen b75cab
		}
roentgen b75cab
	      else
roentgen b75cab
                 if (extractContigSamples16bits (src, dst, cols, sample,
roentgen b75cab
                                                 spp, bps, count, 0, cols))
roentgen b75cab
	         return (1);
roentgen b75cab
	      break;
roentgen b75cab
      case 2: if (extractContigSamples24bits (src, dst, cols, sample,
roentgen b75cab
                                              spp, bps,  count, 0, cols))
roentgen b75cab
	         return (1);
roentgen b75cab
	      break;
roentgen b75cab
      case 3:
roentgen b75cab
      case 4: 
roentgen b75cab
      case 5: if (extractContigSamples32bits (src, dst, cols, sample,
roentgen b75cab
                                              spp, bps,  count, 0, cols))
roentgen b75cab
	         return (1);
roentgen b75cab
	      break;
roentgen b75cab
      default: TIFFError ("extractContigSamplesToTileBuffer", "Unsupported bit depth: %d", bps);
roentgen b75cab
	       return (1);
roentgen b75cab
      }
roentgen b75cab
    if ((dump->outfile != NULL) && (dump->level == 4))
roentgen b75cab
      dump_buffer(dump->outfile, dump->format, 1, dst_rowsize, row, dst);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractContigSamplesToTileBuffer */
roentgen b75cab
roentgen b75cab
static int readContigStripsIntoBuffer (TIFF* in, uint8* buf)
roentgen b75cab
  {
roentgen b75cab
  uint8* bufp = buf;
roentgen b75cab
  int32  bytes_read = 0;
roentgen b75cab
  uint16 strip, nstrips   = TIFFNumberOfStrips(in);
roentgen b75cab
  uint32 stripsize = TIFFStripSize(in);
roentgen b75cab
  uint32 rows = 0;
roentgen b75cab
  uint32 rps = TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rps);
roentgen b75cab
  tsize_t scanline_size = TIFFScanlineSize(in);
roentgen b75cab
roentgen b75cab
  for (strip = 0; strip < nstrips; strip++)
roentgen b75cab
    {
roentgen b75cab
    bytes_read = TIFFReadEncodedStrip (in, strip, bufp, -1);
roentgen b75cab
    rows = bytes_read / scanline_size;
roentgen b75cab
    if ((strip < (nstrips - 1)) && (bytes_read != (int32)stripsize))
roentgen b75cab
      TIFFError("", "Strip %d: read %lu bytes, strip size %lu",
roentgen b75cab
		(int)strip + 1, (unsigned long) bytes_read, (unsigned long)stripsize);
roentgen b75cab
roentgen b75cab
    if (bytes_read < 0 && !ignore)
roentgen b75cab
      {
roentgen b75cab
      TIFFError("", "Error reading strip %lu after %lu rows",
roentgen b75cab
		(unsigned long) strip, (unsigned long)rows);
roentgen b75cab
      return 0;
roentgen b75cab
      }
roentgen b75cab
    bufp += bytes_read;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
 return 1;
roentgen b75cab
  } /* end readContigStripsIntoBuffer */
roentgen b75cab
roentgen b75cab
static int 
roentgen b75cab
combineSeparateSamplesBytes (unsigned char *srcbuffs[], unsigned char *out,
roentgen b75cab
                             uint32 cols, uint32 rows, uint16 spp, uint16 bps,
roentgen b75cab
                             FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int i, bytes_per_sample;
roentgen b75cab
  uint32 row, col, col_offset, src_rowsize, dst_rowsize, row_offset;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  tsample_t s;
roentgen b75cab
roentgen b75cab
  src = srcbuffs[0];
roentgen b75cab
  dst = out;
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateSamplesBytes","Invalid buffer address");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * cols) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * spp * cols) + 7) / 8;
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
        dump_info (dumpfile, format, "combineSeparateSamplesBytes","Input data, Sample %d", s);
roentgen b75cab
        dump_buffer(dumpfile, format, 1, cols, row, srcbuffs[s] + (row * src_rowsize));
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    row_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      col_offset = row_offset + (col * (bps / 8)); 
roentgen b75cab
      for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
roentgen b75cab
        {
roentgen b75cab
        src = srcbuffs[s] + col_offset; 
roentgen b75cab
        for (i = 0; i < bytes_per_sample; i++)
roentgen b75cab
          *(dst + i) = *(src + i);
roentgen b75cab
        src += bytes_per_sample;
roentgen b75cab
        dst += bytes_per_sample;
roentgen b75cab
        }   
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateSamplesBytes","Output data, combined samples");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateSamplesBytes */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateSamples8bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                            uint32 rows, uint16 spp, uint16 bps, 
roentgen b75cab
 	                    FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0;
roentgen b75cab
  int    bytes_per_sample = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize, src_offset; 
roentgen b75cab
  uint32 bit_offset;
roentgen b75cab
  uint32 row, col, src_byte = 0, src_bit = 0;
roentgen b75cab
  uint8  maskbits = 0, matchbits = 0;
roentgen b75cab
  uint8  buff1 = 0, buff2 = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[32];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateSamples8bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  src_rowsize = ((bps * cols) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * cols * spp) + 7) / 8;
roentgen b75cab
  maskbits =  (uint8)-1 >> ( 8 - bps);
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (8 - src_bit - bps); 
roentgen b75cab
      /* load up next sample from each plane */
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
        buff1 = ((*src) & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
        /* If we have a full buffer's worth, write it out */
roentgen b75cab
        if (ready_bits >= 8)
roentgen b75cab
          {
roentgen b75cab
          *dst++ = buff2;
roentgen b75cab
          buff2 = buff1;
roentgen b75cab
          ready_bits -= 8;
roentgen b75cab
          strcpy (action, "Flush");
roentgen b75cab
          }
roentgen b75cab
        else
roentgen b75cab
          {
roentgen b75cab
          buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
          strcpy (action, "Update");
roentgen b75cab
          }
roentgen b75cab
        ready_bits += bps;
roentgen b75cab
 
roentgen b75cab
        if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
          {
roentgen b75cab
          dump_info (dumpfile, format, "",
roentgen b75cab
                   "Row %3d, Col %3d, Samples %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		   row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
          dump_byte (dumpfile, format, "Match bits", matchbits);
roentgen b75cab
          dump_byte (dumpfile, format, "Src   bits", *src);
roentgen b75cab
          dump_byte (dumpfile, format, "Buff1 bits", buff1);
roentgen b75cab
          dump_byte (dumpfile, format, "Buff2 bits", buff2);
roentgen b75cab
          dump_info (dumpfile, format, "","%s", action); 
roentgen b75cab
	  }
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
      buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
roentgen b75cab
      *dst++ = buff1;
roentgen b75cab
      if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
        {
roentgen b75cab
        dump_info (dumpfile, format, "",
roentgen b75cab
	         "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
	         row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
                 dump_byte (dumpfile, format, "Final bits", buff1);
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level >= 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateSamples8bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateSamples8bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateSamples16bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                              uint32 rows, uint16 spp, uint16 bps, 
roentgen b75cab
 	                      FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, bytes_per_sample = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize; 
roentgen b75cab
  uint32 bit_offset, src_offset;
roentgen b75cab
  uint32 row, col, src_byte = 0, src_bit = 0;
roentgen b75cab
  uint16 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint16 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[8];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateSamples16bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  src_rowsize = ((bps * cols) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * cols * spp) + 7) / 8;
roentgen b75cab
  maskbits = (uint16)-1 >> (16 - bps);
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (16 - src_bit - bps); 
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
        if (little_endian)
roentgen b75cab
          buff1 = (src[0] << 8) | src[1];
roentgen b75cab
        else
roentgen b75cab
          buff1 = (src[1] << 8) | src[0];
roentgen b75cab
roentgen b75cab
	buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
	/* If we have a full buffer's worth, write it out */
roentgen b75cab
	if (ready_bits >= 8)
roentgen b75cab
	  {
roentgen b75cab
	    bytebuff = (buff2 >> 8);
roentgen b75cab
	    *dst++ = bytebuff;
roentgen b75cab
	    ready_bits -= 8;
roentgen b75cab
	    /* shift in new bits */
roentgen b75cab
	    buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Flush");
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  { /* add another bps bits to the buffer */
roentgen b75cab
	    bytebuff = 0;
roentgen b75cab
	    buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Update");
roentgen b75cab
	  }
roentgen b75cab
	ready_bits += bps;
roentgen b75cab
roentgen b75cab
	if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	  {
roentgen b75cab
	  dump_info (dumpfile, format, "",
roentgen b75cab
		       "Row %3d, Col %3d, Samples %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		       row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
roentgen b75cab
	  dump_short (dumpfile, format, "Match bits", matchbits);
roentgen b75cab
	  dump_data  (dumpfile, format, "Src   bits", src, 2);
roentgen b75cab
	  dump_short (dumpfile, format, "Buff1 bits", buff1);
roentgen b75cab
	  dump_short (dumpfile, format, "Buff2 bits", buff2);
roentgen b75cab
	  dump_byte  (dumpfile, format, "Write byte", bytebuff);
roentgen b75cab
	  dump_info  (dumpfile, format, "","Ready bits:  %d, %s", ready_bits, action); 
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    /* catch any trailing bits at the end of the line */
roentgen b75cab
    if (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
      bytebuff = (buff2 >> 8);
roentgen b75cab
      *dst++ = bytebuff;
roentgen b75cab
      if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	{
roentgen b75cab
	dump_info (dumpfile, format, "",
roentgen b75cab
		       "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		       row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
	dump_byte (dumpfile, format, "Final bits", bytebuff);
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateSamples16bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateSamples16bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateSamples24bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                              uint32 rows, uint16 spp, uint16 bps, 
roentgen b75cab
	                      FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, bytes_per_sample = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize; 
roentgen b75cab
  uint32 bit_offset, src_offset;
roentgen b75cab
  uint32 row, col, src_byte = 0, src_bit = 0;
roentgen b75cab
  uint32 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint32 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[8];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateSamples24bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  src_rowsize = ((bps * cols) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * cols * spp) + 7) / 8;
roentgen b75cab
  maskbits =  (uint32)-1 >> ( 32 - bps);
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (32 - src_bit - bps); 
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
        if (little_endian)
roentgen b75cab
	  buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
        else
roentgen b75cab
	  buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
	buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
	/* If we have a full buffer's worth, write it out */
roentgen b75cab
	if (ready_bits >= 16)
roentgen b75cab
	  {
roentgen b75cab
	    bytebuff1 = (buff2 >> 24);
roentgen b75cab
	    *dst++ = bytebuff1;
roentgen b75cab
	    bytebuff2 = (buff2 >> 16);
roentgen b75cab
	    *dst++ = bytebuff2;
roentgen b75cab
	    ready_bits -= 16;
roentgen b75cab
roentgen b75cab
	    /* shift in new bits */
roentgen b75cab
	    buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Flush");
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  { /* add another bps bits to the buffer */
roentgen b75cab
	    bytebuff1 = bytebuff2 = 0;
roentgen b75cab
	    buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Update");
roentgen b75cab
	  }
roentgen b75cab
	ready_bits += bps;
roentgen b75cab
roentgen b75cab
	if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	  {
roentgen b75cab
	  dump_info (dumpfile, format, "",
roentgen b75cab
		       "Row %3d, Col %3d, Samples %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		       row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
	  dump_long (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
	  dump_data (dumpfile, format, "Src   bits ", src, 4);
roentgen b75cab
	  dump_long (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
	  dump_long (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
	  dump_byte (dumpfile, format, "Write bits1", bytebuff1);
roentgen b75cab
	  dump_byte (dumpfile, format, "Write bits2", bytebuff2);
roentgen b75cab
	  dump_info (dumpfile, format, "","Ready bits:   %d, %s", ready_bits, action); 
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    /* catch any trailing bits at the end of the line */
roentgen b75cab
    while (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
	bytebuff1 = (buff2 >> 24);
roentgen b75cab
	*dst++ = bytebuff1;
roentgen b75cab
roentgen b75cab
	buff2 = (buff2 << 8);
roentgen b75cab
	bytebuff2 = bytebuff1;
roentgen b75cab
	ready_bits -= 8;
roentgen b75cab
      }
roentgen b75cab
 
roentgen b75cab
    if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "",
roentgen b75cab
		   "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		   row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
roentgen b75cab
      dump_long (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
      dump_data (dumpfile, format, "Src   bits ", src, 4);
roentgen b75cab
      dump_long (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
      dump_long (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits1", bytebuff1);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits2", bytebuff2);
roentgen b75cab
      dump_info (dumpfile, format, "", "Ready bits:  %2d", ready_bits); 
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateSamples24bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateSamples24bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateSamples32bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                              uint32 rows, uint16 spp, uint16 bps, 
roentgen b75cab
	                      FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, bytes_per_sample = 0, shift_width = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize, bit_offset, src_offset;
roentgen b75cab
  uint32 src_byte = 0, src_bit = 0;
roentgen b75cab
  uint32 row, col;
roentgen b75cab
  uint32 longbuff1 = 0, longbuff2 = 0;
roentgen b75cab
  uint64 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint64 buff1 = 0, buff2 = 0, buff3 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[8];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateSamples32bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  src_rowsize = ((bps * cols) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * cols * spp) + 7) / 8;
roentgen b75cab
  maskbits =  (uint64)-1 >> ( 64 - bps);
roentgen b75cab
  shift_width = ((bps + 7) / 8) + 1; 
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (64 - src_bit - bps); 
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
	{
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
	if (little_endian)
roentgen b75cab
	  {
roentgen b75cab
	  longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
          longbuff2 = longbuff1;
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  {
roentgen b75cab
	  longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
          longbuff2 = longbuff1;
roentgen b75cab
	  }
roentgen b75cab
	buff3 = ((uint64)longbuff1 << 32) | longbuff2;
roentgen b75cab
	buff1 = (buff3 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
	/* If we have a full buffer's worth, write it out */
roentgen b75cab
	if (ready_bits >= 32)
roentgen b75cab
	  {
roentgen b75cab
	  bytebuff1 = (buff2 >> 56);
roentgen b75cab
	  *dst++ = bytebuff1;
roentgen b75cab
	  bytebuff2 = (buff2 >> 48);
roentgen b75cab
	  *dst++ = bytebuff2;
roentgen b75cab
	  bytebuff3 = (buff2 >> 40);
roentgen b75cab
	  *dst++ = bytebuff3;
roentgen b75cab
	  bytebuff4 = (buff2 >> 32);
roentgen b75cab
	  *dst++ = bytebuff4;
roentgen b75cab
	  ready_bits -= 32;
roentgen b75cab
                    
roentgen b75cab
	  /* shift in new bits */
roentgen b75cab
	  buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
roentgen b75cab
	  strcpy (action, "Flush");
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  { /* add another bps bits to the buffer */
roentgen b75cab
	  bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
roentgen b75cab
	  buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
	  strcpy (action, "Update");
roentgen b75cab
	  }
roentgen b75cab
	ready_bits += bps;
roentgen b75cab
roentgen b75cab
	if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	  { 
roentgen b75cab
	  dump_info (dumpfile, format, "",
roentgen b75cab
		     "Row %3d, Col %3d, Sample %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		     row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
	  dump_wide (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
	  dump_data (dumpfile, format, "Src   bits ", src, 8);
roentgen b75cab
	  dump_wide (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
	  dump_wide (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
	  dump_info (dumpfile, format, "", "Ready bits:   %d, %s", ready_bits, action); 
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    while (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
      bytebuff1 = (buff2 >> 56);
roentgen b75cab
      *dst++ = bytebuff1;
roentgen b75cab
      buff2 = (buff2 << 8);
roentgen b75cab
      ready_bits -= 8;
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "",
roentgen b75cab
	         "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		 row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
roentgen b75cab
      dump_long (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
      dump_data (dumpfile, format, "Src   bits ", src, 4);
roentgen b75cab
      dump_long (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
      dump_long (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits1", bytebuff1);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits2", bytebuff2);
roentgen b75cab
      dump_info (dumpfile, format, "", "Ready bits:  %2d", ready_bits); 
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateSamples32bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateSamples32bits */
roentgen b75cab
roentgen b75cab
static int 
roentgen b75cab
combineSeparateTileSamplesBytes (unsigned char *srcbuffs[], unsigned char *out,
roentgen b75cab
                                 uint32 cols, uint32 rows, uint32 imagewidth,
roentgen b75cab
                                 uint32 tw, uint16 spp, uint16 bps,
roentgen b75cab
                                 FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int i, bytes_per_sample;
roentgen b75cab
  uint32 row, col, col_offset, src_rowsize, dst_rowsize, src_offset;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  tsample_t s;
roentgen b75cab
roentgen b75cab
  src = srcbuffs[0];
roentgen b75cab
  dst = out;
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateTileSamplesBytes","Invalid buffer address");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  src_rowsize = ((bps * tw) + 7) / 8;
roentgen b75cab
  dst_rowsize = imagewidth * bytes_per_sample * spp;
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
        dump_info (dumpfile, format, "combineSeparateTileSamplesBytes","Input data, Sample %d", s);
roentgen b75cab
        dump_buffer(dumpfile, format, 1, cols, row, srcbuffs[s] + (row * src_rowsize));
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
    TIFFError("","Tile row %4d, Src offset %6d   Dst offset %6d", 
roentgen b75cab
              row, src_offset, dst - out);
roentgen b75cab
#endif
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      col_offset = src_offset + (col * (bps / 8)); 
roentgen b75cab
      for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
roentgen b75cab
        {
roentgen b75cab
        src = srcbuffs[s] + col_offset; 
roentgen b75cab
        for (i = 0; i < bytes_per_sample; i++)
roentgen b75cab
          *(dst + i) = *(src + i);
roentgen b75cab
        dst += bytes_per_sample;
roentgen b75cab
        }   
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateTileSamplesBytes","Output data, combined samples");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateTileSamplesBytes */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateTileSamples8bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                                 uint32 rows, uint32 imagewidth, 
roentgen b75cab
                                 uint32 tw, uint16 spp, uint16 bps, 
roentgen b75cab
 	                         FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize, src_offset; 
roentgen b75cab
  uint32 bit_offset;
roentgen b75cab
  uint32 row, col, src_byte = 0, src_bit = 0;
roentgen b75cab
  uint8  maskbits = 0, matchbits = 0;
roentgen b75cab
  uint8  buff1 = 0, buff2 = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[32];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateTileSamples8bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * tw) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
roentgen b75cab
  maskbits =  (uint8)-1 >> ( 8 - bps);
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (8 - src_bit - bps); 
roentgen b75cab
      /* load up next sample from each plane */
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
        buff1 = ((*src) & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
        /* If we have a full buffer's worth, write it out */
roentgen b75cab
        if (ready_bits >= 8)
roentgen b75cab
          {
roentgen b75cab
          *dst++ = buff2;
roentgen b75cab
          buff2 = buff1;
roentgen b75cab
          ready_bits -= 8;
roentgen b75cab
          strcpy (action, "Flush");
roentgen b75cab
          }
roentgen b75cab
        else
roentgen b75cab
          {
roentgen b75cab
          buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
          strcpy (action, "Update");
roentgen b75cab
          }
roentgen b75cab
        ready_bits += bps;
roentgen b75cab
 
roentgen b75cab
        if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
          {
roentgen b75cab
          dump_info (dumpfile, format, "",
roentgen b75cab
                   "Row %3d, Col %3d, Samples %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		   row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
          dump_byte (dumpfile, format, "Match bits", matchbits);
roentgen b75cab
          dump_byte (dumpfile, format, "Src   bits", *src);
roentgen b75cab
          dump_byte (dumpfile, format, "Buff1 bits", buff1);
roentgen b75cab
          dump_byte (dumpfile, format, "Buff2 bits", buff2);
roentgen b75cab
          dump_info (dumpfile, format, "","%s", action); 
roentgen b75cab
	  }
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
      buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
roentgen b75cab
      *dst++ = buff1;
roentgen b75cab
      if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
        {
roentgen b75cab
        dump_info (dumpfile, format, "",
roentgen b75cab
	         "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
	         row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
                 dump_byte (dumpfile, format, "Final bits", buff1);
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level >= 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateTileSamples8bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateTileSamples8bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateTileSamples16bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                                  uint32 rows, uint32 imagewidth, 
roentgen b75cab
                                  uint32 tw, uint16 spp, uint16 bps, 
roentgen b75cab
 	                          FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize; 
roentgen b75cab
  uint32 bit_offset, src_offset;
roentgen b75cab
  uint32 row, col, src_byte = 0, src_bit = 0;
roentgen b75cab
  uint16 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint16 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[8];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateTileSamples16bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * tw) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
roentgen b75cab
  maskbits = (uint16)-1 >> (16 - bps);
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (16 - src_bit - bps); 
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
        if (little_endian)
roentgen b75cab
          buff1 = (src[0] << 8) | src[1];
roentgen b75cab
        else
roentgen b75cab
          buff1 = (src[1] << 8) | src[0];
roentgen b75cab
	buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
	/* If we have a full buffer's worth, write it out */
roentgen b75cab
	if (ready_bits >= 8)
roentgen b75cab
	  {
roentgen b75cab
	    bytebuff = (buff2 >> 8);
roentgen b75cab
	    *dst++ = bytebuff;
roentgen b75cab
	    ready_bits -= 8;
roentgen b75cab
	    /* shift in new bits */
roentgen b75cab
	    buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Flush");
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  { /* add another bps bits to the buffer */
roentgen b75cab
	    bytebuff = 0;
roentgen b75cab
	    buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Update");
roentgen b75cab
	  }
roentgen b75cab
	ready_bits += bps;
roentgen b75cab
roentgen b75cab
	if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	  {
roentgen b75cab
	  dump_info (dumpfile, format, "",
roentgen b75cab
		       "Row %3d, Col %3d, Samples %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		       row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
roentgen b75cab
	  dump_short (dumpfile, format, "Match bits", matchbits);
roentgen b75cab
	  dump_data  (dumpfile, format, "Src   bits", src, 2);
roentgen b75cab
	  dump_short (dumpfile, format, "Buff1 bits", buff1);
roentgen b75cab
	  dump_short (dumpfile, format, "Buff2 bits", buff2);
roentgen b75cab
	  dump_byte  (dumpfile, format, "Write byte", bytebuff);
roentgen b75cab
	  dump_info  (dumpfile, format, "","Ready bits:  %d, %s", ready_bits, action); 
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    /* catch any trailing bits at the end of the line */
roentgen b75cab
    if (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
      bytebuff = (buff2 >> 8);
roentgen b75cab
      *dst++ = bytebuff;
roentgen b75cab
      if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	{
roentgen b75cab
	dump_info (dumpfile, format, "",
roentgen b75cab
		       "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		       row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
	dump_byte (dumpfile, format, "Final bits", bytebuff);
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateTileSamples16bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateTileSamples16bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateTileSamples24bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                                  uint32 rows, uint32 imagewidth, 
roentgen b75cab
                                  uint32 tw, uint16 spp, uint16 bps, 
roentgen b75cab
 	                          FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize; 
roentgen b75cab
  uint32 bit_offset, src_offset;
roentgen b75cab
  uint32 row, col, src_byte = 0, src_bit = 0;
roentgen b75cab
  uint32 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint32 buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[8];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateTileSamples24bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * tw) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
roentgen b75cab
  maskbits =  (uint32)-1 >> ( 32 - bps);
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (32 - src_bit - bps); 
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
        {
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
        if (little_endian)
roentgen b75cab
	  buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
        else
roentgen b75cab
	  buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
	buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
	/* If we have a full buffer's worth, write it out */
roentgen b75cab
	if (ready_bits >= 16)
roentgen b75cab
	  {
roentgen b75cab
	    bytebuff1 = (buff2 >> 24);
roentgen b75cab
	    *dst++ = bytebuff1;
roentgen b75cab
	    bytebuff2 = (buff2 >> 16);
roentgen b75cab
	    *dst++ = bytebuff2;
roentgen b75cab
	    ready_bits -= 16;
roentgen b75cab
roentgen b75cab
	    /* shift in new bits */
roentgen b75cab
	    buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Flush");
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  { /* add another bps bits to the buffer */
roentgen b75cab
	    bytebuff1 = bytebuff2 = 0;
roentgen b75cab
	    buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
	    strcpy (action, "Update");
roentgen b75cab
	  }
roentgen b75cab
	ready_bits += bps;
roentgen b75cab
roentgen b75cab
	if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	  {
roentgen b75cab
	  dump_info (dumpfile, format, "",
roentgen b75cab
		       "Row %3d, Col %3d, Samples %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		       row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
	  dump_long (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
	  dump_data (dumpfile, format, "Src   bits ", src, 4);
roentgen b75cab
	  dump_long (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
	  dump_long (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
	  dump_byte (dumpfile, format, "Write bits1", bytebuff1);
roentgen b75cab
	  dump_byte (dumpfile, format, "Write bits2", bytebuff2);
roentgen b75cab
	  dump_info (dumpfile, format, "","Ready bits:   %d, %s", ready_bits, action); 
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    /* catch any trailing bits at the end of the line */
roentgen b75cab
    while (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
	bytebuff1 = (buff2 >> 24);
roentgen b75cab
	*dst++ = bytebuff1;
roentgen b75cab
roentgen b75cab
	buff2 = (buff2 << 8);
roentgen b75cab
	bytebuff2 = bytebuff1;
roentgen b75cab
	ready_bits -= 8;
roentgen b75cab
      }
roentgen b75cab
 
roentgen b75cab
    if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "",
roentgen b75cab
		   "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		   row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
roentgen b75cab
      dump_long (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
      dump_data (dumpfile, format, "Src   bits ", src, 4);
roentgen b75cab
      dump_long (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
      dump_long (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits1", bytebuff1);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits2", bytebuff2);
roentgen b75cab
      dump_info (dumpfile, format, "", "Ready bits:  %2d", ready_bits); 
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateTileSamples24bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out + (row * dst_rowsize));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateTileSamples24bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
combineSeparateTileSamples32bits (uint8 *in[], uint8 *out, uint32 cols,
roentgen b75cab
                                  uint32 rows, uint32 imagewidth, 
roentgen b75cab
                                  uint32 tw, uint16 spp, uint16 bps, 
roentgen b75cab
 	                          FILE *dumpfile, int format, int level)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, shift_width = 0;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize, bit_offset, src_offset;
roentgen b75cab
  uint32 src_byte = 0, src_bit = 0;
roentgen b75cab
  uint32 row, col;
roentgen b75cab
  uint32 longbuff1 = 0, longbuff2 = 0;
roentgen b75cab
  uint64 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint64 buff1 = 0, buff2 = 0, buff3 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  unsigned char *src = in[0];
roentgen b75cab
  unsigned char *dst = out;
roentgen b75cab
  char           action[8];
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("combineSeparateTileSamples32bits","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * tw) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((imagewidth * bps * spp) + 7) / 8;
roentgen b75cab
  maskbits =  (uint64)-1 >> ( 64 - bps);
roentgen b75cab
  shift_width = ((bps + 7) / 8) + 1; 
roentgen b75cab
roentgen b75cab
  for (row = 0; row < rows; row++)
roentgen b75cab
    {
roentgen b75cab
    ready_bits = 0;
roentgen b75cab
    buff1 = buff2 = 0;
roentgen b75cab
    dst = out + (row * dst_rowsize);
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    for (col = 0; col < cols; col++)
roentgen b75cab
      {
roentgen b75cab
      /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
      bit_offset = col * bps;
roentgen b75cab
      src_byte = bit_offset / 8;
roentgen b75cab
      src_bit  = bit_offset % 8;
roentgen b75cab
roentgen b75cab
      matchbits = maskbits << (64 - src_bit - bps); 
roentgen b75cab
      for (s = 0; s < spp; s++)
roentgen b75cab
	{
roentgen b75cab
	src = in[s] + src_offset + src_byte;
roentgen b75cab
	if (little_endian)
roentgen b75cab
	  {
roentgen b75cab
	  longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
	  longbuff2 = longbuff1;
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  {
roentgen b75cab
	  longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
          longbuff2 = longbuff1;
roentgen b75cab
	  }
roentgen b75cab
roentgen b75cab
	buff3 = ((uint64)longbuff1 << 32) | longbuff2;
roentgen b75cab
	buff1 = (buff3 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
	/* If we have a full buffer's worth, write it out */
roentgen b75cab
	if (ready_bits >= 32)
roentgen b75cab
	  {
roentgen b75cab
	  bytebuff1 = (buff2 >> 56);
roentgen b75cab
	  *dst++ = bytebuff1;
roentgen b75cab
	  bytebuff2 = (buff2 >> 48);
roentgen b75cab
	  *dst++ = bytebuff2;
roentgen b75cab
	  bytebuff3 = (buff2 >> 40);
roentgen b75cab
	  *dst++ = bytebuff3;
roentgen b75cab
	  bytebuff4 = (buff2 >> 32);
roentgen b75cab
	  *dst++ = bytebuff4;
roentgen b75cab
	  ready_bits -= 32;
roentgen b75cab
                    
roentgen b75cab
	  /* shift in new bits */
roentgen b75cab
	  buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
roentgen b75cab
	  strcpy (action, "Flush");
roentgen b75cab
	  }
roentgen b75cab
	else
roentgen b75cab
	  { /* add another bps bits to the buffer */
roentgen b75cab
	  bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
roentgen b75cab
	  buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
	  strcpy (action, "Update");
roentgen b75cab
	  }
roentgen b75cab
	ready_bits += bps;
roentgen b75cab
roentgen b75cab
	if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
	  { 
roentgen b75cab
	  dump_info (dumpfile, format, "",
roentgen b75cab
		     "Row %3d, Col %3d, Sample %d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		     row + 1, col + 1, s, src_byte, src_bit, dst - out);
roentgen b75cab
	  dump_wide (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
	  dump_data (dumpfile, format, "Src   bits ", src, 8);
roentgen b75cab
	  dump_wide (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
	  dump_wide (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
	  dump_info (dumpfile, format, "", "Ready bits:   %d, %s", ready_bits, action); 
roentgen b75cab
	  }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    while (ready_bits > 0)
roentgen b75cab
      {
roentgen b75cab
      bytebuff1 = (buff2 >> 56);
roentgen b75cab
      *dst++ = bytebuff1;
roentgen b75cab
      buff2 = (buff2 << 8);
roentgen b75cab
      ready_bits -= 8;
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 3))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "",
roentgen b75cab
	         "Row %3d, Col %3d, Src byte offset %3d  bit offset %2d  Dst offset %3d",
roentgen b75cab
		 row + 1, col + 1, src_byte, src_bit, dst - out);
roentgen b75cab
roentgen b75cab
      dump_long (dumpfile, format, "Match bits ", matchbits);
roentgen b75cab
      dump_data (dumpfile, format, "Src   bits ", src, 4);
roentgen b75cab
      dump_long (dumpfile, format, "Buff1 bits ", buff1);
roentgen b75cab
      dump_long (dumpfile, format, "Buff2 bits ", buff2);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits1", bytebuff1);
roentgen b75cab
      dump_byte (dumpfile, format, "Write bits2", bytebuff2);
roentgen b75cab
      dump_info (dumpfile, format, "", "Ready bits:  %2d", ready_bits); 
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((dumpfile != NULL) && (level == 2))
roentgen b75cab
      {
roentgen b75cab
      dump_info (dumpfile, format, "combineSeparateTileSamples32bits","Output data");
roentgen b75cab
      dump_buffer(dumpfile, format, 1, dst_rowsize, row, out);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end combineSeparateTileSamples32bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int readSeparateStripsIntoBuffer (TIFF *in, uint8 *obuf, uint32 length, 
roentgen b75cab
                                         uint32 width, uint16 spp,
roentgen b75cab
                                         struct dump_opts *dump)
roentgen b75cab
  {
roentgen b75cab
  int i, j, bytes_per_sample, bytes_per_pixel, shift_width, result = 1;
roentgen b75cab
  int32  bytes_read = 0;
roentgen b75cab
  uint16 bps, nstrips, planar, strips_per_sample;
roentgen b75cab
  uint32 src_rowsize, dst_rowsize, rows_processed, rps;
roentgen b75cab
  uint32 rows_this_strip = 0;
roentgen b75cab
  tsample_t s;
roentgen b75cab
  tstrip_t  strip;
roentgen b75cab
  tsize_t scanlinesize = TIFFScanlineSize(in);
roentgen b75cab
  tsize_t stripsize    = TIFFStripSize(in);
roentgen b75cab
  unsigned char *srcbuffs[MAX_SAMPLES];
roentgen b75cab
  unsigned char *buff = NULL;
roentgen b75cab
  unsigned char *dst = NULL;
roentgen b75cab
roentgen b75cab
  if (obuf == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("readSeparateStripsIntoBuffer","Invalid buffer argument");
roentgen b75cab
    return (0);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  memset (srcbuffs, '\0', sizeof(srcbuffs));
roentgen b75cab
  TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bps);
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &planar);
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rps);
roentgen b75cab
  if (rps > length)
roentgen b75cab
    rps = length;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
    shift_width = bytes_per_pixel;
roentgen b75cab
  else
roentgen b75cab
    shift_width = bytes_per_sample + 1;
roentgen b75cab
roentgen b75cab
  src_rowsize = ((bps * width) + 7) / 8;
roentgen b75cab
  dst_rowsize = ((bps * width * spp) + 7) / 8;
roentgen b75cab
  dst = obuf;
roentgen b75cab
roentgen b75cab
  if ((dump->infile != NULL) && (dump->level == 3))
roentgen b75cab
    {
roentgen b75cab
    dump_info  (dump->infile, dump->format, "", 
roentgen b75cab
                "Image width %d, length %d, Scanline size, %4d bytes",
roentgen b75cab
                width, length,  scanlinesize);
roentgen b75cab
    dump_info  (dump->infile, dump->format, "", 
roentgen b75cab
                "Bits per sample %d, Samples per pixel %d, Shift width %d",
roentgen b75cab
		bps, spp, shift_width);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* Libtiff seems to assume/require that data for separate planes are 
roentgen b75cab
   * written one complete plane after another and not interleaved in any way.
roentgen b75cab
   * Multiple scanlines and possibly strips of the same plane must be 
roentgen b75cab
   * written before data for any other plane.
roentgen b75cab
   */
roentgen b75cab
  nstrips = TIFFNumberOfStrips(in);
roentgen b75cab
  strips_per_sample = nstrips /spp;
roentgen b75cab
roentgen b75cab
  for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
roentgen b75cab
    {
roentgen b75cab
    srcbuffs[s] = NULL;
roentgen b75cab
    buff = _TIFFmalloc(stripsize);
roentgen b75cab
    if (!buff)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("readSeparateStripsIntoBuffer", 
roentgen b75cab
                 "Unable to allocate strip read buffer for sample %d", s);
roentgen b75cab
      for (i = 0; i < s; i++)
roentgen b75cab
        _TIFFfree (srcbuffs[i]);
roentgen b75cab
      return 0;
roentgen b75cab
      }
roentgen b75cab
    srcbuffs[s] = buff;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  rows_processed = 0;
roentgen b75cab
  for (j = 0; (j < strips_per_sample) && (result == 1); j++)
roentgen b75cab
    {
roentgen b75cab
    for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
roentgen b75cab
      {
roentgen b75cab
      buff = srcbuffs[s];
roentgen b75cab
      strip = (s * strips_per_sample) + j; 
roentgen b75cab
      bytes_read = TIFFReadEncodedStrip (in, strip, buff, stripsize);
roentgen b75cab
      rows_this_strip = bytes_read / src_rowsize;
roentgen b75cab
      if (bytes_read < 0 && !ignore)
roentgen b75cab
        {
roentgen b75cab
        TIFFError(TIFFFileName(in),
roentgen b75cab
	          "Error, can't read strip %lu for sample %d",
roentgen b75cab
         	   (unsigned long) strip, s + 1);
roentgen b75cab
        result = 0;
roentgen b75cab
        break;
roentgen b75cab
        }
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
      TIFFError("", "Strip %2d, read %5d bytes for %4d scanlines, shift width %d", 
roentgen b75cab
		strip, bytes_read, rows_this_strip, shift_width);
roentgen b75cab
#endif
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if (rps > rows_this_strip)
roentgen b75cab
      rps = rows_this_strip;
roentgen b75cab
    dst = obuf + (dst_rowsize * rows_processed);
roentgen b75cab
    if ((bps % 8) == 0)
roentgen b75cab
      {
roentgen b75cab
      if (combineSeparateSamplesBytes (srcbuffs, dst, width, rps,
roentgen b75cab
                                       spp, bps, dump->infile, 
roentgen b75cab
                                       dump->format, dump->level))
roentgen b75cab
        {
roentgen b75cab
        result = 0;
roentgen b75cab
        break;
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      switch (shift_width)
roentgen b75cab
        {
roentgen b75cab
        case 1: if (combineSeparateSamples8bits (srcbuffs, dst, width, rps,
roentgen b75cab
                                                 spp, bps, dump->infile,
roentgen b75cab
                                                 dump->format, dump->level))
roentgen b75cab
	          {
roentgen b75cab
                  result = 0;
roentgen b75cab
                  break;
roentgen b75cab
      	          }
roentgen b75cab
	        break;
roentgen b75cab
        case 2: if (combineSeparateSamples16bits (srcbuffs, dst, width, rps,
roentgen b75cab
                                                  spp, bps, dump->infile,
roentgen b75cab
                                                  dump->format, dump->level))
roentgen b75cab
	          {
roentgen b75cab
                  result = 0;
roentgen b75cab
                  break;
roentgen b75cab
		  }
roentgen b75cab
	        break;
roentgen b75cab
        case 3: if (combineSeparateSamples24bits (srcbuffs, dst, width, rps,
roentgen b75cab
                                                  spp, bps, dump->infile,
roentgen b75cab
                                                  dump->format, dump->level))
roentgen b75cab
	          {
roentgen b75cab
                  result = 0;
roentgen b75cab
                  break;
roentgen b75cab
       	          }
roentgen b75cab
                break;
roentgen b75cab
        case 4: 
roentgen b75cab
        case 5:
roentgen b75cab
        case 6:
roentgen b75cab
        case 7:
roentgen b75cab
        case 8: if (combineSeparateSamples32bits (srcbuffs, dst, width, rps,
roentgen b75cab
                                                  spp, bps, dump->infile,
roentgen b75cab
                                                  dump->format, dump->level))
roentgen b75cab
	          {
roentgen b75cab
                  result = 0;
roentgen b75cab
                  break;
roentgen b75cab
		  }
roentgen b75cab
	        break;
roentgen b75cab
        default: TIFFError ("readSeparateStripsIntoBuffer", "Unsupported bit depth: %d", bps);
roentgen b75cab
                  result = 0;
roentgen b75cab
                  break;
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
 
roentgen b75cab
    if ((rows_processed + rps) > length)
roentgen b75cab
      {
roentgen b75cab
      rows_processed = length;
roentgen b75cab
      rps = length - rows_processed;
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      rows_processed += rps;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* free any buffers allocated for each plane or scanline and 
roentgen b75cab
   * any temporary buffers 
roentgen b75cab
   */
roentgen b75cab
  for (s = 0; (s < spp) && (s < MAX_SAMPLES); s++)
roentgen b75cab
    {
roentgen b75cab
    buff = srcbuffs[s];
roentgen b75cab
    if (buff != NULL)
roentgen b75cab
      _TIFFfree(buff);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (result);
roentgen b75cab
  } /* end readSeparateStripsIntoBuffer */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
get_page_geometry (char *name, struct pagedef *page)
roentgen b75cab
    {
roentgen b75cab
    char *ptr;
roentgen b75cab
    int n; 
roentgen b75cab
roentgen b75cab
    for (ptr = name; *ptr; ptr++)
roentgen b75cab
      *ptr = (char)tolower((int)*ptr);
roentgen b75cab
roentgen b75cab
    for (n = 0; n < MAX_PAPERNAMES; n++)
roentgen b75cab
      {
roentgen b75cab
      if (strcmp(name, PaperTable[n].name) == 0)
roentgen b75cab
        {
roentgen b75cab
	page->width = PaperTable[n].width;
roentgen b75cab
	page->length = PaperTable[n].length;
roentgen b75cab
        strncpy (page->name, PaperTable[n].name, 15);
roentgen b75cab
        page->name[15] = '\0';
roentgen b75cab
        return (0);
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
  return (1);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
initPageSetup (struct pagedef *page, struct pageseg *pagelist, 
roentgen b75cab
               struct buffinfo seg_buffs[])
roentgen b75cab
   {
roentgen b75cab
   int i; 
roentgen b75cab
roentgen b75cab
   strcpy (page->name, "");
roentgen b75cab
   page->mode = PAGE_MODE_NONE;
roentgen b75cab
   page->res_unit = RESUNIT_NONE;
roentgen b75cab
   page->hres = 0.0;
roentgen b75cab
   page->vres = 0.0;
roentgen b75cab
   page->width = 0.0;
roentgen b75cab
   page->length = 0.0;
roentgen b75cab
   page->hmargin = 0.0;
roentgen b75cab
   page->vmargin = 0.0;
roentgen b75cab
   page->rows = 0;
roentgen b75cab
   page->cols = 0;
roentgen b75cab
   page->orient = ORIENTATION_NONE;
roentgen b75cab
roentgen b75cab
   for (i = 0; i < MAX_SECTIONS; i++)
roentgen b75cab
     {
roentgen b75cab
     pagelist[i].x1 = (uint32)0;
roentgen b75cab
     pagelist[i].x2 = (uint32)0;
roentgen b75cab
     pagelist[i].y1 = (uint32)0;
roentgen b75cab
     pagelist[i].y2 = (uint32)0;
roentgen b75cab
     pagelist[i].buffsize = (uint32)0;
roentgen b75cab
     pagelist[i].position = 0;
roentgen b75cab
     pagelist[i].total = 0;
roentgen b75cab
     }
roentgen b75cab
roentgen b75cab
   for (i = 0; i < MAX_OUTBUFFS; i++)
roentgen b75cab
     {
roentgen b75cab
     seg_buffs[i].size = 0;
roentgen b75cab
     seg_buffs[i].buffer = NULL;
roentgen b75cab
     }
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
initImageData (struct image_data *image)
roentgen b75cab
  {
roentgen b75cab
  image->xres = 0.0;
roentgen b75cab
  image->yres = 0.0;
roentgen b75cab
  image->width = 0;
roentgen b75cab
  image->length = 0;
roentgen b75cab
  image->res_unit = RESUNIT_NONE;
roentgen b75cab
  image->bps = 0;
roentgen b75cab
  image->spp = 0;
roentgen b75cab
  image->planar = 0;
roentgen b75cab
  image->photometric = 0;
roentgen b75cab
  image->orientation = 0;
roentgen b75cab
  image->compression = COMPRESSION_NONE;
roentgen b75cab
  image->adjustments = 0;
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
initCropMasks (struct crop_mask *cps)
roentgen b75cab
   {
roentgen b75cab
   int i;
roentgen b75cab
roentgen b75cab
   cps->crop_mode = CROP_NONE;
roentgen b75cab
   cps->res_unit  = RESUNIT_NONE;
roentgen b75cab
   cps->edge_ref  = EDGE_TOP;
roentgen b75cab
   cps->width = 0;
roentgen b75cab
   cps->length = 0;
roentgen b75cab
   for (i = 0; i < 4; i++)
roentgen b75cab
     cps->margins[i] = 0.0;
roentgen b75cab
   cps->bufftotal = (uint32)0;
roentgen b75cab
   cps->combined_width = (uint32)0;
roentgen b75cab
   cps->combined_length = (uint32)0;
roentgen b75cab
   cps->rotation = (uint16)0;
roentgen b75cab
   cps->photometric = INVERT_DATA_AND_TAG;
roentgen b75cab
   cps->mirror   = (uint16)0;
roentgen b75cab
   cps->invert   = (uint16)0;
roentgen b75cab
   cps->zones    = (uint32)0;
roentgen b75cab
   cps->regions  = (uint32)0;
roentgen b75cab
   for (i = 0; i < MAX_REGIONS; i++)
roentgen b75cab
     {
roentgen b75cab
     cps->corners[i].X1 = 0.0;
roentgen b75cab
     cps->corners[i].X2 = 0.0;
roentgen b75cab
     cps->corners[i].Y1 = 0.0;
roentgen b75cab
     cps->corners[i].Y2 = 0.0;
roentgen b75cab
     cps->regionlist[i].x1 = 0;
roentgen b75cab
     cps->regionlist[i].x2 = 0;
roentgen b75cab
     cps->regionlist[i].y1 = 0;
roentgen b75cab
     cps->regionlist[i].y2 = 0;
roentgen b75cab
     cps->regionlist[i].width = 0;
roentgen b75cab
     cps->regionlist[i].length = 0;
roentgen b75cab
     cps->regionlist[i].buffsize = 0;
roentgen b75cab
     cps->regionlist[i].buffptr = NULL;
roentgen b75cab
     cps->zonelist[i].position = 0;
roentgen b75cab
     cps->zonelist[i].total = 0;
roentgen b75cab
     }
roentgen b75cab
   cps->exp_mode = ONE_FILE_COMPOSITE;
roentgen b75cab
   cps->img_mode = COMPOSITE_IMAGES;
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
static void initDumpOptions(struct dump_opts *dump)
roentgen b75cab
  {
roentgen b75cab
  dump->debug  = 0;
roentgen b75cab
  dump->format = DUMP_NONE;
roentgen b75cab
  dump->level  = 1;
roentgen b75cab
  sprintf (dump->mode, "w");
roentgen b75cab
  memset (dump->infilename, '\0', PATH_MAX + 1);
roentgen b75cab
  memset (dump->outfilename, '\0',PATH_MAX + 1);
roentgen b75cab
  dump->infile = NULL;
roentgen b75cab
  dump->outfile = NULL;
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
/* Compute pixel offsets into the image for margins and fixed regions */
roentgen b75cab
static int
roentgen b75cab
computeInputPixelOffsets(struct crop_mask *crop, struct image_data *image,
roentgen b75cab
                         struct offset *off)
roentgen b75cab
  {
roentgen b75cab
  double scale;
roentgen b75cab
  float xres, yres;
roentgen b75cab
  /* Values for these offsets are in pixels from start of image, not bytes,
roentgen b75cab
   * and are indexed from zero to width - 1 or length - 1 */
roentgen b75cab
  uint32 tmargin, bmargin, lmargin, rmargin;
roentgen b75cab
  uint32 startx, endx;   /* offsets of first and last columns to extract */
roentgen b75cab
  uint32 starty, endy;   /* offsets of first and last row to extract */
roentgen b75cab
  uint32 width, length, crop_width, crop_length; 
roentgen b75cab
  uint32 i, max_width, max_length, zwidth, zlength, buffsize;
roentgen b75cab
  uint32 x1, x2, y1, y2;
roentgen b75cab
roentgen b75cab
  if (image->res_unit != RESUNIT_INCH && image->res_unit != RESUNIT_CENTIMETER)
roentgen b75cab
    {
roentgen b75cab
    xres = 1.0;
roentgen b75cab
    yres = 1.0;
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (((image->xres == 0) || (image->yres == 0)) && 
roentgen b75cab
         (crop->res_unit != RESUNIT_NONE) &&
roentgen b75cab
	((crop->crop_mode & CROP_REGIONS) || (crop->crop_mode & CROP_MARGINS) ||
roentgen b75cab
 	 (crop->crop_mode & CROP_LENGTH)  || (crop->crop_mode & CROP_WIDTH)))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("computeInputPixelOffsets", "Cannot compute margins or fixed size sections without image resolution");
roentgen b75cab
      TIFFError("computeInputPixelOffsets", "Specify units in pixels and try again");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    xres = image->xres;
roentgen b75cab
    yres = image->yres;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* Translate user units to image units */
roentgen b75cab
  scale = 1.0;
roentgen b75cab
  switch (crop->res_unit) {
roentgen b75cab
    case RESUNIT_CENTIMETER:
roentgen b75cab
         if (image->res_unit == RESUNIT_INCH)
roentgen b75cab
	   scale = 1.0/2.54;
roentgen b75cab
	 break;
roentgen b75cab
    case RESUNIT_INCH:
roentgen b75cab
	 if (image->res_unit == RESUNIT_CENTIMETER)
roentgen b75cab
	     scale = 2.54;
roentgen b75cab
	 break;
roentgen b75cab
    case RESUNIT_NONE: /* Dimensions in pixels */
roentgen b75cab
    default:
roentgen b75cab
    break;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (crop->crop_mode & CROP_REGIONS)
roentgen b75cab
    {
roentgen b75cab
    max_width = max_length = 0;
roentgen b75cab
    for (i = 0; i < crop->regions; i++)
roentgen b75cab
      {
roentgen b75cab
      if ((crop->res_unit == RESUNIT_INCH) || (crop->res_unit == RESUNIT_CENTIMETER))
roentgen b75cab
        {
roentgen b75cab
	x1 = (uint32) (crop->corners[i].X1 * scale * xres);
roentgen b75cab
	x2 = (uint32) (crop->corners[i].X2 * scale * xres);
roentgen b75cab
	y1 = (uint32) (crop->corners[i].Y1 * scale * yres);
roentgen b75cab
	y2 = (uint32) (crop->corners[i].Y2 * scale * yres);
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	x1 = (uint32) (crop->corners[i].X1);
roentgen b75cab
	x2 = (uint32) (crop->corners[i].X2);
roentgen b75cab
	y1 = (uint32) (crop->corners[i].Y1);
roentgen b75cab
	y2 = (uint32) (crop->corners[i].Y2);       
roentgen b75cab
	}
roentgen b75cab
      if (x1 < 1)
roentgen b75cab
        crop->regionlist[i].x1 = 0;
roentgen b75cab
      else
roentgen b75cab
        crop->regionlist[i].x1 = (uint32) (x1 - 1);
roentgen b75cab
roentgen b75cab
      if (x2 > image->width - 1)
roentgen b75cab
        crop->regionlist[i].x2 = image->width - 1;
roentgen b75cab
      else
roentgen b75cab
        crop->regionlist[i].x2 = (uint32) (x2 - 1);
roentgen b75cab
      zwidth  = crop->regionlist[i].x2 - crop->regionlist[i].x1 + 1; 
roentgen b75cab
roentgen b75cab
      if (y1 < 1)
roentgen b75cab
        crop->regionlist[i].y1 = 0;
roentgen b75cab
      else
roentgen b75cab
        crop->regionlist[i].y1 = (uint32) (y1 - 1);
roentgen b75cab
roentgen b75cab
      if (y2 > image->length - 1)
roentgen b75cab
        crop->regionlist[i].y2 = image->length - 1;
roentgen b75cab
      else
roentgen b75cab
        crop->regionlist[i].y2 = (uint32) (y2 - 1);
roentgen b75cab
roentgen b75cab
      zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1; 
roentgen b75cab
roentgen b75cab
      if (zwidth > max_width)
roentgen b75cab
        max_width = zwidth;
roentgen b75cab
      if (zlength > max_length)
roentgen b75cab
        max_length = zlength;
roentgen b75cab
roentgen b75cab
      buffsize = (uint32)
roentgen b75cab
          (((zwidth * image->bps * image->spp + 7 ) / 8) * (zlength + 1));
roentgen b75cab
roentgen b75cab
      crop->regionlist[i].buffsize = buffsize;
roentgen b75cab
      crop->bufftotal += buffsize;
roentgen b75cab
      if (crop->img_mode == COMPOSITE_IMAGES)
roentgen b75cab
        {
roentgen b75cab
        switch (crop->edge_ref)
roentgen b75cab
          {
roentgen b75cab
          case EDGE_LEFT:
roentgen b75cab
          case EDGE_RIGHT:
roentgen b75cab
               crop->combined_length = zlength;
roentgen b75cab
               crop->combined_width += zwidth;
roentgen b75cab
               break;
roentgen b75cab
          case EDGE_BOTTOM:
roentgen b75cab
          case EDGE_TOP:  /* width from left, length from top */
roentgen b75cab
          default:
roentgen b75cab
               crop->combined_width = zwidth;
roentgen b75cab
               crop->combined_length += zlength;
roentgen b75cab
	       break;
roentgen b75cab
          }
roentgen b75cab
	}
roentgen b75cab
      }
roentgen b75cab
    return (0);
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  /* Convert crop margins into offsets into image
roentgen b75cab
   * Margins are expressed as pixel rows and columns, not bytes
roentgen b75cab
   */
roentgen b75cab
  if (crop->crop_mode & CROP_MARGINS)
roentgen b75cab
    {
roentgen b75cab
    if (crop->res_unit != RESUNIT_INCH && crop->res_unit != RESUNIT_CENTIMETER)
roentgen b75cab
      { /* User has specified pixels as reference unit */
roentgen b75cab
      tmargin = (uint32)(crop->margins[0]);
roentgen b75cab
      lmargin = (uint32)(crop->margins[1]);
roentgen b75cab
      bmargin = (uint32)(crop->margins[2]);
roentgen b75cab
      rmargin = (uint32)(crop->margins[3]);
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      { /* inches or centimeters specified */
roentgen b75cab
      tmargin = (uint32)(crop->margins[0] * scale * yres);
roentgen b75cab
      lmargin = (uint32)(crop->margins[1] * scale * xres);
roentgen b75cab
      bmargin = (uint32)(crop->margins[2] * scale * yres);
roentgen b75cab
      rmargin = (uint32)(crop->margins[3] * scale * xres);
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((lmargin + rmargin) > image->width)
roentgen b75cab
      {
roentgen b75cab
      TIFFError("computeInputPixelOffsets", "Combined left and right margins exceed image width");
roentgen b75cab
      lmargin = (uint32) 0;
roentgen b75cab
      rmargin = (uint32) 0;
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    if ((tmargin + bmargin) > image->length)
roentgen b75cab
      {
roentgen b75cab
      TIFFError("computeInputPixelOffsets", "Combined top and bottom margins exceed image length"); 
roentgen b75cab
      tmargin = (uint32) 0; 
roentgen b75cab
      bmargin = (uint32) 0;
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    { /* no margins requested */
roentgen b75cab
    tmargin = (uint32) 0;
roentgen b75cab
    lmargin = (uint32) 0;
roentgen b75cab
    bmargin = (uint32) 0;
roentgen b75cab
    rmargin = (uint32) 0;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* Width, height, and margins are expressed as pixel offsets into image */
roentgen b75cab
  if (crop->res_unit != RESUNIT_INCH && crop->res_unit != RESUNIT_CENTIMETER)
roentgen b75cab
    {
roentgen b75cab
    if (crop->crop_mode & CROP_WIDTH)
roentgen b75cab
      width = (uint32)crop->width;
roentgen b75cab
    else
roentgen b75cab
      width = image->width - lmargin - rmargin;
roentgen b75cab
roentgen b75cab
    if (crop->crop_mode & CROP_LENGTH)
roentgen b75cab
      length  = (uint32)crop->length;
roentgen b75cab
    else
roentgen b75cab
      length = image->length - tmargin - bmargin;
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (crop->crop_mode & CROP_WIDTH)
roentgen b75cab
      width = (uint32)(crop->width * scale * image->xres);
roentgen b75cab
    else
roentgen b75cab
      width = image->width - lmargin - rmargin;
roentgen b75cab
roentgen b75cab
    if (crop->crop_mode & CROP_LENGTH)
roentgen b75cab
      length  = (uint32)(crop->length * scale * image->yres);
roentgen b75cab
    else
roentgen b75cab
      length = image->length - tmargin - bmargin;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  off->tmargin = tmargin;
roentgen b75cab
  off->bmargin = bmargin;
roentgen b75cab
  off->lmargin = lmargin;
roentgen b75cab
  off->rmargin = rmargin;
roentgen b75cab
roentgen b75cab
  /* Calculate regions defined by margins, width, and length. 
roentgen b75cab
   * Coordinates expressed as 0 to imagewidth - 1, imagelength - 1,
roentgen b75cab
   * since they are used to compute offsets into buffers */
roentgen b75cab
  switch (crop->edge_ref) {
roentgen b75cab
    case EDGE_BOTTOM:
roentgen b75cab
         startx = lmargin;
roentgen b75cab
         if ((startx + width) >= (image->width - rmargin))
roentgen b75cab
           endx = image->width - rmargin - 1;
roentgen b75cab
         else
roentgen b75cab
           endx = startx + width - 1;
roentgen b75cab
roentgen b75cab
         endy = image->length - bmargin - 1;
roentgen b75cab
         if ((endy - length) <= tmargin)
roentgen b75cab
           starty = tmargin;
roentgen b75cab
         else
roentgen b75cab
           starty = endy - length + 1;
roentgen b75cab
         break;
roentgen b75cab
    case EDGE_RIGHT:
roentgen b75cab
         endx = image->width - rmargin - 1;
roentgen b75cab
         if ((endx - width) <= lmargin)
roentgen b75cab
           startx = lmargin;
roentgen b75cab
         else
roentgen b75cab
           startx = endx - width + 1;
roentgen b75cab
roentgen b75cab
         starty = tmargin;
roentgen b75cab
         if ((starty + length) >= (image->length - bmargin))
roentgen b75cab
           endy = image->length - bmargin - 1;
roentgen b75cab
         else
roentgen b75cab
           endy = starty + length - 1;
roentgen b75cab
         break;
roentgen b75cab
    case EDGE_TOP:  /* width from left, length from top */
roentgen b75cab
    case EDGE_LEFT:
roentgen b75cab
    default:
roentgen b75cab
         startx = lmargin;
roentgen b75cab
         if ((startx + width) >= (image->width - rmargin))
roentgen b75cab
           endx = image->width - rmargin - 1;
roentgen b75cab
         else
roentgen b75cab
           endx = startx + width - 1;
roentgen b75cab
roentgen b75cab
         starty = tmargin;
roentgen b75cab
         if ((starty + length) >= (image->length - bmargin))
roentgen b75cab
           endy = image->length - bmargin - 1;
roentgen b75cab
         else
roentgen b75cab
           endy = starty + length - 1;
roentgen b75cab
         break;
roentgen b75cab
    }
roentgen b75cab
  off->startx = startx;
roentgen b75cab
  off->starty = starty;
roentgen b75cab
  off->endx   = endx;
roentgen b75cab
  off->endy   = endy;
roentgen b75cab
roentgen b75cab
  crop_width  = endx - startx + 1;
roentgen b75cab
  crop_length = endy - starty + 1;
roentgen b75cab
roentgen b75cab
  if (crop_width <= 0)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("computeInputPixelOffsets", 
roentgen b75cab
               "Invalid left/right margins and /or image crop width requested");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
  if (crop_width > image->width)
roentgen b75cab
    crop_width = image->width;
roentgen b75cab
roentgen b75cab
  if (crop_length <= 0)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("computeInputPixelOffsets", 
roentgen b75cab
              "Invalid top/bottom margins and /or image crop length requested");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
  if (crop_length > image->length)
roentgen b75cab
    crop_length = image->length;
roentgen b75cab
roentgen b75cab
  off->crop_width = crop_width;
roentgen b75cab
  off->crop_length = crop_length;
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end computeInputPixelOffsets */
roentgen b75cab
roentgen b75cab
/* 
roentgen b75cab
 * Translate crop options into pixel offsets for one or more regions of the image.
roentgen b75cab
 * Options are applied in this order: margins, specific width and length, zones,
roentgen b75cab
 * but all are optional. Margins are relative to each edge. Width, length and
roentgen b75cab
 * zones are relative to the specified reference edge. Zones are expressed as
roentgen b75cab
 * X:Y where X is the ordinal value in a set of Y equal sized portions. eg.
roentgen b75cab
 * 2:3 would indicate the middle third of the region qualified by margins and
roentgen b75cab
 * any explicit width and length specified. Regions are specified by coordinates
roentgen b75cab
 * of the top left and lower right corners with range 1 to width or height.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
getCropOffsets(struct image_data *image, struct crop_mask *crop, struct dump_opts *dump)
roentgen b75cab
  {
roentgen b75cab
  struct offset offsets;
roentgen b75cab
  int    i;
roentgen b75cab
  int32  test;
roentgen b75cab
  uint32 seg, total, need_buff = 0;
roentgen b75cab
  uint32 buffsize;
roentgen b75cab
  uint32 zwidth, zlength;
roentgen b75cab
roentgen b75cab
  memset(&offsets, '\0', sizeof(struct offset));
roentgen b75cab
  crop->bufftotal = 0;
roentgen b75cab
  crop->combined_width  = (uint32)0;
roentgen b75cab
  crop->combined_length = (uint32)0;
roentgen b75cab
  crop->selections = 0;
roentgen b75cab
roentgen b75cab
  /* Compute pixel offsets if margins or fixed width or length specified */
roentgen b75cab
  if ((crop->crop_mode & CROP_MARGINS) ||
roentgen b75cab
      (crop->crop_mode & CROP_REGIONS) ||
roentgen b75cab
      (crop->crop_mode & CROP_LENGTH)  || 
roentgen b75cab
      (crop->crop_mode & CROP_WIDTH))
roentgen b75cab
    {
roentgen b75cab
    if (computeInputPixelOffsets(crop, image, &offsets))
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("getCropOffsets", "Unable to compute crop margins");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    need_buff = TRUE;
roentgen b75cab
    crop->selections = crop->regions;
roentgen b75cab
    /* Regions are only calculated from top and left edges with no margins */
roentgen b75cab
    if (crop->crop_mode & CROP_REGIONS)
roentgen b75cab
      return (0);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    { /* cropped area is the full image */
roentgen b75cab
    offsets.tmargin = 0;
roentgen b75cab
    offsets.lmargin = 0;
roentgen b75cab
    offsets.bmargin = 0;
roentgen b75cab
    offsets.rmargin = 0;
roentgen b75cab
    offsets.crop_width = image->width;
roentgen b75cab
    offsets.crop_length = image->length;
roentgen b75cab
    offsets.startx = 0;
roentgen b75cab
    offsets.endx = image->width - 1;
roentgen b75cab
    offsets.starty = 0;
roentgen b75cab
    offsets.endy = image->length - 1;
roentgen b75cab
    need_buff = FALSE;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (dump->outfile != NULL)
roentgen b75cab
    {
roentgen b75cab
    dump_info (dump->outfile, dump->format, "", "Margins: Top: %d  Left: %d  Bottom: %d  Right: %d", 
roentgen b75cab
           offsets.tmargin, offsets.lmargin, offsets.bmargin, offsets.rmargin); 
roentgen b75cab
    dump_info (dump->outfile, dump->format, "", "Crop region within margins: Adjusted Width:  %6d  Length: %6d", 
roentgen b75cab
           offsets.crop_width, offsets.crop_length);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!(crop->crop_mode & CROP_ZONES)) /* no crop zones requested */
roentgen b75cab
    {
roentgen b75cab
    if (need_buff == FALSE)  /* No margins or fixed width or length areas */
roentgen b75cab
      {
roentgen b75cab
      crop->selections = 0;
roentgen b75cab
      crop->combined_width  = image->width;
roentgen b75cab
      crop->combined_length = image->length;
roentgen b75cab
      return (0);
roentgen b75cab
      }
roentgen b75cab
    else 
roentgen b75cab
      {
roentgen b75cab
      /* Use one region for margins and fixed width or length areas
roentgen b75cab
       * even though it was not formally declared as a region.
roentgen b75cab
       */
roentgen b75cab
      crop->selections = 1;
roentgen b75cab
      crop->zones = 1;
roentgen b75cab
      crop->zonelist[0].total = 1;
roentgen b75cab
      crop->zonelist[0].position = 1;
roentgen b75cab
      }
roentgen b75cab
    }     
roentgen b75cab
  else
roentgen b75cab
    crop->selections = crop->zones;
roentgen b75cab
roentgen b75cab
  for (i = 0; i < crop->zones; i++)
roentgen b75cab
    {
roentgen b75cab
    seg = crop->zonelist[i].position;
roentgen b75cab
    total = crop->zonelist[i].total;
roentgen b75cab
roentgen b75cab
    switch (crop->edge_ref) 
roentgen b75cab
      {
roentgen b75cab
      case EDGE_LEFT: /* zones from left to right, length from top */
roentgen b75cab
           zlength = offsets.crop_length;
roentgen b75cab
	   crop->regionlist[i].y1 = offsets.starty;
roentgen b75cab
           crop->regionlist[i].y2 = offsets.endy;
roentgen b75cab
roentgen b75cab
           crop->regionlist[i].x1 = offsets.startx + 
roentgen b75cab
                                  (uint32)(offsets.crop_width * 1.0 * (seg - 1) / total);
roentgen b75cab
           test = (int32)offsets.startx + 
roentgen b75cab
                  (int32)(offsets.crop_width * 1.0 * seg / total);
roentgen b75cab
           if (test < 1 )
roentgen b75cab
             crop->regionlist[i].x2 = 0;
roentgen b75cab
           else
roentgen b75cab
	     {
roentgen b75cab
	     if (test > (int32)(image->width - 1))
roentgen b75cab
               crop->regionlist[i].x2 = image->width - 1;
roentgen b75cab
             else
roentgen b75cab
	       crop->regionlist[i].x2 = test - 1;
roentgen b75cab
             }
roentgen b75cab
           zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1  + 1;
roentgen b75cab
roentgen b75cab
	   /* This is passed to extractCropZone or extractCompositeZones */
roentgen b75cab
           crop->combined_length = (uint32)zlength;
roentgen b75cab
           if (crop->exp_mode == COMPOSITE_IMAGES)
roentgen b75cab
             crop->combined_width += (uint32)zwidth;
roentgen b75cab
           else
roentgen b75cab
             crop->combined_width = (uint32)zwidth;
roentgen b75cab
           break;
roentgen b75cab
      case EDGE_BOTTOM: /* width from left, zones from bottom to top */
roentgen b75cab
           zwidth = offsets.crop_width;
roentgen b75cab
	   crop->regionlist[i].x1 = offsets.startx;
roentgen b75cab
           crop->regionlist[i].x2 = offsets.endx;
roentgen b75cab
roentgen b75cab
           test = offsets.endy - (uint32)(offsets.crop_length * 1.0 * seg / total);
roentgen b75cab
           if (test < 1 )
roentgen b75cab
	     crop->regionlist[i].y1 = 0;
roentgen b75cab
           else
roentgen b75cab
	     crop->regionlist[i].y1 = test + 1;
roentgen b75cab
roentgen b75cab
           test = offsets.endy - (offsets.crop_length * 1.0 * (seg - 1) / total);
roentgen b75cab
           if (test < 1 )
roentgen b75cab
             crop->regionlist[i].y2 = 0;
roentgen b75cab
           else
roentgen b75cab
	     {
roentgen b75cab
             if (test > (int32)(image->length - 1))
roentgen b75cab
               crop->regionlist[i].y2 = image->length - 1;
roentgen b75cab
             else 
roentgen b75cab
               crop->regionlist[i].y2 = test;
roentgen b75cab
	     }
roentgen b75cab
           zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
roentgen b75cab
roentgen b75cab
	   /* This is passed to extractCropZone or extractCompositeZones */
roentgen b75cab
           if (crop->exp_mode == COMPOSITE_IMAGES)
roentgen b75cab
             crop->combined_length += (uint32)zlength;
roentgen b75cab
           else
roentgen b75cab
             crop->combined_length = (uint32)zlength;
roentgen b75cab
           crop->combined_width = (uint32)zwidth;
roentgen b75cab
           break;
roentgen b75cab
      case EDGE_RIGHT: /* zones from right to left, length from top */
roentgen b75cab
           zlength = offsets.crop_length;
roentgen b75cab
	   crop->regionlist[i].y1 = offsets.starty;
roentgen b75cab
           crop->regionlist[i].y2 = offsets.endy;
roentgen b75cab
roentgen b75cab
           crop->regionlist[i].x1 = offsets.startx +
roentgen b75cab
                                  (uint32)(offsets.crop_width  * (total - seg) * 1.0 / total);
roentgen b75cab
           test = offsets.startx + 
roentgen b75cab
	          (offsets.crop_width * (total - seg + 1) * 1.0 / total);
roentgen b75cab
           if (test < 1 )
roentgen b75cab
             crop->regionlist[i].x2 = 0;
roentgen b75cab
           else
roentgen b75cab
	     {
roentgen b75cab
	     if (test > (int32)(image->width - 1))
roentgen b75cab
               crop->regionlist[i].x2 = image->width - 1;
roentgen b75cab
             else
roentgen b75cab
               crop->regionlist[i].x2 = test - 1;
roentgen b75cab
             }
roentgen b75cab
           zwidth = crop->regionlist[i].x2 - crop->regionlist[i].x1  + 1;
roentgen b75cab
roentgen b75cab
	   /* This is passed to extractCropZone or extractCompositeZones */
roentgen b75cab
           crop->combined_length = (uint32)zlength;
roentgen b75cab
           if (crop->exp_mode == COMPOSITE_IMAGES)
roentgen b75cab
             crop->combined_width += (uint32)zwidth;
roentgen b75cab
           else
roentgen b75cab
             crop->combined_width = (uint32)zwidth;
roentgen b75cab
           break;
roentgen b75cab
      case EDGE_TOP: /* width from left, zones from top to bottom */
roentgen b75cab
      default:
roentgen b75cab
           zwidth = offsets.crop_width;
roentgen b75cab
	   crop->regionlist[i].x1 = offsets.startx;
roentgen b75cab
           crop->regionlist[i].x2 = offsets.endx;
roentgen b75cab
roentgen b75cab
           crop->regionlist[i].y1 = offsets.starty + (uint32)(offsets.crop_length * 1.0 * (seg - 1) / total);
roentgen b75cab
           test = offsets.starty + (uint32)(offsets.crop_length * 1.0 * seg / total);
roentgen b75cab
           if (test < 1 )
roentgen b75cab
             crop->regionlist[i].y2 = 0;
roentgen b75cab
           else
roentgen b75cab
	     {
roentgen b75cab
	     if (test > (int32)(image->length - 1))
roentgen b75cab
	       crop->regionlist[i].y2 = image->length - 1;
roentgen b75cab
             else
roentgen b75cab
	       crop->regionlist[i].y2 = test - 1;
roentgen b75cab
	     }
roentgen b75cab
           zlength = crop->regionlist[i].y2 - crop->regionlist[i].y1 + 1;
roentgen b75cab
roentgen b75cab
	   /* This is passed to extractCropZone or extractCompositeZones */
roentgen b75cab
           if (crop->exp_mode == COMPOSITE_IMAGES)
roentgen b75cab
             crop->combined_length += (uint32)zlength;
roentgen b75cab
           else
roentgen b75cab
             crop->combined_length = (uint32)zlength;
roentgen b75cab
           crop->combined_width = (uint32)zwidth;
roentgen b75cab
           break;
roentgen b75cab
      } /* end switch statement */
roentgen b75cab
roentgen b75cab
    buffsize = (uint32)
roentgen b75cab
          ((((zwidth * image->bps * image->spp) + 7 ) / 8) * (zlength + 1));
roentgen b75cab
    crop->regionlist[i].width = (uint32) zwidth;
roentgen b75cab
    crop->regionlist[i].length = (uint32) zlength;
roentgen b75cab
    crop->regionlist[i].buffsize = buffsize;
roentgen b75cab
    crop->bufftotal += buffsize;
roentgen b75cab
roentgen b75cab
roentgen b75cab
  if (dump->outfile != NULL)
roentgen b75cab
    dump_info (dump->outfile, dump->format, "",  "Zone %d, width: %4d, length: %4d, x1: %4d  x2: %4d  y1: %4d  y2: %4d",
roentgen b75cab
                    i + 1, (uint32)zwidth, (uint32)zlength,
roentgen b75cab
		    crop->regionlist[i].x1, crop->regionlist[i].x2, 
roentgen b75cab
                    crop->regionlist[i].y1, crop->regionlist[i].y2);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end getCropOffsets */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
computeOutputPixelOffsets (struct crop_mask *crop, struct image_data *image,
roentgen b75cab
                           struct pagedef *page, struct pageseg *sections,
roentgen b75cab
                           struct dump_opts* dump)
roentgen b75cab
  {
roentgen b75cab
  double scale;
roentgen b75cab
  double pwidth, plength;          /* Output page width and length in user units*/
roentgen b75cab
  uint32 iwidth, ilength;          /* Input image width and length in pixels*/
roentgen b75cab
  uint32 owidth, olength;          /* Output image width and length in pixels*/
roentgen b75cab
  uint32 orows, ocols;             /* rows and cols for output */
roentgen b75cab
  uint32 hmargin, vmargin;         /* Horizontal and vertical margins */
roentgen b75cab
  uint32 x1, x2, y1, y2, line_bytes;
roentgen b75cab
  unsigned int orientation;
roentgen b75cab
  uint32 i, j, k;
roentgen b75cab
 
roentgen b75cab
  scale = 1.0;
roentgen b75cab
  if (page->res_unit == RESUNIT_NONE)
roentgen b75cab
    page->res_unit = image->res_unit;
roentgen b75cab
roentgen b75cab
  switch (image->res_unit) {
roentgen b75cab
    case RESUNIT_CENTIMETER:
roentgen b75cab
         if (page->res_unit == RESUNIT_INCH)
roentgen b75cab
	   scale = 1.0/2.54;
roentgen b75cab
	 break;
roentgen b75cab
    case RESUNIT_INCH:
roentgen b75cab
	 if (page->res_unit == RESUNIT_CENTIMETER)
roentgen b75cab
	     scale = 2.54;
roentgen b75cab
	 break;
roentgen b75cab
    case RESUNIT_NONE: /* Dimensions in pixels */
roentgen b75cab
    default:
roentgen b75cab
    break;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* get width, height, resolutions of input image selection */
roentgen b75cab
  if (crop->combined_width > 0)
roentgen b75cab
    iwidth = crop->combined_width;
roentgen b75cab
  else
roentgen b75cab
    iwidth = image->width;
roentgen b75cab
  if (crop->combined_length > 0)
roentgen b75cab
    ilength = crop->combined_length;
roentgen b75cab
  else
roentgen b75cab
    ilength = image->length;
roentgen b75cab
roentgen b75cab
  if (page->hres <= 1.0)
roentgen b75cab
    page->hres = image->xres;
roentgen b75cab
  if (page->vres <= 1.0)
roentgen b75cab
    page->vres = image->yres;
roentgen b75cab
roentgen b75cab
  if ((page->hres < 1.0) || (page->vres < 1.0))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("computeOutputPixelOffsets",
roentgen b75cab
    "Invalid horizontal or vertical resolution specified or read from input image");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* If no page sizes are being specified, we just use the input image size to
roentgen b75cab
   * calculate maximum margins that can be taken from image.
roentgen b75cab
   */
roentgen b75cab
  if (page->width <= 0)
roentgen b75cab
    pwidth = iwidth;
roentgen b75cab
  else
roentgen b75cab
    pwidth = page->width;
roentgen b75cab
roentgen b75cab
  if (page->length <= 0)
roentgen b75cab
    plength = ilength;
roentgen b75cab
  else
roentgen b75cab
    plength = page->length;
roentgen b75cab
roentgen b75cab
  if (dump->debug)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("", "Page size: %s, Vres: %3.2f, Hres: %3.2f, "
roentgen b75cab
                   "Hmargin: %3.2f, Vmargin: %3.2f",
roentgen b75cab
	     page->name, page->vres, page->hres,
roentgen b75cab
             page->hmargin, page->vmargin);
roentgen b75cab
    TIFFError("", "Res_unit: %d, Scale: %3.2f, Page width: %3.2f, length: %3.2f", 
roentgen b75cab
           page->res_unit, scale, pwidth, plength);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* compute margins at specified unit and resolution */
roentgen b75cab
  if (page->mode & PAGE_MODE_MARGINS)
roentgen b75cab
    {
roentgen b75cab
    if (page->res_unit == RESUNIT_INCH || page->res_unit == RESUNIT_CENTIMETER)
roentgen b75cab
      { /* inches or centimeters specified */
roentgen b75cab
      hmargin = (uint32)(page->hmargin * scale * page->hres * ((image->bps + 7)/ 8));
roentgen b75cab
      vmargin = (uint32)(page->vmargin * scale * page->vres * ((image->bps + 7)/ 8));
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      { /* Otherwise user has specified pixels as reference unit */
roentgen b75cab
      hmargin = (uint32)(page->hmargin * scale * ((image->bps + 7)/ 8));
roentgen b75cab
      vmargin = (uint32)(page->vmargin * scale * ((image->bps + 7)/ 8));
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if ((hmargin * 2.0) > (pwidth * page->hres))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("computeOutputPixelOffsets", 
roentgen b75cab
                "Combined left and right margins exceed page width");
roentgen b75cab
      hmargin = (uint32) 0;
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    if ((vmargin * 2.0) > (plength * page->vres))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("computeOutputPixelOffsets", 
roentgen b75cab
                "Combined top and bottom margins exceed page length"); 
roentgen b75cab
      vmargin = (uint32) 0; 
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    hmargin = 0;
roentgen b75cab
    vmargin = 0;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (page->mode & PAGE_MODE_ROWSCOLS )
roentgen b75cab
    {
roentgen b75cab
    /* Maybe someday but not for now */
roentgen b75cab
    if (page->mode & PAGE_MODE_MARGINS)
roentgen b75cab
      TIFFError("computeOutputPixelOffsets", 
roentgen b75cab
      "Output margins cannot be specified with rows and columns"); 
roentgen b75cab
roentgen b75cab
    owidth  = TIFFhowmany(iwidth, page->cols);
roentgen b75cab
    olength = TIFFhowmany(ilength, page->rows);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (page->mode & PAGE_MODE_PAPERSIZE )
roentgen b75cab
      {
roentgen b75cab
      owidth  = (uint32)((pwidth * page->hres) - (hmargin * 2));
roentgen b75cab
      olength = (uint32)((plength * page->vres) - (vmargin * 2));
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      owidth = (uint32)(iwidth - (hmargin * 2 * page->hres));
roentgen b75cab
      olength = (uint32)(ilength - (vmargin * 2 * page->vres));
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (owidth > iwidth)
roentgen b75cab
    owidth = iwidth;
roentgen b75cab
  if (olength > ilength)
roentgen b75cab
    olength = ilength;
roentgen b75cab
roentgen b75cab
  /* Compute the number of pages required for Portrait or Landscape */
roentgen b75cab
  switch (page->orient)
roentgen b75cab
    {
roentgen b75cab
    case ORIENTATION_NONE:
roentgen b75cab
    case ORIENTATION_PORTRAIT:
roentgen b75cab
         ocols = TIFFhowmany(iwidth, owidth);
roentgen b75cab
         orows = TIFFhowmany(ilength, olength);
roentgen b75cab
         orientation = ORIENTATION_PORTRAIT;
roentgen b75cab
         break;
roentgen b75cab
roentgen b75cab
    case ORIENTATION_LANDSCAPE:
roentgen b75cab
         ocols = TIFFhowmany(iwidth, olength);
roentgen b75cab
         orows = TIFFhowmany(ilength, owidth);
roentgen b75cab
         x1 = olength;
roentgen b75cab
         olength = owidth;
roentgen b75cab
         owidth = x1;
roentgen b75cab
         orientation = ORIENTATION_LANDSCAPE;
roentgen b75cab
         break;
roentgen b75cab
roentgen b75cab
    case ORIENTATION_AUTO:
roentgen b75cab
    default:
roentgen b75cab
         x1 = TIFFhowmany(iwidth, owidth);
roentgen b75cab
         x2 = TIFFhowmany(ilength, olength); 
roentgen b75cab
         y1 = TIFFhowmany(iwidth, olength);
roentgen b75cab
         y2 = TIFFhowmany(ilength, owidth); 
roentgen b75cab
roentgen b75cab
         if ( (x1 * x2) < (y1 * y2))
roentgen b75cab
           { /* Portrait */
roentgen b75cab
           ocols = x1;
roentgen b75cab
           orows = x2;
roentgen b75cab
           orientation = ORIENTATION_PORTRAIT;
roentgen b75cab
	   }
roentgen b75cab
         else
roentgen b75cab
           { /* Landscape */
roentgen b75cab
           ocols = y1;
roentgen b75cab
           orows = y2;
roentgen b75cab
           x1 = olength;
roentgen b75cab
           olength = owidth;
roentgen b75cab
           owidth = x1;
roentgen b75cab
           orientation = ORIENTATION_LANDSCAPE;
roentgen b75cab
           }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (ocols < 1)
roentgen b75cab
    ocols = 1;
roentgen b75cab
  if (orows < 1)
roentgen b75cab
    orows = 1;
roentgen b75cab
roentgen b75cab
  /* If user did not specify rows and cols, set them from calcuation */
roentgen b75cab
  if (page->rows < 1)
roentgen b75cab
    page->rows = orows;
roentgen b75cab
  if (page->cols < 1)
roentgen b75cab
    page->cols = ocols;
roentgen b75cab
roentgen b75cab
  line_bytes = TIFFhowmany8(owidth * image->bps) * image->spp;
roentgen b75cab
roentgen b75cab
  if ((page->rows * page->cols) > MAX_SECTIONS)
roentgen b75cab
   {
roentgen b75cab
   TIFFError("computeOutputPixelOffsets",
roentgen b75cab
	     "Rows and Columns exceed maximum sections\nIncrease resolution or reduce sections");
roentgen b75cab
   return (-1);
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
  /* build the list of offsets for each output section */
roentgen b75cab
  for (k = 0, i = 0 && k <= MAX_SECTIONS; i < orows; i++)
roentgen b75cab
    {
roentgen b75cab
    y1 = (uint32)(olength * i);
roentgen b75cab
    y2 = (uint32)(olength * (i +  1) - 1);
roentgen b75cab
    if (y2 >= ilength)
roentgen b75cab
      y2 = ilength - 1;
roentgen b75cab
    for (j = 0; j < ocols; j++, k++)
roentgen b75cab
      {
roentgen b75cab
      x1 = (uint32)(owidth * j); 
roentgen b75cab
      x2 = (uint32)(owidth * (j + 1) - 1);
roentgen b75cab
      if (x2 >= iwidth)
roentgen b75cab
        x2 = iwidth - 1;
roentgen b75cab
      sections[k].x1 = x1;
roentgen b75cab
      sections[k].x2 = x2;
roentgen b75cab
      sections[k].y1 = y1;
roentgen b75cab
      sections[k].y2 = y2;
roentgen b75cab
      sections[k].buffsize = line_bytes * olength;
roentgen b75cab
      sections[k].position = k + 1;
roentgen b75cab
      sections[k].total = orows * ocols;
roentgen b75cab
      } 
roentgen b75cab
    } 
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end computeOutputPixelOffsets */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
loadImage(TIFF* in, struct image_data *image, struct dump_opts *dump, unsigned char **read_ptr)
roentgen b75cab
  {
roentgen b75cab
  uint32   i;
roentgen b75cab
  float    xres = 0.0, yres = 0.0;
roentgen b75cab
  uint16   nstrips = 0, ntiles = 0, planar = 0;
roentgen b75cab
  uint16   bps = 0, spp = 0, res_unit = 0;
roentgen b75cab
  uint16   orientation = 0;
roentgen b75cab
  uint16   input_compression = 0, input_photometric = 0;
roentgen b75cab
  uint16   subsampling_horiz, subsampling_vert;
roentgen b75cab
  uint32   width = 0, length = 0;
roentgen b75cab
  uint32   stsize = 0, tlsize = 0, buffsize = 0, scanlinesize = 0;
roentgen b75cab
  uint32   tw = 0, tl = 0;       /* Tile width and length */
roentgen b75cab
  uint32   tile_rowsize = 0;
roentgen b75cab
  unsigned char *read_buff = NULL;
roentgen b75cab
  unsigned char *new_buff  = NULL;
roentgen b75cab
  int      readunit = 0;
roentgen b75cab
  static   uint32  prev_readsize = 0;
roentgen b75cab
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_BITSPERSAMPLE, &bps);
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_SAMPLESPERPIXEL, &spp);
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &planar);
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_ORIENTATION, &orientation);
roentgen b75cab
  if (! TIFFGetFieldDefaulted(in, TIFFTAG_PHOTOMETRIC, &input_photometric))
roentgen b75cab
    TIFFError("loadImage","Image lacks Photometric interpreation tag");
roentgen b75cab
  if (! TIFFGetField(in, TIFFTAG_IMAGEWIDTH,  &width))
roentgen b75cab
    TIFFError("loadimage","Image lacks image width tag");
roentgen b75cab
  if(! TIFFGetField(in, TIFFTAG_IMAGELENGTH, &length))
roentgen b75cab
    TIFFError("loadimage","Image lacks image length tag");
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_XRESOLUTION, &xres);
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_YRESOLUTION, &yres);
roentgen b75cab
  if (!TIFFGetFieldDefaulted(in, TIFFTAG_RESOLUTIONUNIT, &res_unit))
roentgen b75cab
    res_unit = RESUNIT_INCH;
roentgen b75cab
  if (!TIFFGetField(in, TIFFTAG_COMPRESSION, &input_compression))
roentgen b75cab
    input_compression = COMPRESSION_NONE;
roentgen b75cab
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
  char compressionid[16];
roentgen b75cab
roentgen b75cab
  switch (input_compression)
roentgen b75cab
    {
roentgen b75cab
    case COMPRESSION_NONE:	/* 1  dump mode */
roentgen b75cab
	 strcpy (compressionid, "None/dump");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_CCITTRLE:	  /* 2 CCITT modified Huffman RLE */
roentgen b75cab
	 strcpy (compressionid, "Huffman RLE");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_CCITTFAX3:	  /* 3 CCITT Group 3 fax encoding */
roentgen b75cab
	 strcpy (compressionid, "Group3 Fax");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_CCITTFAX4:	  /* 4 CCITT Group 4 fax encoding */
roentgen b75cab
	 strcpy (compressionid, "Group4 Fax");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_LZW:	  /* 5 Lempel-Ziv  & Welch */
roentgen b75cab
	 strcpy (compressionid, "LZW");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_OJPEG:	  /* 6 !6.0 JPEG */
roentgen b75cab
	 strcpy (compressionid, "Old Jpeg");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_JPEG:	  /* 7 %JPEG DCT compression */
roentgen b75cab
	 strcpy (compressionid, "New Jpeg");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_NEXT:	  /* 32766 NeXT 2-bit RLE */
roentgen b75cab
	 strcpy (compressionid, "Next RLE");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_CCITTRLEW:   /* 32771 #1 w/ word alignment */
roentgen b75cab
	 strcpy (compressionid, "CITTRLEW");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_PACKBITS:	  /* 32773 Macintosh RLE */
roentgen b75cab
	 strcpy (compressionid, "Mac Packbits");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_THUNDERSCAN: /* 32809 ThunderScan RLE */
roentgen b75cab
	 strcpy (compressionid, "Thunderscan");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_IT8CTPAD:	  /* 32895 IT8 CT w/padding */
roentgen b75cab
	 strcpy (compressionid, "IT8 padded");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_IT8LW:	  /* 32896 IT8 Linework RLE */
roentgen b75cab
	 strcpy (compressionid, "IT8 RLE");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_IT8MP:	  /* 32897 IT8 Monochrome picture */
roentgen b75cab
	 strcpy (compressionid, "IT8 mono");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_IT8BL:	  /* 32898 IT8 Binary line art */
roentgen b75cab
	 strcpy (compressionid, "IT8 lineart");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_PIXARFILM:	  /* 32908 Pixar companded 10bit LZW */
roentgen b75cab
	 strcpy (compressionid, "Pixar 10 bit");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_PIXARLOG:	  /* 32909 Pixar companded 11bit ZIP */
roentgen b75cab
	 strcpy (compressionid, "Pixar 11bit");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_DEFLATE:	  /* 32946 Deflate compression */
roentgen b75cab
	 strcpy (compressionid, "Deflate");
roentgen b75cab
         break;         
roentgen b75cab
    case COMPRESSION_ADOBE_DEFLATE: /* 8 Deflate compression */
roentgen b75cab
	 strcpy (compressionid, "Adobe deflate");
roentgen b75cab
         break;         
roentgen b75cab
    default:
roentgen b75cab
	 strcpy (compressionid, "None/unknown");
roentgen b75cab
         break;         
roentgen b75cab
    }
roentgen b75cab
  TIFFError("loadImage", "Input compression %s", compressionid);
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
  scanlinesize = TIFFScanlineSize(in);
roentgen b75cab
  image->bps = bps;
roentgen b75cab
  image->spp = spp;
roentgen b75cab
  image->planar = planar;
roentgen b75cab
  image->width = width;
roentgen b75cab
  image->length = length;
roentgen b75cab
  image->xres = xres;
roentgen b75cab
  image->yres = yres;
roentgen b75cab
  image->res_unit = res_unit;
roentgen b75cab
  image->compression = input_compression;
roentgen b75cab
  image->photometric = input_photometric;
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
  char photometricid[12];
roentgen b75cab
roentgen b75cab
  switch (input_photometric)
roentgen b75cab
    {
roentgen b75cab
    case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
         strcpy (photometricid, "MinIsWhite");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
         strcpy (photometricid, "MinIsBlack");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_RGB:
roentgen b75cab
         strcpy (photometricid, "RGB");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_PALETTE:
roentgen b75cab
         strcpy (photometricid, "Palette");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_MASK:
roentgen b75cab
         strcpy (photometricid, "Mask");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_SEPARATED:
roentgen b75cab
         strcpy (photometricid, "Separated");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_YCBCR:
roentgen b75cab
         strcpy (photometricid, "YCBCR");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_CIELAB:
roentgen b75cab
         strcpy (photometricid, "CIELab");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_ICCLAB:
roentgen b75cab
         strcpy (photometricid, "ICCLab");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_ITULAB:
roentgen b75cab
         strcpy (photometricid, "ITULab");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_LOGL:
roentgen b75cab
         strcpy (photometricid, "LogL");
roentgen b75cab
         break;
roentgen b75cab
    case PHOTOMETRIC_LOGLUV:
roentgen b75cab
         strcpy (photometricid, "LOGLuv");
roentgen b75cab
         break;
roentgen b75cab
    default:
roentgen b75cab
         strcpy (photometricid, "Unknown");
roentgen b75cab
         break;
roentgen b75cab
    }
roentgen b75cab
  TIFFError("loadImage", "Input photometric interpretation %s", photometricid);
roentgen b75cab
roentgen b75cab
#endif
roentgen b75cab
  image->orientation = orientation;
roentgen b75cab
  switch (orientation)
roentgen b75cab
    {
roentgen b75cab
    case 0:
roentgen b75cab
    case ORIENTATION_TOPLEFT:
roentgen b75cab
         image->adjustments = 0;
roentgen b75cab
	 break;
roentgen b75cab
    case ORIENTATION_TOPRIGHT:
roentgen b75cab
         image->adjustments = MIRROR_HORIZ;
roentgen b75cab
	 break;
roentgen b75cab
    case ORIENTATION_BOTRIGHT:
roentgen b75cab
         image->adjustments = ROTATECW_180;
roentgen b75cab
	 break;
roentgen b75cab
    case ORIENTATION_BOTLEFT:
roentgen b75cab
         image->adjustments = MIRROR_VERT; 
roentgen b75cab
	 break;
roentgen b75cab
    case ORIENTATION_LEFTTOP:
roentgen b75cab
         image->adjustments = MIRROR_VERT | ROTATECW_90;
roentgen b75cab
	 break;
roentgen b75cab
    case ORIENTATION_RIGHTTOP:
roentgen b75cab
         image->adjustments = ROTATECW_90;
roentgen b75cab
	 break;
roentgen b75cab
    case ORIENTATION_RIGHTBOT:
roentgen b75cab
         image->adjustments = MIRROR_VERT | ROTATECW_270;
roentgen b75cab
	 break; 
roentgen b75cab
    case ORIENTATION_LEFTBOT:
roentgen b75cab
         image->adjustments = ROTATECW_270;
roentgen b75cab
	 break;
roentgen b75cab
    default:
roentgen b75cab
         image->adjustments = 0;
roentgen b75cab
         image->orientation = ORIENTATION_TOPLEFT;
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
  if ((bps == 0) || (spp == 0))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("loadImage", "Invalid samples per pixel (%d) or bits per sample (%d)",
roentgen b75cab
	       spp, bps);
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (TIFFIsTiled(in))
roentgen b75cab
    {
roentgen b75cab
    readunit = TILE;
roentgen b75cab
    tlsize = TIFFTileSize(in);
roentgen b75cab
    ntiles = TIFFNumberOfTiles(in);
roentgen b75cab
    TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
roentgen b75cab
    TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
roentgen b75cab
roentgen b75cab
    tile_rowsize  = TIFFTileRowSize(in);      
roentgen b75cab
    buffsize = tlsize * ntiles;
roentgen b75cab
roentgen b75cab
        
roentgen b75cab
    if (buffsize < (uint32)(ntiles * tl * tile_rowsize))
roentgen b75cab
      {
roentgen b75cab
      buffsize = ntiles * tl * tile_rowsize;
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
      TIFFError("loadImage",
roentgen b75cab
	        "Tilesize %u is too small, using ntiles * tilelength * tilerowsize %lu",
roentgen b75cab
                tlsize, (unsigned long)buffsize);
roentgen b75cab
#endif
roentgen b75cab
      }
roentgen b75cab
    
roentgen b75cab
    if (dump->infile != NULL)
roentgen b75cab
      dump_info (dump->infile, dump->format, "", 
roentgen b75cab
                 "Tilesize: %u, Number of Tiles: %u, Tile row size: %u",
roentgen b75cab
                 tlsize, ntiles, tile_rowsize);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    readunit = STRIP;
roentgen b75cab
    TIFFGetFieldDefaulted(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
roentgen b75cab
    stsize = TIFFStripSize(in);
roentgen b75cab
    nstrips = TIFFNumberOfStrips(in);
roentgen b75cab
    buffsize = stsize * nstrips;
roentgen b75cab
    
roentgen b75cab
    if (buffsize < (uint32) (((length * width * spp * bps) + 7) / 8))
roentgen b75cab
      {
roentgen b75cab
      buffsize =  ((length * width * spp * bps) + 7) / 8;
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
      TIFFError("loadImage",
roentgen b75cab
	        "Stripsize %u is too small, using imagelength * width * spp * bps / 8 = %lu",
roentgen b75cab
                stsize, (unsigned long)buffsize);
roentgen b75cab
#endif
roentgen b75cab
      }
roentgen b75cab
    
roentgen b75cab
    if (dump->infile != NULL)
roentgen b75cab
      dump_info (dump->infile, dump->format, "",
roentgen b75cab
                 "Stripsize: %u, Number of Strips: %u, Rows per Strip: %u, Scanline size: %u",
roentgen b75cab
		 stsize, nstrips, rowsperstrip, scanlinesize);
roentgen b75cab
    }
roentgen b75cab
  
roentgen b75cab
  if (input_compression == COMPRESSION_JPEG)
roentgen b75cab
    {  /* Force conversion to RGB */
roentgen b75cab
    jpegcolormode = JPEGCOLORMODE_RGB;
roentgen b75cab
    TIFFSetField(in, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
roentgen b75cab
    }
roentgen b75cab
  /* The clause up to the read statement is taken from Tom Lane's tiffcp patch */
roentgen b75cab
  else 
roentgen b75cab
    {   /* Otherwise, can't handle subsampled input */
roentgen b75cab
    if (input_photometric == PHOTOMETRIC_YCBCR)
roentgen b75cab
      {
roentgen b75cab
      TIFFGetFieldDefaulted(in, TIFFTAG_YCBCRSUBSAMPLING,
roentgen b75cab
 		           &subsampling_horiz, &subsampling_vert);
roentgen b75cab
      if (subsampling_horiz != 1 || subsampling_vert != 1)
roentgen b75cab
        {
roentgen b75cab
	TIFFError("loadImage", 
roentgen b75cab
		"Can't copy/convert subsampled image with subsampling %d horiz %d vert",
roentgen b75cab
                subsampling_horiz, subsampling_vert);
roentgen b75cab
        return (-1);
roentgen b75cab
        }
roentgen b75cab
	}
roentgen b75cab
    }
roentgen b75cab
 
roentgen b75cab
  read_buff = *read_ptr;
roentgen b75cab
  if (!read_buff)
roentgen b75cab
    read_buff = (unsigned char *)_TIFFmalloc(buffsize);
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (prev_readsize < buffsize)
roentgen b75cab
      {
roentgen b75cab
      new_buff = _TIFFrealloc(read_buff, buffsize);
roentgen b75cab
      if (!new_buff)
roentgen b75cab
        {
roentgen b75cab
	free (read_buff);
roentgen b75cab
        read_buff = (unsigned char *)_TIFFmalloc(buffsize);
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        read_buff = new_buff;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!read_buff)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("loadImage", "Unable to allocate/reallocate read buffer");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  prev_readsize = buffsize;
roentgen b75cab
  *read_ptr = read_buff;
roentgen b75cab
roentgen b75cab
  /* N.B. The read functions used copy separate plane data into a buffer as interleaved
roentgen b75cab
   * samples rather than separate planes so the same logic works to extract regions
roentgen b75cab
   * regardless of the way the data are organized in the input file.
roentgen b75cab
   */
roentgen b75cab
  switch (readunit) {
roentgen b75cab
    case STRIP:
roentgen b75cab
         if (planar == PLANARCONFIG_CONTIG)
roentgen b75cab
           {
roentgen b75cab
	     if (!(readContigStripsIntoBuffer(in, read_buff)))
roentgen b75cab
	     {
roentgen b75cab
	     TIFFError("loadImage", "Unable to read contiguous strips into buffer");
roentgen b75cab
	     return (-1);
roentgen b75cab
             }
roentgen b75cab
           }
roentgen b75cab
         else
roentgen b75cab
           {
roentgen b75cab
	   if (!(readSeparateStripsIntoBuffer(in, read_buff, length, width, spp, dump)))
roentgen b75cab
	     {
roentgen b75cab
	     TIFFError("loadImage", "Unable to read separate strips into buffer");
roentgen b75cab
	     return (-1);
roentgen b75cab
             }
roentgen b75cab
           }
roentgen b75cab
         break;
roentgen b75cab
roentgen b75cab
    case TILE:
roentgen b75cab
         if (planar == PLANARCONFIG_CONTIG)
roentgen b75cab
           {
roentgen b75cab
	   if (!(readContigTilesIntoBuffer(in, read_buff, length, width, tw, tl, spp, bps)))
roentgen b75cab
	     {
roentgen b75cab
	     TIFFError("loadImage", "Unable to read contiguous tiles into buffer");
roentgen b75cab
	     return (-1);
roentgen b75cab
             }
roentgen b75cab
           }
roentgen b75cab
         else
roentgen b75cab
           {
roentgen b75cab
	   if (!(readSeparateTilesIntoBuffer(in, read_buff, length, width, tw, tl, spp, bps)))
roentgen b75cab
	     {
roentgen b75cab
	     TIFFError("loadImage", "Unable to read separate tiles into buffer");
roentgen b75cab
	     return (-1);
roentgen b75cab
             }
roentgen b75cab
           }
roentgen b75cab
         break;
roentgen b75cab
    default: TIFFError("loadImage", "Unsupported image file format");
roentgen b75cab
          return (-1);
roentgen b75cab
          break;
roentgen b75cab
    }
roentgen b75cab
  if ((dump->infile != NULL) && (dump->level == 2))
roentgen b75cab
    {
roentgen b75cab
    dump_info  (dump->infile, dump->format, "loadImage", 
roentgen b75cab
                "Image width %d, length %d, Raw image data, %4d bytes",
roentgen b75cab
                width, length,  buffsize);
roentgen b75cab
    dump_info  (dump->infile, dump->format, "", 
roentgen b75cab
                "Bits per sample %d, Samples per pixel %d", bps, spp);
roentgen b75cab
roentgen b75cab
    for (i = 0; i < length; i++)
roentgen b75cab
      dump_buffer(dump->infile, dump->format, 1, scanlinesize, 
roentgen b75cab
                  i, read_buff + (i * scanlinesize));
roentgen b75cab
    }
roentgen b75cab
  return (0);
roentgen b75cab
  }   /* end loadImage */
roentgen b75cab
roentgen b75cab
static int  correct_orientation(struct image_data *image, unsigned char **work_buff_ptr)
roentgen b75cab
  {
roentgen b75cab
  uint16 mirror, rotation;
roentgen b75cab
  unsigned char *work_buff;
roentgen b75cab
roentgen b75cab
  work_buff = *work_buff_ptr;
roentgen b75cab
  if ((image == NULL) || (work_buff == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("correct_orientatin", "Invalid image or buffer pointer");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if ((image->adjustments & MIRROR_HORIZ) || (image->adjustments & MIRROR_VERT))
roentgen b75cab
    {
roentgen b75cab
    mirror = (uint16)(image->adjustments & MIRROR_BOTH);
roentgen b75cab
    if (mirrorImage(image->spp, image->bps, mirror, 
roentgen b75cab
        image->width, image->length, work_buff))
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("correct_orientation", "Unable to mirror image");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (image->adjustments & ROTATE_ANY)
roentgen b75cab
    {
roentgen b75cab
    if (image->adjustments & ROTATECW_90)
roentgen b75cab
      rotation = (uint16) 90;
roentgen b75cab
    else
roentgen b75cab
    if (image->adjustments & ROTATECW_180)
roentgen b75cab
      rotation = (uint16) 180;
roentgen b75cab
    else
roentgen b75cab
    if (image->adjustments & ROTATECW_270)
roentgen b75cab
      rotation = (uint16) 270;
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("correct_orientation", "Invalid rotation value: %d", 
roentgen b75cab
                  image->adjustments & ROTATE_ANY);
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
 
roentgen b75cab
    if (rotateImage(rotation, image, &image->width, &image->length, work_buff_ptr))
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("correct_orientation", "Unable to rotate image");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    image->orientation = ORIENTATION_TOPLEFT;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end correct_orientation */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Extract multiple zones from an image and combine into a single composite image */
roentgen b75cab
static int
roentgen b75cab
extractCompositeRegions(struct image_data *image,  struct crop_mask *crop, 
roentgen b75cab
                        unsigned char *read_buff, unsigned char *crop_buff)
roentgen b75cab
  {
roentgen b75cab
  int       shift_width, bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32    i, trailing_bits, prev_trailing_bits;
roentgen b75cab
  uint32    row, first_row, last_row, first_col, last_col;
roentgen b75cab
  uint32    src_rowsize, dst_rowsize, src_offset, dst_offset;
roentgen b75cab
  uint32    crop_width, crop_length, img_width, img_length;
roentgen b75cab
  uint32    prev_length, prev_width, composite_width;
roentgen b75cab
  uint16    bps, spp;
roentgen b75cab
  uint8    *src, *dst;
roentgen b75cab
  tsample_t count, sample = 0;   /* Update to extract one or more samples */
roentgen b75cab
roentgen b75cab
  img_width = image->width;
roentgen b75cab
  img_length = image->length;
roentgen b75cab
  bps = image->bps;
roentgen b75cab
  spp = image->spp;
roentgen b75cab
  count = spp;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if ((bps % 8) == 0)
roentgen b75cab
    shift_width = 0;
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
      shift_width = bytes_per_pixel;
roentgen b75cab
    else
roentgen b75cab
      shift_width = bytes_per_sample + 1;
roentgen b75cab
    }
roentgen b75cab
  src = read_buff;
roentgen b75cab
  dst = crop_buff;
roentgen b75cab
roentgen b75cab
  /* These are setup for adding additional sections */
roentgen b75cab
  prev_width = prev_length = 0;
roentgen b75cab
  prev_trailing_bits = trailing_bits = 0;
roentgen b75cab
  composite_width = crop->combined_width;
roentgen b75cab
  crop->combined_width = 0;
roentgen b75cab
  crop->combined_length = 0;
roentgen b75cab
roentgen b75cab
  for (i = 0; i < crop->selections; i++)
roentgen b75cab
    {
roentgen b75cab
    /* rows, columns, width, length are expressed in pixels */
roentgen b75cab
    first_row = crop->regionlist[i].y1;
roentgen b75cab
    last_row  = crop->regionlist[i].y2;
roentgen b75cab
    first_col = crop->regionlist[i].x1;
roentgen b75cab
    last_col  = crop->regionlist[i].x2;
roentgen b75cab
roentgen b75cab
    crop_width = last_col - first_col + 1;
roentgen b75cab
    crop_length = last_row - first_row + 1;
roentgen b75cab
roentgen b75cab
    /* These should not be needed for composite images */
roentgen b75cab
    crop->regionlist[i].width = crop_width;
roentgen b75cab
    crop->regionlist[i].length = crop_length;
roentgen b75cab
    crop->regionlist[i].buffptr = crop_buff;
roentgen b75cab
roentgen b75cab
    src_rowsize = ((img_width * bps * spp) + 7) / 8;
roentgen b75cab
    dst_rowsize = (((crop_width * bps * count) + 7) / 8);
roentgen b75cab
roentgen b75cab
    switch (crop->edge_ref)
roentgen b75cab
      {
roentgen b75cab
      default:
roentgen b75cab
      case EDGE_TOP:
roentgen b75cab
      case EDGE_BOTTOM:
roentgen b75cab
	   if ((i > 0) && (crop_width != crop->regionlist[i - 1].width))
roentgen b75cab
             {
roentgen b75cab
	     TIFFError ("extractCompositeRegions", 
roentgen b75cab
                          "Only equal width regions can be combined for -E top or bottom");
roentgen b75cab
	     return (1);
roentgen b75cab
             }
roentgen b75cab
roentgen b75cab
           crop->combined_width = crop_width;
roentgen b75cab
           crop->combined_length += crop_length;
roentgen b75cab
roentgen b75cab
           for (row = first_row; row <= last_row; row++)
roentgen b75cab
             {
roentgen b75cab
	     src_offset = row * src_rowsize;
roentgen b75cab
	     dst_offset = (row - first_row) * dst_rowsize;
roentgen b75cab
             src = read_buff + src_offset;
roentgen b75cab
             dst = crop_buff + dst_offset + (prev_length * dst_rowsize);
roentgen b75cab
             switch (shift_width)
roentgen b75cab
               {
roentgen b75cab
               case 0: if (extractContigSamplesBytes (src, dst, img_width, sample,
roentgen b75cab
                                                      spp, bps, count, first_col,
roentgen b75cab
                                                      last_col + 1))
roentgen b75cab
                         {
roentgen b75cab
		         TIFFError("extractCompositeRegions",
roentgen b75cab
                                   "Unable to extract row %d", row);
roentgen b75cab
		         return (1);
roentgen b75cab
		         }
roentgen b75cab
		       break;
roentgen b75cab
               case 1: if (bps == 1)
roentgen b75cab
                         { 
roentgen b75cab
                         if (extractContigSamplesShifted8bits (src, dst, img_width,
roentgen b75cab
                                                               sample, spp, bps, count, 
roentgen b75cab
                                                               first_col, last_col + 1,
roentgen b75cab
                                                               prev_trailing_bits))
roentgen b75cab
                           {
roentgen b75cab
		           TIFFError("extractCompositeRegions",
roentgen b75cab
                                     "Unable to extract row %d", row);
roentgen b75cab
		           return (1);
roentgen b75cab
		           }
roentgen b75cab
		         break;
roentgen b75cab
			 }
roentgen b75cab
                       else
roentgen b75cab
                         if (extractContigSamplesShifted16bits (src, dst, img_width,
roentgen b75cab
                                                                sample, spp, bps, count, 
roentgen b75cab
                                                                first_col, last_col + 1,
roentgen b75cab
                                                                prev_trailing_bits))
roentgen b75cab
                           {
roentgen b75cab
		           TIFFError("extractCompositeRegions",
roentgen b75cab
                                     "Unable to extract row %d", row);
roentgen b75cab
		           return (1);
roentgen b75cab
		           }
roentgen b75cab
		        break;
roentgen b75cab
               case 2:  if (extractContigSamplesShifted24bits (src, dst, img_width,
roentgen b75cab
                                                               sample, spp, bps, count, 
roentgen b75cab
                                                               first_col, last_col + 1,
roentgen b75cab
                                                               prev_trailing_bits))
roentgen b75cab
                          {
roentgen b75cab
		          TIFFError("extractCompositeRegions",
roentgen b75cab
                                    "Unable to extract row %d", row);
roentgen b75cab
		          return (1);
roentgen b75cab
		          }
roentgen b75cab
		        break;
roentgen b75cab
               case 3:
roentgen b75cab
               case 4:
roentgen b75cab
               case 5:  if (extractContigSamplesShifted32bits (src, dst, img_width,
roentgen b75cab
                                                               sample, spp, bps, count, 
roentgen b75cab
                                                               first_col, last_col + 1,
roentgen b75cab
                                                               prev_trailing_bits))
roentgen b75cab
                          {
roentgen b75cab
		          TIFFError("extractCompositeRegions",
roentgen b75cab
                                    "Unable to extract row %d", row);
roentgen b75cab
		          return (1);
roentgen b75cab
		          }
roentgen b75cab
		        break;
roentgen b75cab
               default: TIFFError("extractCompositeRegions", "Unsupported bit depth %d", bps);
roentgen b75cab
		        return (1);
roentgen b75cab
	       }
roentgen b75cab
             }
roentgen b75cab
           prev_length += crop_length;
roentgen b75cab
	   break;
roentgen b75cab
      case EDGE_LEFT:  /* splice the pieces of each row together, side by side */
roentgen b75cab
      case EDGE_RIGHT:
roentgen b75cab
	   if ((i > 0) && (crop_length != crop->regionlist[i - 1].length))
roentgen b75cab
             {
roentgen b75cab
	     TIFFError ("extractCompositeRegions", 
roentgen b75cab
                          "Only equal length regions can be combined for -E left or right");
roentgen b75cab
	     return (1);
roentgen b75cab
             }
roentgen b75cab
           crop->combined_width += crop_width;
roentgen b75cab
           crop->combined_length = crop_length;
roentgen b75cab
           dst_rowsize = (((composite_width * bps * count) + 7) / 8);
roentgen b75cab
           trailing_bits = (crop_width * bps * count) % 8;
roentgen b75cab
           for (row = first_row; row <= last_row; row++)
roentgen b75cab
             {
roentgen b75cab
	     src_offset = row * src_rowsize;
roentgen b75cab
	     dst_offset = (row - first_row) * dst_rowsize;
roentgen b75cab
             src = read_buff + src_offset;
roentgen b75cab
             dst = crop_buff + dst_offset + prev_width;
roentgen b75cab
roentgen b75cab
             switch (shift_width)
roentgen b75cab
               {
roentgen b75cab
               case 0: if (extractContigSamplesBytes (src, dst, img_width,
roentgen b75cab
                                                      sample, spp, bps, count,
roentgen b75cab
                                                      first_col, last_col + 1))
roentgen b75cab
                         {
roentgen b75cab
		         TIFFError("extractCompositeRegions",
roentgen b75cab
                                   "Unable to extract row %d", row);
roentgen b75cab
		         return (1);
roentgen b75cab
		         }
roentgen b75cab
		       break;
roentgen b75cab
               case 1: if (bps == 1)
roentgen b75cab
                         { 
roentgen b75cab
                         if (extractContigSamplesShifted8bits (src, dst, img_width,
roentgen b75cab
                                                               sample, spp, bps, count, 
roentgen b75cab
                                                               first_col, last_col + 1,
roentgen b75cab
                                                               prev_trailing_bits))
roentgen b75cab
                           {
roentgen b75cab
		           TIFFError("extractCompositeRegions",
roentgen b75cab
                                     "Unable to extract row %d", row);
roentgen b75cab
		           return (1);
roentgen b75cab
		           }
roentgen b75cab
		         break;
roentgen b75cab
			 }
roentgen b75cab
                       else
roentgen b75cab
                         if (extractContigSamplesShifted16bits (src, dst, img_width,
roentgen b75cab
                                                                sample, spp, bps, count, 
roentgen b75cab
                                                                first_col, last_col + 1,
roentgen b75cab
                                                                prev_trailing_bits))
roentgen b75cab
                           {
roentgen b75cab
		           TIFFError("extractCompositeRegions",
roentgen b75cab
                                     "Unable to extract row %d", row);
roentgen b75cab
		           return (1);
roentgen b75cab
		           }
roentgen b75cab
		        break;
roentgen b75cab
              case 2:  if (extractContigSamplesShifted24bits (src, dst, img_width,
roentgen b75cab
                                                               sample, spp, bps, count, 
roentgen b75cab
                                                               first_col, last_col + 1,
roentgen b75cab
                                                               prev_trailing_bits))
roentgen b75cab
                          {
roentgen b75cab
		          TIFFError("extractCompositeRegions",
roentgen b75cab
                                    "Unable to extract row %d", row);
roentgen b75cab
		          return (1);
roentgen b75cab
		          }
roentgen b75cab
		        break;
roentgen b75cab
               case 3:
roentgen b75cab
               case 4:
roentgen b75cab
               case 5:  if (extractContigSamplesShifted32bits (src, dst, img_width,
roentgen b75cab
                                                               sample, spp, bps, count, 
roentgen b75cab
                                                               first_col, last_col + 1,
roentgen b75cab
                                                               prev_trailing_bits))
roentgen b75cab
                          {
roentgen b75cab
		          TIFFError("extractCompositeRegions",
roentgen b75cab
                                    "Unable to extract row %d", row);
roentgen b75cab
		          return (1);
roentgen b75cab
		          }
roentgen b75cab
		        break;
roentgen b75cab
               default: TIFFError("extractCompositeRegions", "Unsupported bit depth %d", bps);
roentgen b75cab
		        return (1);
roentgen b75cab
	       }
roentgen b75cab
	     }
roentgen b75cab
	   prev_width += (crop_width * bps * count) / 8;
roentgen b75cab
           prev_trailing_bits += trailing_bits;
roentgen b75cab
           if (prev_trailing_bits > 7)
roentgen b75cab
	     prev_trailing_bits-= 8;
roentgen b75cab
	   break;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  if (crop->combined_width != composite_width)
roentgen b75cab
    TIFFError("combineSeparateRegions","Combined width does not match composite width");
roentgen b75cab
      
roentgen b75cab
  return (0);
roentgen b75cab
  }  /* end extractCompositeRegions */
roentgen b75cab
roentgen b75cab
/* Copy a single region of input buffer to an output buffer. 
roentgen b75cab
 * The read functions used copy separate plane data into a buffer 
roentgen b75cab
 * as interleaved samples rather than separate planes so the same
roentgen b75cab
 * logic works to extract regions regardless of the way the data 
roentgen b75cab
 * are organized in the input file. This function can be used to
roentgen b75cab
 * extract one or more samples from the input image by updating the 
roentgen b75cab
 * parameters for starting sample and number of samples to copy in the
roentgen b75cab
 * fifth and eighth arguments of the call to extractContigSamples.
roentgen b75cab
 * They would be passed as new elements of the crop_mask struct.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractSeparateRegion(struct image_data *image,  struct crop_mask *crop,
roentgen b75cab
                      unsigned char *read_buff, unsigned char *crop_buff,
roentgen b75cab
                      int region)
roentgen b75cab
  {
roentgen b75cab
  int     shift_width, prev_trailing_bits = 0;
roentgen b75cab
  uint32  bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32  src_rowsize, dst_rowsize;
roentgen b75cab
  uint32  row, first_row, last_row, first_col, last_col;
roentgen b75cab
  uint32  src_offset, dst_offset;
roentgen b75cab
  uint32  crop_width, crop_length, img_width, img_length;
roentgen b75cab
  uint16  bps, spp;
roentgen b75cab
  uint8  *src, *dst;
roentgen b75cab
  tsample_t count, sample = 0;   /* Update to extract more or more samples */
roentgen b75cab
roentgen b75cab
  img_width = image->width;
roentgen b75cab
  img_length = image->length;
roentgen b75cab
  bps = image->bps;
roentgen b75cab
  spp = image->spp;
roentgen b75cab
  count = spp;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8; 
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if ((bps % 8) == 0)
roentgen b75cab
    shift_width = 0; /* Byte aligned data only */
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
      shift_width = bytes_per_pixel;
roentgen b75cab
    else
roentgen b75cab
      shift_width = bytes_per_sample + 1;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  /* rows, columns, width, length are expressed in pixels */
roentgen b75cab
  first_row = crop->regionlist[region].y1;
roentgen b75cab
  last_row  = crop->regionlist[region].y2;
roentgen b75cab
  first_col = crop->regionlist[region].x1;
roentgen b75cab
  last_col  = crop->regionlist[region].x2;
roentgen b75cab
roentgen b75cab
  crop_width = last_col - first_col + 1;
roentgen b75cab
  crop_length = last_row - first_row + 1;
roentgen b75cab
roentgen b75cab
  crop->regionlist[region].width = crop_width;
roentgen b75cab
  crop->regionlist[region].length = crop_length;
roentgen b75cab
  crop->regionlist[region].buffptr = crop_buff;
roentgen b75cab
roentgen b75cab
  src = read_buff;
roentgen b75cab
  dst = crop_buff;
roentgen b75cab
  src_rowsize = ((img_width * bps * spp) + 7) / 8;
roentgen b75cab
  dst_rowsize = (((crop_width * bps * spp) + 7) / 8);
roentgen b75cab
roentgen b75cab
  for (row = first_row; row <= last_row; row++)
roentgen b75cab
    {
roentgen b75cab
    src_offset = row * src_rowsize;
roentgen b75cab
    dst_offset = (row  - first_row) * dst_rowsize;
roentgen b75cab
    src = read_buff + src_offset;
roentgen b75cab
    dst = crop_buff + dst_offset;
roentgen b75cab
roentgen b75cab
    switch (shift_width)
roentgen b75cab
      {
roentgen b75cab
      case 0: if (extractContigSamplesBytes (src, dst, img_width, sample,
roentgen b75cab
                                             spp, bps, count, first_col,
roentgen b75cab
                                             last_col + 1))
roentgen b75cab
                {
roentgen b75cab
	        TIFFError("extractSeparateRegion",
roentgen b75cab
                          "Unable to extract row %d", row);
roentgen b75cab
	        return (1);
roentgen b75cab
	        }
roentgen b75cab
	      break;
roentgen b75cab
      case 1: if (bps == 1)
roentgen b75cab
                { 
roentgen b75cab
                if (extractContigSamplesShifted8bits (src, dst, img_width,
roentgen b75cab
                                                      sample, spp, bps, count, 
roentgen b75cab
                                                      first_col, last_col + 1,
roentgen b75cab
                                                      prev_trailing_bits))
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError("extractSeparateRegion",
roentgen b75cab
                            "Unable to extract row %d", row);
roentgen b75cab
		  return (1);
roentgen b75cab
		  }
roentgen b75cab
		  break;
roentgen b75cab
		}
roentgen b75cab
              else
roentgen b75cab
                if (extractContigSamplesShifted16bits (src, dst, img_width,
roentgen b75cab
                                                       sample, spp, bps, count, 
roentgen b75cab
                                                       first_col, last_col + 1,
roentgen b75cab
                                                       prev_trailing_bits))
roentgen b75cab
                  {
roentgen b75cab
		  TIFFError("extractSeparateRegion",
roentgen b75cab
                            "Unable to extract row %d", row);
roentgen b75cab
		  return (1);
roentgen b75cab
		  }
roentgen b75cab
	      break;
roentgen b75cab
      case 2:  if (extractContigSamplesShifted24bits (src, dst, img_width,
roentgen b75cab
                                                     sample, spp, bps, count, 
roentgen b75cab
                                                     first_col, last_col + 1,
roentgen b75cab
                                                     prev_trailing_bits))
roentgen b75cab
                {
roentgen b75cab
		TIFFError("extractSeparateRegion",
roentgen b75cab
                          "Unable to extract row %d", row);
roentgen b75cab
		return (1);
roentgen b75cab
		}
roentgen b75cab
	      break;
roentgen b75cab
      case 3:
roentgen b75cab
      case 4:
roentgen b75cab
      case 5:  if (extractContigSamplesShifted32bits (src, dst, img_width,
roentgen b75cab
                                                     sample, spp, bps, count, 
roentgen b75cab
                                                     first_col, last_col + 1,
roentgen b75cab
                                                     prev_trailing_bits))
roentgen b75cab
                {
roentgen b75cab
		TIFFError("extractSeparateRegion",
roentgen b75cab
                          "Unable to extract row %d", row);
roentgen b75cab
		return (1);
roentgen b75cab
		}
roentgen b75cab
	      break;
roentgen b75cab
      default: TIFFError("extractSeparateRegion", "Unsupported bit depth %d", bps);
roentgen b75cab
	       return (1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
          
roentgen b75cab
  return (0);
roentgen b75cab
  }  /* end extractSeparateRegion */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
extractImageSection(struct image_data *image, struct pageseg *section, 
roentgen b75cab
                    unsigned char *src_buff, unsigned char *sect_buff)
roentgen b75cab
  {
roentgen b75cab
  unsigned  char  bytebuff1, bytebuff2;
roentgen b75cab
  unsigned  char *src, *dst;
roentgen b75cab
roentgen b75cab
  uint32    img_width, img_length, img_rowsize;
roentgen b75cab
  uint32    j, shift1, shift2, trailing_bits;
roentgen b75cab
  uint32    row, first_row, last_row, first_col, last_col;
roentgen b75cab
  uint32    src_offset, dst_offset, row_offset, col_offset;
roentgen b75cab
  uint32    offset1, offset2, full_bytes;
roentgen b75cab
  uint32    sect_width, sect_length;
roentgen b75cab
  uint16    bps, spp;
roentgen b75cab
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
  int      k;
roentgen b75cab
  unsigned char bitset;
roentgen b75cab
  static char *bitarray = NULL;
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
  img_width = image->width;
roentgen b75cab
  img_length = image->length;
roentgen b75cab
  bps = image->bps;
roentgen b75cab
  spp = image->spp;
roentgen b75cab
roentgen b75cab
  src = src_buff;
roentgen b75cab
  dst = sect_buff;
roentgen b75cab
  src_offset = 0;
roentgen b75cab
  dst_offset = 0;
roentgen b75cab
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
  if (bitarray == NULL)
roentgen b75cab
    {
roentgen b75cab
    if ((bitarray = (char *)malloc(img_width)) == NULL)
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("", "DEBUG: Unable to allocate debugging bitarray");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
  /* rows, columns, width, length are expressed in pixels */
roentgen b75cab
  first_row = section->y1;
roentgen b75cab
  last_row  = section->y2;
roentgen b75cab
  first_col = section->x1;
roentgen b75cab
  last_col  = section->x2;
roentgen b75cab
roentgen b75cab
  sect_width = last_col - first_col + 1;
roentgen b75cab
  sect_length = last_row - first_row + 1;
roentgen b75cab
  img_rowsize = ((img_width * bps + 7) / 8) * spp;
roentgen b75cab
  full_bytes = (sect_width * spp * bps) / 8;   /* number of COMPLETE bytes per row in section */
roentgen b75cab
  trailing_bits = (sect_width * bps) % 8;
roentgen b75cab
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
    TIFFError ("", "First row: %d, last row: %d, First col: %d, last col: %d\n",
roentgen b75cab
           first_row, last_row, first_col, last_col);
roentgen b75cab
    TIFFError ("", "Image width: %d, Image length: %d, bps: %d, spp: %d\n",
roentgen b75cab
	   img_width, img_length, bps, spp);
roentgen b75cab
    TIFFError ("", "Sect  width: %d,  Sect length: %d, full bytes: %d trailing bits %d\n", 
roentgen b75cab
           sect_width, sect_length, full_bytes, trailing_bits);
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
  if ((bps % 8) == 0)
roentgen b75cab
    {
roentgen b75cab
    col_offset = first_col * spp * bps / 8;
roentgen b75cab
    for (row = first_row; row <= last_row; row++)
roentgen b75cab
      {
roentgen b75cab
      /* row_offset = row * img_width * spp * bps / 8; */
roentgen b75cab
      row_offset = row * img_rowsize;
roentgen b75cab
      src_offset = row_offset + col_offset;
roentgen b75cab
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
        TIFFError ("", "Src offset: %8d, Dst offset: %8d", src_offset, dst_offset); 
roentgen b75cab
#endif
roentgen b75cab
      _TIFFmemcpy (sect_buff + dst_offset, src_buff + src_offset, full_bytes);
roentgen b75cab
      dst_offset += full_bytes;
roentgen b75cab
      }        
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    { /* bps != 8 */
roentgen b75cab
    shift1  = spp * ((first_col * bps) % 8);
roentgen b75cab
    shift2  = spp * ((last_col * bps) % 8);
roentgen b75cab
    for (row = first_row; row <= last_row; row++)
roentgen b75cab
      {
roentgen b75cab
      /* pull out the first byte */
roentgen b75cab
      row_offset = row * img_rowsize;
roentgen b75cab
      offset1 = row_offset + (first_col * bps / 8);
roentgen b75cab
      offset2 = row_offset + (last_col * bps / 8);
roentgen b75cab
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
      for (j = 0, k = 7; j < 8; j++, k--)
roentgen b75cab
        {
roentgen b75cab
        bitset = *(src_buff + offset1) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
        sprintf(&bitarray[j], (bitset) ? "1" : "0");
roentgen b75cab
        }
roentgen b75cab
      sprintf(&bitarray[8], " ");
roentgen b75cab
      sprintf(&bitarray[9], " ");
roentgen b75cab
      for (j = 10, k = 7; j < 18; j++, k--)
roentgen b75cab
        {
roentgen b75cab
        bitset = *(src_buff + offset2) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
        sprintf(&bitarray[j], (bitset) ? "1" : "0");
roentgen b75cab
        }
roentgen b75cab
      bitarray[18] = '\0';
roentgen b75cab
      TIFFError ("", "Row: %3d Offset1: %d,  Shift1: %d,    Offset2: %d,  Shift2:  %d\n", 
roentgen b75cab
                 row, offset1, shift1, offset2, shift2); 
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
      bytebuff1 = bytebuff2 = 0;
roentgen b75cab
      if (shift1 == 0) /* the region is byte and sample alligned */
roentgen b75cab
        {
roentgen b75cab
	_TIFFmemcpy (sect_buff + dst_offset, src_buff + offset1, full_bytes);
roentgen b75cab
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	TIFFError ("", "        Alligned data src offset1: %8d, Dst offset: %8d\n", offset1, dst_offset); 
roentgen b75cab
	sprintf(&bitarray[18], "\n");
roentgen b75cab
	sprintf(&bitarray[19], "\t");
roentgen b75cab
        for (j = 20, k = 7; j < 28; j++, k--)
roentgen b75cab
          {
roentgen b75cab
          bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
          sprintf(&bitarray[j], (bitset) ? "1" : "0");
roentgen b75cab
          }
roentgen b75cab
        bitarray[28] = ' ';
roentgen b75cab
        bitarray[29] = ' ';
roentgen b75cab
#endif
roentgen b75cab
        dst_offset += full_bytes;
roentgen b75cab
roentgen b75cab
        if (trailing_bits != 0)
roentgen b75cab
          {
roentgen b75cab
	  bytebuff2 = src_buff[offset2] & ((unsigned char)255 << (7 - shift2));
roentgen b75cab
          sect_buff[dst_offset] = bytebuff2;
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	  TIFFError ("", "        Trailing bits src offset:  %8d, Dst offset: %8d\n", 
roentgen b75cab
                              offset2, dst_offset); 
roentgen b75cab
          for (j = 30, k = 7; j < 38; j++, k--)
roentgen b75cab
            {
roentgen b75cab
            bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
            sprintf(&bitarray[j], (bitset) ? "1" : "0");
roentgen b75cab
            }
roentgen b75cab
          bitarray[38] = '\0';
roentgen b75cab
          TIFFError ("", "\tFirst and last bytes before and after masking:\n\t%s\n\n", bitarray);
roentgen b75cab
#endif
roentgen b75cab
          dst_offset++;
roentgen b75cab
          }
roentgen b75cab
        }
roentgen b75cab
      else   /* each destination byte will have to be built from two source bytes*/
roentgen b75cab
        {
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	  TIFFError ("", "        Unalligned data src offset: %8d, Dst offset: %8d\n", offset1 , dst_offset); 
roentgen b75cab
#endif
roentgen b75cab
        for (j = 0; j <= full_bytes; j++) 
roentgen b75cab
          {
roentgen b75cab
	  bytebuff1 = src_buff[offset1 + j] & ((unsigned char)255 >> shift1);
roentgen b75cab
	  bytebuff2 = src_buff[offset1 + j + 1] & ((unsigned char)255 << (7 - shift1));
roentgen b75cab
          sect_buff[dst_offset + j] = (bytebuff1 << shift1) | (bytebuff2 >> (8 - shift1));
roentgen b75cab
          }
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	sprintf(&bitarray[18], "\n");
roentgen b75cab
	sprintf(&bitarray[19], "\t");
roentgen b75cab
        for (j = 20, k = 7; j < 28; j++, k--)
roentgen b75cab
          {
roentgen b75cab
          bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
          sprintf(&bitarray[j], (bitset) ? "1" : "0");
roentgen b75cab
          }
roentgen b75cab
        bitarray[28] = ' ';
roentgen b75cab
        bitarray[29] = ' ';
roentgen b75cab
#endif
roentgen b75cab
        dst_offset += full_bytes;
roentgen b75cab
roentgen b75cab
        if (trailing_bits != 0)
roentgen b75cab
          {
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	    TIFFError ("", "        Trailing bits   src offset: %8d, Dst offset: %8d\n", offset1 + full_bytes, dst_offset); 
roentgen b75cab
#endif
roentgen b75cab
	  if (shift2 > shift1)
roentgen b75cab
            {
roentgen b75cab
	    bytebuff1 = src_buff[offset1 + full_bytes] & ((unsigned char)255 << (7 - shift2));
roentgen b75cab
            bytebuff2 = bytebuff1 & ((unsigned char)255 << shift1);
roentgen b75cab
            sect_buff[dst_offset] = bytebuff2;
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	    TIFFError ("", "        Shift2 > Shift1\n"); 
roentgen b75cab
#endif
roentgen b75cab
            }
roentgen b75cab
          else
roentgen b75cab
            {
roentgen b75cab
	    if (shift2 < shift1)
roentgen b75cab
              {
roentgen b75cab
              bytebuff2 = ((unsigned char)255 << (shift1 - shift2 - 1));
roentgen b75cab
	      sect_buff[dst_offset] &= bytebuff2;
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	      TIFFError ("", "        Shift2 < Shift1\n"); 
roentgen b75cab
#endif
roentgen b75cab
              }
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
            else
roentgen b75cab
	      TIFFError ("", "        Shift2 == Shift1\n"); 
roentgen b75cab
#endif
roentgen b75cab
            }
roentgen b75cab
	  }
roentgen b75cab
#ifdef DEVELMODE
roentgen b75cab
	  sprintf(&bitarray[28], " ");
roentgen b75cab
	  sprintf(&bitarray[29], " ");
roentgen b75cab
          for (j = 30, k = 7; j < 38; j++, k--)
roentgen b75cab
            {
roentgen b75cab
            bitset = *(sect_buff + dst_offset) & (((unsigned char)1 << k)) ? 1 : 0;
roentgen b75cab
            sprintf(&bitarray[j], (bitset) ? "1" : "0");
roentgen b75cab
            }
roentgen b75cab
          bitarray[38] = '\0';
roentgen b75cab
          TIFFError ("", "\tFirst and last bytes before and after masking:\n\t%s\n\n", bitarray);
roentgen b75cab
#endif
roentgen b75cab
        dst_offset++;
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end extractImageSection */
roentgen b75cab
roentgen b75cab
static int 
roentgen b75cab
writeSelections(TIFF *in, TIFF **out, struct crop_mask *crop, 
roentgen b75cab
                struct image_data *image, struct dump_opts *dump,
roentgen b75cab
                struct buffinfo seg_buffs[], char *mp, char *filename, 
roentgen b75cab
                unsigned int *page, unsigned int total_pages)
roentgen b75cab
  {
roentgen b75cab
  int i, page_count;
roentgen b75cab
  int autoindex = 0;
roentgen b75cab
  unsigned char *crop_buff = NULL;
roentgen b75cab
roentgen b75cab
  /* Where we open a new file depends on the export mode */  
roentgen b75cab
  switch (crop->exp_mode)
roentgen b75cab
    {
roentgen b75cab
    case ONE_FILE_COMPOSITE: /* Regions combined into single image */
roentgen b75cab
         autoindex = 0;
roentgen b75cab
         crop_buff = seg_buffs[0].buffer;
roentgen b75cab
         if (update_output_file (out, mp, autoindex, filename, page))
roentgen b75cab
           return (1);
roentgen b75cab
         page_count = total_pages;
roentgen b75cab
         if (writeCroppedImage(in, *out, image, dump,
roentgen b75cab
                               crop->combined_width, 
roentgen b75cab
                               crop->combined_length,
roentgen b75cab
                               crop_buff, *page, total_pages))
roentgen b75cab
            {
roentgen b75cab
             TIFFError("writeRegions", "Unable to write new image");
roentgen b75cab
             return (-1);
roentgen b75cab
             }
roentgen b75cab
	 break;
roentgen b75cab
    case ONE_FILE_SEPARATED: /* Regions as separated images */
roentgen b75cab
         autoindex = 0;
roentgen b75cab
         if (update_output_file (out, mp, autoindex, filename, page))
roentgen b75cab
           return (1);
roentgen b75cab
         page_count = crop->selections * total_pages;
roentgen b75cab
         for (i = 0; i < crop->selections; i++)
roentgen b75cab
           {
roentgen b75cab
           crop_buff = seg_buffs[i].buffer;
roentgen b75cab
           if (writeCroppedImage(in, *out, image, dump,
roentgen b75cab
                                 crop->regionlist[i].width, 
roentgen b75cab
                                 crop->regionlist[i].length, 
roentgen b75cab
                                 crop_buff, *page, page_count))
roentgen b75cab
             {
roentgen b75cab
             TIFFError("writeRegions", "Unable to write new image");
roentgen b75cab
             return (-1);
roentgen b75cab
             }
roentgen b75cab
	   }
roentgen b75cab
         break;
roentgen b75cab
    case FILE_PER_IMAGE_COMPOSITE: /* Regions as composite image */
roentgen b75cab
         autoindex = 1;
roentgen b75cab
         if (update_output_file (out, mp, autoindex, filename, page))
roentgen b75cab
           return (1);
roentgen b75cab
roentgen b75cab
         crop_buff = seg_buffs[0].buffer;
roentgen b75cab
         if (writeCroppedImage(in, *out, image, dump,
roentgen b75cab
                               crop->combined_width, 
roentgen b75cab
                               crop->combined_length, 
roentgen b75cab
                               crop_buff, *page, total_pages))
roentgen b75cab
           {
roentgen b75cab
           TIFFError("writeRegions", "Unable to write new image");
roentgen b75cab
           return (-1);
roentgen b75cab
           }
roentgen b75cab
         break;
roentgen b75cab
    case FILE_PER_IMAGE_SEPARATED: /* Regions as separated images */
roentgen b75cab
         autoindex = 1;
roentgen b75cab
         page_count = crop->selections;
roentgen b75cab
         if (update_output_file (out, mp, autoindex, filename, page))
roentgen b75cab
           return (1);
roentgen b75cab
                
roentgen b75cab
         for (i = 0; i < crop->selections; i++)
roentgen b75cab
           {
roentgen b75cab
           crop_buff = seg_buffs[i].buffer;
roentgen b75cab
           /* Write the current region to the current file */
roentgen b75cab
           if (writeCroppedImage(in, *out, image, dump,
roentgen b75cab
                                 crop->regionlist[i].width, 
roentgen b75cab
                                 crop->regionlist[i].length, 
roentgen b75cab
                                 crop_buff, *page, page_count))
roentgen b75cab
             {
roentgen b75cab
             TIFFError("writeRegions", "Unable to write new image");
roentgen b75cab
             return (-1);
roentgen b75cab
             }
roentgen b75cab
           }
roentgen b75cab
         break;
roentgen b75cab
    case FILE_PER_SELECTION:
roentgen b75cab
         autoindex = 1;
roentgen b75cab
	 page_count = 1;
roentgen b75cab
         for (i = 0; i < crop->selections; i++)
roentgen b75cab
           {
roentgen b75cab
           if (update_output_file (out, mp, autoindex, filename, page))
roentgen b75cab
             return (1);
roentgen b75cab
roentgen b75cab
           crop_buff = seg_buffs[i].buffer;
roentgen b75cab
           /* Write the current region to the current file */
roentgen b75cab
           if (writeCroppedImage(in, *out, image, dump,
roentgen b75cab
                                 crop->regionlist[i].width, 
roentgen b75cab
                                 crop->regionlist[i].length, 
roentgen b75cab
                                 crop_buff, *page, page_count))
roentgen b75cab
             {
roentgen b75cab
             TIFFError("writeRegions", "Unable to write new image");
roentgen b75cab
             return (-1);
roentgen b75cab
             }
roentgen b75cab
           }
roentgen b75cab
	 break;
roentgen b75cab
    default: return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end writeRegions */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
writeImageSections(TIFF *in, TIFF *out, struct image_data *image,
roentgen b75cab
		   struct pagedef *page, struct pageseg *sections,
roentgen b75cab
		   struct dump_opts * dump, unsigned char *src_buff,
roentgen b75cab
                   unsigned char **sect_buff_ptr)
roentgen b75cab
  {
roentgen b75cab
  double  hres, vres;
roentgen b75cab
  uint32  i, k, width, length, sectsize;
roentgen b75cab
  unsigned char *sect_buff = *sect_buff_ptr;
roentgen b75cab
roentgen b75cab
  hres = page->hres;
roentgen b75cab
  vres = page->vres;
roentgen b75cab
roentgen b75cab
  k = page->cols * page->rows;
roentgen b75cab
  if ((k < 1) || (k > MAX_SECTIONS))
roentgen b75cab
   {
roentgen b75cab
   TIFFError("writeImageSections",
roentgen b75cab
	     "%d Rows and Columns exceed maximum sections\nIncrease resolution or reduce sections", k);
roentgen b75cab
   return (-1);
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
  for (i = 0; i < k; i++)
roentgen b75cab
    {
roentgen b75cab
    width  = sections[i].x2 - sections[i].x1 + 1;
roentgen b75cab
    length = sections[i].y2 - sections[i].y1 + 1;
roentgen b75cab
    sectsize = (uint32)
roentgen b75cab
	    ceil((width * image->bps + 7) / (double)8) * image->spp * length;
roentgen b75cab
    /* allocate a buffer if we don't have one already */
roentgen b75cab
    if (createImageSection(sectsize, sect_buff_ptr))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("writeImageSections", "Unable to allocate section buffer");
roentgen b75cab
      exit (-1);
roentgen b75cab
      }
roentgen b75cab
    sect_buff = *sect_buff_ptr;
roentgen b75cab
roentgen b75cab
    if (extractImageSection (image, &sections[i], src_buff, sect_buff))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("writeImageSections", "Unable to extract image sections");
roentgen b75cab
      exit (-1);
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
  /* call the write routine here instead of outside the loop */
roentgen b75cab
    if (writeSingleSection(in, out, image, dump, width, length, hres, vres, sect_buff))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("writeImageSections", "Unable to write image section");
roentgen b75cab
      exit (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end writeImageSections */
roentgen b75cab
roentgen b75cab
/* Code in this function is heavily indebted to code in tiffcp
roentgen b75cab
 * with modifications by Richard Nolde to handle orientation correctly.
roentgen b75cab
 * It will have to be updated significantly if support is added to
roentgen b75cab
 * extract one or more samples from original image since the 
roentgen b75cab
 * original code assumes we are always copying all samples.
roentgen b75cab
 */
roentgen b75cab
static int  
roentgen b75cab
writeSingleSection(TIFF *in, TIFF *out, struct image_data *image,
roentgen b75cab
                   struct dump_opts *dump, uint32 width, uint32 length,
roentgen b75cab
                   double hres, double vres,
roentgen b75cab
                   unsigned char *sect_buff)
roentgen b75cab
  {
roentgen b75cab
  uint16 bps, spp;
roentgen b75cab
  uint16 input_compression, input_photometric;
roentgen b75cab
  uint16 input_planar;
roentgen b75cab
  struct cpTag* p;
roentgen b75cab
roentgen b75cab
  /*  Calling this seems to reset the compression mode on the TIFF *in file.
roentgen b75cab
  TIFFGetField(in, TIFFTAG_JPEGCOLORMODE, &input_jpeg_colormode);
roentgen b75cab
  */
roentgen b75cab
  input_compression = image->compression;
roentgen b75cab
  input_photometric = image->photometric;
roentgen b75cab
roentgen b75cab
  spp = image->spp;
roentgen b75cab
  bps = image->bps;
roentgen b75cab
  TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bps);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
roentgen b75cab
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
  TIFFError("writeSingleSection", "Input compression: %s",
roentgen b75cab
	    (input_compression == COMPRESSION_OJPEG) ? "Old Jpeg" :
roentgen b75cab
	    ((input_compression == COMPRESSION_JPEG) ?  "New Jpeg" : "Non Jpeg"));
roentgen b75cab
#endif
roentgen b75cab
  /* This is the global variable compression which is set 
roentgen b75cab
   * if the user has specified a command line option for 
roentgen b75cab
   * a compression option.  Should be passed around in one
roentgen b75cab
   * of the parameters instead of as a global. If no user
roentgen b75cab
   * option specified it will still be (uint16) -1. */
roentgen b75cab
  if (compression != (uint16)-1)
roentgen b75cab
    TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
roentgen b75cab
  else
roentgen b75cab
    { /* OJPEG is no longer supported for writing so upgrade to JPEG */
roentgen b75cab
    if (input_compression == COMPRESSION_OJPEG)
roentgen b75cab
      {
roentgen b75cab
      compression = COMPRESSION_JPEG;
roentgen b75cab
      jpegcolormode = JPEGCOLORMODE_RAW;
roentgen b75cab
      TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
roentgen b75cab
      }
roentgen b75cab
    else /* Use the compression from the input file */
roentgen b75cab
      TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (compression == COMPRESSION_JPEG)
roentgen b75cab
    {
roentgen b75cab
    if ((input_photometric == PHOTOMETRIC_PALETTE) ||  /* color map indexed */
roentgen b75cab
        (input_photometric == PHOTOMETRIC_MASK))       /* holdout mask */
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("writeSingleSection",
roentgen b75cab
                 "JPEG compression cannot be used with %s image data",
roentgen b75cab
		 (input_photometric == PHOTOMETRIC_PALETTE) ?
roentgen b75cab
                 "palette" : "mask");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    if ((input_photometric == PHOTOMETRIC_RGB) &&
roentgen b75cab
	(jpegcolormode == JPEGCOLORMODE_RGB))
roentgen b75cab
      TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
roentgen b75cab
    else
roentgen b75cab
	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (compression == COMPRESSION_SGILOG || compression == COMPRESSION_SGILOG24)
roentgen b75cab
      TIFFSetField(out, TIFFTAG_PHOTOMETRIC, spp == 1 ?
roentgen b75cab
			PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
roentgen b75cab
    else
roentgen b75cab
      TIFFSetField(out, TIFFTAG_PHOTOMETRIC, image->photometric);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
  TIFFError("writeSingleSection", "Input photometric: %s",
roentgen b75cab
	    (input_photometric == PHOTOMETRIC_RGB) ? "RGB" :
roentgen b75cab
	    ((input_photometric == PHOTOMETRIC_YCBCR) ?  "YCbCr" : "Not RGB or YCbCr"));
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
  if (((input_photometric == PHOTOMETRIC_LOGL) ||
roentgen b75cab
       (input_photometric ==  PHOTOMETRIC_LOGLUV)) &&
roentgen b75cab
      ((compression != COMPRESSION_SGILOG) && 
roentgen b75cab
       (compression != COMPRESSION_SGILOG24)))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("writeSingleSection",
roentgen b75cab
              "LogL and LogLuv source data require SGI_LOG or SGI_LOG24 compression");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (fillorder != 0)
roentgen b75cab
    TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
roentgen b75cab
  else
roentgen b75cab
    CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
roentgen b75cab
roentgen b75cab
  /* The loadimage function reads input orientation and sets
roentgen b75cab
   * image->orientation. The correct_image_orientation function
roentgen b75cab
   * applies the required rotation and mirror operations to 
roentgen b75cab
   * present the data in TOPLEFT orientation and updates 
roentgen b75cab
   * image->orientation if any transforms are performed, 
roentgen b75cab
   * as per EXIF standard.
roentgen b75cab
   */
roentgen b75cab
  TIFFSetField(out, TIFFTAG_ORIENTATION, image->orientation);
roentgen b75cab
roentgen b75cab
  /*
roentgen b75cab
   * Choose tiles/strip for the output image according to
roentgen b75cab
   * the command line arguments (-tiles, -strips) and the
roentgen b75cab
   * structure of the input image.
roentgen b75cab
   */
roentgen b75cab
  if (outtiled == -1)
roentgen b75cab
    outtiled = TIFFIsTiled(in);
roentgen b75cab
  if (outtiled) {
roentgen b75cab
    /*
roentgen b75cab
     * Setup output file's tile width&height.  If either
roentgen b75cab
     * is not specified, use either the value from the
roentgen b75cab
     * input image or, if nothing is defined, use the
roentgen b75cab
     * library default.
roentgen b75cab
     */
roentgen b75cab
    if (tilewidth == (uint32) 0)
roentgen b75cab
      TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
roentgen b75cab
    if (tilelength == (uint32) 0)
roentgen b75cab
      TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
roentgen b75cab
roentgen b75cab
    if (tilewidth == 0 || tilelength == 0)
roentgen b75cab
      TIFFDefaultTileSize(out, &tilewidth, &tilelength);
roentgen b75cab
    TIFFDefaultTileSize(out, &tilewidth, &tilelength);
roentgen b75cab
    TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
roentgen b75cab
    TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
roentgen b75cab
    } else {
roentgen b75cab
       /*
roentgen b75cab
	* RowsPerStrip is left unspecified: use either the
roentgen b75cab
	* value from the input image or, if nothing is defined,
roentgen b75cab
	* use the library default.
roentgen b75cab
	*/
roentgen b75cab
	if (rowsperstrip == (uint32) 0)
roentgen b75cab
          {
roentgen b75cab
	  if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
roentgen b75cab
	    rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
roentgen b75cab
          if (compression != COMPRESSION_JPEG)
roentgen b75cab
            {
roentgen b75cab
  	    if (rowsperstrip > length)
roentgen b75cab
	      rowsperstrip = length;
roentgen b75cab
	    }
roentgen b75cab
	  }
roentgen b75cab
	else 
roentgen b75cab
          if (rowsperstrip == (uint32) -1)
roentgen b75cab
	    rowsperstrip = length;
roentgen b75cab
	TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &input_planar);
roentgen b75cab
  if (config != (uint16) -1)
roentgen b75cab
    TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
roentgen b75cab
  else
roentgen b75cab
    CopyField(TIFFTAG_PLANARCONFIG, config);
roentgen b75cab
  if (spp <= 4)
roentgen b75cab
    CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
roentgen b75cab
  CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
roentgen b75cab
roentgen b75cab
/* SMinSampleValue & SMaxSampleValue */
roentgen b75cab
  switch (compression) {
roentgen b75cab
    /* These are references to GLOBAL variables set by defaults
roentgen b75cab
     * and /or the compression flag
roentgen b75cab
     */
roentgen b75cab
    case COMPRESSION_JPEG:
roentgen b75cab
         if (((bps % 8) == 0) || ((bps % 12) == 0))
roentgen b75cab
	   {
roentgen b75cab
           TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
roentgen b75cab
	   TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
roentgen b75cab
           }
roentgen b75cab
         else
roentgen b75cab
           {
roentgen b75cab
	   TIFFError("writeSingleSection",
roentgen b75cab
                     "JPEG compression requires 8 or 12 bits per sample");
roentgen b75cab
           return (-1);
roentgen b75cab
           }
roentgen b75cab
	 break;
roentgen b75cab
   case COMPRESSION_LZW:
roentgen b75cab
   case COMPRESSION_ADOBE_DEFLATE:
roentgen b75cab
   case COMPRESSION_DEFLATE:
roentgen b75cab
	if (predictor != (uint16)-1)
roentgen b75cab
          TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
roentgen b75cab
	else
roentgen b75cab
	  CopyField(TIFFTAG_PREDICTOR, predictor);
roentgen b75cab
	break;
roentgen b75cab
   case COMPRESSION_CCITTFAX3:
roentgen b75cab
   case COMPRESSION_CCITTFAX4:
roentgen b75cab
	if (compression == COMPRESSION_CCITTFAX3) {
roentgen b75cab
          if (g3opts != (uint32) -1)
roentgen b75cab
	    TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
roentgen b75cab
	  else
roentgen b75cab
	    CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
roentgen b75cab
	} else
roentgen b75cab
	    CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
roentgen b75cab
	break;
roentgen b75cab
   }
roentgen b75cab
   { uint32 len32;
roentgen b75cab
     void** data;
roentgen b75cab
     if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
roentgen b75cab
       TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
roentgen b75cab
   }
roentgen b75cab
   { uint16 ninks;
roentgen b75cab
     const char* inknames;
roentgen b75cab
     if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
roentgen b75cab
       TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
roentgen b75cab
       if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
roentgen b75cab
	 int inknameslen = strlen(inknames) + 1;
roentgen b75cab
	 const char* cp = inknames;
roentgen b75cab
	 while (ninks > 1) {
roentgen b75cab
	   cp = strchr(cp, '\0');
roentgen b75cab
	   if (cp) {
roentgen b75cab
	     cp++;
roentgen b75cab
	     inknameslen += (strlen(cp) + 1);
roentgen b75cab
	   }
roentgen b75cab
	   ninks--;
roentgen b75cab
         }
roentgen b75cab
	 TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
roentgen b75cab
       }
roentgen b75cab
     }
roentgen b75cab
   }
roentgen b75cab
   {
roentgen b75cab
   unsigned short pg0, pg1;
roentgen b75cab
   if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
roentgen b75cab
     if (pageNum < 0) /* only one input file */
roentgen b75cab
	TIFFSetField(out, TIFFTAG_PAGENUMBER, pg0, pg1);
roentgen b75cab
     else 
roentgen b75cab
	TIFFSetField(out, TIFFTAG_PAGENUMBER, pageNum++, 0);
roentgen b75cab
     }
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
  for (p = tags; p < &tags[NTAGS]; p++)
roentgen b75cab
		CopyTag(p->tag, p->count, p->type);
roentgen b75cab
roentgen b75cab
  /* Update these since they are overwritten from input res by loop above */
roentgen b75cab
  TIFFSetField(out, TIFFTAG_XRESOLUTION, (float)hres);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_YRESOLUTION, (float)vres);
roentgen b75cab
roentgen b75cab
  /* Compute the tile or strip dimensions and write to disk */
roentgen b75cab
  if (outtiled)
roentgen b75cab
    {
roentgen b75cab
    if (config == PLANARCONFIG_CONTIG)
roentgen b75cab
      writeBufferToContigTiles (out, sect_buff, length, width, spp, dump);
roentgen b75cab
    else
roentgen b75cab
      writeBufferToSeparateTiles (out, sect_buff, length, width, spp, dump);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (config == PLANARCONFIG_CONTIG)
roentgen b75cab
      writeBufferToContigStrips (out, sect_buff, length);
roentgen b75cab
    else
roentgen b75cab
      writeBufferToSeparateStrips(out, sect_buff, length, width, spp, dump);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!TIFFWriteDirectory(out))
roentgen b75cab
    {
roentgen b75cab
    TIFFClose(out);
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end writeSingleSection */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Create a buffer to write one section at a time */
roentgen b75cab
static int
roentgen b75cab
createImageSection(uint32 sectsize, unsigned char **sect_buff_ptr)
roentgen b75cab
  {
roentgen b75cab
  unsigned  char *sect_buff = NULL;
roentgen b75cab
  unsigned  char *new_buff  = NULL;
roentgen b75cab
  static    uint32  prev_sectsize = 0;
roentgen b75cab
  
roentgen b75cab
  sect_buff = *sect_buff_ptr;
roentgen b75cab
roentgen b75cab
  if (!sect_buff)
roentgen b75cab
    {
roentgen b75cab
    sect_buff = (unsigned char *)_TIFFmalloc(sectsize);
roentgen b75cab
    *sect_buff_ptr = sect_buff;
roentgen b75cab
    _TIFFmemset(sect_buff, 0, sectsize);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (prev_sectsize < sectsize)
roentgen b75cab
      {
roentgen b75cab
      new_buff = _TIFFrealloc(sect_buff, sectsize);
roentgen b75cab
      if (!new_buff)
roentgen b75cab
        {
roentgen b75cab
	free (sect_buff);
roentgen b75cab
        sect_buff = (unsigned char *)_TIFFmalloc(sectsize);
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        sect_buff = new_buff;
roentgen b75cab
roentgen b75cab
      _TIFFmemset(sect_buff, 0, sectsize);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!sect_buff)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("createImageSection", "Unable to allocate/reallocate section buffer");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
  prev_sectsize = sectsize;
roentgen b75cab
  *sect_buff_ptr = sect_buff;
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }  /* end createImageSection */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Process selections defined by regions, zones, margins, or fixed sized areas */
roentgen b75cab
static int
roentgen b75cab
processCropSelections(struct image_data *image, struct crop_mask *crop, 
roentgen b75cab
                      unsigned char **read_buff_ptr, struct buffinfo seg_buffs[])
roentgen b75cab
  {
roentgen b75cab
  int       i;
roentgen b75cab
  uint32    width, length, total_width, total_length;
roentgen b75cab
  tsize_t   cropsize;
roentgen b75cab
  unsigned  char *crop_buff = NULL;
roentgen b75cab
  unsigned  char *read_buff = NULL;
roentgen b75cab
  unsigned  char *next_buff = NULL;
roentgen b75cab
  tsize_t   prev_cropsize = 0;
roentgen b75cab
roentgen b75cab
  read_buff = *read_buff_ptr;
roentgen b75cab
roentgen b75cab
  if (crop->img_mode == COMPOSITE_IMAGES)
roentgen b75cab
    {
roentgen b75cab
    cropsize = crop->bufftotal;
roentgen b75cab
    crop_buff = seg_buffs[0].buffer; 
roentgen b75cab
    if (!crop_buff)
roentgen b75cab
      crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      prev_cropsize = seg_buffs[0].size;
roentgen b75cab
      if (prev_cropsize < cropsize)
roentgen b75cab
        {
roentgen b75cab
        next_buff = _TIFFrealloc(crop_buff, cropsize);
roentgen b75cab
        if (! next_buff)
roentgen b75cab
          {
roentgen b75cab
          _TIFFfree (crop_buff);
roentgen b75cab
          crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
roentgen b75cab
          }
roentgen b75cab
        else
roentgen b75cab
          crop_buff = next_buff;
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if (!crop_buff)
roentgen b75cab
      {
roentgen b75cab
      TIFFError("processCropSelections", "Unable to allocate/reallocate crop buffer");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
 
roentgen b75cab
    _TIFFmemset(crop_buff, 0, cropsize);
roentgen b75cab
    seg_buffs[0].buffer = crop_buff;
roentgen b75cab
    seg_buffs[0].size = cropsize;
roentgen b75cab
roentgen b75cab
    /* Checks for matching width or length as required */
roentgen b75cab
    if (extractCompositeRegions(image, crop, read_buff, crop_buff) != 0)
roentgen b75cab
      return (1);
roentgen b75cab
roentgen b75cab
    if (crop->crop_mode & CROP_INVERT)
roentgen b75cab
      {
roentgen b75cab
      switch (crop->photometric)
roentgen b75cab
        {
roentgen b75cab
        /* Just change the interpretation */
roentgen b75cab
        case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
        case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
	     image->photometric = crop->photometric;
roentgen b75cab
	     break;
roentgen b75cab
        case INVERT_DATA_ONLY:
roentgen b75cab
        case INVERT_DATA_AND_TAG:
roentgen b75cab
             if (invertImage(image->photometric, image->spp, image->bps, 
roentgen b75cab
                             crop->combined_width, crop->combined_length, crop_buff))
roentgen b75cab
               {
roentgen b75cab
               TIFFError("processCropSelections", 
roentgen b75cab
                         "Failed to invert colorspace for composite regions");
roentgen b75cab
               return (-1);
roentgen b75cab
               }
roentgen b75cab
             if (crop->photometric == INVERT_DATA_AND_TAG)
roentgen b75cab
               {
roentgen b75cab
               switch (image->photometric)
roentgen b75cab
                 {
roentgen b75cab
                 case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
 	              image->photometric = PHOTOMETRIC_MINISBLACK;
roentgen b75cab
	              break;
roentgen b75cab
                 case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
 	              image->photometric = PHOTOMETRIC_MINISWHITE;
roentgen b75cab
	              break;
roentgen b75cab
                 default:
roentgen b75cab
	              break;
roentgen b75cab
	         }
roentgen b75cab
	       }
roentgen b75cab
             break;
roentgen b75cab
        default: break;
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    /* Mirror and Rotate will not work with multiple regions unless they are the same width */
roentgen b75cab
    if (crop->crop_mode & CROP_MIRROR)
roentgen b75cab
      {
roentgen b75cab
      if (mirrorImage(image->spp, image->bps, crop->mirror, 
roentgen b75cab
                      crop->combined_width, crop->combined_length, crop_buff))
roentgen b75cab
        {
roentgen b75cab
        TIFFError("processCropSelections", "Failed to mirror composite regions %s", 
roentgen b75cab
	         (crop->rotation == MIRROR_HORIZ) ? "horizontally" : "vertically");
roentgen b75cab
        return (-1);
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
roentgen b75cab
    if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
roentgen b75cab
      {
roentgen b75cab
      if (rotateImage(crop->rotation, image, &crop->combined_width, 
roentgen b75cab
                      &crop->combined_length, &crop_buff))
roentgen b75cab
        {
roentgen b75cab
        TIFFError("processCropSelections", 
roentgen b75cab
                  "Failed to rotate composite regions by %d degrees", crop->rotation);
roentgen b75cab
        return (-1);
roentgen b75cab
        }
roentgen b75cab
      seg_buffs[0].buffer = crop_buff;
roentgen b75cab
      seg_buffs[0].size = (((crop->combined_width * image->bps + 7 ) / 8)
roentgen b75cab
                            * image->spp) * crop->combined_length; 
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  else  /* Separated Images */
roentgen b75cab
    {
roentgen b75cab
    total_width = total_length = 0;
roentgen b75cab
    for (i = 0; i < crop->selections; i++)
roentgen b75cab
      {
roentgen b75cab
      cropsize = crop->bufftotal;
roentgen b75cab
      crop_buff = seg_buffs[i].buffer; 
roentgen b75cab
      if (!crop_buff)
roentgen b75cab
        crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        prev_cropsize = seg_buffs[0].size;
roentgen b75cab
        if (prev_cropsize < cropsize)
roentgen b75cab
          {
roentgen b75cab
          next_buff = _TIFFrealloc(crop_buff, cropsize);
roentgen b75cab
          if (! next_buff)
roentgen b75cab
            {
roentgen b75cab
            _TIFFfree (crop_buff);
roentgen b75cab
            crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
roentgen b75cab
            }
roentgen b75cab
          else
roentgen b75cab
            crop_buff = next_buff;
roentgen b75cab
          }
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (!crop_buff)
roentgen b75cab
        {
roentgen b75cab
        TIFFError("processCropSelections", "Unable to allocate/reallocate crop buffer");
roentgen b75cab
        return (-1);
roentgen b75cab
        }
roentgen b75cab
 
roentgen b75cab
      _TIFFmemset(crop_buff, 0, cropsize);
roentgen b75cab
      seg_buffs[i].buffer = crop_buff;
roentgen b75cab
      seg_buffs[i].size = cropsize;
roentgen b75cab
roentgen b75cab
      if (extractSeparateRegion(image, crop, read_buff, crop_buff, i))
roentgen b75cab
        {
roentgen b75cab
	TIFFError("processCropSelections", "Unable to extract cropped region %d from image", i);
roentgen b75cab
        return (-1);
roentgen b75cab
        }
roentgen b75cab
    
roentgen b75cab
      width  = crop->regionlist[i].width;
roentgen b75cab
      length = crop->regionlist[i].length;
roentgen b75cab
roentgen b75cab
      if (crop->crop_mode & CROP_INVERT)
roentgen b75cab
        {
roentgen b75cab
        switch (crop->photometric)
roentgen b75cab
          {
roentgen b75cab
          /* Just change the interpretation */
roentgen b75cab
          case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
          case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
	       image->photometric = crop->photometric;
roentgen b75cab
	       break;
roentgen b75cab
          case INVERT_DATA_ONLY:
roentgen b75cab
          case INVERT_DATA_AND_TAG:
roentgen b75cab
               if (invertImage(image->photometric, image->spp, image->bps, 
roentgen b75cab
                               width, length, crop_buff))
roentgen b75cab
                 {
roentgen b75cab
                 TIFFError("processCropSelections", 
roentgen b75cab
                           "Failed to invert colorspace for region");
roentgen b75cab
                 return (-1);
roentgen b75cab
                 }
roentgen b75cab
               if (crop->photometric == INVERT_DATA_AND_TAG)
roentgen b75cab
                 {
roentgen b75cab
                 switch (image->photometric)
roentgen b75cab
                   {
roentgen b75cab
                   case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
 	                image->photometric = PHOTOMETRIC_MINISBLACK;
roentgen b75cab
	                break;
roentgen b75cab
                   case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
 	                image->photometric = PHOTOMETRIC_MINISWHITE;
roentgen b75cab
	                break;
roentgen b75cab
                   default:
roentgen b75cab
	                break;
roentgen b75cab
	           }
roentgen b75cab
	         }
roentgen b75cab
               break;
roentgen b75cab
          default: break;
roentgen b75cab
          }
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (crop->crop_mode & CROP_MIRROR)
roentgen b75cab
        {
roentgen b75cab
        if (mirrorImage(image->spp, image->bps, crop->mirror, 
roentgen b75cab
                        width, length, crop_buff))
roentgen b75cab
          {
roentgen b75cab
          TIFFError("processCropSelections", "Failed to mirror crop region %s", 
roentgen b75cab
	           (crop->rotation == MIRROR_HORIZ) ? "horizontally" : "vertically");
roentgen b75cab
          return (-1);
roentgen b75cab
          }
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
roentgen b75cab
        {
roentgen b75cab
	if (rotateImage(crop->rotation, image, &crop->regionlist[i].width, 
roentgen b75cab
			&crop->regionlist[i].length, &crop_buff))
roentgen b75cab
          {
roentgen b75cab
          TIFFError("processCropSelections", 
roentgen b75cab
                    "Failed to rotate crop region by %d degrees", crop->rotation);
roentgen b75cab
          return (-1);
roentgen b75cab
          }
roentgen b75cab
        total_width  += crop->regionlist[i].width;
roentgen b75cab
        total_length += crop->regionlist[i].length;
roentgen b75cab
        crop->combined_width = total_width;
roentgen b75cab
        crop->combined_length = total_length;
roentgen b75cab
        seg_buffs[i].buffer = crop_buff;
roentgen b75cab
        seg_buffs[i].size = (((crop->regionlist[i].width * image->bps + 7 ) / 8)
roentgen b75cab
                               * image->spp) * crop->regionlist[i].length; 
roentgen b75cab
        }
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end processCropSelections */
roentgen b75cab
roentgen b75cab
/* Copy the crop section of the data from the current image into a buffer
roentgen b75cab
 * and adjust the IFD values to reflect the new size. If no cropping is
roentgen b75cab
 * required, use the origial read buffer as the crop buffer.
roentgen b75cab
 *
roentgen b75cab
 * There is quite a bit of redundancy between this routine and the more
roentgen b75cab
 * specialized processCropSelections, but this provides
roentgen b75cab
 * the most optimized path when no Zones or Regions are required.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
createCroppedImage(struct image_data *image, struct crop_mask *crop, 
roentgen b75cab
                   unsigned char **read_buff_ptr, unsigned char **crop_buff_ptr)
roentgen b75cab
  {
roentgen b75cab
  tsize_t   cropsize;
roentgen b75cab
  unsigned  char *read_buff = NULL;
roentgen b75cab
  unsigned  char *crop_buff = NULL;
roentgen b75cab
  unsigned  char *new_buff  = NULL;
roentgen b75cab
  static    tsize_t  prev_cropsize = 0;
roentgen b75cab
roentgen b75cab
  read_buff = *read_buff_ptr;
roentgen b75cab
roentgen b75cab
  /* process full image, no crop buffer needed */
roentgen b75cab
  crop_buff = read_buff;
roentgen b75cab
  *crop_buff_ptr = read_buff;
roentgen b75cab
  crop->combined_width = image->width;
roentgen b75cab
  crop->combined_length = image->length;
roentgen b75cab
roentgen b75cab
  cropsize = crop->bufftotal;
roentgen b75cab
  crop_buff = *crop_buff_ptr;
roentgen b75cab
  if (!crop_buff)
roentgen b75cab
    {
roentgen b75cab
    crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
roentgen b75cab
    *crop_buff_ptr = crop_buff;
roentgen b75cab
    _TIFFmemset(crop_buff, 0, cropsize);
roentgen b75cab
    prev_cropsize = cropsize;
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (prev_cropsize < cropsize)
roentgen b75cab
      {
roentgen b75cab
      new_buff = _TIFFrealloc(crop_buff, cropsize);
roentgen b75cab
      if (!new_buff)
roentgen b75cab
        {
roentgen b75cab
	free (crop_buff);
roentgen b75cab
        crop_buff = (unsigned char *)_TIFFmalloc(cropsize);
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        crop_buff = new_buff;
roentgen b75cab
      _TIFFmemset(crop_buff, 0, cropsize);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!crop_buff)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("createCroppedImage", "Unable to allocate/reallocate crop buffer");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
  *crop_buff_ptr = crop_buff;
roentgen b75cab
roentgen b75cab
  if (crop->crop_mode & CROP_INVERT)
roentgen b75cab
    {
roentgen b75cab
    switch (crop->photometric)
roentgen b75cab
      {
roentgen b75cab
      /* Just change the interpretation */
roentgen b75cab
      case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
      case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
	   image->photometric = crop->photometric;
roentgen b75cab
	   break;
roentgen b75cab
      case INVERT_DATA_ONLY:
roentgen b75cab
      case INVERT_DATA_AND_TAG:
roentgen b75cab
           if (invertImage(image->photometric, image->spp, image->bps, 
roentgen b75cab
                           crop->combined_width, crop->combined_length, crop_buff))
roentgen b75cab
             {
roentgen b75cab
             TIFFError("createCroppedImage", 
roentgen b75cab
                       "Failed to invert colorspace for image or cropped selection");
roentgen b75cab
             return (-1);
roentgen b75cab
             }
roentgen b75cab
           if (crop->photometric == INVERT_DATA_AND_TAG)
roentgen b75cab
             {
roentgen b75cab
             switch (image->photometric)
roentgen b75cab
               {
roentgen b75cab
               case PHOTOMETRIC_MINISWHITE:
roentgen b75cab
 	            image->photometric = PHOTOMETRIC_MINISBLACK;
roentgen b75cab
	            break;
roentgen b75cab
               case PHOTOMETRIC_MINISBLACK:
roentgen b75cab
 	            image->photometric = PHOTOMETRIC_MINISWHITE;
roentgen b75cab
	            break;
roentgen b75cab
               default:
roentgen b75cab
	            break;
roentgen b75cab
	       }
roentgen b75cab
	     }
roentgen b75cab
           break;
roentgen b75cab
      default: break;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (crop->crop_mode & CROP_MIRROR)
roentgen b75cab
    {
roentgen b75cab
    if (mirrorImage(image->spp, image->bps, crop->mirror, 
roentgen b75cab
                    crop->combined_width, crop->combined_length, crop_buff))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("createCroppedImage", "Failed to mirror image or cropped selection %s", 
roentgen b75cab
	       (crop->rotation == MIRROR_HORIZ) ? "horizontally" : "vertically");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (crop->crop_mode & CROP_ROTATE) /* rotate should be last as it can reallocate the buffer */
roentgen b75cab
    {
roentgen b75cab
    if (rotateImage(crop->rotation, image, &crop->combined_width, 
roentgen b75cab
                    &crop->combined_length, crop_buff_ptr))
roentgen b75cab
      {
roentgen b75cab
      TIFFError("createCroppedImage", 
roentgen b75cab
                "Failed to rotate image or cropped selection by %d degrees", crop->rotation);
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (crop_buff == read_buff) /* we used the read buffer for the crop buffer */
roentgen b75cab
    *read_buff_ptr = NULL;    /* so we don't try to free it later */
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end createCroppedImage */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Code in this function is heavily indebted to code in tiffcp
roentgen b75cab
 * with modifications by Richard Nolde to handle orientation correctly.
roentgen b75cab
 * It will have to be updated significantly if support is added to
roentgen b75cab
 * extract one or more samples from original image since the 
roentgen b75cab
 * original code assumes we are always copying all samples.
roentgen b75cab
 * Use of global variables for config, compression and others
roentgen b75cab
 * should be replaced by addition to the crop_mask struct (which
roentgen b75cab
 * will be renamed to proc_opts indicating that is controlls
roentgen b75cab
 * user supplied processing options, not just cropping) and 
roentgen b75cab
 * then passed in as an argument.
roentgen b75cab
 */
roentgen b75cab
static int  
roentgen b75cab
writeCroppedImage(TIFF *in, TIFF *out, struct image_data *image, 
roentgen b75cab
                  struct dump_opts *dump, uint32 width, uint32 length, 
roentgen b75cab
                  unsigned char *crop_buff, int pagenum, int total_pages)
roentgen b75cab
  {
roentgen b75cab
  uint16 bps, spp;
roentgen b75cab
  uint16 input_compression, input_photometric;
roentgen b75cab
  uint16 input_planar;
roentgen b75cab
  struct cpTag* p;
roentgen b75cab
roentgen b75cab
  input_compression = image->compression;
roentgen b75cab
  input_photometric = image->photometric;
roentgen b75cab
  spp = image->spp;
roentgen b75cab
  bps = image->bps;
roentgen b75cab
roentgen b75cab
  TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_IMAGELENGTH, length);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bps);
roentgen b75cab
  TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, spp);
roentgen b75cab
roentgen b75cab
#ifdef DEBUG2
roentgen b75cab
  TIFFError("writeCroppedImage", "Input compression: %s",
roentgen b75cab
	    (input_compression == COMPRESSION_OJPEG) ? "Old Jpeg" :
roentgen b75cab
	    ((input_compression == COMPRESSION_JPEG) ?  "New Jpeg" : "Non Jpeg"));
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
  if (compression != (uint16)-1)
roentgen b75cab
    TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (input_compression == COMPRESSION_OJPEG)
roentgen b75cab
      {
roentgen b75cab
      compression = COMPRESSION_JPEG;
roentgen b75cab
      jpegcolormode = JPEGCOLORMODE_RAW;
roentgen b75cab
      TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_JPEG);
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      CopyField(TIFFTAG_COMPRESSION, compression);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (compression == COMPRESSION_JPEG)
roentgen b75cab
    {
roentgen b75cab
    if ((input_photometric == PHOTOMETRIC_PALETTE) ||  /* color map indexed */
roentgen b75cab
        (input_photometric == PHOTOMETRIC_MASK))       /* $holdout mask */
roentgen b75cab
      {
roentgen b75cab
      TIFFError ("writeCroppedImage",
roentgen b75cab
                 "JPEG compression cannot be used with %s image data",
roentgen b75cab
      	        (input_photometric == PHOTOMETRIC_PALETTE) ?
roentgen b75cab
                 "palette" : "mask");
roentgen b75cab
      return (-1);
roentgen b75cab
      }
roentgen b75cab
    if ((input_photometric == PHOTOMETRIC_RGB) &&
roentgen b75cab
	(jpegcolormode == JPEGCOLORMODE_RGB))
roentgen b75cab
      TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
roentgen b75cab
    else
roentgen b75cab
	TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (compression == COMPRESSION_SGILOG || compression == COMPRESSION_SGILOG24)
roentgen b75cab
      {
roentgen b75cab
      TIFFSetField(out, TIFFTAG_PHOTOMETRIC, spp == 1 ?
roentgen b75cab
			PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      if (input_compression == COMPRESSION_SGILOG ||
roentgen b75cab
          input_compression == COMPRESSION_SGILOG24)
roentgen b75cab
        {
roentgen b75cab
        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, spp == 1 ?
roentgen b75cab
			  PHOTOMETRIC_LOGL : PHOTOMETRIC_LOGLUV);
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, image->photometric);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (((input_photometric == PHOTOMETRIC_LOGL) ||
roentgen b75cab
       (input_photometric ==  PHOTOMETRIC_LOGLUV)) &&
roentgen b75cab
      ((compression != COMPRESSION_SGILOG) && 
roentgen b75cab
       (compression != COMPRESSION_SGILOG24)))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("writeCroppedImage",
roentgen b75cab
              "LogL and LogLuv source data require SGI_LOG or SGI_LOG24 compression");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (fillorder != 0)
roentgen b75cab
    TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
roentgen b75cab
  else
roentgen b75cab
    CopyTag(TIFFTAG_FILLORDER, 1, TIFF_SHORT);
roentgen b75cab
roentgen b75cab
  /* The loadimage function reads input orientation and sets
roentgen b75cab
   * image->orientation. The correct_image_orientation function
roentgen b75cab
   * applies the required rotation and mirror operations to 
roentgen b75cab
   * present the data in TOPLEFT orientation and updates 
roentgen b75cab
   * image->orientation if any transforms are performed, 
roentgen b75cab
   * as per EXIF standard. 
roentgen b75cab
   */
roentgen b75cab
  TIFFSetField(out, TIFFTAG_ORIENTATION, image->orientation);
roentgen b75cab
	
roentgen b75cab
  /*
roentgen b75cab
   * Choose tiles/strip for the output image according to
roentgen b75cab
   * the command line arguments (-tiles, -strips) and the
roentgen b75cab
   * structure of the input image.
roentgen b75cab
   */
roentgen b75cab
  if (outtiled == -1)
roentgen b75cab
    outtiled = TIFFIsTiled(in);
roentgen b75cab
  if (outtiled) {
roentgen b75cab
    /*
roentgen b75cab
     * Setup output file's tile width&height.  If either
roentgen b75cab
     * is not specified, use either the value from the
roentgen b75cab
     * input image or, if nothing is defined, use the
roentgen b75cab
     * library default.
roentgen b75cab
     */
roentgen b75cab
    if (tilewidth == (uint32) 0)
roentgen b75cab
      TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
roentgen b75cab
    if (tilelength == (uint32) 0)
roentgen b75cab
      TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
roentgen b75cab
roentgen b75cab
    if (tilewidth == 0 || tilelength == 0)
roentgen b75cab
      TIFFDefaultTileSize(out, &tilewidth, &tilelength);
roentgen b75cab
    TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
roentgen b75cab
    TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
roentgen b75cab
    } else {
roentgen b75cab
       /*
roentgen b75cab
	* RowsPerStrip is left unspecified: use either the
roentgen b75cab
	* value from the input image or, if nothing is defined,
roentgen b75cab
	* use the library default.
roentgen b75cab
	*/
roentgen b75cab
	if (rowsperstrip == (uint32) 0)
roentgen b75cab
          {
roentgen b75cab
	  if (!TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip))
roentgen b75cab
	    rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
roentgen b75cab
          if (compression != COMPRESSION_JPEG)
roentgen b75cab
            {
roentgen b75cab
  	    if (rowsperstrip > length)
roentgen b75cab
	      rowsperstrip = length;
roentgen b75cab
	    }
roentgen b75cab
	  }
roentgen b75cab
	else 
roentgen b75cab
          if (rowsperstrip == (uint32) -1)
roentgen b75cab
	    rowsperstrip = length;
roentgen b75cab
	TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
  TIFFGetFieldDefaulted(in, TIFFTAG_PLANARCONFIG, &input_planar);
roentgen b75cab
  if (config != (uint16) -1)
roentgen b75cab
    TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
roentgen b75cab
  else
roentgen b75cab
    CopyField(TIFFTAG_PLANARCONFIG, config);
roentgen b75cab
  if (spp <= 4)
roentgen b75cab
    CopyTag(TIFFTAG_TRANSFERFUNCTION, 4, TIFF_SHORT);
roentgen b75cab
  CopyTag(TIFFTAG_COLORMAP, 4, TIFF_SHORT);
roentgen b75cab
roentgen b75cab
/* SMinSampleValue & SMaxSampleValue */
roentgen b75cab
  switch (compression) {
roentgen b75cab
    case COMPRESSION_JPEG:
roentgen b75cab
         if (((bps % 8) == 0) || ((bps % 12) == 0))
roentgen b75cab
	   {
roentgen b75cab
           TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
roentgen b75cab
	   TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
roentgen b75cab
           }
roentgen b75cab
         else
roentgen b75cab
           {
roentgen b75cab
	   TIFFError("writeCroppedImage",
roentgen b75cab
                     "JPEG compression requires 8 or 12 bits per sample");
roentgen b75cab
           return (-1);
roentgen b75cab
           }
roentgen b75cab
	 break;
roentgen b75cab
   case COMPRESSION_LZW:
roentgen b75cab
   case COMPRESSION_ADOBE_DEFLATE:
roentgen b75cab
   case COMPRESSION_DEFLATE:
roentgen b75cab
	if (predictor != (uint16)-1)
roentgen b75cab
          TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
roentgen b75cab
	else
roentgen b75cab
	  CopyField(TIFFTAG_PREDICTOR, predictor);
roentgen b75cab
	break;
roentgen b75cab
   case COMPRESSION_CCITTFAX3:
roentgen b75cab
   case COMPRESSION_CCITTFAX4:
roentgen b75cab
        if (bps != 1)
roentgen b75cab
          {
roentgen b75cab
	  TIFFError("writeCroppedImage",
roentgen b75cab
            "Group 3/4 compression is not usable with bps > 1");
roentgen b75cab
          return (-1);
roentgen b75cab
	  }
roentgen b75cab
	if (compression == COMPRESSION_CCITTFAX3) {
roentgen b75cab
          if (g3opts != (uint32) -1)
roentgen b75cab
	    TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
roentgen b75cab
	  else
roentgen b75cab
	    CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
roentgen b75cab
	} else
roentgen b75cab
	    CopyTag(TIFFTAG_GROUP4OPTIONS, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_BADFAXLINES, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_CLEANFAXDATA, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_CONSECUTIVEBADFAXLINES, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_FAXRECVTIME, 1, TIFF_LONG);
roentgen b75cab
	    CopyTag(TIFFTAG_FAXSUBADDRESS, 1, TIFF_ASCII);
roentgen b75cab
	 break;
roentgen b75cab
    case COMPRESSION_NONE:
roentgen b75cab
         break;
roentgen b75cab
    default: break;
roentgen b75cab
   }
roentgen b75cab
   { uint32 len32;
roentgen b75cab
     void** data;
roentgen b75cab
     if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &len32, &data))
roentgen b75cab
       TIFFSetField(out, TIFFTAG_ICCPROFILE, len32, data);
roentgen b75cab
   }
roentgen b75cab
   { uint16 ninks;
roentgen b75cab
     const char* inknames;
roentgen b75cab
     if (TIFFGetField(in, TIFFTAG_NUMBEROFINKS, &ninks)) {
roentgen b75cab
       TIFFSetField(out, TIFFTAG_NUMBEROFINKS, ninks);
roentgen b75cab
       if (TIFFGetField(in, TIFFTAG_INKNAMES, &inknames)) {
roentgen b75cab
	 int inknameslen = strlen(inknames) + 1;
roentgen b75cab
	 const char* cp = inknames;
roentgen b75cab
	 while (ninks > 1) {
roentgen b75cab
	   cp = strchr(cp, '\0');
roentgen b75cab
	   if (cp) {
roentgen b75cab
	     cp++;
roentgen b75cab
	     inknameslen += (strlen(cp) + 1);
roentgen b75cab
	   }
roentgen b75cab
	   ninks--;
roentgen b75cab
         }
roentgen b75cab
	 TIFFSetField(out, TIFFTAG_INKNAMES, inknameslen, inknames);
roentgen b75cab
       }
roentgen b75cab
     }
roentgen b75cab
   }
roentgen b75cab
   {
roentgen b75cab
   unsigned short pg0, pg1;
roentgen b75cab
   if (TIFFGetField(in, TIFFTAG_PAGENUMBER, &pg0, &pg1)) {
roentgen b75cab
     TIFFSetField(out, TIFFTAG_PAGENUMBER, pagenum, total_pages);
roentgen b75cab
     }
roentgen b75cab
   }
roentgen b75cab
roentgen b75cab
  for (p = tags; p < &tags[NTAGS]; p++)
roentgen b75cab
		CopyTag(p->tag, p->count, p->type);
roentgen b75cab
roentgen b75cab
  /* Compute the tile or strip dimensions and write to disk */
roentgen b75cab
  if (outtiled)
roentgen b75cab
    {
roentgen b75cab
    if (config == PLANARCONFIG_CONTIG)
roentgen b75cab
      {
roentgen b75cab
      if (writeBufferToContigTiles (out, crop_buff, length, width, spp, dump))
roentgen b75cab
        TIFFError("","Unable to write contiguous tile data for page %d", pagenum);
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      if (writeBufferToSeparateTiles (out, crop_buff, length, width, spp, dump))
roentgen b75cab
        TIFFError("","Unable to write separate tile data for page %d", pagenum);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  else
roentgen b75cab
    {
roentgen b75cab
    if (config == PLANARCONFIG_CONTIG)
roentgen b75cab
      {
roentgen b75cab
      if (writeBufferToContigStrips (out, crop_buff, length))
roentgen b75cab
        TIFFError("","Unable to write contiguous strip data for page %d", pagenum);
roentgen b75cab
      }
roentgen b75cab
    else
roentgen b75cab
      {
roentgen b75cab
      if (writeBufferToSeparateStrips(out, crop_buff, length, width, spp, dump))
roentgen b75cab
        TIFFError("","Unable to write separate strip data for page %d", pagenum);
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!TIFFWriteDirectory(out))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("","Failed to write IFD for page number %d", pagenum);
roentgen b75cab
    TIFFClose(out);
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end writeCroppedImage */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
rotateContigSamples8bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                         uint32 length,   uint32 col, uint8 *src, uint8 *dst)
roentgen b75cab
  {
roentgen b75cab
  int      ready_bits = 0;
roentgen b75cab
  uint32   src_byte = 0, src_bit = 0;
roentgen b75cab
  uint32   row, rowsize = 0, bit_offset = 0;
roentgen b75cab
  uint8    matchbits = 0, maskbits = 0;
roentgen b75cab
  uint8    buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8   *next;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("rotateContigSamples8bits","Invalid src or destination buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  rowsize = ((bps * spp * width) + 7) / 8;
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint8)-1 >> ( 8 - bps);
roentgen b75cab
  buff1 = buff2 = 0;
roentgen b75cab
roentgen b75cab
  for (row = 0; row < length ; row++)
roentgen b75cab
    {
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      switch (rotation)
roentgen b75cab
	{
roentgen b75cab
        case  90: next = src + src_byte - (row * rowsize);
roentgen b75cab
                  break;
roentgen b75cab
        case 270: next = src + src_byte + (row * rowsize);
roentgen b75cab
	          break;
roentgen b75cab
	default:  TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
roentgen b75cab
                  return (1);
roentgen b75cab
        }
roentgen b75cab
      matchbits = maskbits << (8 - src_bit - bps); 
roentgen b75cab
      buff1 = ((*next) & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
       /* If we have a full buffer's worth, write it out */
roentgen b75cab
      if (ready_bits >= 8)
roentgen b75cab
        {
roentgen b75cab
        *dst++ = buff2;
roentgen b75cab
        buff2 = buff1;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
roentgen b75cab
    *dst++ = buff1;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }  /* end rotateContigSamples8bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
rotateContigSamples16bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                         uint32 length,   uint32 col, uint8 *src, uint8 *dst)
roentgen b75cab
  {
roentgen b75cab
  int      ready_bits = 0;
roentgen b75cab
  uint32   row, rowsize, bit_offset;
roentgen b75cab
  uint32   src_byte = 0, src_bit = 0;
roentgen b75cab
  uint16   matchbits = 0, maskbits = 0;
roentgen b75cab
  uint16   buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8    bytebuff = 0;
roentgen b75cab
  uint8   *next;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("rotateContigSamples16bits","Invalid src or destination buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  rowsize = ((bps * spp * width) + 7) / 8;
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint16)-1 >> (16 - bps);
roentgen b75cab
  buff1 = buff2 = 0;
roentgen b75cab
  for (row = 0; row < length; row++)
roentgen b75cab
    {
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      switch (rotation)
roentgen b75cab
	{
roentgen b75cab
        case  90: next = src + src_byte - (row * rowsize);
roentgen b75cab
                  break;
roentgen b75cab
        case 270: next = src + src_byte + (row * rowsize);
roentgen b75cab
	          break;
roentgen b75cab
	default:  TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
roentgen b75cab
                  return (1);
roentgen b75cab
        }
roentgen b75cab
      matchbits = maskbits << (16 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        buff1 = (next[0] << 8) | next[1];
roentgen b75cab
      else
roentgen b75cab
        buff1 = (next[1] << 8) | next[0];
roentgen b75cab
roentgen b75cab
      buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      /* If we have a full buffer's worth, write it out */
roentgen b75cab
      if (ready_bits >= 8)
roentgen b75cab
        {
roentgen b75cab
        bytebuff = (buff2 >> 8);
roentgen b75cab
        *dst++ = bytebuff;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff = (buff2 >> 8);
roentgen b75cab
    *dst++ = bytebuff;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }  /* end rotateContigSamples16bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
rotateContigSamples24bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                          uint32 length,   uint32 col, uint8 *src, uint8 *dst)
roentgen b75cab
  {
roentgen b75cab
  int      ready_bits = 0;
roentgen b75cab
  uint32   row, rowsize, bit_offset;
roentgen b75cab
  uint32   src_byte = 0, src_bit = 0;
roentgen b75cab
  uint32   matchbits = 0, maskbits = 0;
roentgen b75cab
  uint32   buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8    bytebuff1 = 0, bytebuff2 = 0;
roentgen b75cab
  uint8   *next;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("rotateContigSamples24bits","Invalid src or destination buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  rowsize = ((bps * spp * width) + 7) / 8;
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint32)-1 >> (32 - bps);
roentgen b75cab
  buff1 = buff2 = 0;
roentgen b75cab
  for (row = 0; row < length; row++)
roentgen b75cab
    {
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      switch (rotation)
roentgen b75cab
	{
roentgen b75cab
        case  90: next = src + src_byte - (row * rowsize);
roentgen b75cab
                  break;
roentgen b75cab
        case 270: next = src + src_byte + (row * rowsize);
roentgen b75cab
	          break;
roentgen b75cab
	default:  TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
roentgen b75cab
                  return (1);
roentgen b75cab
        }
roentgen b75cab
      matchbits = maskbits << (32 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
	buff1 = (next[0] << 24) | (next[1] << 16) | (next[2] << 8) | next[3];
roentgen b75cab
      else
roentgen b75cab
	buff1 = (next[3] << 24) | (next[2] << 16) | (next[1] << 8) | next[0];
roentgen b75cab
      buff1 = (buff1 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      /* If we have a full buffer's worth, write it out */
roentgen b75cab
      if (ready_bits >= 16)
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 24);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 16);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        ready_bits -= 16;
roentgen b75cab
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff1 = bytebuff2 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
 /* catch any trailing bits at the end of the line */
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 24);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    bytebuff2 = bytebuff1;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
 
roentgen b75cab
  return (0);
roentgen b75cab
  }  /* end rotateContigSamples24bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
rotateContigSamples32bits(uint16 rotation, uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                          uint32 length,   uint32 col, uint8 *src, uint8 *dst)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, shift_width = 0;
roentgen b75cab
  int    bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32 row, rowsize, bit_offset;
roentgen b75cab
  uint32 src_byte, src_bit;
roentgen b75cab
  uint32 longbuff1 = 0, longbuff2 = 0;
roentgen b75cab
  uint64 maskbits = 0, matchbits = 0;
roentgen b75cab
  uint64 buff1 = 0, buff2 = 0, buff3 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
roentgen b75cab
  uint8   *next;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("rotateContigSamples24bits","Invalid src or destination buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8;
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
    shift_width = bytes_per_pixel;
roentgen b75cab
  else
roentgen b75cab
    shift_width = bytes_per_sample + 1;
roentgen b75cab
roentgen b75cab
  rowsize = ((bps * spp * width) + 7) / 8;
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  maskbits =  (uint64)-1 >> (64 - bps);
roentgen b75cab
  buff1 = buff2 = 0;
roentgen b75cab
  for (row = 0; row < length; row++)
roentgen b75cab
    {
roentgen b75cab
    bit_offset = col * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      switch (rotation)
roentgen b75cab
	{
roentgen b75cab
        case  90: next = src + src_byte - (row * rowsize);
roentgen b75cab
                  break;
roentgen b75cab
        case 270: next = src + src_byte + (row * rowsize);
roentgen b75cab
	          break;
roentgen b75cab
	default:  TIFFError("rotateContigSamples8bits", "Invalid rotation %d", rotation);
roentgen b75cab
                  return (1);
roentgen b75cab
        }
roentgen b75cab
      matchbits = maskbits << (64 - src_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (next[0] << 24) | (next[1] << 16) | (next[2] << 8) | next[3];
roentgen b75cab
        longbuff2 = longbuff1;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (next[3] << 24) | (next[2] << 16) | (next[1] << 8) | next[0];
roentgen b75cab
        longbuff2 = longbuff1;
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
      buff3 = ((uint64)longbuff1 << 32) | longbuff2;
roentgen b75cab
      buff1 = (buff3 & matchbits) << (src_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 32)
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 56);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 48);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        bytebuff3 = (buff2 >> 40);
roentgen b75cab
        *dst++ = bytebuff3;
roentgen b75cab
        bytebuff4 = (buff2 >> 32);
roentgen b75cab
        *dst++ = bytebuff4;
roentgen b75cab
        ready_bits -= 32;
roentgen b75cab
                    
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 56);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end rotateContigSamples32bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Rotate an image by a multiple of 90 degrees clockwise */
roentgen b75cab
static int
roentgen b75cab
rotateImage(uint16 rotation, struct image_data *image, uint32 *img_width, 
roentgen b75cab
            uint32 *img_length, unsigned char **ibuff_ptr)
roentgen b75cab
  {
roentgen b75cab
  int      shift_width;
roentgen b75cab
  uint32   bytes_per_pixel, bytes_per_sample;
roentgen b75cab
  uint32   row, rowsize, src_offset, dst_offset;
roentgen b75cab
  uint32   i, col, width, length;
roentgen b75cab
  uint32   colsize, buffsize, col_offset, pix_offset;
roentgen b75cab
  unsigned char *ibuff;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  uint16   spp, bps;
roentgen b75cab
  float    res_temp;
roentgen b75cab
  unsigned char *rbuff = NULL;
roentgen b75cab
roentgen b75cab
  width  = *img_width;
roentgen b75cab
  length = *img_length;
roentgen b75cab
  spp = image->spp;
roentgen b75cab
  bps = image->bps;
roentgen b75cab
roentgen b75cab
  rowsize = ((bps * spp * width) + 7) / 8;
roentgen b75cab
  colsize = ((bps * spp * length) + 7) / 8;
roentgen b75cab
  if ((colsize * width) > (rowsize * length))
roentgen b75cab
    buffsize = (colsize + 1) * width;
roentgen b75cab
  else
roentgen b75cab
    buffsize = (rowsize + 1) * length;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8;
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
    shift_width = bytes_per_pixel;
roentgen b75cab
  else
roentgen b75cab
    shift_width = bytes_per_sample + 1;
roentgen b75cab
roentgen b75cab
  switch (rotation)
roentgen b75cab
    {
roentgen b75cab
    case 0:
roentgen b75cab
    case 360: return (0);
roentgen b75cab
    case 90:
roentgen b75cab
    case 180:
roentgen b75cab
    case 270: break;
roentgen b75cab
    default:  TIFFError("rotateImage", "Invalid rotation angle %d", rotation);
roentgen b75cab
              return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (!(rbuff = (unsigned char *)_TIFFmalloc(buffsize)))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("rotateImage", "Unable to allocate rotation buffer of %1u bytes", buffsize);
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
  _TIFFmemset(rbuff, '\0', buffsize);
roentgen b75cab
roentgen b75cab
  ibuff = *ibuff_ptr;
roentgen b75cab
  switch (rotation)
roentgen b75cab
    {
roentgen b75cab
    case 180: if ((bps % 8) == 0) /* byte alligned data */
roentgen b75cab
                { 
roentgen b75cab
                src = ibuff;
roentgen b75cab
                pix_offset = (spp * bps) / 8;
roentgen b75cab
                for (row = 0; row < length; row++)
roentgen b75cab
                   {
roentgen b75cab
		   dst_offset = (length - row - 1) * rowsize;
roentgen b75cab
                   for (col = 0; col < width; col++)
roentgen b75cab
                     { 
roentgen b75cab
		     col_offset = (width - col - 1) * pix_offset;
roentgen b75cab
                     dst = rbuff + dst_offset + col_offset;
roentgen b75cab
roentgen b75cab
		     for (i = 0; i  < bytes_per_pixel; i++)
roentgen b75cab
		       *dst++ = *src++;
roentgen b75cab
                     }
roentgen b75cab
                   }
roentgen b75cab
                }
roentgen b75cab
	      else
roentgen b75cab
                { /* non 8 bit per sample data */ 
roentgen b75cab
                for (row = 0; row < length; row++)
roentgen b75cab
                  {
roentgen b75cab
		  src_offset = row * rowsize;
roentgen b75cab
		  dst_offset = (length - row - 1) * rowsize;
roentgen b75cab
		  src = ibuff + src_offset;
roentgen b75cab
                  dst = rbuff + dst_offset;
roentgen b75cab
                  switch (shift_width)
roentgen b75cab
                    {
roentgen b75cab
                    case 1: if (bps == 1)
roentgen b75cab
			      {
roentgen b75cab
                              if (reverseSamples8bits(spp, bps, width, src, dst))
roentgen b75cab
                                {
roentgen b75cab
		                _TIFFfree(rbuff);
roentgen b75cab
                                return (-1);
roentgen b75cab
                                }
roentgen b75cab
                              break;
roentgen b75cab
                              }
roentgen b75cab
                            if (reverseSamples16bits(spp, bps, width, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    case 2: if (reverseSamples24bits(spp, bps, width, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    case 3: 
roentgen b75cab
                    case 4: 
roentgen b75cab
                    case 5: if (reverseSamples32bits(spp, bps, width, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    default: TIFFError("rotateImage","Unsupported bit depth %d", bps);
roentgen b75cab
		             _TIFFfree(rbuff);
roentgen b75cab
                             return (-1);      
roentgen b75cab
                    }
roentgen b75cab
		  }
roentgen b75cab
		}
roentgen b75cab
              _TIFFfree(ibuff);
roentgen b75cab
              *(ibuff_ptr) = rbuff;
roentgen b75cab
              break;
roentgen b75cab
roentgen b75cab
    case 90:  if ((bps % 8) == 0) /* byte aligned data */
roentgen b75cab
                {
roentgen b75cab
                for (col = 0; col < width; col++)
roentgen b75cab
                  {
roentgen b75cab
		  src_offset = ((length - 1) * rowsize) + (col * bytes_per_pixel);
roentgen b75cab
                  dst_offset = col * colsize;
roentgen b75cab
		  src = ibuff + src_offset;
roentgen b75cab
		  dst = rbuff + dst_offset;
roentgen b75cab
                  for (row = length; row > 0; row--)
roentgen b75cab
                    {
roentgen b75cab
                    for (i = 0; i < bytes_per_pixel; i++)
roentgen b75cab
                      *dst++ = *(src + i);
roentgen b75cab
		    src -= rowsize;
roentgen b75cab
                    }
roentgen b75cab
		  }
roentgen b75cab
		}
roentgen b75cab
              else
roentgen b75cab
                { /* non 8 bit per sample data */ 
roentgen b75cab
                for (col = 0; col < width; col++)
roentgen b75cab
                  {
roentgen b75cab
		  src_offset = (length - 1) * rowsize;
roentgen b75cab
                  dst_offset = col * colsize;
roentgen b75cab
		  src = ibuff + src_offset;
roentgen b75cab
		  dst = rbuff + dst_offset;
roentgen b75cab
                  switch (shift_width)
roentgen b75cab
                    {
roentgen b75cab
                    case 1: if (bps == 1)
roentgen b75cab
			      {
roentgen b75cab
                              if (rotateContigSamples8bits(rotation, spp, bps, width, 
roentgen b75cab
				   	                 length, col, src, dst))
roentgen b75cab
                                {
roentgen b75cab
		                _TIFFfree(rbuff);
roentgen b75cab
                                return (-1);
roentgen b75cab
                                }
roentgen b75cab
                              break;
roentgen b75cab
                              }
roentgen b75cab
                            if (rotateContigSamples16bits(rotation, spp, bps, width, 
roentgen b75cab
				   	                 length, col, src, dst))
roentgen b75cab
                              {
roentgen b75cab
	                      _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
		              }
roentgen b75cab
		            break;
roentgen b75cab
                    case 2: if (rotateContigSamples24bits(rotation, spp, bps, width, 
roentgen b75cab
					                  length, col, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    case 3: 
roentgen b75cab
                    case 4: 
roentgen b75cab
                    case 5: if (rotateContigSamples32bits(rotation, spp, bps, width, 
roentgen b75cab
					                  length, col, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    default: TIFFError("rotateImage","Unsupported bit depth %d", bps);
roentgen b75cab
		             _TIFFfree(rbuff);
roentgen b75cab
                             return (-1);      
roentgen b75cab
		    }
roentgen b75cab
		  }
roentgen b75cab
		}
roentgen b75cab
              _TIFFfree(ibuff);
roentgen b75cab
              *(ibuff_ptr) = rbuff;
roentgen b75cab
roentgen b75cab
              *img_width = length;
roentgen b75cab
              *img_length = width;
roentgen b75cab
              image->width = length;
roentgen b75cab
              image->length = width;
roentgen b75cab
              res_temp = image->xres;
roentgen b75cab
              image->xres = image->yres;
roentgen b75cab
              image->yres = res_temp;
roentgen b75cab
	      break;
roentgen b75cab
roentgen b75cab
    case 270: if ((bps % 8) == 0) /* byte aligned data */
roentgen b75cab
                {
roentgen b75cab
                for (col = 0; col < width; col++)
roentgen b75cab
                  {
roentgen b75cab
		  src_offset = col * bytes_per_pixel;
roentgen b75cab
                  dst_offset = (width - col - 1) * colsize;
roentgen b75cab
		  src = ibuff + src_offset;
roentgen b75cab
		  dst = rbuff + dst_offset;
roentgen b75cab
                  for (row = length; row > 0; row--)
roentgen b75cab
                    {
roentgen b75cab
                    for (i = 0; i < bytes_per_pixel; i++)
roentgen b75cab
                      *dst++ = *(src + i);
roentgen b75cab
		    src += rowsize;
roentgen b75cab
                    }
roentgen b75cab
		  }
roentgen b75cab
		}
roentgen b75cab
              else
roentgen b75cab
                { /* non 8 bit per sample data */ 
roentgen b75cab
                for (col = 0; col < width; col++)
roentgen b75cab
                  {
roentgen b75cab
		  src_offset = 0;
roentgen b75cab
                  dst_offset = (width - col - 1) * colsize;
roentgen b75cab
		  src = ibuff + src_offset;
roentgen b75cab
		  dst = rbuff + dst_offset;
roentgen b75cab
                  switch (shift_width)
roentgen b75cab
                    {
roentgen b75cab
                    case 1: if (bps == 1)
roentgen b75cab
			      {
roentgen b75cab
                              if (rotateContigSamples8bits(rotation, spp, bps, width, 
roentgen b75cab
				   	                 length, col, src, dst))
roentgen b75cab
                                {
roentgen b75cab
		                _TIFFfree(rbuff);
roentgen b75cab
                                return (-1);
roentgen b75cab
                                }
roentgen b75cab
                              break;
roentgen b75cab
                              }
roentgen b75cab
                            if (rotateContigSamples16bits(rotation, spp, bps, width, 
roentgen b75cab
				   	                 length, col, src, dst))
roentgen b75cab
                              {
roentgen b75cab
	                      _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
		              }
roentgen b75cab
		            break;
roentgen b75cab
                    case 2: if (rotateContigSamples24bits(rotation, spp, bps, width, 
roentgen b75cab
					                  length, col, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    case 3: 
roentgen b75cab
                    case 4: 
roentgen b75cab
                    case 5: if (rotateContigSamples32bits(rotation, spp, bps, width, 
roentgen b75cab
					                  length, col, src, dst))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(rbuff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             break;
roentgen b75cab
                    default: TIFFError("rotateImage","Unsupported bit depth %d", bps);
roentgen b75cab
		             _TIFFfree(rbuff);
roentgen b75cab
                             return (-1);      
roentgen b75cab
		    }
roentgen b75cab
		  }
roentgen b75cab
		}
roentgen b75cab
              _TIFFfree(ibuff);
roentgen b75cab
              *(ibuff_ptr) = rbuff;
roentgen b75cab
roentgen b75cab
              *img_width = length;
roentgen b75cab
              *img_length = width;
roentgen b75cab
              image->width = length;
roentgen b75cab
              image->length = width;
roentgen b75cab
              res_temp = image->xres;
roentgen b75cab
              image->xres = image->yres;
roentgen b75cab
              image->yres = res_temp;
roentgen b75cab
              break;
roentgen b75cab
    default:
roentgen b75cab
              break;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end rotateImage */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
reverseSamples8bits (uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                     uint8 *ibuff, uint8 *obuff)
roentgen b75cab
  {
roentgen b75cab
  int      ready_bits = 0;
roentgen b75cab
  uint32   col;
roentgen b75cab
  uint32   src_byte, src_bit;
roentgen b75cab
  uint32   bit_offset = 0;
roentgen b75cab
  uint8    match_bits = 0, mask_bits = 0;
roentgen b75cab
  uint8    buff1 = 0, buff2 = 0;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
  if ((ibuff == NULL) || (obuff == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("reverseSamples8bits","Invalid image or work buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  mask_bits =  (uint8)-1 >> ( 8 - bps);
roentgen b75cab
  dst = obuff;
roentgen b75cab
  for (col = width; col > 0; col--)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = (col - 1) * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        src_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        src_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = ibuff + src_byte;
roentgen b75cab
      match_bits = mask_bits << (8 - src_bit - bps); 
roentgen b75cab
      buff1 = ((*src) & match_bits) << (src_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 8)
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
      else  /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        *dst++ = buff2;
roentgen b75cab
        buff2 = buff1;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  if (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    buff1 = (buff2 & ((unsigned int)255 << (8 - ready_bits)));
roentgen b75cab
    *dst++ = buff1;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end reverseSamples8bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
reverseSamples16bits (uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                      uint8 *ibuff, uint8 *obuff)
roentgen b75cab
  {
roentgen b75cab
  int      ready_bits = 0;
roentgen b75cab
  uint32   col;
roentgen b75cab
  uint32   src_byte = 0, high_bit = 0;
roentgen b75cab
  uint32   bit_offset = 0;
roentgen b75cab
  uint16   match_bits = 0, mask_bits = 0;
roentgen b75cab
  uint16   buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8    bytebuff = 0;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
  if ((ibuff == NULL) || (obuff == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("reverseSample16bits","Invalid image or work buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  mask_bits =  (uint16)-1 >> (16 - bps);
roentgen b75cab
  dst = obuff;
roentgen b75cab
  for (col = width; col > 0; col--)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = (col - 1) * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        high_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        high_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = ibuff + src_byte;
roentgen b75cab
      match_bits = mask_bits << (16 - high_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        buff1 = (src[0] << 8) | src[1];
roentgen b75cab
      else
roentgen b75cab
        buff1 = (src[1] << 8) | src[0];
roentgen b75cab
      buff1 = (buff1 & match_bits) << (high_bit);
roentgen b75cab
      
roentgen b75cab
      if (ready_bits < 8)
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff = (buff2 >> 8);
roentgen b75cab
        *dst++ = bytebuff;
roentgen b75cab
        ready_bits -= 8;
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 8) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff = (buff2 >> 8);
roentgen b75cab
    *dst++ = bytebuff;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end reverseSamples16bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
reverseSamples24bits (uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                      uint8 *ibuff, uint8 *obuff)
roentgen b75cab
  {
roentgen b75cab
  int      ready_bits = 0;
roentgen b75cab
  uint32   col;
roentgen b75cab
  uint32   src_byte = 0, high_bit = 0;
roentgen b75cab
  uint32   bit_offset = 0;
roentgen b75cab
  uint32   match_bits = 0, mask_bits = 0;
roentgen b75cab
  uint32   buff1 = 0, buff2 = 0;
roentgen b75cab
  uint8    bytebuff1 = 0, bytebuff2 = 0;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
  if ((ibuff == NULL) || (obuff == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("reverseSamples24bits","Invalid image or work buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  mask_bits =  (uint32)-1 >> (32 - bps);
roentgen b75cab
  dst = obuff;
roentgen b75cab
  for (col = width; col > 0; col--)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = (col - 1) * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        high_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        high_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = ibuff + src_byte;
roentgen b75cab
      match_bits = mask_bits << (32 - high_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
	buff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
      else
roentgen b75cab
	buff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
      buff1 = (buff1 & match_bits) << (high_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 16)
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff1 = bytebuff2 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 24);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 16);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        ready_bits -= 16;
roentgen b75cab
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 16) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
 /* catch any trailing bits at the end of the line */
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 24);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    bytebuff2 = bytebuff1;
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
 
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end reverseSamples24bits */
roentgen b75cab
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
reverseSamples32bits (uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                      uint8 *ibuff, uint8 *obuff)
roentgen b75cab
  {
roentgen b75cab
  int    ready_bits = 0, shift_width = 0;
roentgen b75cab
  int    bytes_per_sample, bytes_per_pixel;
roentgen b75cab
  uint32 bit_offset;
roentgen b75cab
  uint32 src_byte = 0, high_bit = 0;
roentgen b75cab
  uint32 col;
roentgen b75cab
  uint32 longbuff1 = 0, longbuff2 = 0;
roentgen b75cab
  uint64 mask_bits = 0, match_bits = 0;
roentgen b75cab
  uint64 buff1 = 0, buff2 = 0, buff3 = 0;
roentgen b75cab
  uint8  bytebuff1 = 0, bytebuff2 = 0, bytebuff3 = 0, bytebuff4 = 0;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
  tsample_t sample;
roentgen b75cab
roentgen b75cab
  if ((ibuff == NULL) || (obuff == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("reverseSamples32bits","Invalid image or work buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  ready_bits = 0;
roentgen b75cab
  mask_bits =  (uint64)-1 >> (64 - bps);
roentgen b75cab
  dst = obuff;
roentgen b75cab
roentgen b75cab
  bytes_per_sample = (bps + 7) / 8;
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
    shift_width = bytes_per_pixel;
roentgen b75cab
  else
roentgen b75cab
    shift_width = bytes_per_sample + 1;
roentgen b75cab
roentgen b75cab
  for (col = width; col > 0; col--)
roentgen b75cab
    {
roentgen b75cab
    /* Compute src byte(s) and bits within byte(s) */
roentgen b75cab
    bit_offset = (col - 1) * bps * spp;
roentgen b75cab
    for (sample = 0; sample < spp; sample++)
roentgen b75cab
      {
roentgen b75cab
      if (sample == 0)
roentgen b75cab
        {
roentgen b75cab
        src_byte = bit_offset / 8;
roentgen b75cab
        high_bit  = bit_offset % 8;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
        src_byte = (bit_offset + (sample * bps)) / 8;
roentgen b75cab
        high_bit  = (bit_offset + (sample * bps)) % 8;
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
      src = ibuff + src_byte;
roentgen b75cab
      match_bits = mask_bits << (64 - high_bit - bps); 
roentgen b75cab
      if (little_endian)
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
roentgen b75cab
        longbuff2 = longbuff1;
roentgen b75cab
        }
roentgen b75cab
      else
roentgen b75cab
        {
roentgen b75cab
	longbuff1 = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
roentgen b75cab
        longbuff2 = longbuff1;
roentgen b75cab
	}
roentgen b75cab
      buff3 = ((uint64)longbuff1 << 32) | longbuff2;
roentgen b75cab
      buff1 = (buff3 & match_bits) << (high_bit);
roentgen b75cab
roentgen b75cab
      if (ready_bits < 32)
roentgen b75cab
        { /* add another bps bits to the buffer */
roentgen b75cab
        bytebuff1 = bytebuff2 = bytebuff3 = bytebuff4 = 0;
roentgen b75cab
        buff2 = (buff2 | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      else /* If we have a full buffer's worth, write it out */
roentgen b75cab
        {
roentgen b75cab
        bytebuff1 = (buff2 >> 56);
roentgen b75cab
        *dst++ = bytebuff1;
roentgen b75cab
        bytebuff2 = (buff2 >> 48);
roentgen b75cab
        *dst++ = bytebuff2;
roentgen b75cab
        bytebuff3 = (buff2 >> 40);
roentgen b75cab
        *dst++ = bytebuff3;
roentgen b75cab
        bytebuff4 = (buff2 >> 32);
roentgen b75cab
        *dst++ = bytebuff4;
roentgen b75cab
        ready_bits -= 32;
roentgen b75cab
                    
roentgen b75cab
        /* shift in new bits */
roentgen b75cab
        buff2 = ((buff2 << 32) | (buff1 >> ready_bits));
roentgen b75cab
        }
roentgen b75cab
      ready_bits += bps;
roentgen b75cab
      }
roentgen b75cab
    }
roentgen b75cab
  while (ready_bits > 0)
roentgen b75cab
    {
roentgen b75cab
    bytebuff1 = (buff2 >> 56);
roentgen b75cab
    *dst++ = bytebuff1;
roentgen b75cab
    buff2 = (buff2 << 8);
roentgen b75cab
    ready_bits -= 8;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end reverseSamples32bits */
roentgen b75cab
roentgen b75cab
static int
roentgen b75cab
reverseSamplesBytes (uint16 spp, uint16 bps, uint32 width, 
roentgen b75cab
                     uint8 *src, uint8 *dst)
roentgen b75cab
  {
roentgen b75cab
  int i;
roentgen b75cab
  uint32  col, bytes_per_pixel, col_offset;
roentgen b75cab
  uint8   bytebuff1;
roentgen b75cab
  unsigned char swapbuff[32];
roentgen b75cab
  
roentgen b75cab
  if ((src == NULL) || (dst == NULL))
roentgen b75cab
    {
roentgen b75cab
    TIFFError("reverseSamplesBytes","Invalid input or output buffer");
roentgen b75cab
    return (1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
  switch (bps / 8)
roentgen b75cab
     {
roentgen b75cab
     case 8:  /* Use memcpy for multiple bytes per sample data */
roentgen b75cab
     case 4:
roentgen b75cab
     case 3:
roentgen b75cab
     case 2: for (col = 0; col < (width / 2); col++)
roentgen b75cab
               {
roentgen b75cab
	       col_offset = col * bytes_per_pixel;                     
roentgen b75cab
	       _TIFFmemcpy (swapbuff, src + col_offset, bytes_per_pixel);
roentgen b75cab
	       _TIFFmemcpy (src + col_offset, dst - col_offset - bytes_per_pixel, bytes_per_pixel);
roentgen b75cab
	       _TIFFmemcpy (dst - col_offset - bytes_per_pixel, swapbuff, bytes_per_pixel);
roentgen b75cab
               }
roentgen b75cab
	     break;
roentgen b75cab
     case 1: /* Use byte copy only for single byte per sample data */
roentgen b75cab
             for (col = 0; col < (width / 2); col++)
roentgen b75cab
               { 
roentgen b75cab
	       for (i = 0; i < spp; i++)
roentgen b75cab
                  {
roentgen b75cab
		  bytebuff1 = *src;
roentgen b75cab
		  *src++ = *(dst - spp + i);
roentgen b75cab
                  *(dst - spp + i) = bytebuff1;
roentgen b75cab
		  }
roentgen b75cab
		dst -= spp;
roentgen b75cab
                }
roentgen b75cab
	     break;
roentgen b75cab
     default: TIFFError("reverseSamplesBytes","Unsupported bit depth %d", bps);
roentgen b75cab
       return (1);
roentgen b75cab
     }
roentgen b75cab
  return (0);
roentgen b75cab
  } /* end reverseSamplesBytes */
roentgen b75cab
roentgen b75cab
roentgen b75cab
/* Mirror an image horizontally or vertically */
roentgen b75cab
static int
roentgen b75cab
mirrorImage(uint16 spp, uint16 bps, uint16 mirror, uint32 width, uint32 length, unsigned char *ibuff)
roentgen b75cab
  {
roentgen b75cab
  int      shift_width;
roentgen b75cab
  uint32   bytes_per_pixel, bytes_per_sample;
roentgen b75cab
  uint32   row, rowsize, row_offset;
roentgen b75cab
  unsigned char *line_buff = NULL;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  unsigned char *dst;
roentgen b75cab
roentgen b75cab
  src = ibuff;
roentgen b75cab
  rowsize = ((width * bps * spp) + 7) / 8;
roentgen b75cab
  switch (mirror)
roentgen b75cab
    {
roentgen b75cab
    case MIRROR_BOTH:
roentgen b75cab
    case MIRROR_VERT: 
roentgen b75cab
             line_buff = (unsigned char *)_TIFFmalloc(rowsize);
roentgen b75cab
             if (line_buff == NULL)
roentgen b75cab
               {
roentgen b75cab
	       TIFFError ("mirrorImage", "Unable to allocate mirror line buffer of %1u bytes", rowsize);
roentgen b75cab
               return (-1);
roentgen b75cab
               }
roentgen b75cab
roentgen b75cab
             dst = ibuff + (rowsize * (length - 1));
roentgen b75cab
             for (row = 0; row < length / 2; row++)
roentgen b75cab
               {
roentgen b75cab
	      _TIFFmemcpy(line_buff, src, rowsize);
roentgen b75cab
	      _TIFFmemcpy(src, dst,  rowsize);
roentgen b75cab
	      _TIFFmemcpy(dst, line_buff, rowsize);
roentgen b75cab
               src += (rowsize);
roentgen b75cab
               dst -= (rowsize);                                 
roentgen b75cab
               }
roentgen b75cab
             if (line_buff)
roentgen b75cab
               _TIFFfree(line_buff);
roentgen b75cab
             if (mirror == MIRROR_VERT)
roentgen b75cab
               break;
roentgen b75cab
    case MIRROR_HORIZ :
roentgen b75cab
              if ((bps % 8) == 0) /* byte alligned data */
roentgen b75cab
                { 
roentgen b75cab
                for (row = 0; row < length; row++)
roentgen b75cab
                  {
roentgen b75cab
		  row_offset = row * rowsize;
roentgen b75cab
                  src = ibuff + row_offset;
roentgen b75cab
                  dst = ibuff + row_offset + rowsize;
roentgen b75cab
                  if (reverseSamplesBytes(spp, bps, width, src, dst))
roentgen b75cab
                    {
roentgen b75cab
		    return (-1);
roentgen b75cab
                    }
roentgen b75cab
		  }
roentgen b75cab
		}
roentgen b75cab
	      else
roentgen b75cab
                { /* non 8 bit per sample  data */
roentgen b75cab
                if (!(line_buff = (unsigned char *)_TIFFmalloc(rowsize + 1)))
roentgen b75cab
                  {
roentgen b75cab
                  TIFFError("mirrorImage", "Unable to allocate mirror line buffer");
roentgen b75cab
                  return (-1);
roentgen b75cab
                  }
roentgen b75cab
                bytes_per_sample = (bps + 7) / 8;
roentgen b75cab
                bytes_per_pixel  = ((bps * spp) + 7) / 8;
roentgen b75cab
                if (bytes_per_pixel < (bytes_per_sample + 1))
roentgen b75cab
                  shift_width = bytes_per_pixel;
roentgen b75cab
                else
roentgen b75cab
                  shift_width = bytes_per_sample + 1;
roentgen b75cab
roentgen b75cab
                for (row = 0; row < length; row++)
roentgen b75cab
                  {
roentgen b75cab
		  row_offset = row * rowsize;
roentgen b75cab
                  src = ibuff + row_offset;
roentgen b75cab
                  _TIFFmemset (line_buff, '\0', rowsize);
roentgen b75cab
                  switch (shift_width)
roentgen b75cab
                    {
roentgen b75cab
                    case 1: if (reverseSamples16bits(spp, bps, width, src, line_buff))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(line_buff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             _TIFFmemcpy (src, line_buff, rowsize);
roentgen b75cab
                             break;
roentgen b75cab
                    case 2: if (reverseSamples24bits(spp, bps, width, src, line_buff))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(line_buff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             _TIFFmemcpy (src, line_buff, rowsize);
roentgen b75cab
                             break;
roentgen b75cab
                    case 3: 
roentgen b75cab
                    case 4: 
roentgen b75cab
                    case 5: if (reverseSamples32bits(spp, bps, width, src, line_buff))
roentgen b75cab
                              {
roentgen b75cab
		              _TIFFfree(line_buff);
roentgen b75cab
                              return (-1);
roentgen b75cab
                              }
roentgen b75cab
                             _TIFFmemcpy (src, line_buff, rowsize);
roentgen b75cab
                             break;
roentgen b75cab
                    default: TIFFError("mirrorImage","Unsupported bit depth %d", bps);
roentgen b75cab
		             _TIFFfree(line_buff);
roentgen b75cab
                             return (-1);      
roentgen b75cab
                    }
roentgen b75cab
		  }
roentgen b75cab
                if (line_buff)
roentgen b75cab
                  _TIFFfree(line_buff);
roentgen b75cab
		}
roentgen b75cab
             break;
roentgen b75cab
roentgen b75cab
    default: TIFFError ("mirrorImage", "Invalid mirror axis %d", mirror);
roentgen b75cab
             return (-1);
roentgen b75cab
             break;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
/* Invert the light and dark values for a bilevel or grayscale image */
roentgen b75cab
static int
roentgen b75cab
invertImage(uint16 photometric, uint16 spp, uint16 bps, uint32 width, uint32 length, unsigned char *work_buff)
roentgen b75cab
  {
roentgen b75cab
  uint32   row, col;
roentgen b75cab
  unsigned char  bytebuff1, bytebuff2, bytebuff3, bytebuff4;
roentgen b75cab
  unsigned char *src;
roentgen b75cab
  uint16        *src_uint16;
roentgen b75cab
  uint32        *src_uint32;
roentgen b75cab
roentgen b75cab
  if (spp != 1)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("invertImage", "Image inversion not supported for more than one sample per pixel");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  if (photometric !=  PHOTOMETRIC_MINISWHITE && photometric !=  PHOTOMETRIC_MINISBLACK)
roentgen b75cab
    {
roentgen b75cab
    TIFFError("invertImage", "Only black and white and grayscale images can be inverted");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  src = work_buff;
roentgen b75cab
  if (src == NULL)
roentgen b75cab
    {
roentgen b75cab
    TIFFError ("invertImage", "Invalid crop buffer passed to invertImage");
roentgen b75cab
    return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  switch (bps)
roentgen b75cab
    {
roentgen b75cab
    case 32: src_uint32 = (uint32 *)src;
roentgen b75cab
             for (row = 0; row < length; row++)
roentgen b75cab
               for (col = 0; col < width; col++)
roentgen b75cab
                 {
roentgen b75cab
		 *src_uint32 = (uint32)0xFFFFFFFF - *src_uint32;
roentgen b75cab
                  src_uint32++;
roentgen b75cab
                 }
roentgen b75cab
            break;
roentgen b75cab
    case 16: src_uint16 = (uint16 *)src;
roentgen b75cab
             for (row = 0; row < length; row++)
roentgen b75cab
               for (col = 0; col < width; col++)
roentgen b75cab
                 {
roentgen b75cab
		 *src_uint16 = (uint16)0xFFFF - *src_uint16;
roentgen b75cab
                  src_uint16++;
roentgen b75cab
                 }
roentgen b75cab
            break;
roentgen b75cab
    case 8: for (row = 0; row < length; row++)
roentgen b75cab
              for (col = 0; col < width; col++)
roentgen b75cab
                {
roentgen b75cab
		*src = (uint8)255 - *src;
roentgen b75cab
                 src++;
roentgen b75cab
                }
roentgen b75cab
            break;
roentgen b75cab
    case 4: for (row = 0; row < length; row++)
roentgen b75cab
              for (col = 0; col < width; col++)
roentgen b75cab
                {
roentgen b75cab
		bytebuff1 = 16 - (uint8)(*src & 240 >> 4);
roentgen b75cab
		bytebuff2 = 16 - (*src & 15);
roentgen b75cab
		*src = bytebuff1 << 4 & bytebuff2;
roentgen b75cab
                src++;
roentgen b75cab
                }
roentgen b75cab
            break;
roentgen b75cab
    case 2: for (row = 0; row < length; row++)
roentgen b75cab
              for (col = 0; col < width; col++)
roentgen b75cab
                {
roentgen b75cab
		bytebuff1 = 4 - (uint8)(*src & 192 >> 6);
roentgen b75cab
		bytebuff2 = 4 - (uint8)(*src & 48  >> 4);
roentgen b75cab
		bytebuff3 = 4 - (uint8)(*src & 12  >> 2);
roentgen b75cab
		bytebuff4 = 4 - (uint8)(*src & 3);
roentgen b75cab
		*src = (bytebuff1 << 6) || (bytebuff2 << 4) || (bytebuff3 << 2) || bytebuff4;
roentgen b75cab
                src++;
roentgen b75cab
                }
roentgen b75cab
            break;
roentgen b75cab
    case 1: for (row = 0; row < length; row++)
roentgen b75cab
              for (col = 0; col < width; col += 8 /(spp * bps))
roentgen b75cab
                {
roentgen b75cab
                *src = ~(*src);
roentgen b75cab
                src++;
roentgen b75cab
                }
roentgen b75cab
            break;
roentgen b75cab
    default: TIFFError("invertImage", "Unsupported bit depth %d", bps);
roentgen b75cab
      return (-1);
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
  return (0);
roentgen b75cab
  }
roentgen b75cab
roentgen b75cab
/* vim: set ts=8 sts=8 sw=8 noet: */
roentgen b75cab
/*
roentgen b75cab
 * Local Variables:
roentgen b75cab
 * mode: c
roentgen b75cab
 * c-basic-offset: 8
roentgen b75cab
 * fill-column: 78
roentgen b75cab
 * End:
roentgen b75cab
 */