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