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-04-28 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              12 : int IsInt( const char *pszArg )
      52                 : {
      53              12 :     if( pszArg[0] == '-' )
      54               0 :         pszArg++;
      55                 : 
      56              12 :     if( *pszArg == '\0' )
      57               0 :         return FALSE;
      58                 : 
      59              48 :     while( *pszArg != '\0' )
      60                 :     {
      61              24 :         if( *pszArg < '0' || *pszArg > '9' )
      62               0 :             return FALSE;
      63              24 :         pszArg++;
      64                 :     }
      65                 : 
      66              12 :     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              16 : 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              16 :     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              16 :     GDALAllRegister();
     100              16 :     GDALSetCacheMax( 100000000 );
     101              16 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
     102              16 :     if( argc < 1 )
     103               0 :         exit( -argc );
     104                 :     
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      Parse arguments.                                                */
     107                 : /* -------------------------------------------------------------------- */
     108                 :     int i;
     109              16 :     const char *pszOutFile = NULL;
     110              16 :     const char *pszInFile = NULL;
     111              16 :     int nMaxNonBlack = 2;
     112              16 :     int nNearDist = 15;
     113              16 :     int bNearWhite = FALSE;
     114              16 :     int bSetAlpha = FALSE;
     115              16 :     int bSetMask = FALSE;
     116              16 :     const char* pszDriverName = "HFA";
     117              16 :     int bFormatExplicitelySet = FALSE;
     118              16 :     char** papszCreationOptions = NULL;
     119              16 :     int bQuiet = FALSE;
     120                 : 
     121              16 :     Colors oColors;
     122                 :     
     123              88 :     for( i = 1; i < argc; i++ )
     124                 :     {
     125              74 :         if( EQUAL(argv[i], "--utility_version") )
     126                 :         {
     127                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
     128               2 :                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
     129               2 :             return 0;
     130                 :         }
     131              82 :         else if( EQUAL(argv[i], "-o") && i < argc-1 )
     132              10 :             pszOutFile = argv[++i];
     133              76 :         else if( EQUAL(argv[i], "-of") && i < argc-1 )
     134                 :         {
     135              14 :             pszDriverName = argv[++i];
     136              14 :             bFormatExplicitelySet = TRUE;
     137                 :         }
     138              48 :         else if( EQUAL(argv[i], "-white") ) {
     139               2 :             bNearWhite = TRUE;
     140                 :         }
     141                 : 
     142                 :         /***** -color c1,c2,c3...cn *****/
     143                 :         
     144              50 :         else if( EQUAL(argv[i], "-color") && i < argc-1 ) {
     145               4 :             Color oColor;
     146                 :             
     147                 :             /***** tokenize the arg on , *****/
     148                 :             
     149                 :             char **papszTokens;
     150               4 :             papszTokens = CSLTokenizeString2( argv[++i], ",", 0 );
     151                 : 
     152                 :             /***** loop over the tokens *****/
     153                 :             
     154                 :             int iToken;
     155              32 :             for( iToken = 0; papszTokens && papszTokens[iToken]; iToken++ )
     156                 :             {
     157                 : 
     158                 :                 /***** ensure the token is an int and add it to the color *****/
     159                 :                 
     160              12 :                 if ( IsInt( papszTokens[iToken] ) )
     161              12 :                     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               4 :             CSLDestroy( papszTokens );
     171                 : 
     172                 :             /***** check if the number of bands is consistant *****/
     173                 : 
     174               4 :             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               4 :             oColors.push_back( oColor );
     185                 :             
     186                 :         }
     187                 :         
     188              54 :         else if( EQUAL(argv[i], "-nb") && i < argc-1 )
     189              12 :             nMaxNonBlack = atoi(argv[++i]);
     190              30 :         else if( EQUAL(argv[i], "-near") && i < argc-1 )
     191               0 :             nNearDist = atoi(argv[++i]);
     192              30 :         else if( EQUAL(argv[i], "-setalpha") )
     193               6 :             bSetAlpha = TRUE;
     194              24 :         else if( EQUAL(argv[i], "-setmask") )
     195               4 :             bSetMask = TRUE;
     196              22 :         else if( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
     197               2 :             bQuiet = TRUE;
     198              22 :         else if( EQUAL(argv[i], "-co") && i < argc-1 )
     199               4 :             papszCreationOptions = CSLAddString(papszCreationOptions, argv[++i]);
     200              14 :         else if( argv[i][0] == '-' )
     201               0 :             Usage();
     202              14 :         else if( pszInFile == NULL )
     203              14 :             pszInFile = argv[i];
     204                 :         else
     205               0 :             Usage();
     206                 :     }
     207                 : 
     208              14 :     if( pszInFile == NULL )
     209               0 :         Usage();
     210                 : 
     211              14 :     if( pszOutFile == NULL )
     212               4 :         pszOutFile = pszInFile;
     213                 : 
     214                 : /* -------------------------------------------------------------------- */
     215                 : /*      Open input file.                                                */
     216                 : /* -------------------------------------------------------------------- */
     217              14 :     GDALDatasetH hInDS, hOutDS = NULL;
     218                 :     int nXSize, nYSize, nBands;
     219                 : 
     220              14 :     if( pszOutFile == pszInFile )
     221               4 :         hInDS = hOutDS = GDALOpen( pszInFile, GA_Update );
     222                 :     else
     223              10 :         hInDS = GDALOpen( pszInFile, GA_ReadOnly );
     224                 : 
     225              14 :     if( hInDS == NULL )
     226               0 :         exit( 1 );
     227                 : 
     228              14 :     nXSize = GDALGetRasterXSize( hInDS );
     229              14 :     nYSize = GDALGetRasterYSize( hInDS );
     230              14 :     nBands = GDALGetRasterCount( hInDS );
     231              14 :     int nDstBands = nBands;
     232                 : 
     233              14 :     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              14 :     if( hOutDS == NULL )
     243                 :     {
     244              10 :         GDALDriverH hDriver = GDALGetDriverByName( pszDriverName );
     245              10 :         if (hDriver == NULL)
     246               0 :             exit(1);
     247                 : 
     248              10 :         if (!bQuiet && !bFormatExplicitelySet)
     249               0 :             CheckExtensionConsistency(pszOutFile, pszDriverName);
     250                 : 
     251              10 :         if (bSetAlpha)
     252                 :         {
     253                 :             /***** fixme there should be a way to preserve alpha band data not in the collar *****/
     254               4 :             if (nBands == 4)
     255               0 :                 nBands --;
     256                 :             else
     257               4 :                 nDstBands ++;
     258                 :         }
     259                 : 
     260              10 :         if (bSetMask)
     261                 :         {
     262               2 :             if (nBands == 4)
     263               0 :                 nDstBands = nBands = 3;
     264                 :         }
     265                 : 
     266                 :         hOutDS = GDALCreate( hDriver, pszOutFile, 
     267                 :                              nXSize, nYSize, nDstBands, GDT_Byte, 
     268              10 :                              papszCreationOptions );
     269              10 :         if( hOutDS == NULL )
     270               0 :             exit( 1 );
     271                 : 
     272                 :         double adfGeoTransform[6];
     273                 : 
     274              10 :         if( GDALGetGeoTransform( hInDS, adfGeoTransform ) == CE_None )
     275                 :         {
     276               8 :             GDALSetGeoTransform( hOutDS, adfGeoTransform );
     277               8 :             GDALSetProjection( hOutDS, GDALGetProjectionRef( hInDS ) );
     278                 :         }
     279                 :     }
     280                 :     else
     281                 :     {
     282               4 :         if (bSetAlpha)
     283                 :         {
     284               2 :             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               2 :             nBands --;
     294                 :         }
     295                 : 
     296               4 :         if (bSetMask)
     297                 :         {
     298               2 :             if (nBands == 4)
     299               0 :                 nDstBands = nBands = 3;
     300                 :         }
     301                 :     }
     302                 : 
     303                 :     /***** set a color if there are no colors set? *****/
     304                 : 
     305              14 :     if ( oColors.size() == 0) {
     306              12 :         Color oColor;
     307                 : 
     308                 :         /***** loop over the bands to get the right number of values *****/
     309                 : 
     310                 :         int iBand;
     311              48 :         for (iBand = 0; iBand < nBands ; iBand++) {
     312                 : 
     313                 :             /***** black or white? *****/
     314                 : 
     315              36 :             if (bNearWhite) 
     316               6 :                 oColor.push_back(255);
     317                 :             else
     318              30 :                 oColor.push_back(0);
     319                 :         }
     320                 : 
     321                 :         /***** add the color to the colors *****/
     322                 : 
     323              12 :         oColors.push_back(oColor);
     324                 :             
     325                 :     }
     326                 : 
     327                 :     /***** does the number of bands match the number of color values? *****/
     328                 : 
     329              14 :     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              14 :     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              56 :     for( iBand = 0; iBand < nBands; iBand++ )
     349                 :     {
     350              42 :         GDALRasterBandH hBand = GDALGetRasterBand(hInDS, iBand+1);
     351              42 :         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              42 :         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              14 :     GDALRasterBandH hMaskBand = NULL;
     365                 :     
     366              14 :     if (bSetMask) {
     367                 : 
     368                 :         /***** if there isn't already a mask band on the output file create one *****/
     369                 :         
     370               4 :         if ( GMF_PER_DATASET != GDALGetMaskFlags( GDALGetRasterBand(hOutDS, 1) ) )
     371                 :         {
     372                 : 
     373               2 :             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               4 :         if (bSetMask) {
     381               4 :             hMaskBand = GDALGetMaskBand(GDALGetRasterBand(hOutDS, 1));
     382                 :         }
     383                 :     }
     384                 : 
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      Allocate a line buffer.                                         */
     387                 : /* -------------------------------------------------------------------- */
     388                 :     GByte *pabyLine;
     389              14 :     GByte *pabyMask=NULL;
     390                 :     
     391                 :     int   *panLastLineCounts;
     392                 : 
     393              14 :     pabyLine = (GByte *) CPLMalloc(nXSize * nDstBands);
     394                 :     
     395              14 :     if (bSetMask)
     396               4 :         pabyMask = (GByte *) CPLMalloc(nXSize);
     397                 :     
     398              14 :     panLastLineCounts = (int *) CPLCalloc(sizeof(int),nXSize);
     399                 : 
     400                 : /* -------------------------------------------------------------------- */
     401                 : /*      Processing data one line at a time.                             */
     402                 : /* -------------------------------------------------------------------- */
     403                 :     int iLine;
     404                 : 
     405             714 :     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             700 :                                     nBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     412             700 :         if( eErr != CE_None )
     413               0 :             break;
     414                 :         
     415             700 :         if (bSetAlpha)
     416                 :         {
     417                 :             int iCol;
     418           15300 :             for(iCol = 0; iCol < nXSize; iCol ++)
     419                 :             {
     420           15000 :                 pabyLine[iCol * nDstBands + nDstBands - 1] = 255;
     421                 :             }
     422                 :         }
     423                 :         
     424             700 :         if (bSetMask)
     425                 :         {
     426                 :             int iCol;
     427           10200 :             for(iCol = 0; iCol < nXSize; iCol ++)
     428                 :             {
     429           10000 :                 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             700 :                     );
     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             700 :                     );
     447                 :         
     448                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
     449                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     450             700 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     451                 : 
     452             700 :         if( eErr != CE_None )
     453               0 :             break;
     454                 :     
     455                 :         /***** write out the mask band line *****/
     456                 : 
     457             700 :         if (bSetMask) {
     458                 : 
     459                 :             eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
     460                 :                                   pabyMask, nXSize, 1, GDT_Byte,
     461             200 :                                   0, 0 );
     462                 :                              
     463             200 :             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             700 :         if (!bQuiet)
     471             600 :             GDALTermProgress( 0.5 * ((iLine+1) / (double) nYSize), NULL, NULL );
     472                 :     }
     473                 : 
     474                 : /* -------------------------------------------------------------------- */
     475                 : /*      Now process from the bottom back up                            .*/
     476                 : /* -------------------------------------------------------------------- */
     477              14 :     memset( panLastLineCounts, 0, sizeof(int) * nXSize);
     478                 :     
     479             714 :     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             700 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     486             700 :         if( eErr != CE_None )
     487               0 :             break;
     488                 : 
     489                 :         /***** read the mask band line back in *****/
     490                 : 
     491             700 :         if (bSetMask) {
     492                 : 
     493                 :             eErr = GDALRasterIO ( hMaskBand, GF_Read, 0, iLine, nXSize, 1,
     494                 :                                   pabyMask, nXSize, 1, GDT_Byte,
     495             200 :                                   0, 0 );
     496                 :                              
     497                 :                                 
     498             200 :             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             700 :                    );
     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             700 :                     );
     517                 :         
     518                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
     519                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     520             700 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     521             700 :         if( eErr != CE_None )
     522               0 :             break;
     523                 : 
     524                 :         /***** write out the mask band line *****/
     525                 : 
     526             700 :         if (bSetMask) {
     527                 : 
     528                 :             eErr = GDALRasterIO ( hMaskBand, GF_Write, 0, iLine, nXSize, 1,
     529                 :                                   pabyMask, nXSize, 1, GDT_Byte,
     530             200 :                                   0, 0 );
     531                 :                              
     532                 :                                 
     533             200 :             if( eErr != CE_None )
     534               0 :                 break;
     535                 :         }
     536                 : 
     537                 :         
     538             700 :         if (!bQuiet)
     539                 :             GDALTermProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, 
     540             600 :                             NULL, NULL );
     541                 :     }
     542                 : 
     543              14 :     CPLFree(pabyLine);
     544              14 :     if (bSetMask)
     545               4 :         CPLFree(pabyMask);
     546                 :     
     547              14 :     CPLFree( panLastLineCounts );
     548                 : 
     549              14 :     GDALClose( hOutDS );
     550              14 :     if( hInDS != hOutDS )
     551              10 :         GDALClose( hInDS );
     552              14 :     GDALDumpOpenDatasets( stderr );
     553              14 :     CSLDestroy( argv );
     554              14 :     CSLDestroy( papszCreationOptions );
     555              14 :     GDALDestroyDriverManager();
     556                 :     
     557              14 :     return 0;
     558                 : }
     559                 : 
     560                 : /************************************************************************/
     561                 : /*                            ProcessLine()                             */
     562                 : /*                                                                      */
     563                 : /*      Process a single scanline of image data.                        */
     564                 : /************************************************************************/
     565                 : 
     566            2800 : 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            2800 :     GByte nReplacevalue = 0;
     574            2800 :     if( bNearWhite )
     575             400 :         nReplacevalue = 255;
     576                 : 
     577                 :     /* -------------------------------------------------------------------- */
     578                 :     /*      Vertical checking.                                              */
     579                 :     /* -------------------------------------------------------------------- */
     580                 :     
     581            2800 :     if( bDoVerticalCheck )
     582                 :     {
     583            1400 :         int nXSize = MAX(iStart+1,iEnd+1);
     584                 : 
     585           71400 :         for( i = 0; i < nXSize; i++ )
     586                 :         {
     587                 : 
     588                 :             // are we already terminated for this column?
     589                 : 
     590           70000 :             if( panLastLineCounts[i] > nMaxNonBlack )
     591           48974 :                 continue;
     592                 : 
     593                 :             /***** is the pixel valid data? ****/
     594                 : 
     595           21026 :             int bIsNonBlack = FALSE;
     596                 : 
     597                 :             /***** loop over the colors *****/
     598                 : 
     599                 :             int iColor;
     600           21026 :             for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
     601                 : 
     602           24122 :                 Color oColor = (*poColors)[iColor];
     603                 : 
     604           24122 :                 bIsNonBlack = FALSE;
     605                 : 
     606                 :                 /***** loop over the bands *****/
     607                 : 
     608                 :                 int iBand;
     609           83862 :                 for( iBand = 0; iBand < nSrcBands; iBand++ )
     610                 :                 {
     611           64004 :                     int nPix = pabyLine[i * nDstBands + iBand];
     612                 : 
     613           64004 :                     if( oColor[iBand] - nPix > nNearDist ||
     614                 :                        nPix > nNearDist + oColor[iBand] )
     615                 :                     {
     616            4264 :                         bIsNonBlack = TRUE;
     617            4264 :                         break;
     618                 :                     }
     619                 :                 }
     620                 :                 
     621           24122 :                 if (bIsNonBlack == FALSE)
     622                 :                     break;          
     623                 :             }
     624                 : 
     625           21026 :             if (bIsNonBlack) {
     626            1168 :                 panLastLineCounts[i]++;
     627                 : 
     628            1168 :                 if( panLastLineCounts[i] > nMaxNonBlack )
     629            1104 :                     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           79688 :             for( iBand = 0; iBand < nSrcBands; iBand++ )
     638           59766 :                 pabyLine[i * nDstBands + iBand] = nReplacevalue;
     639                 : 
     640                 :             /***** alpha *****/
     641                 : 
     642           19922 :             if( nDstBands > nSrcBands )
     643            4914 :                 pabyLine[i * nDstBands + nDstBands - 1] = 0;
     644                 : 
     645                 :             /***** mask *****/
     646                 : 
     647           19922 :             if (pabyMask != NULL)
     648            3936 :                 pabyMask[i] = 0;
     649                 :         }
     650                 :     }
     651                 : 
     652                 :     /* -------------------------------------------------------------------- */
     653                 :     /*      Horizontal Checking.                                            */
     654                 :     /* -------------------------------------------------------------------- */
     655                 :     
     656            2800 :     if( bDoHorizontalCheck )
     657                 :     {
     658            2800 :         int nNonBlackPixels = 0;
     659                 : 
     660                 :         /***** on a bottom up pass assume nMaxNonBlack is 0 *****/ 
     661                 : 
     662            2800 :         if (bBottomUp)
     663            1400 :             nMaxNonBlack = 0;
     664                 : 
     665            2800 :         if( iStart < iEnd )
     666            1400 :             iDir = 1;
     667                 :         else
     668            1400 :             iDir = -1;
     669            2800 :         int bDoTest = TRUE;
     670                 : 
     671          140000 :         for( i = iStart; i != iEnd; i += iDir )
     672                 :         {
     673                 : 
     674                 :             /***** not seen any valid data? *****/
     675                 : 
     676          137200 :             if ( bDoTest ) {
     677                 : 
     678                 :                 /***** is the pixel valid data? ****/
     679                 : 
     680           46002 :                 int bIsNonBlack = FALSE;
     681                 : 
     682                 :                 /***** loop over the colors *****/
     683                 : 
     684                 :                 int iColor;
     685           46002 :                 for (iColor = 0; iColor < (int)poColors->size(); iColor++) {
     686                 : 
     687           46322 :                     Color oColor = (*poColors)[iColor];
     688                 : 
     689           46322 :                     bIsNonBlack = FALSE;
     690                 : 
     691                 :                     /***** loop over the bands *****/
     692                 : 
     693                 :                     int iBand;
     694          176666 :                     for( iBand = 0; iBand < nSrcBands; iBand++ )
     695                 :                     {
     696          133328 :                         int nPix = pabyLine[i * nDstBands + iBand];
     697                 : 
     698          133328 :                         if( oColor[iBand] - nPix > nNearDist ||
     699                 :                            nPix > nNearDist + oColor[iBand] )
     700                 :                         {
     701            2984 :                             bIsNonBlack = TRUE;
     702            2984 :                             break;
     703                 :                         }
     704                 :                     }
     705                 :                     
     706           46322 :                     if (bIsNonBlack == FALSE)
     707                 :                         break;          
     708                 :                 }
     709                 : 
     710           46002 :                 if (bIsNonBlack) {
     711                 : 
     712                 :                     /***** use nNonBlackPixels in grey areas  *****/
     713                 :                     /***** from the verical pass's grey areas ****/
     714                 : 
     715            2664 :                     if( panLastLineCounts[i] <= nMaxNonBlack )
     716               0 :                         nNonBlackPixels = panLastLineCounts[i];
     717                 :                     else 
     718            2664 :                         nNonBlackPixels++;
     719                 :                 }
     720                 : 
     721           46002 :                 if( nNonBlackPixels > nMaxNonBlack ) {
     722            2600 :                     bDoTest = FALSE;
     723            2600 :                     continue;
     724                 :                 }
     725                 : 
     726                 :                 /***** replace the pixel values *****/
     727                 : 
     728                 :                 int iBand;
     729          173608 :                 for( iBand = 0; iBand < nSrcBands; iBand++ )
     730          130206 :                     pabyLine[i * nDstBands + iBand] = nReplacevalue;
     731                 : 
     732                 :                 /***** alpha *****/
     733                 : 
     734           43402 :                 if( nDstBands > nSrcBands )
     735           11172 :                     pabyLine[i * nDstBands + nDstBands - 1] = 0;
     736                 : 
     737                 :                 /***** mask *****/
     738                 : 
     739           43402 :                 if (pabyMask != NULL)
     740            8724 :                     pabyMask[i] = 0;
     741                 :             }
     742                 : 
     743                 :             /***** seen valid data but test if the *****/
     744                 :             /***** vertical pass saw any non valid data *****/
     745                 : 
     746           91198 :             else if( panLastLineCounts[i] == 0 ) {
     747            1400 :                 bDoTest = TRUE;
     748            1400 :                 nNonBlackPixels = 0;
     749                 :             }        
     750                 :         }
     751                 :     }
     752                 : 
     753            2800 : }
     754                 : 

Generated by: LCOV version 1.7