+ if ( argc < 2 ) {
+ Sys_Printf( "Usage: q3map [-v] -minimap [-size n] [-sharpen f] [-samples n | -random n] [-o filename.tga] [-minmax Xmin Ymin Zmin Xmax Ymax Zmax] <mapname>\n" );
+ return 0;
+ }
+
+ /* load the BSP first */
+ strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
+ StripExtension( source );
+ DefaultExtension( source, ".bsp" );
+ Sys_Printf( "Loading %s\n", source );
+ BeginMapShaderFile( source );
+ LoadShaderInfo();
+ LoadBSPFile( source );
+
+ minimap.model = &bspModels[0];
+ VectorCopy( minimap.model->mins, mins );
+ VectorCopy( minimap.model->maxs, maxs );
+
+ *minimapFilename = 0;
+ minimapSharpen = game->miniMapSharpen;
+ minimap.width = minimap.height = game->miniMapSize;
+ border = game->miniMapBorder;
+ keepaspect = game->miniMapKeepAspect;
+ mode = game->miniMapMode;
+
+ autolevel = qfalse;
+ minimap.samples = 1;
+ minimap.sample_offsets = NULL;
+ minimap.boost = 1.0;
+ minimap.brightness = 0.0;
+ minimap.contrast = 1.0;
+
+ /* process arguments */
+ for ( i = 1; i < ( argc - 1 ); i++ )
+ {
+ if ( !strcmp( argv[ i ], "-size" ) ) {
+ minimap.width = minimap.height = atoi( argv[i + 1] );
+ i++;
+ Sys_Printf( "Image size set to %i\n", minimap.width );
+ }
+ else if ( !strcmp( argv[ i ], "-sharpen" ) ) {
+ minimapSharpen = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Sharpening coefficient set to %f\n", minimapSharpen );
+ }
+ else if ( !strcmp( argv[ i ], "-samples" ) ) {
+ minimap.samples = atoi( argv[i + 1] );
+ i++;
+ Sys_Printf( "Samples set to %i\n", minimap.samples );
+ if ( minimap.sample_offsets ) {
+ free( minimap.sample_offsets );
+ }
+ minimap.sample_offsets = malloc( 2 * sizeof( *minimap.sample_offsets ) * minimap.samples );
+ MiniMapMakeSampleOffsets();
+ }
+ else if ( !strcmp( argv[ i ], "-random" ) ) {
+ minimap.samples = atoi( argv[i + 1] );
+ i++;
+ Sys_Printf( "Random samples set to %i\n", minimap.samples );
+ if ( minimap.sample_offsets ) {
+ free( minimap.sample_offsets );
+ }
+ minimap.sample_offsets = NULL;
+ }
+ else if ( !strcmp( argv[ i ], "-border" ) ) {
+ border = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Border set to %f\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-keepaspect" ) ) {
+ keepaspect = qtrue;
+ Sys_Printf( "Keeping aspect ratio by letterboxing\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-nokeepaspect" ) ) {
+ keepaspect = qfalse;
+ Sys_Printf( "Not keeping aspect ratio\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-o" ) ) {
+ strcpy( minimapFilename, argv[i + 1] );
+ i++;
+ Sys_Printf( "Output file name set to %s\n", minimapFilename );
+ }
+ else if ( !strcmp( argv[ i ], "-minmax" ) && i < ( argc - 7 ) ) {
+ mins[0] = atof( argv[i + 1] );
+ mins[1] = atof( argv[i + 2] );
+ mins[2] = atof( argv[i + 3] );
+ maxs[0] = atof( argv[i + 4] );
+ maxs[1] = atof( argv[i + 5] );
+ maxs[2] = atof( argv[i + 6] );
+ i += 6;
+ Sys_Printf( "Map mins/maxs overridden\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-gray" ) ) {
+ mode = MINIMAP_MODE_GRAY;
+ Sys_Printf( "Writing as white-on-black image\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-black" ) ) {
+ mode = MINIMAP_MODE_BLACK;
+ Sys_Printf( "Writing as black alpha image\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-white" ) ) {
+ mode = MINIMAP_MODE_WHITE;
+ Sys_Printf( "Writing as white alpha image\n" );
+ }
+ else if ( !strcmp( argv[ i ], "-boost" ) && i < ( argc - 2 ) ) {
+ minimap.boost = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Contrast boost set to %f\n", minimap.boost );
+ }
+ else if ( !strcmp( argv[ i ], "-brightness" ) && i < ( argc - 2 ) ) {
+ minimap.brightness = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Brightness set to %f\n", minimap.brightness );
+ }
+ else if ( !strcmp( argv[ i ], "-contrast" ) && i < ( argc - 2 ) ) {
+ minimap.contrast = atof( argv[i + 1] );
+ i++;
+ Sys_Printf( "Contrast set to %f\n", minimap.contrast );
+ }
+ else if ( !strcmp( argv[ i ], "-autolevel" ) ) {
+ autolevel = qtrue;
+ Sys_Printf( "Auto level enabled\n", border );
+ }
+ else if ( !strcmp( argv[ i ], "-noautolevel" ) ) {
+ autolevel = qfalse;
+ Sys_Printf( "Auto level disabled\n", border );
+ }
+ }
+
+ MiniMapMakeMinsMaxs( mins, maxs, border, keepaspect );
+
+ if ( !*minimapFilename ) {
+ ExtractFileBase( source, basename );
+ ExtractFilePath( source, path );
+ sprintf( relativeMinimapFilename, game->miniMapNameFormat, basename );
+ MergeRelativePath( minimapFilename, path, relativeMinimapFilename );
+ Sys_Printf( "Output file name automatically set to %s\n", minimapFilename );
+ }
+ ExtractFilePath( minimapFilename, path );
+ Q_mkdir( path );
+
+ if ( minimapSharpen >= 0 ) {
+ minimap.sharpen_centermult = 8 * minimapSharpen + 1;
+ minimap.sharpen_boxmult = -minimapSharpen;
+ }
+
+ minimap.data1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) );
+ data4b = safe_malloc( minimap.width * minimap.height * 4 );
+ if ( minimapSharpen >= 0 ) {
+ minimap.sharpendata1f = safe_malloc( minimap.width * minimap.height * sizeof( *minimap.data1f ) );
+ }
+
+ MiniMapSetupBrushes();
+
+ if ( minimap.samples <= 1 ) {
+ Sys_Printf( "\n--- MiniMapNoSupersampling (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapNoSupersampling );
+ }
+ else
+ {
+ if ( minimap.sample_offsets ) {
+ Sys_Printf( "\n--- MiniMapSupersampled (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSupersampled );
+ }
+ else
+ {
+ Sys_Printf( "\n--- MiniMapRandomlySupersampled (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapRandomlySupersampled );
+ }
+ }
+
+ if ( minimap.boost != 1.0 ) {
+ Sys_Printf( "\n--- MiniMapContrastBoost (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapContrastBoost );
+ }
+
+ if ( autolevel ) {
+ Sys_Printf( "\n--- MiniMapAutoLevel (%d) ---\n", minimap.height );
+ float mi = 1, ma = 0;
+ float s, o;
+
+ // TODO threads!
+ q = minimap.data1f;
+ for ( y = 0; y < minimap.height; ++y )
+ for ( x = 0; x < minimap.width; ++x )
+ {
+ float v = *q++;
+ if ( v < mi ) {
+ mi = v;
+ }
+ if ( v > ma ) {
+ ma = v;
+ }
+ }
+ if ( ma > mi ) {
+ s = 1 / ( ma - mi );
+ o = mi / ( ma - mi );
+
+ // equations:
+ // brightness + contrast * v
+ // after autolevel:
+ // brightness + contrast * (v * s - o)
+ // =
+ // (brightness - contrast * o) + (contrast * s) * v
+ minimap.brightness = minimap.brightness - minimap.contrast * o;
+ minimap.contrast *= s;
+
+ Sys_Printf( "Auto level: Brightness changed to %f\n", minimap.brightness );
+ Sys_Printf( "Auto level: Contrast changed to %f\n", minimap.contrast );
+ }
+ else{
+ Sys_Printf( "Auto level: failed because all pixels are the same value\n" );
+ }
+ }
+
+ if ( minimap.brightness != 0 || minimap.contrast != 1 ) {
+ Sys_Printf( "\n--- MiniMapBrightnessContrast (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapBrightnessContrast );
+ }
+
+ if ( minimap.sharpendata1f ) {
+ Sys_Printf( "\n--- MiniMapSharpen (%d) ---\n", minimap.height );
+ RunThreadsOnIndividual( minimap.height, qtrue, MiniMapSharpen );
+ q = minimap.sharpendata1f;
+ }
+ else
+ {
+ q = minimap.data1f;
+ }
+
+ Sys_Printf( "\nConverting..." );
+
+ switch ( mode )