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