LCOV - code coverage report
Current view: directory - apps - nearblack.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 271 226 83.4 %
Date: 2012-12-26 Functions: 4 3 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: nearblack.cpp 22783 2011-07-23 19:28:16Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Utilities
       5                 :  * Purpose:  Convert nearly black or nearly white border to exact black/white.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  * ****************************************************************************
       9                 :  * Copyright (c) 2006, MapShots Inc (www.mapshots.com)
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal.h"
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include <vector>
      34                 : #include "commonutils.h"
      35                 : 
      36                 : CPL_CVSID("$Id: nearblack.cpp 22783 2011-07-23 19:28:16Z rouault $");
      37                 : 
      38                 : typedef std::vector<int> Color;
      39                 : typedef std::vector< Color > Colors;
      40                 : 
      41                 : static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
      42                 :                          int iEnd, int nSrcBands, int nDstBands, int nNearDist,
      43                 :                          int nMaxNonBlack, int bNearWhite, Colors *poColors,
      44                 :                          int *panLastLineCounts, int bDoHorizontalCheck,
      45                 :                          int bDoVerticalCheck, int bBottomUp);
      46                 : 
      47                 : /************************************************************************/
      48                 : /*                            IsInt()                                   */
      49                 : /************************************************************************/
      50                 : 
      51               6 : int IsInt( const char *pszArg )
      52                 : {
      53               6 :     if( pszArg[0] == '-' )
      54               0 :         pszArg++;
      55                 : 
      56               6 :     if( *pszArg == '\0' )
      57               0 :         return FALSE;
      58                 : 
      59              24 :     while( *pszArg != '\0' )
      60                 :     {
      61              12 :         if( *pszArg < '0' || *pszArg > '9' )
      62               0 :             return FALSE;
      63              12 :         pszArg++;
      64                 :     }
      65                 : 
      66               6 :     return TRUE;
      67                 : }
      68                 : 
      69                 : /************************************************************************/
      70                 : /*                               Usage()                                */
      71                 : /************************************************************************/
      72                 : 
      73               0 : void Usage()
      74                 : {
      75                 :     printf( "nearblack [-of format] [-white | [-color c1,c2,c3...cn]*] [-near dist] [-nb non_black_pixels]\n"
      76               0 :             "          [-setalpha] [-setmask] [-o outfile] [-q] [-co \"NAME=VALUE\"]* infile\n" );
      77               0 :     exit( 1 );
      78                 : }
      79                 : 
      80                 : /************************************************************************/
      81                 : /*                                main()                                */
      82                 : /************************************************************************/
      83                 : 
      84               8 : int main( int argc, char ** argv )
      85                 : 
      86                 : {
      87                 :     /* Check that we are running against at least GDAL 1.4 (probably older in fact !) */
      88                 :     /* Note to developers : if we use newer API, please change the requirement */
      89               8 :     if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
      90                 :     {
      91                 :         fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
      92               0 :                 "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
      93               0 :         exit(1);
      94                 :     }
      95                 : 
      96                 : /* -------------------------------------------------------------------- */
      97                 : /*      Generic arg processing.                                         */
      98                 : /* -------------------------------------------------------------------- */
      99               8 :     GDALAllRegister();
     100               8 :     GDALSetCacheMax( 100000000 );
     101               8 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
     102               8 :     if( argc < 1 )
     103               0 :         exit( -argc );
     104                 :     
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      Parse arguments.                                                */
     107                 : /* -------------------------------------------------------------------- */
     108                 :     int i;
     109               8 :     const char *pszOutFile = NULL;
     110               8 :     const char *pszInFile = NULL;
     111               8 :     int nMaxNonBlack = 2;
     112               8 :     int nNearDist = 15;
     113               8 :     int bNearWhite = FALSE;
     114               8 :     int bSetAlpha = FALSE;
     115               8 :     int bSetMask = FALSE;
     116               8 :     const char* pszDriverName = "HFA";
     117               8 :     int bFormatExplicitelySet = FALSE;
     118               8 :     char** papszCreationOptions = NULL;
     119               8 :     int bQuiet = FALSE;
     120                 : 
     121               8 :     Colors oColors;
     122                 :     
     123              44 :     for( i = 1; i < argc; i++ )
     124                 :     {
     125              37 :         if( EQUAL(argv[i], "--utility_version") )
     126                 :         {
     127                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
     128               1 :                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
     129               1 :             return 0;
     130                 :         }
     131              41 :         else if( EQUAL(argv[i], "-o") && i < argc-1 )
     132               5 :             pszOutFile = argv[++i];
     133              38 :         else if( EQUAL(argv[i], "-of") && i < argc-1 )
     134                 :         {
     135               7 :             pszDriverName = argv[++i];
     136               7 :             bFormatExplicitelySet = TRUE;
     137                 :         }
     138              24 :         else if( EQUAL(argv[i], "-white") ) {
     139               1 :             bNearWhite = TRUE;
     140                 :         }
     141                 : 
     142                 :         /***** -color c1,c2,c3...cn *****/
     143                 :         
     144              25 :         else if( EQUAL(argv[i], "-color") && i < argc-1 ) {
     145               2 :             Color oColor;
     146                 :             
     147                 :             /***** tokenize the arg on , *****/
     148                 :             
     149                 :             char **papszTokens;
     150               2 :             papszTokens = CSLTokenizeString2( argv[++i], ",", 0 );
     151                 : 
     152                 :             /***** loop over the tokens *****/
     153                 :             
     154                 :             int iToken;
     155              16 :             for( iToken = 0; papszTokens && papszTokens[iToken]; iToken++ )
     156                 :             {
     157                 : 
     158                 :                 /***** ensure the token is an int and add it to the color *****/
     159                 :                 
     160               6 :                 if ( IsInt( papszTokens[iToken] ) )
     161               6 :                     oColor.push_back( atoi( papszTokens[iToken] ) );
     162                 :                 else {
     163                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     164               0 :                              "Colors must be valid integers." );
     165               0 :                     CSLDestroy( papszTokens );
     166               0 :                     exit(1);
     167                 :                 }
     168                 :             }
     169                 :             
     170               2 :             CSLDestroy( papszTokens );
     171                 : 
     172                 :             /***** check if the number of bands is consistant *****/
     173                 : 
     174               2 :             if ( oColors.size() > 0 &&
     175                 :                  oColors.front().size() != oColor.size() )
     176                 :             {
     177                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     178               0 :                          "ERROR: all -color args must have the same number of values.\n" );
     179               0 :                 exit(1);
     180                 :             }
     181                 : 
     182                 :             /***** add the color to the colors *****/
     183                 :             
     184               2 :             oColors.push_back( oColor );
     185                 :             
     186                 :         }
     187                 :         
     188              27 :         else if( EQUAL(argv[i], "-nb") && i < argc-1 )
     189               6 :             nMaxNonBlack = atoi(argv[++i]);
     190              15 :         else if( EQUAL(argv[i], "-near") && i < argc-1 )
     191               0 :             nNearDist = atoi(argv[++i]);
     192              15 :         else if( EQUAL(argv[i], "-setalpha") )
     193               3 :             bSetAlpha = TRUE;
     194              12 :         else if( EQUAL(argv[i], "-setmask") )
     195               2 :             bSetMask = TRUE;
     196              11 :         else if( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
     197               1 :             bQuiet = TRUE;
     198              11 :         else if( EQUAL(argv[i], "-co") && i < argc-1 )
     199               2 :             papszCreationOptions = CSLAddString(papszCreationOptions, argv[++i]);
     200               7 :         else if( argv[i][0] == '-' )
     201               0 :             Usage();
     202               7 :         else if( pszInFile == NULL )
     203               7 :             pszInFile = argv[i];
     204                 :         else
     205               0 :             Usage();
     206                 :     }
     207                 : 
     208               7 :     if( pszInFile == NULL )
     209               0 :         Usage();
     210                 : 
     211               7 :     if( pszOutFile == NULL )
     212               2 :         pszOutFile = pszInFile;
     213                 : 
     214                 : /* -------------------------------------------------------------------- */
     215                 : /*      Open input file.                                                */
     216                 : /* -------------------------------------------------------------------- */
     217               7 :     GDALDatasetH hInDS, hOutDS = NULL;
     218                 :     int nXSize, nYSize, nBands;
     219                 : 
     220               7 :     if( pszOutFile == pszInFile )
     221               2 :         hInDS = hOutDS = GDALOpen( pszInFile, GA_Update );
     222                 :     else
     223               5 :         hInDS = GDALOpen( pszInFile, GA_ReadOnly );
     224                 : 
     225               7 :     if( hInDS == NULL )
     226               0 :         exit( 1 );
     227                 : 
     228               7 :     nXSize = GDALGetRasterXSize( hInDS );
     229               7 :     nYSize = GDALGetRasterYSize( hInDS );
     230               7 :     nBands = GDALGetRasterCount( hInDS );
     231               7 :     int nDstBands = nBands;
     232                 : 
     233               7 :     if( hOutDS != NULL && papszCreationOptions != NULL)
     234                 :     {
     235                 :         CPLError(CE_Warning, CPLE_AppDefined,
     236               0 :                   "Warning: creation options are ignored when writing to an existing file.");
     237                 :     }
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Do we need to create output file?                               */
     241                 : /* -------------------------------------------------------------------- */
     242               7 :     if( hOutDS == NULL )
     243                 :     {
     244               5 :         GDALDriverH hDriver = GDALGetDriverByName( pszDriverName );
     245               5 :         if (hDriver == NULL)
     246               0 :             exit(1);
     247                 : 
     248               5 :         if (!bQuiet && !bFormatExplicitelySet)
     249               0 :             CheckExtensionConsistency(pszOutFile, pszDriverName);
     250                 : 
     251               5 :         if (bSetAlpha)
     252                 :         {
     253                 :             /***** fixme there should be a way to preserve alpha band data not in the collar *****/
     254               2 :             if (nBands == 4)
     255               0 :                 nBands --;
     256                 :             else
     257               2 :                 nDstBands ++;
     258                 :         }
     259                 : 
     260               5 :         if (bSetMask)
     261                 :         {
     262               1 :             if (nBands == 4)
     263               0 :                 nDstBands = nBands = 3;
     264                 :         }
     265                 : 
     266                 :         hOutDS = GDALCreate( hDriver, pszOutFile, 
     267                 :                              nXSize, nYSize, nDstBands, GDT_Byte, 
     268               5 :                              papszCreationOptions );
     269               5 :         if( hOutDS == NULL )
     270               0 :             exit( 1 );
     271                 : 
     272                 :         double adfGeoTransform[6];
     273                 : 
     274               5 :         if( GDALGetGeoTransform( hInDS, adfGeoTransform ) == CE_None )
     275                 :         {
     276               4 :             GDALSetGeoTransform( hOutDS, adfGeoTransform );
     277               4 :             GDALSetProjection( hOutDS, GDALGetProjectionRef( hInDS ) );
     278                 :         }
     279                 :     }
     280                 :     else
     281                 :     {
     282               2 :         if (bSetAlpha)
     283                 :         {
     284               1 :             if (nBands != 4 &&
     285                 :                 (nBands < 2 ||
     286                 :                  GDALGetRasterColorInterpretation(GDALGetRasterBand(hOutDS, nBands)) != GCI_AlphaBand))
     287                 :             {
     288                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     289               0 :                         "Last band is not an alpha band.");
     290               0 :                 exit(1);
     291                 :             }
     292                 : 
     293               1 :             nBands --;
     294                 :         }
     295                 : 
     296               2 :         if (bSetMask)
     297                 :         {
     298               1 :             if (nBands == 4)
     299               0 :                 nDstBands = nBands = 3;
     300                 :         }
     301                 :     }
     302                 : 
     303                 :     /***** set a color if there are no colors set? *****/
     304                 : 
     305               7 :     if ( oColors.size() == 0) {
     306               6 :         Color oColor;
     307                 : 
     308                 :         /***** loop over the bands to get the right number of values *****/
     309                 : 
     310                 :         int iBand;
     311              24 :         for (iBand = 0; iBand < nBands ; iBand++) {
     312                 : 
     313                 :             /***** black or white? *****/
     314                 : 
     315              18 :             if (bNearWhite) 
     316               3 :                 oColor.push_back(255);
     317                 :             else
     318              15 :                 oColor.push_back(0);
     319                 :         }
     320                 : 
     321                 :         /***** add the color to the colors *****/
     322                 : 
     323               6 :         oColors.push_back(oColor);
     324                 :             
     325                 :     }
     326                 : 
     327                 :     /***** does the number of bands match the number of color values? *****/
     328                 : 
     329               7 :     if ( (int)oColors.front().size() != nBands ) {
     330                 :         CPLError( CE_Failure, CPLE_AppDefined,
     331               0 :                   "-color args must have the same number of values as the non alpha input band count.\n" );
     332               0 :         exit(1); 
     333                 :     }
     334                 : 
     335                 :     /***** check the input and output datasets are the same size *****/
     336                 :     
     337               7 :     if (GDALGetRasterXSize(hOutDS) != nXSize ||
     338                 :         GDALGetRasterYSize(hOutDS) != nYSize)
     339                 :     {
     340                 :         CPLError(CE_Failure, CPLE_AppDefined,
     341                 :                  "The dimensions of the output dataset don't match "
     342               0 :                  "the dimensions of the input dataset.");
     343               0 :         exit(1);
     344                 :     }
     345                 : 
     346                 : 
     347                 :     int iBand;
     348              28 :     for( iBand = 0; iBand < nBands; iBand++ )
     349                 :     {
     350              21 :         GDALRasterBandH hBand = GDALGetRasterBand(hInDS, iBand+1);
     351              21 :         if (GDALGetRasterDataType(hBand) != GDT_Byte)
     352                 :         {
     353                 :             CPLError(CE_Warning, CPLE_AppDefined,
     354               0 :                      "Band %d is not of type GDT_Byte. It can lead to unexpected results.", iBand+1);
     355                 :         }
     356              21 :         if (GDALGetRasterColorTable(hBand) != NULL)
     357                 :         {
     358                 :             CPLError(CE_Warning, CPLE_AppDefined,
     359                 :                      "Band %d has a color table, which is ignored by nearblack. "
     360               0 :                      "It can lead to unexpected results.", iBand+1);
     361                 :         }
     362                 :     }
     363                 : 
     364               7 :     GDALRasterBandH hMaskBand = NULL;
     365                 :     
     366               7 :     if (bSetMask) {
     367                 : 
     368                 :         /***** if there isn't already a mask band on the output file create one *****/
     369                 :         
     370               2 :         if ( GMF_PER_DATASET != GDALGetMaskFlags( GDALGetRasterBand(hOutDS, 1) ) )
     371                 :         {
     372                 : 
     373               1 :             if ( CE_None != GDALCreateDatasetMaskBand(hOutDS, GMF_PER_DATASET) ) {
     374                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     375               0 :                          "Failed to create mask band on output DS");
     376               0 :                 bSetMask = FALSE;
     377                 :             }
     378                 :         }
     379                 : 
     380               2 :         if (bSetMask) {
     381               2 :             hMaskBand = GDALGetMaskBand(GDALGetRasterBand(hOutDS, 1));
     382                 :         }
     383                 :     }
     384                 : 
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      Allocate a line buffer.                                         */
     387                 : /* -------------------------------------------------------------------- */
     388                 :     GByte *pabyLine;
     389               7 :     GByte *pabyMask=NULL;
     390                 :     
     391                 :     int   *panLastLineCounts;
     392                 : 
     393               7 :     pabyLine = (GByte *) CPLMalloc(nXSize * nDstBands);
     394                 :     
     395               7 :     if (bSetMask)
     396               2 :         pabyMask = (GByte *) CPLMalloc(nXSize);
     397                 :     
     398               7 :     panLastLineCounts = (int *) CPLCalloc(sizeof(int),nXSize);
     399                 : 
     400                 : /* -------------------------------------------------------------------- */
     401                 : /*      Processing data one line at a time.                             */
     402                 : /* -------------------------------------------------------------------- */
     403                 :     int iLine;
     404                 : 
     405             357 :     for( iLine = 0; iLine < nYSize; iLine++ )
     406                 :     {
     407                 :         CPLErr eErr;
     408                 : 
     409                 :         eErr = GDALDatasetRasterIO( hInDS, GF_Read, 0, iLine, nXSize, 1, 
     410                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     411             350 :                                     nBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     412             350 :         if( eErr != CE_None )
     413               0 :             break;
     414                 :         
     415             350 :         if (bSetAlpha)
     416                 :         {
     417                 :             int iCol;
     418            7650 :             for(iCol = 0; iCol < nXSize; iCol ++)
     419                 :             {
     420            7500 :                 pabyLine[iCol * nDstBands + nDstBands - 1] = 255;
     421                 :             }
     422                 :         }
     423                 :         
     424             350 :         if (bSetMask)
     425                 :         {
     426                 :             int iCol;
     427            5100 :             for(iCol = 0; iCol < nXSize; iCol ++)
     428                 :             {
     429            5000 :                 pabyMask[iCol] = 255;
     430                 :             }
     431                 :         }
     432                 :         
     433                 :         ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
     434                 :                      nNearDist, nMaxNonBlack, bNearWhite, &oColors,
     435                 :                      panLastLineCounts,
     436                 :                      TRUE, // bDoHorizontalCheck
     437                 :                      TRUE, // bDoVerticalCheck
     438                 :                      FALSE // bBottomUp
     439             350 :                     );
     440                 :         ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
     441                 :                      nNearDist, nMaxNonBlack, bNearWhite, &oColors,
     442                 :                      panLastLineCounts,
     443                 :                      TRUE,  // bDoHorizontalCheck
     444                 :                      FALSE, // bDoVerticalCheck
     445                 :                      FALSE  // bBottomUp
     446             350 :                     );
     447                 :         
     448                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
     449                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     450             350 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     451                 : 
     452             350 :         if( eErr != CE_None )
     453               0 :             break;
     454                 :     
     455                 :         /***** write out the mask band line *****/
     456                 : 
     457             350 :         if (bSetMask) {
     458                 : 
     459                 :             eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
     460                 :                                   pabyMask, nXSize, 1, GDT_Byte,
     461             100 :                                   0, 0 );
     462                 :                              
     463             100 :             if( eErr != CE_None ) {
     464                 :                 CPLError(CE_Warning, CPLE_AppDefined,
     465               0 :                          "ERROR writeing out line to mask band.");
     466               0 :                break;
     467                 :             }
     468                 :         }
     469                 :         
     470             350 :         if (!bQuiet)
     471             300 :             GDALTermProgress( 0.5 * ((iLine+1) / (double) nYSize), NULL, NULL );
     472                 :     }
     473                 : 
     474                 : /* -------------------------------------------------------------------- */
     475                 : /*      Now process from the bottom back up                            .*/
     476                 : /* -------------------------------------------------------------------- */
     477               7 :     memset( panLastLineCounts, 0, sizeof(int) * nXSize);
     478                 :     
     479             357 :     for( iLine = nYSize-1; iLine >= 0; iLine-- )
     480                 :     {
     481                 :         CPLErr eErr;
     482                 : 
     483                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Read, 0, iLine, nXSize, 1, 
     484                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     485             350 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     486             350 :         if( eErr != CE_None )
     487               0 :             break;
     488                 : 
     489                 :         /***** read the mask band line back in *****/
     490                 : 
     491             350 :         if (bSetMask) {
     492                 : 
     493                 :             eErr = GDALRasterIO ( hMaskBand, GF_Read, 0, iLine, nXSize, 1,
     494                 :                                   pabyMask, nXSize, 1, GDT_Byte,
     495             100 :                                   0, 0 );
     496                 :                              
     497                 :                                 
     498             100 :             if( eErr != CE_None )
     499               0 :                 break;
     500                 :         }
     501                 : 
     502                 :         
     503                 :         ProcessLine( pabyLine, pabyMask, 0, nXSize-1, nBands, nDstBands,
     504                 :                      nNearDist, nMaxNonBlack, bNearWhite, &oColors,
     505                 :                      panLastLineCounts,
     506                 :                      TRUE, // bDoHorizontalCheck
     507                 :                      TRUE, // bDoVerticalCheck
     508                 :                      TRUE  // bBottomUp
     509             350 :                    );
     510                 :         ProcessLine( pabyLine, pabyMask, nXSize-1, 0, nBands, nDstBands,
     511                 :                      nNearDist, nMaxNonBlack, bNearWhite, &oColors,
     512                 :                      panLastLineCounts,
     513                 :                      TRUE,  // bDoHorizontalCheck
     514                 :                      FALSE, // bDoVerticalCheck
     515                 :                      TRUE   // bBottomUp
     516             350 :                     );
     517                 :         
     518                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
     519                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     520             350 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     521             350 :         if( eErr != CE_None )
     522               0 :             break;
     523                 : 
     524                 :         /***** write out the mask band line *****/
     525                 : 
     526             350 :         if (bSetMask) {
     527                 : 
     528                 :             eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
     529                 :                                   pabyMask, nXSize, 1, GDT_Byte,
     530             100 :                                   0, 0 );
     531                 :                              
     532                 :                                 
     533             100 :             if( eErr != CE_None )
     534               0 :                 break;
     535                 :         }
     536                 : 
     537                 :         
     538             350 :         if (!bQuiet)
     539                 :             GDALTermProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, 
     540             300 :                             NULL, NULL );
     541                 :     }
     542                 : 
     543               7 :     CPLFree(pabyLine);
     544               7 :     if (bSetMask)
     545               2 :         CPLFree(pabyMask);
     546                 :     
     547               7 :     CPLFree( panLastLineCounts );
     548                 : 
     549               7 :     GDALClose( hOutDS );
     550               7 :     if( hInDS != hOutDS )
     551               5 :         GDALClose( hInDS );
     552               7 :     GDALDumpOpenDatasets( stderr );
     553               7 :     CSLDestroy( argv );
     554               7 :     CSLDestroy( papszCreationOptions );
     555               7 :     GDALDestroyDriverManager();
     556                 :     
     557               7 :     return 0;
     558                 : }
     559                 : 
     560                 : /************************************************************************/
     561                 : /*                            ProcessLine()                             */
     562                 : /*                                                                      */
     563                 : /*      Process a single scanline of image data.                        */
     564                 : /************************************************************************/
     565                 : 
     566            1400 : static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
     567                 :                         int iEnd, int nSrcBands, int nDstBands, int nNearDist,
     568                 :                         int nMaxNonBlack, int bNearWhite, Colors *poColors,
     569                 :                         int *panLastLineCounts, int bDoHorizontalCheck,
     570                 :                         int bDoVerticalCheck, int bBottomUp )
     571                 : {
     572                 :     int iDir, i;
     573            1400 :     GByte nReplacevalue = 0;
     574            1400 :     if( bNearWhite )
     575             200 :         nReplacevalue = 255;
     576                 : 
     577                 :     /* -------------------------------------------------------------------- */
     578                 :     /*      Vertical checking.                                              */
     579                 :     /* -------------------------------------------------------------------- */
     580                 :     
     581            1400 :     if( bDoVerticalCheck )
     582                 :     {
     583             700 :         int nXSize = MAX(iStart+1,iEnd+1);
     584                 : 
     585           35700 :         for( i = 0; i < nXSize; i++ )
     586                 :         {
     587                 : 
     588                 :             // are we already terminated for this column?
     589                 : 
     590           35000 :             if( panLastLineCounts[i] > nMaxNonBlack )
     591           24487 :                 continue;
     592                 : 
     593                 :             /***** is the pixel valid data? ****/
     594                 : 
     595           10513 :             int bIsNonBlack = FALSE;
     596                 : 
     597                 :             /***** loop over the colors *****/
     598                 : 
     599                 :             int iColor;
     600           10513 :             for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
     601                 : 
     602           12061 :                 Color oColor = (*poColors)[iColor];
     603                 : 
     604           12061 :                 bIsNonBlack = FALSE;
     605                 : 
     606                 :                 /***** loop over the bands *****/
     607                 : 
     608                 :                 int iBand;
     609           41931 :                 for( iBand = 0; iBand < nSrcBands; iBand++ )
     610                 :                 {
     611           32002 :                     int nPix = pabyLine[i * nDstBands + iBand];
     612                 : 
     613           32002 :                     if( oColor[iBand] - nPix > nNearDist ||
     614                 :                        nPix > nNearDist + oColor[iBand] )
     615                 :                     {
     616            2132 :                         bIsNonBlack = TRUE;
     617            2132 :                         break;
     618                 :                     }
     619                 :                 }
     620                 :                 
     621           12061 :                 if (bIsNonBlack == FALSE)
     622                 :                     break;          
     623                 :             }
     624                 : 
     625           10513 :             if (bIsNonBlack) {
     626             584 :                 panLastLineCounts[i]++;
     627                 : 
     628             584 :                 if( panLastLineCounts[i] > nMaxNonBlack )
     629             552 :                     continue; 
     630                 :             }
     631                 :             //else
     632                 :             //  panLastLineCounts[i] = 0; // not sure this even makes sense 
     633                 : 
     634                 :             /***** replace the pixel values *****/
     635                 : 
     636                 :             int iBand;
     637           39844 :             for( iBand = 0; iBand < nSrcBands; iBand++ )
     638           29883 :                 pabyLine[i * nDstBands + iBand] = nReplacevalue;
     639                 : 
     640                 :             /***** alpha *****/
     641                 : 
     642            9961 :             if( nDstBands > nSrcBands )
     643            2457 :                 pabyLine[i * nDstBands + nDstBands - 1] = 0;
     644                 : 
     645                 :             /***** mask *****/
     646                 : 
     647            9961 :             if (pabyMask != NULL)
     648            1968 :                 pabyMask[i] = 0;
     649                 :         }
     650                 :     }
     651                 : 
     652                 :     /* -------------------------------------------------------------------- */
     653                 :     /*      Horizontal Checking.                                            */
     654                 :     /* -------------------------------------------------------------------- */
     655                 :     
     656            1400 :     if( bDoHorizontalCheck )
     657                 :     {
     658            1400 :         int nNonBlackPixels = 0;
     659                 : 
     660                 :         /***** on a bottom up pass assume nMaxNonBlack is 0 *****/ 
     661                 : 
     662            1400 :         if (bBottomUp)
     663             700 :             nMaxNonBlack = 0;
     664                 : 
     665            1400 :         if( iStart < iEnd )
     666             700 :             iDir = 1;
     667                 :         else
     668             700 :             iDir = -1;
     669            1400 :         int bDoTest = TRUE;
     670                 : 
     671           70000 :         for( i = iStart; i != iEnd; i += iDir )
     672                 :         {
     673                 : 
     674                 :             /***** not seen any valid data? *****/
     675                 : 
     676           68600 :             if ( bDoTest ) {
     677                 : 
     678                 :                 /***** is the pixel valid data? ****/
     679                 : 
     680           23001 :                 int bIsNonBlack = FALSE;
     681                 : 
     682                 :                 /***** loop over the colors *****/
     683                 : 
     684                 :                 int iColor;
     685           23001 :                 for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
     686                 : 
     687           23161 :                     Color oColor = (*poColors)[iColor];
     688                 : 
     689           23161 :                     bIsNonBlack = FALSE;
     690                 : 
     691                 :                     /***** loop over the bands *****/
     692                 : 
     693                 :                     int iBand;
     694           88333 :                     for( iBand = 0; iBand < nSrcBands; iBand++ )
     695                 :                     {
     696           66664 :                         int nPix = pabyLine[i * nDstBands + iBand];
     697                 : 
     698           66664 :                         if( oColor[iBand] - nPix > nNearDist ||
     699                 :                            nPix > nNearDist + oColor[iBand] )
     700                 :                         {
     701            1492 :                             bIsNonBlack = TRUE;
     702            1492 :                             break;
     703                 :                         }
     704                 :                     }
     705                 :                     
     706           23161 :                     if (bIsNonBlack == FALSE)
     707                 :                         break;          
     708                 :                 }
     709                 : 
     710           23001 :                 if (bIsNonBlack) {
     711                 : 
     712                 :                     /***** use nNonBlackPixels in grey areas  *****/
     713                 :                     /***** from the verical pass's grey areas ****/
     714                 : 
     715            1332 :                     if( panLastLineCounts[i] <= nMaxNonBlack )
     716               0 :                         nNonBlackPixels = panLastLineCounts[i];
     717                 :                     else 
     718            1332 :                         nNonBlackPixels++;
     719                 :                 }
     720                 : 
     721           23001 :                 if( nNonBlackPixels > nMaxNonBlack ) {
     722            1300 :                     bDoTest = FALSE;
     723            1300 :                     continue;
     724                 :                 }
     725                 : 
     726                 :                 /***** replace the pixel values *****/
     727                 : 
     728                 :                 int iBand;
     729           86804 :                 for( iBand = 0; iBand < nSrcBands; iBand++ )
     730           65103 :                     pabyLine[i * nDstBands + iBand] = nReplacevalue;
     731                 : 
     732                 :                 /***** alpha *****/
     733                 : 
     734           21701 :                 if( nDstBands > nSrcBands )
     735            5586 :                     pabyLine[i * nDstBands + nDstBands - 1] = 0;
     736                 : 
     737                 :                 /***** mask *****/
     738                 : 
     739           21701 :                 if (pabyMask != NULL)
     740            4362 :                     pabyMask[i] = 0;
     741                 :             }
     742                 : 
     743                 :             /***** seen valid data but test if the *****/
     744                 :             /***** vertical pass saw any non valid data *****/
     745                 : 
     746           45599 :             else if( panLastLineCounts[i] == 0 ) {
     747             700 :                 bDoTest = TRUE;
     748             700 :                 nNonBlackPixels = 0;
     749                 :             }        
     750                 :         }
     751                 :     }
     752                 : 
     753            1400 : }
     754                 : 

Generated by: LCOV version 1.7