From 5e557c568746f95f7421f0be8bca3fdcd86ebc13 Mon Sep 17 00:00:00 2001
From: Andrey Kiselev <[EMAIL REDACTED]>
Date: Fri, 6 Apr 2007 14:22:39 +0000
Subject: [PATCH] Significant update in functionsality as per bug
http://bugzilla.remotesensing.org/show_bug.cgi?id=1525
---
tools/tiffcrop.c | 3029 ++++++++++++++++++++++++++--------------------
1 file changed, 1731 insertions(+), 1298 deletions(-)
diff --git a/tools/tiffcrop.c b/tools/tiffcrop.c
index 9cd5f133..5a8b86f2 100644
--- a/tools/tiffcrop.c
+++ b/tools/tiffcrop.c
@@ -1,6 +1,8 @@
-/* $Id: tiffcrop.c,v 1.3 2007-02-24 15:57:01 dron Exp $ */
+/* $Id: tiffcrop.c,v 1.3.2.1 2007-04-06 14:22:39 dron Exp $ */
/* tiffcrop.c -- a port of tiffcp.c extended to include cropping of selections
+ *
+ * Original code:
*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
@@ -24,34 +26,45 @@
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
- * Richard Nolde 10/2006 Add support for the options below to extract
+ * Richard Nolde Updated 2/2007 Add support for the options below to extract
* sections of image(s) and to modify the whole image or selected portion
* with rotations, mirroring, and colorscale/colormap inversion of selected
* types of TIFF images when appropriate
*
* Options:
- * -u units [in, cm, px ] inches, centimeters or pixels
- * -x # horizontal dimension of region to extract expressed in current
+ * -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 # set horizontal margin of output page to # expressed in current
+ * units
+ * -K # set vertical margin of output page to # expressed in current
* units
- * -y # vertical dimension of region to extract expressed in current
+ * -X # horizontal dimension of region to extract expressed in current
* units
- * -e t|l|r|b edge to use as origin
+ * -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 #:#,#:# up to six zones of the image designated as zone X of Y,
+ * -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 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
+ * -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
* -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 invert the colormap, black to white, for bilevel
- * and grayscale images
+ * or vertically
+ * -I invert the colormap, black to white, for bilevel and grayscale
+ * images
*/
#include "tif_config.h"
@@ -68,20 +81,28 @@
# include <unistd.h>
#endif
-#include "tiffio.h"
-
#ifndef HAVE_GETOPT
extern int getopt(int, char**, char*);
#endif
+#include "tiffio.h"
+
+#if defined(VMS)
+# define unlink delete
+#endif
+
#define streq(a,b) (strcmp((a),(b)) == 0)
#define strneq(a,b,n) (strncmp((a),(b),(n)) == 0)
+/* NB: the uint32 casts are to silence certain ANSI-C compilers */
+#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
+#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
+
#define TRUE 1
#define FALSE 0
/*
- * Definitions and data structures required to support cropping and image
+ * Definitions and data structures required to support cropping and inmage
* manipulations.
*/
@@ -89,6 +110,7 @@ extern int getopt(int, char**, char*);
#define EDGE_LEFT 2
#define EDGE_BOTTOM 3
#define EDGE_RIGHT 4
+
#define MIRROR_HORIZ 1
#define MIRROR_VERT 2
@@ -104,7 +126,8 @@ extern int getopt(int, char**, char*);
#define STRIP 1
#define TILE 2
-#define MAX_ZONES 6 /* number of sections on a singel page */
+#define MAX_ZONES 32 /* number of sections to extract from a single page */
+#define MAX_SECTIONS 64 /* number of sections from one page to write to output */
#define MAX_IMAGES 256 /* number of images in descrete list */
/* Offsets into buffer for margins and fixed width and length */
@@ -131,33 +154,142 @@ struct pageseg {
uint32 x2; /* index of right edge */
uint32 y1; /* index of top edge */
uint32 y2; /* index of bottom edge */
- int total; /* total equal sized divisions of crop area */
- int position; /* ordinal of segment to be extracted */
uint32 buffsize; /* size of buffer needed to hold the cropped region */
+ int position; /* ordinal of segment to be extracted */
+ int total; /* total equal sized divisions of crop area */
};
/* Cropping parameters from command line and image data */
struct crop_mask {
- uint16 crop_mode; /* Crop options to be applied */
- uint16 res_unit; /* Resolution unit for margins and selections */
- uint16 edge_ref; /* Reference edge from which zones are calculated */
- 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 */
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 */
- int zones; /* Number of zones requested */
+ uint32 zones; /* Number of zones requested */
+ uint16 crop_mode; /* Crop options to be applied */
+ uint16 res_unit; /* Resolution unit for margins and selections */
+ uint16 edge_ref; /* Reference edge from which zones are calculated */
+ 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 */
struct pageseg zonelist[MAX_ZONES]; /* Zones within page or master crop region */
};
-/*
- * Global variables saving state of the program.
- */
-static int outtiled = -1;
+#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
+
+
+struct paperdef {
+ char name[MAX_PAPERNAME_LENGTH];
+ double width;
+ double length;
+ double asratio;
+ };
+
+/* 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.111, 46.806, 0.707},
+ {"a1", 23.389, 33.111, 0.706},
+ {"a2", 16.542, 23.389, 0.707},
+ {"a3", 11.694, 16.542, 0.707},
+ {"a4", 8.264, 11.694, 0.707},
+ {"a5", 5.833, 8.264, 0.706},
+ {"a6", 4.125, 5.833, 0.707},
+ {"a7", 2.917, 4.125, 0.707},
+ {"a8", 2.056, 2.917, 0.705},
+ {"a9", 1.458, 2.056, 0.709},
+ {"a10", 1.014, 1.458, 0.695},
+ {"b0", 39.375, 55.667, 0.707},
+ {"b1", 27.833, 39.375, 0.707},
+ {"b2", 19.681, 27.833, 0.707},
+ {"b3", 13.903, 19.681, 0.706},
+ {"b4", 9.847, 13.903, 0.708},
+ {"b5", 6.931, 9.847, 0.704},
+ {"b6", 4.917, 6.931, 0.709},
+ {"c0", 36.097, 51.069, 0.707},
+ {"c1", 25.514, 36.097, 0.707},
+ {"c2", 18.028, 25.514, 0.707},
+ {"c3", 12.750, 18.028, 0.707},
+ {"c4", 9.014, 12.750, 0.707},
+ {"c5", 6.375, 9.014, 0.707},
+ {"c6", 4.486, 6.375, 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;
+};
+
+/* 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 */
+};
+
+static int outtiled = -1;
static uint32 tilewidth;
static uint32 tilelength;
@@ -168,33 +300,48 @@ static uint16 fillorder;
static uint16 orientation;
static uint32 rowsperstrip;
static uint32 g3opts;
-static int ignore = FALSE; /* if true, ignore read errors */
+static int ignore = FALSE; /* if true, ignore read errors */
static uint32 defg3opts = (uint32) -1;
-static int quality = 75; /* JPEG quality */
-static int jpegcolormode = JPEGCOLORMODE_RGB;
+static int quality = 75; /* JPEG quality */
+static int jpegcolormode = JPEGCOLORMODE_RGB;
static uint16 defcompression = (uint16) -1;
static uint16 defpredictor = (uint16) -1;
-static TIFF* bias = NULL;
-static int pageNum = 0;
-/*
- * Helper functions declarations.
- */
static int processCompressOptions(char*);
-static int tiffcp(TIFF*, TIFF*);
static void usage(void);
-static int initCropMasks (struct crop_mask *cps);
-static int computeOffsets(uint16, float, float, uint32, uint32,
- struct crop_mask *, struct offset *);
-static int getCropOffsets(TIFF*, struct crop_mask *);
-static int loadImage(TIFF*, unsigned char **);
-static int extractCropRegions(TIFF *, struct crop_mask *, unsigned char *, unsigned char *);
-static int createCroppedImage(TIFF*, struct crop_mask *, unsigned char **, unsigned char **);
-static int rotateImage(uint16, uint16, uint16, uint32 *, uint32 *, unsigned char **);
-static int mirrorImage(uint16, uint16, uint16, uint32, uint32, unsigned char *);
-static int invertImage(uint16, uint16, uint16, uint32, uint32, unsigned char *);
-static int writeCroppedImage(TIFF *, TIFF *, struct crop_mask *, unsigned char *);
+/* New 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 *);
+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 *);
+static int loadImage(TIFF *, struct image_data *, unsigned char **);
+static int getCropOffsets(struct image_data *, struct crop_mask *);
+static int extractCropRegions(TIFF *, struct crop_mask *,
+ unsigned char *, unsigned char *);
+static int createCroppedImage(TIFF*, struct image_data *, struct crop_mask *,
+ unsigned char **, unsigned char **);
+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 *);
+static int writeCroppedImage(TIFF *, TIFF *, struct crop_mask *,
+ unsigned char *);
+static int createImageSection(uint32, unsigned char **);
+static int extractImageSection(struct image_data *, struct pageseg *,
+ unsigned char *, unsigned char *);
+static int writeSingleSection(TIFF *, TIFF *, uint32, uint32,
+ double, double, unsigned char *);
+static int writeImageSections(TIFF *, TIFF *, struct image_data *,
+ struct pagedef *, struct pageseg *,
+ unsigned char *, unsigned char **);
+static int pageNum = 0;
int
main(int argc, char* argv[])
@@ -205,68 +352,44 @@ main(int argc, char* argv[])
uint32 deftilelength = (uint32) -1;
uint32 defrowsperstrip = (uint32) 0;
uint32 dirnum = 0;
- uint32 bias_image = 0;
+
TIFF* in = NULL;
- TIFF* out;
- char mode[10];
+ TIFF* out = NULL;
+ char mode[10];
char* mp = mode;
- struct crop_mask crop_data; /* Cropping parameters for image */
- unsigned char *read_buff = NULL; /* input image data buffer */
- unsigned char *crop_buff = NULL; /* crop area buffer */
- char *opt_offset = NULL; /* Postion in string of value sought */
- char *opt_ptr = NULL; /* Pointer to next token in option set */
- char *sep = NULL; /* pointer to a token separator */
- uint32 start, end, image_count = 0, next_image = 0;
- uint32 imagelist[MAX_IMAGES + 1]; /* individually specified images */
- uint32 i, j;
- int c;
+ int c;
+
+ /** RJN additions **/
+ struct image_data image; /* Image parameters for one image */
+ struct crop_mask crop_data; /* Cropping parameters for all images */
+ struct pagedef page; /* Page definition for output pages */
+ struct pageseg sections[MAX_SECTIONS]; /* Sections of one output page */
+ 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 */
+ 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;
+ unsigned int image_count = 0;
+ unsigned int next_image = 0;
+ unsigned int imagelist[MAX_IMAGES + 1]; /* individually specified images */
extern int optind;
extern char* optarg;
+ initImageData(&image);
initCropMasks(&crop_data);
+ initPageSetup(&page, sections);
*mp++ = 'w';
*mp = '\0';
- while ((c = getopt(argc, argv, "ab:c:d:f:il:p:r:st:w:BLMCE:F:IN:m:R:U:X:Y:")) != -1)
+ while ((c = getopt(argc, argv, "ac:d:f:il:m:p:r:st:w:BCE:F:H:IJ:K:LMN:O:P:R:S:U:V:X:Y:Z:")) != -1)
switch (c) {
- case 'b': if (bias) { /* this file is bias image subtracted from others */
- fputs ("Only 1 bias image may be specified\n", stderr);
- exit (-2);
- }
- {
- uint16 samples = (uint16) -1;
- char *biasFn = optarg;
- sep = strpbrk(biasFn, ":");
- if (sep)
- {
- *sep = '\0';
- bias_image = atoi(sep +1);
- }
- bias = TIFFOpen (biasFn, "r");
- if (!bias)
- exit (-5);
- if (bias_image) {
- if (!TIFFSetDirectory(bias, bias_image))
- {
- fputs ("Invalid IFD for bias image", stderr);
- exit (-7);
- }
- }
- if (TIFFIsTiled (bias)) {
- fputs ("Bias image must be organized in strips\n", stderr);
- exit (-7);
- }
- TIFFGetField(bias, TIFFTAG_SAMPLESPERPIXEL, &samples);
- if (samples != 1) {
- fputs ("Bias image must be monochrome\n", stderr);
- exit (-7);
- }
- }
- break;
- case 'a': mode[0] = 'a'; /* append to output */
+ case 'a': mode[0] = 'a'; /* append to output */
break;
- case 'c': if (!processCompressOptions(optarg)) /* compression scheme */
+ case 'c': if (!processCompressOptions(optarg)) /* compression scheme */
usage();
break;
case 'd': dirnum = strtoul(optarg, NULL, 0); /* initial directory offset */
@@ -278,7 +401,7 @@ main(int argc, char* argv[])
else
usage();
break;
- case 'i': ignore = TRUE; /* ignore errors */
+ case 'i': ignore = TRUE; /* ignore errors */
break;
case 'l': outtiled = TRUE; /* tile length */
deftilelength = atoi(optarg);
@@ -314,7 +437,7 @@ main(int argc, char* argv[])
case 'C': *mp++ = 'c'; *mp = '\0';
break;
/* image manipulation routine options */
- case 'm': /* margins to exclude from selection*/
+ 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, ",:");
@@ -324,6 +447,9 @@ main(int argc, char* argv[])
crop_data.margins[i] = atof(opt_ptr);
}
break;
+ case 'D': /* down sample */
+ fprintf (stderr, "Down sampling not yet implemented\n");
+ break;
case 'E': /* edge reference */
switch (tolower(optarg[0]))
{
@@ -338,7 +464,7 @@ main(int argc, char* argv[])
default: fprintf (stderr, "Edge reference must be top, bottom, left, or right.\n");
usage();
}
- break;
+ break;
case 'F': /* flip eg mirror image or cropped segment, M was already used */
crop_data.crop_mode |= CROP_MIRROR;
switch (tolower(optarg[0]))
@@ -348,12 +474,24 @@ main(int argc, char* argv[])
case 'v': crop_data.mirror = MIRROR_VERT;
break;
default: fprintf (stderr, "Flip mode must be h or v.\n");
- usage();
+ usage();
}
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;
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));
@@ -377,10 +515,10 @@ main(int argc, char* argv[])
imagelist[i++] = j;
image_count = MAX_IMAGES / 2;
break;
- }
+ }
else
{
- if (streq(opt_ptr, "last"))
+ if (streq(opt_ptr, "last"))
imagelist[i++] = MAX_IMAGES;
else /* single value between commas */
{
@@ -399,11 +537,51 @@ main(int argc, char* argv[])
imagelist[i++] = j;
}
}
- }
+ }
}
}
- image_count = i;
- break;
+ 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: fprintf (stderr,
+ "Orientation must be portrait, landscape, or auto.\n\n");
+ usage();
+ }
+ break;
+ case 'P': /* page size selection */
+ if (get_page_geometry (optarg, &page))
+ {
+ if (!strcmp(optarg, "list"))
+ {
+ fprintf (stderr, "Name Width Length (in inches)\n");
+ for (i = 0; i < MAX_PAPERNAMES - 1; i++)
+ fprintf (stderr, "%-15.15s %5.2f %5.2f%s",
+ PaperTable[i].name, PaperTable[i].width,
+ PaperTable[i].length, i % 2 ? " " : "\n");
+ fprintf (stderr, "\n\n");
+ exit (-1);
+ }
+
+ fprintf (stderr, "Invalid papersize %s\n\n", optarg);
+ fprintf (stderr, "Select one of:\n");
+ for (i = 0; i < MAX_PAPERNAMES; i++)
+ fprintf (stderr, "%-15.15s%s", PaperTable[i].name, i % 5 ? " " : "\n");
+ fprintf (stderr, "\n\n");
+ 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))
@@ -414,20 +592,57 @@ main(int argc, char* argv[])
break;
case 270: crop_data.rotation = (uint16)270;
break;
- default: fprintf (stderr,
- "Rotation must be 90, 180, or 270 degrees clockwise.\n");
+ default: fprintf (stderr,
+ "Rotation must be 90, 180, or 270 degrees clockwise.\n\n");
usage();
}
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)
+ {
+ fprintf (stderr,
+ "Limit of %d subdivisions, ie rows x columns, exceeded\n", 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;
+ {
+ crop_data.res_unit = RESUNIT_NONE;
+ page.res_unit = RESUNIT_NONE;
+ }
else
+ {
+ fprintf (stderr, "Illegal unit of measure: %s\n\n", optarg);
usage();
+ }
+ 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;
@@ -440,15 +655,21 @@ main(int argc, char* argv[])
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_ZONES));
- (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);
- }
+ ((opt_ptr != NULL) && (i < MAX_ZONES));
+ (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_ZONES */
+ if ((opt_ptr != NULL) && (i >= MAX_ZONES))
+ {
+ fprintf (stderr, "Zone list exceed limit of %d zones\n", MAX_ZONES);
+ exit (-1);
+ }
break;
case '?': usage();
/*NOTREACHED*/
@@ -481,7 +702,7 @@ main(int argc, char* argv[])
if (dirnum == MAX_IMAGES - 1)
dirnum = TIFFNumberOfDirectories(in) - 1;
- if (dirnum != 0 && !TIFFSetDirectory(in, dirnum))
+ if (dirnum != 0 && !TIFFSetDirectory(in, (tdir_t)dirnum))
{
TIFFError(TIFFFileName(in),"Error, setting subdirectory at %#x", dirnum);
(void) TIFFClose(out);
@@ -499,38 +720,55 @@ main(int argc, char* argv[])
tilelength = deftilelength;
g3opts = defg3opts;
+ if (loadImage(in, &image, &read_buff))
+ {
+ TIFFError("main", "Unable to load source image");
+ exit (-1);
+ }
+
if (crop_data.crop_mode != CROP_NONE)
{
- if (getCropOffsets(in, &crop_data))
+ if (getCropOffsets(&image, &crop_data))
{
TIFFError("main", "Unable to define crop regions");
exit (-1);
}
- if (loadImage(in, &read_buff))
+ /* Does this even need to be called if we are not cropping? */
+ if (createCroppedImage(in, &image, &crop_data, &read_buff, &crop_buff))
{
- TIFFError("main", "Unable to load source image");
+ TIFFError("main", "Unable to create output image");
exit (-1);
}
- if (createCroppedImage(in, &crop_data, &read_buff, &crop_buff))
+ }
+
+ /* Check output qualifiers and build loops to break output image into pages */
+ if (page.mode != PAGE_MODE_NONE)
+ {
+ if (crop_data.crop_mode == CROP_NONE)
+ sect_src = read_buff;
+ else
+ sect_src = crop_buff;
+
+ if (computeOutputPixelOffsets(&crop_data, &image, &page, sections))
{
- TIFFError("main", "Unable to create output image");
+ TIFFError("main", "Unable to compute output section data");
exit (-1);
}
- if (writeCroppedImage(in, out, &crop_data, crop_buff))
+
+ if (writeImageSections(in, out, &image, &page, sections, sect_src, §_buff))
{
- TIFFError("main", "Unable to write new image");
+ TIFFError("main", "Unable to write image sections");
exit (-1);
}
}
else
- {
- if (!tiffcp(in, out) || !TIFFWriteDirectory(out))
+ if (writeCroppedImage(in, out, &crop_data, crop_buff))
{
- TIFFClose(out);
- return (1);
+ TIFFError("main", "Unable to write new image");
+ exit (-1);
}
- }
+
/* No image list specified, just read the next image */
if (image_count == 0)
dirnum++;
@@ -543,7 +781,7 @@ main(int argc, char* argv[])
if (dirnum == MAX_IMAGES - 1)
dirnum = TIFFNumberOfDirectories(in) - 1;
- if (!TIFFSetDirectory(in, dirnum))
+ if (!TIFFSetDirectory(in, (tdir_t)dirnum))
break;
}
}
@@ -552,11 +790,14 @@ main(int argc, char* argv[])
/* If we did not use the read buffer as the crop buffer */
if (read_buff)
- _TIFFfree(read_buff);
+ _TIFFfree(read_buff);
if (crop_buff)
_TIFFfree(crop_buff);
+ if (sect_buff)
+ _TIFFfree(sect_buff);
+
TIFFClose(out);
return (0);
@@ -635,11 +876,6 @@ char* stuff[] = {
" -s write output in strips",
" -t write output in tiles",
" -i ignore read errors",
-" -b file:# bias (dark) monochrome image to be subtracted from all others",
-" Note that bias filename may be of the form filename:#",
-" where # specifies image file directory for bias filename.",
-" For example: tiffcrop -b bias.tif:1 esp.tif test.tif",
-" subtract 2nd image in bias.tif from all images in esp.tiff producing test.tif",
"",
" -r # make each strip have no more than # rows",
" -w # set output tile width (pixels)",
@@ -679,12 +915,21 @@ char* stuff[] = {
" -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",
+" -m #,#,#,# margins from edges f
(Patch may be truncated, please check the link at the top of this post.)