1 //=========================================================================================================//
2 //CAIR Example Suite
3
4 //=========================================================================================================//
5 //Copyright (C) 2009 Joseph Auman (brain.recall@gmail.com)
6
7 //=========================================================================================================//
8 //This library is free software; you can redistribute it and/or
9 //modify it under the terms of the GNU Lesser General Public
10 //License as published by the Free Software Foundation; either
11 //version 2.1 of the License, or (at your option) any later version.
12 //This library is distributed in the hope that it will be useful,
13 //but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 //Lesser General Public License for more details.
16 //You should have received a copy of the GNU Lesser General Public
17 //License along with this library; if not, write to the Free Software
18 //Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
20 //=========================================================================================================//
21 //This is a simple test program for CAIR.
22 //=========================================================================================================//
23
24 #include <iostream>
25 #include <ctime>
26 #include "CAIR.h"
27 #include "CAIR_CML.h"
28 #include "./EasyBMP/EasyBMP.h"
29
30 enum Arg_Param { INPUT_FILENAME = 0, GOAL_X, GOAL_Y, OUTPUT_FILENAME, RESULT_TYPE, CONVOLUTION, WEIGHT_FILENAME, WEIGHT_SCALE, ENERGY_TYPE, THREAD_COUNT };
31
32 using namespace std;
33
34 //=========================================================================================================//
BMP_to_CML(BMP * Source,CML_color * Dest)35 void BMP_to_CML( BMP * Source, CML_color * Dest )
36 {
37 (*Dest).D_Resize( (*Source).TellWidth(), (*Source).TellHeight() );
38
39 for( int y = 0; y < (*Source).TellHeight(); y++ )
40 {
41 for( int x = 0; x < (*Source).TellWidth(); x++ )
42 {
43 (*Dest)(x,y).alpha = (*Source)(x,y)->Alpha;
44 (*Dest)(x,y).red = (*Source)(x,y)->Red;
45 (*Dest)(x,y).green = (*Source)(x,y)->Green;
46 (*Dest)(x,y).blue = (*Source)(x,y)->Blue;
47 }
48 }
49 }
50
51 //=========================================================================================================//
CML_to_BMP(CML_color * Source,BMP * Dest)52 void CML_to_BMP( CML_color * Source, BMP * Dest )
53 {
54 (*Dest).SetSize( (*Source).Width(), (*Source).Height() );
55
56 for( int y = 0; y < (*Source).Height(); y++ )
57 {
58 for( int x = 0; x < (*Source).Width(); x++ )
59 {
60 (*(*Dest)(x,y)).Alpha = (*Source)(x,y).alpha;
61 (*(*Dest)(x,y)).Red = (*Source)(x,y).red;
62 (*(*Dest)(x,y)).Green = (*Source)(x,y).green;
63 (*(*Dest)(x,y)).Blue = (*Source)(x,y).blue;
64 }
65 }
66 }
67
68 //=========================================================================================================//
69 //simple weight tester
70 //_NOT_ intended as the means to set Weights. Best to use a graphical interface for that.
71 //top_x/y define the top left corner of the rectangle, bot_x/y define the bottom right corner.
Weight_Rectangle(CML_int * Weights,int top_x,int top_y,int bot_x,int bot_y,int weight)72 void Weight_Rectangle( CML_int * Weights, int top_x, int top_y, int bot_x, int bot_y, int weight )
73 {
74 int i = 0, j = 0;
75
76 for( i = top_x; i < (top_x + (bot_x-top_x)); i++ )
77 {
78 for( j = top_y; j < (top_y + (bot_y-top_y)); j++ )
79 {
80 (*Weights)(i,j) = weight;
81 }
82 }
83 }
84
85 //=========================================================================================================//
86 //search argParameter
getArgParameter(Arg_Param arg,int argc,char * argv[])87 char * getArgParameter( Arg_Param arg, int argc, char * argv[] )
88 {
89 char * sToBeFind = NULL;
90
91 switch(arg)
92 {
93 case INPUT_FILENAME :
94 sToBeFind = "-I";
95 break;
96
97 case OUTPUT_FILENAME :
98 sToBeFind = "-O";
99 break;
100
101 case GOAL_X :
102 sToBeFind = "-X";
103 break;
104
105 case GOAL_Y :
106 sToBeFind = "-Y";
107 break;
108
109 case RESULT_TYPE :
110 sToBeFind = "-R";
111 break;
112
113 case CONVOLUTION :
114 sToBeFind = "-C";
115 break;
116
117 case WEIGHT_FILENAME :
118 sToBeFind = "-W";
119 break;
120
121 case WEIGHT_SCALE :
122 sToBeFind = "-S";
123 break;
124 case ENERGY_TYPE :
125 sToBeFind = "-E";
126 break;
127 case THREAD_COUNT :
128 sToBeFind = "-T";
129 break;
130 }
131
132 for ( int i = 1 ; i < argc ; i++ )//minus one, because we return the next
133 {
134 if( memcmp ( argv[i], sToBeFind, 2 ) == 0 )//find if
135 return argv[i+1];
136 }
137 return NULL;
138 }
139
140 //=========================================================================================================//
Print_Usage()141 void Print_Usage()
142 {
143 cout << "CAIR CLI Usage: cair -I <input_file>" << endl;
144 cout << "Other options:" << endl;
145 cout << " -O <output_file>" << endl;
146 cout << " Default: Dependent on operation" << endl;
147 cout << " -W <weight_file>" << endl;
148 cout << " Bitmap with: Black- no weight" << endl;
149 cout << " Green- Protect weight" << endl;
150 cout << " Red- Remove weight" << endl;
151 cout << " Default: Weights are all zero" << endl;
152 cout << " -S <weight_scale>" << endl;
153 cout << " Default: 100,000" << endl;
154 cout << " -X <goal_x>" << endl;
155 cout << " Default: Source image width" << endl;
156 cout << " -Y <goal_y>" << endl;
157 cout << " Default: Source image height" << endl;
158 cout << " -R <expected_result>" << endl;
159 cout << " CAIR: 0" << endl;
160 cout << " Grayscale: 1" << endl;
161 cout << " Edge: 2" << endl;
162 cout << " Vertical Energy: 3" << endl;
163 cout << " Horizontal Energy: 4" << endl;
164 cout << " Removal: 5" << endl;
165 cout << " CAIR_HD: 6" << endl;
166 cout << " Default: CAIR" << endl;
167 cout << " -C <convoluton_type>" << endl;
168 cout << " Prewitt: 0" << endl;
169 cout << " V1: 1" << endl;
170 cout << " V_SQUARE: 2" << endl;
171 cout << " Sobel: 3" << endl;
172 cout << " Laplacian: 4" << endl;
173 cout << " Default: Prewitt" << endl << endl;
174 cout << " -E <energy_type>" << endl;
175 cout << " Backward: 0" << endl;
176 cout << " Forward: 1" << endl;
177 cout << " Default: Backward" << endl;
178 cout << " -T <thread_count>" << endl;
179 cout << " Default : CAIR_NUM_THREADS (" << CAIR_NUM_THREADS << ")" << endl;
180 cout << "http://sourceforge.net/projects/c-a-i-r/" << endl;
181 }
182
183 //=========================================================================================================//
184 //callback test function
cancel_callback(float percent_done)185 bool cancel_callback( float percent_done )
186 {
187 cout << "Percent done: " << (int)(percent_done * 100) << "%" << endl;
188
189 return true;
190 }
191
192 //=========================================================================================================//
193 //simple tester
main(int argc,char * argv[])194 int main( int argc, char * argv[] )
195 {
196 cout << "Welcome to the Content Aware Image Resizer (CAIR) Test Application!" << endl;
197
198 BMP Image;
199 BMP Resized;
200 time_t start;
201 time_t end;
202
203 char * output_filename;
204 char * input_filename;
205 char * weight_filename;
206 int goal_x;
207 int goal_y;
208 int weight_scale;
209 int result_type;//type of result : 0 image, 1 grayscale, 2 edge, 3 V-energy
210 CAIR_convolution convolution;
211 CAIR_energy ener;
212
213 //set parameters
214 input_filename = getArgParameter( INPUT_FILENAME , argc, argv);
215 if( input_filename == NULL )
216 {
217 cout << "Error: Input image required" << endl;
218 Print_Usage();
219 return 0;
220 }
221
222 //set image
223 Image.ReadFromFile( input_filename );
224 CML_color Source( Image.TellWidth(), Image.TellHeight() );
225 CML_color Dest( Image.TellWidth(), Image.TellHeight() );
226
227 //default parameters
228 char * temp = NULL;
229
230 //the -X param
231 temp = getArgParameter( GOAL_X, argc, argv );
232 if( temp != NULL )
233 {
234 goal_x = atoi( temp );
235 }
236 else
237 {
238 goal_x = Image.TellWidth();
239 }
240
241 //the -Y param
242 temp = getArgParameter( GOAL_Y, argc, argv );
243 if( temp != NULL )
244 {
245 goal_y = atoi( temp );
246 }
247 else
248 {
249 goal_y = Image.TellHeight();
250 }
251
252 //the -R param
253 temp = getArgParameter( RESULT_TYPE, argc, argv );
254 if( temp != NULL )
255 {
256 result_type = atoi( temp );
257 }
258 else
259 {
260 result_type = 0;
261 }
262
263 //the -C param
264 temp = getArgParameter( CONVOLUTION, argc, argv );
265 if( temp != NULL )
266 {
267 convolution = (CAIR_convolution)atoi( temp );
268 }
269 else
270 {
271 convolution = PREWITT;
272 }
273
274 //the -O param
275 output_filename = getArgParameter( OUTPUT_FILENAME, argc, argv );
276 if( output_filename == NULL )
277 {
278 switch( result_type )
279 {
280 case 0 :
281 output_filename = "output.bmp";
282 break;
283 case 1 :
284 output_filename = "out_grayscale.bmp";
285 break;
286 case 2 :
287 output_filename = "out_edge.bmp";
288 break;
289 case 3 :
290 output_filename = "out_energy_V.bmp";
291 break;
292 case 4 :
293 output_filename = "out_energy_H.bmp";
294 break;
295 case 5 :
296 output_filename = "out_Remove.bmp";
297 break;
298 case 6 :
299 output_filename = "outputHD.bmp";
300 break;
301 }
302 }
303
304 //the -S param
305 temp = getArgParameter( WEIGHT_SCALE, argc, argv );
306 if( temp != NULL )
307 {
308 weight_scale = atoi( temp );
309 }
310 else
311 {
312 weight_scale = 100000;
313 }
314
315 //the -E param
316 temp = getArgParameter( ENERGY_TYPE, argc, argv );
317 if( temp != NULL )
318 {
319 ener = (CAIR_energy)atoi( temp );
320 }
321 else
322 {
323 ener = BACKWARD;
324 }
325
326 //the -T param
327 temp = getArgParameter( THREAD_COUNT, argc, argv );
328 if( temp != NULL )
329 {
330 CAIR_Threads( atoi(temp) );
331 }
332
333
334 //the -W param
335 //set weights
336 CML_int Weights( Image.TellWidth(), Image.TellHeight() );
337 CML_int D_Weights( 1, 1 );
338 Weights.Fill( 0 );
339 //Weight_Rectangle( &Weights, 436, 411, 524, 604, -100000 ); //only useful for test.bmp
340 //Weight_Rectangle( &Weights, 524, 487, 548, 552, -100000 );
341 //Weight_Rectangle( &Weights, 532, 325, 1023, 468, 100000 );
342 //Weight_Rectangle( &Weights, 551, 468, 1023, 544, 100000 );
343 //Weight_Rectangle( &Weights, 605, 544, 1023, 588, 100000 );
344 //Weight_Rectangle( &Weights, 624, 227, 1023, 325, 100000 );
345 weight_filename = getArgParameter( WEIGHT_FILENAME, argc, argv );
346 if( weight_filename != NULL )
347 {
348 BMP weight;
349 weight.ReadFromFile( weight_filename );
350
351 for( int x = 0; x < Image.TellWidth(); x++ )
352 {
353 for( int y = 0; y < Image.TellHeight(); y++ )
354 {
355 Weights(x,y) += weight_scale * (weight(x,y)->Green / 255);
356 Weights(x,y) += -weight_scale * (weight(x,y)->Red / 255);
357 }
358 }
359 }
360
361
362 //resize and write out the image
363 cout << "Please wait... ";
364 start = clock ();
365
366 BMP_to_CML( &Image, &Source );
367
368 switch( result_type )
369 {
370 case 0 :
371 CAIR( &Source, &Weights, goal_x, goal_y, convolution, ener, &D_Weights, &Dest, NULL ); //try cancel_callback
372 break;
373 case 1 :
374 CAIR_Grayscale( &Source, &Dest );
375 break;
376 case 2 :
377 CAIR_Edge( &Source, convolution, &Dest );
378 break;
379 case 3 :
380 CAIR_V_Energy( &Source, convolution, ener, &Dest );
381 break;
382 case 4 :
383 CAIR_H_Energy( &Source, convolution, ener, &Dest );
384 break;
385 case 5 :
386 CAIR_Removal( &Source, &Weights, AUTO, 1, convolution, ener, &D_Weights, &Dest, NULL );
387 break;
388 case 6 :
389 CAIR_HD( &Source, &Weights, goal_x, goal_y, convolution, ener, &D_Weights, &Dest, NULL );
390 break;
391 }
392
393 Resized.SetSize( Dest.Width(), Dest.Height() );
394 CML_to_BMP( &Dest, &Resized );
395
396 end=clock();
397 int timeInSec = (int)(end - start) / CLOCKS_PER_SEC;
398
399 printf ("Took: %d.%03ld seconds.\n", timeInSec, (end - start) * 1000 / CLOCKS_PER_SEC-timeInSec*1000 );
400 Resized.WriteToFile( output_filename );
401
402 return 0;
403 }
404