1 /*
2  *  PTblender $id$
3  *
4  *  Based on the program PTStitcher by Helmut Dersch.
5  *
6  *  Implements the colour and brightness correction originally found
7  *  in PTStitcher.
8  *
9  *  Jan 2006
10  *
11  *  This program is free software; you can redistribute it and/or
12  *  modify it under the terms of the GNU General Public
13  *  License as published by the Free Software Foundation; either
14  *  version 2 of the License, or (at your option) any later version.
15  *
16  *  This software is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *  General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this software; see the file COPYING.  If not, a copy
23  *  can be downloaded from http://www.gnu.org/licenses/gpl.html, or
24  *  obtained by writing to the Free Software Foundation, Inc.,
25  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  *
28  *  Author: Daniel M German dmgerman at uvic doooot ca
29  *
30  */
31 
32 
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/types.h>
38 #include <errno.h>
39 
40 #ifndef _MSC_VER
41 #include <unistd.h>
42 #else
43 #include "compat_win32/getopt.h"
44 #endif
45 
46 
47 #include "filter.h"
48 #include "panorama.h"
49 #include "PTcommon.h"
50 #include "ColourBrightness.h"
51 #include "pttiff.h"
52 
53 #define DEFAULT_PREFIX "blended%04d"
54 
55 #define PT_BLENDER_USAGE "PTblender [options] <tiffFiles>+\n\n"\
56                          "Options:\n"\
57                          "  -p <prefix>\tPrefix for output filename. Defaults to blended%%4d\n"\
58                          "  -k <index>\tIndex to image to use as a reference (0-based, defaults to 0)\n"\
59                          "  -t [0,1,2]\tType of colour correction:\n"\
60                          "  \t\t\t 0 full (default), 1 brightness only, 2 colour only\n"\
61                          "  -c\t\tOutput curves smooth (Output 1 per each corrected file)\n"\
62                          "  -m\t\tOutput curves arbitrary map (Output 1 per each corrected file)\n"\
63                          "  -f\t\tForce processing (ignore warnings)\n"\
64                          "  -x\t\tDelete source files (use with care)\n"\
65                          "  -q\t\tQuiet run\n"\
66                          "  -h\t\tShow this message\n"\
67                          "\n"
68 
69 #define PT_BLENDER_VERSION "PTblender Version " VERSION ", originally written by Helmut Dersch, rewritten by Daniel M German\n"
70 
71 
main(int argc,char * argv[])72 int main(int argc,char *argv[])
73 {
74     int returnValue = -1;
75     int opt;
76     int referenceImage = 0;
77     fullPath *ptrInputFiles   = NULL;
78     fullPath *ptrOutputFiles  = NULL;
79 
80     int counter;
81     char outputPrefix[MAX_PATH_LENGTH];
82     char *endPtr;
83     int filesCount = 0;
84     char tempString[MAX_PATH_LENGTH];
85     int base = 0;
86     int outputCurvesType = 0; // if 1 => create Photoshop curve files (.acv)
87     int typeCorrection = 0;
88     int ptForceProcessing = 0;
89     int ptDeleteSources = 0;
90 
91     counter = 0;
92 
93     printf(PT_BLENDER_VERSION);
94 
95 
96     strcpy(outputPrefix, DEFAULT_PREFIX);
97 
98     while ((opt = getopt(argc, argv, "p:k:t:fqcmh")) != -1) {
99 
100 	// o and f -> set output file
101 	// h       -> help
102 	// q       -> quiet?
103 	// k       -> base image, defaults to first
104 
105 	switch(opt) {  // fhoqs        f: 102 h:104  111 113 115  o:f:hsq
106 	case 'p':
107 	    if (strlen(optarg) < MAX_PATH_LENGTH) {
108 		strcpy(outputPrefix, optarg);
109 	    } else {
110 		PrintError("Illegal length for output prefix");
111 		goto end;
112 	    }
113 	    break;
114 	case 'k':
115 	    referenceImage = strtol(optarg, &endPtr, 10);
116 	    if (errno != 0) {
117 		PrintError("Invalid integer in -k option");
118 		goto end;
119 	    }
120 	    break;
121 	case 't':
122 	    typeCorrection = strtol(optarg, &endPtr, 10);
123 	    if (errno != 0 || (typeCorrection < 0 || typeCorrection > 2)) {
124 		PrintError("Invalid integer in -t option");
125 		goto end;
126 	    }
127 	    break;
128 	case 'f':
129 	    ptForceProcessing = 1;
130 	case 'q':
131 	    ptQuietFlag = 1;
132 	    break;
133 	case 'c':
134 	    if (outputCurvesType == CB_OUTPUT_CURVE_ARBITRARY) {
135 		PrintError("Can't use both -c and -m options");
136 		goto end;
137 	    }
138 	    outputCurvesType = CB_OUTPUT_CURVE_SMOOTH;
139 	    break;
140 	case 'm':
141 	    if (outputCurvesType == CB_OUTPUT_CURVE_SMOOTH) {
142 		PrintError("Can't use both -c and -m options");
143 		goto end;
144 	    }
145 	    outputCurvesType = CB_OUTPUT_CURVE_ARBITRARY;
146 	    break;
147 	case 'x':
148 	    ptDeleteSources = 1;
149             break;
150 	case 'h':
151 	    printf(PT_BLENDER_USAGE);
152         returnValue = 0;
153 	    goto end;
154 	default:
155 	    break;
156 	}
157     }
158 
159     filesCount = argc - optind;
160 
161     if ((ptrInputFiles = calloc(filesCount, sizeof(fullPath))) == NULL ||
162 	(ptrOutputFiles = calloc(filesCount, sizeof(fullPath))) == NULL)  {
163 	PrintError("Not enough memory");
164 	goto end;
165     }
166 
167     base = optind;
168     for (; optind < argc; optind++) {
169 	char *currentParm;
170 
171 	currentParm = argv[optind];
172 
173 	if (StringtoFullPath(&ptrInputFiles[optind-base], currentParm) !=0) { // success
174 	    PrintError("Syntax error: Not a valid pathname");
175 	    goto end;
176 	}
177     }
178 
179     if (filesCount <= 0) {
180 	PrintError("No files specified in the command line");
181 	fprintf(stderr, PT_BLENDER_USAGE);
182 	goto end;
183     }
184 
185     if (referenceImage < 0 || referenceImage >= filesCount) {
186 	PrintError(tempString, "Illegal reference image number %d. It should be between 0 and %d\n",
187 		referenceImage, filesCount-1);
188 	goto end;
189     }
190 
191     //We can't output curves for type 1 or 2 corrections
192     if (outputCurvesType != 0) {
193 	if (typeCorrection!= 0) {
194 	    PrintError("Output of curves is not supported for correction type %d", typeCorrection);
195 	    goto end;
196 	}
197     }
198     if (panoFileOutputNamesCreate(ptrOutputFiles, filesCount, outputPrefix) == 0) {
199 	goto end;
200     }
201 
202 
203 
204     if (!ptForceProcessing) {
205 	char *temp;
206 	if ((temp = panoFileExists(ptrOutputFiles, filesCount)) != NULL) {
207 	    PrintError("Output filename(s) exists. Use -f to overwrite");
208 	    goto end;
209 	}
210 
211 	if (!panoTiffVerifyAreCompatible(ptrInputFiles, filesCount, TRUE)) {
212 	    PrintError("TIFFs are not compatible");
213 	    goto end;
214 	}
215     }
216 
217     if (! ptQuietFlag) printf("Colour correcting photo using %d as a base type %d\n", referenceImage, typeCorrection);
218 
219     ColourBrightness(ptrInputFiles, ptrOutputFiles, filesCount, referenceImage, typeCorrection, outputCurvesType);
220 
221     returnValue = 0; // success
222 
223 end:
224 
225     if (ptDeleteSources && returnValue!=-1 && ptrInputFiles) {
226 	int i;
227 	for (i = 0; i < filesCount; i++) {
228 	    remove(ptrInputFiles[i].name);
229 	}
230     }
231     free(ptrInputFiles);
232     free(ptrOutputFiles);
233 
234     return returnValue;
235 }
236 
237