summaryrefslogtreecommitdiff
path: root/tiff/tools/tiffcrop.c
diff options
context:
space:
mode:
Diffstat (limited to 'tiff/tools/tiffcrop.c')
-rw-r--r--tiff/tools/tiffcrop.c9012
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, &sect_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, &sections[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:
- */