LCOV - code coverage report
Current view: directory - apps - nearblack.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 281 232 82.6 %
Date: 2013-03-30 Functions: 4 3 75.0 %

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

Generated by: LCOV version 1.7