LTP GCOV extension - code coverage report
Current view: directory - apps - nearblack.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 182
Code covered: 84.6 % Executed lines: 154

       1                 : /******************************************************************************
       2                 :  * $Id: nearblack.cpp 18712 2010-02-03 22:02:41Z 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                 : 
      34                 : CPL_CVSID("$Id: nearblack.cpp 18712 2010-02-03 22:02:41Z rouault $");
      35                 : 
      36                 : static void ProcessLine( GByte *pabyLine, int iStart, int iEnd, int nSrcBands, int nDstBands,
      37                 :                          int nNearDist, int nMaxNonBlack, int bNearWhite,
      38                 :                          int *panLastLineCounts, 
      39                 :                          int bDoHorizontalCheck, 
      40                 :                          int bDoVerticalCheck );
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                               Usage()                                */
      44                 : /************************************************************************/
      45                 : 
      46               0 : void Usage()
      47                 : {
      48                 :     printf( "nearblack [-of format] [-white] [-near dist] [-nb non_black_pixels]\n"
      49               0 :             "          [-setalpha] [-o outfile] [-q] [-co \"NAME=VALUE\"]* infile\n" );
      50               0 :     exit( 1 );
      51                 : }
      52                 : 
      53                 : /************************************************************************/
      54                 : /*                                main()                                */
      55                 : /************************************************************************/
      56                 : 
      57               5 : int main( int argc, char ** argv )
      58                 : 
      59                 : {
      60                 :     /* Check that we are running against at least GDAL 1.4 (probably older in fact !) */
      61                 :     /* Note to developers : if we use newer API, please change the requirement */
      62               5 :     if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
      63                 :     {
      64                 :         fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
      65               0 :                 "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
      66               0 :         exit(1);
      67                 :     }
      68                 : 
      69                 : /* -------------------------------------------------------------------- */
      70                 : /*      Generic arg processing.                                         */
      71                 : /* -------------------------------------------------------------------- */
      72               5 :     GDALAllRegister();
      73               5 :     GDALSetCacheMax( 100000000 );
      74               5 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
      75               5 :     if( argc < 1 )
      76               0 :         exit( -argc );
      77                 :     
      78                 : /* -------------------------------------------------------------------- */
      79                 : /*      Parse arguments.                                                */
      80                 : /* -------------------------------------------------------------------- */
      81                 :     int i;
      82               5 :     const char *pszOutFile = NULL;
      83               5 :     const char *pszInFile = NULL;
      84               5 :     int nMaxNonBlack = 2;
      85               5 :     int nNearDist = 15;
      86               5 :     int bNearWhite = FALSE;
      87               5 :     int bSetAlpha = FALSE;
      88               5 :     const char* pszDriverName = "HFA";
      89               5 :     char** papszCreationOptions = NULL;
      90               5 :     int bQuiet = FALSE;
      91                 :     
      92              26 :     for( i = 1; i < argc; i++ )
      93                 :     {
      94              22 :         if( EQUAL(argv[i], "--utility_version") )
      95                 :         {
      96                 :             printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
      97               1 :                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
      98               1 :             return 0;
      99                 :         }
     100              24 :         else if( EQUAL(argv[i], "-o") && i < argc-1 )
     101               3 :             pszOutFile = argv[++i];
     102              22 :         else if( EQUAL(argv[i], "-of") && i < argc-1 )
     103               4 :             pszDriverName = argv[++i];
     104              14 :         else if( EQUAL(argv[i], "-white") )
     105               1 :             bNearWhite = TRUE;
     106              17 :         else if( EQUAL(argv[i], "-nb") && i < argc-1 )
     107               4 :             nMaxNonBlack = atoi(argv[++i]);
     108               9 :         else if( EQUAL(argv[i], "-near") && i < argc-1 )
     109               0 :             nNearDist = atoi(argv[++i]);
     110               9 :         else if( EQUAL(argv[i], "-setalpha") )
     111               3 :             bSetAlpha = TRUE;
     112               7 :         else if( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
     113               1 :             bQuiet = TRUE;
     114               6 :         else if( EQUAL(argv[i], "-co") && i < argc-1 )
     115               1 :             papszCreationOptions = CSLAddString(papszCreationOptions, argv[++i]);
     116               4 :         else if( argv[i][0] == '-' )
     117               0 :             Usage();
     118               4 :         else if( pszInFile == NULL )
     119               4 :             pszInFile = argv[i];
     120                 :         else
     121               0 :             Usage();
     122                 :     }
     123                 : 
     124               4 :     if( pszInFile == NULL )
     125               0 :         Usage();
     126                 : 
     127               4 :     if( pszOutFile == NULL )
     128               1 :         pszOutFile = pszInFile;
     129                 : 
     130                 : /* -------------------------------------------------------------------- */
     131                 : /*      Open input file.                                                */
     132                 : /* -------------------------------------------------------------------- */
     133               4 :     GDALDatasetH hInDS, hOutDS = NULL;
     134                 :     int nXSize, nYSize, nBands;
     135                 : 
     136               4 :     if( pszOutFile == pszInFile )
     137               1 :         hInDS = hOutDS = GDALOpen( pszInFile, GA_Update );
     138                 :     else
     139               3 :         hInDS = GDALOpen( pszInFile, GA_ReadOnly );
     140                 : 
     141               4 :     if( hInDS == NULL )
     142               0 :         exit( 1 );
     143                 : 
     144               4 :     nXSize = GDALGetRasterXSize( hInDS );
     145               4 :     nYSize = GDALGetRasterYSize( hInDS );
     146               4 :     nBands = GDALGetRasterCount( hInDS );
     147               4 :     int nDstBands = nBands;
     148                 : 
     149               4 :     if( hOutDS != NULL && papszCreationOptions != NULL)
     150                 :     {
     151                 :         CPLError(CE_Warning, CPLE_AppDefined,
     152               0 :                   "Warning: creation options are ignored when writing to an existing file.");
     153                 :     }
     154                 : 
     155                 : /* -------------------------------------------------------------------- */
     156                 : /*      Do we need to create output file?                               */
     157                 : /* -------------------------------------------------------------------- */
     158               4 :     if( hOutDS == NULL )
     159                 :     {
     160               3 :         GDALDriverH hDriver = GDALGetDriverByName( pszDriverName );
     161               3 :         if (hDriver == NULL)
     162               0 :             exit(1);
     163                 : 
     164               3 :         if (bSetAlpha)
     165                 :         {
     166               2 :             if (nBands == 3)
     167               2 :                 nDstBands ++;
     168               0 :             else if (nBands == 4)
     169               0 :                 nBands --;
     170                 :             else
     171                 :             {
     172                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     173                 :                          "Number of bands of file = %d. Expected 3 or 4.",
     174               0 :                          nBands);
     175               0 :                 exit(1);
     176                 :             }
     177                 :         }
     178                 : 
     179                 :         hOutDS = GDALCreate( hDriver, pszOutFile, 
     180                 :                              nXSize, nYSize, nDstBands, GDT_Byte, 
     181               3 :                              papszCreationOptions );
     182               3 :         if( hOutDS == NULL )
     183               0 :             exit( 1 );
     184                 : 
     185                 :         double adfGeoTransform[6];
     186                 : 
     187               3 :         if( GDALGetGeoTransform( hInDS, adfGeoTransform ) == CE_None )
     188                 :         {
     189               3 :             GDALSetGeoTransform( hOutDS, adfGeoTransform );
     190               3 :             GDALSetProjection( hOutDS, GDALGetProjectionRef( hInDS ) );
     191                 :         }
     192                 :     }
     193                 :     else
     194                 :     {
     195               1 :         if (bSetAlpha)
     196                 :         {
     197               1 :             if (nBands != 4)
     198                 :             {
     199                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     200                 :                         "Number of bands of output file = %d. Expected 4.",
     201               0 :                         nBands);
     202               0 :                 exit(1);
     203                 :             }
     204                 : 
     205               1 :             nBands --;
     206                 :         }
     207                 :     }
     208                 : 
     209               4 :     if (GDALGetRasterXSize(hOutDS) != nXSize ||
     210                 :         GDALGetRasterYSize(hOutDS) != nYSize)
     211                 :     {
     212                 :         CPLError(CE_Failure, CPLE_AppDefined,
     213                 :                  "The dimensions of the output dataset don't match "
     214               0 :                  "the dimensions of the input dataset.");
     215               0 :         exit(1);
     216                 :     }
     217                 : 
     218                 : 
     219                 :     int iBand;
     220              16 :     for( iBand = 0; iBand < nBands; iBand++ )
     221                 :     {
     222              12 :         GDALRasterBandH hBand = GDALGetRasterBand(hInDS, iBand+1);
     223              12 :         if (GDALGetRasterDataType(hBand) != GDT_Byte)
     224                 :         {
     225                 :             CPLError(CE_Warning, CPLE_AppDefined,
     226               0 :                      "Band %d is not of type GDT_Byte. It can lead to unexpected results.", iBand+1);
     227                 :         }
     228              12 :         if (GDALGetRasterColorTable(hBand) != NULL)
     229                 :         {
     230                 :             CPLError(CE_Warning, CPLE_AppDefined,
     231                 :                      "Band %d has a color table, which is ignored by nearblack. "
     232               0 :                      "It can lead to unexpected results.", iBand+1);
     233                 :         }
     234                 :     }
     235                 : 
     236                 : /* -------------------------------------------------------------------- */
     237                 : /*      Allocate a line buffer.                                         */
     238                 : /* -------------------------------------------------------------------- */
     239                 :     GByte *pabyLine;
     240                 :     int   *panLastLineCounts;
     241                 : 
     242               4 :     pabyLine = (GByte *) CPLMalloc(nXSize * nDstBands);
     243                 : 
     244               4 :     panLastLineCounts = (int *) CPLCalloc(sizeof(int),nXSize);
     245                 : 
     246                 : /* -------------------------------------------------------------------- */
     247                 : /*      Processing data one line at a time.                             */
     248                 : /* -------------------------------------------------------------------- */
     249                 :     int iLine;
     250                 : 
     251             204 :     for( iLine = 0; iLine < nYSize; iLine++ )
     252                 :     {
     253                 :         CPLErr eErr;
     254                 : 
     255                 :         eErr = GDALDatasetRasterIO( hInDS, GF_Read, 0, iLine, nXSize, 1, 
     256                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     257             200 :                                     nBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     258             200 :         if( eErr != CE_None )
     259               0 :             break;
     260                 :         
     261             200 :         if (bSetAlpha)
     262                 :         {
     263                 :             int iCol;
     264            7650 :             for(iCol = 0; iCol < nXSize; iCol ++)
     265                 :             {
     266            7500 :                 pabyLine[iCol * nDstBands + nDstBands - 1] = 255;
     267                 :             }
     268                 :         }
     269                 :         
     270                 :         ProcessLine( pabyLine, 0, nXSize-1, nBands, nDstBands, nNearDist, nMaxNonBlack,
     271             200 :                      bNearWhite, panLastLineCounts, TRUE, TRUE );
     272                 :         ProcessLine( pabyLine, nXSize-1, 0, nBands, nDstBands, nNearDist, nMaxNonBlack,
     273             200 :                      bNearWhite, NULL, TRUE, FALSE );
     274                 :         
     275                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
     276                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     277             200 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     278             200 :         if( eErr != CE_None )
     279               0 :             break;
     280                 :         
     281             200 :         if (!bQuiet)
     282             150 :             GDALTermProgress( 0.5 * ((iLine+1) / (double) nYSize), NULL, NULL );
     283                 :     }
     284                 : 
     285                 : /* -------------------------------------------------------------------- */
     286                 : /*      Now process from the bottom back up, doing only the vertical pass.*/
     287                 : /* -------------------------------------------------------------------- */
     288               4 :     memset( panLastLineCounts, 0, sizeof(int) * nXSize);
     289                 :     
     290             204 :     for( iLine = nYSize-1; iLine >= 0; iLine-- )
     291                 :     {
     292                 :         CPLErr eErr;
     293                 : 
     294                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Read, 0, iLine, nXSize, 1, 
     295                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     296             200 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     297             200 :         if( eErr != CE_None )
     298               0 :             break;
     299                 :         
     300                 :         ProcessLine( pabyLine, 0, nXSize-1, nBands, nDstBands, nNearDist, nMaxNonBlack,
     301             200 :                      bNearWhite, panLastLineCounts, FALSE, TRUE );
     302                 :         
     303                 :         eErr = GDALDatasetRasterIO( hOutDS, GF_Write, 0, iLine, nXSize, 1, 
     304                 :                                     pabyLine, nXSize, 1, GDT_Byte, 
     305             200 :                                     nDstBands, NULL, nDstBands, nXSize * nDstBands, 1 );
     306             200 :         if( eErr != CE_None )
     307               0 :             break;
     308                 :         
     309             200 :         if (!bQuiet)
     310                 :             GDALTermProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, 
     311             150 :                             NULL, NULL );
     312                 :     }
     313                 : 
     314               4 :     CPLFree(pabyLine);
     315               4 :     CPLFree( panLastLineCounts );
     316                 : 
     317               4 :     GDALClose( hOutDS );
     318               4 :     if( hInDS != hOutDS )
     319               3 :         GDALClose( hInDS );
     320               4 :     GDALDumpOpenDatasets( stderr );
     321               4 :     CSLDestroy( argv );
     322               4 :     CSLDestroy( papszCreationOptions );
     323               4 :     GDALDestroyDriverManager();
     324                 :     
     325               4 :     return 0;
     326                 : }
     327                 : 
     328                 : /************************************************************************/
     329                 : /*                            ProcessLine()                             */
     330                 : /*                                                                      */
     331                 : /*      Process a single scanline of image data.                        */
     332                 : /************************************************************************/
     333                 : 
     334                 : static void ProcessLine( GByte *pabyLine, int iStart, int iEnd, int nSrcBands,
     335                 :                          int nDstBands,
     336                 :                          int nNearDist, int nMaxNonBlack, int bNearWhite,
     337                 :                          int *panLastLineCounts, 
     338                 :                          int bDoHorizontalCheck, 
     339             600 :                          int bDoVerticalCheck )
     340                 : 
     341                 : {
     342                 :     int iDir, i;
     343                 : 
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*      Vertical checking.                                              */
     346                 : /* -------------------------------------------------------------------- */
     347             600 :     if( bDoVerticalCheck )
     348                 :     {
     349             400 :         int nXSize = MAX(iStart+1,iEnd+1);
     350                 : 
     351           20400 :         for( i = 0; i < nXSize; i++ )
     352                 :         {
     353                 :             int iBand;
     354           20000 :             int bIsNonBlack = FALSE;
     355                 : 
     356                 :             // are we already terminated for this column?
     357           20000 :             if( panLastLineCounts[i] > nMaxNonBlack )
     358           16199 :                 continue;
     359                 : 
     360           14145 :             for( iBand = 0; iBand < nSrcBands; iBand++ )
     361                 :             {
     362                 : 
     363           10704 :                 if( bNearWhite )
     364                 :                 {
     365            1563 :                     if( (255 - pabyLine[i * nDstBands + iBand]) > nNearDist )
     366                 :                     {
     367              96 :                         bIsNonBlack = TRUE;
     368              96 :                         break;
     369                 :                     }
     370                 :                 }
     371                 :                 else
     372                 :                 {
     373            9141 :                     if( pabyLine[i * nDstBands + iBand] > nNearDist )
     374                 :                     {
     375             264 :                         bIsNonBlack = TRUE;
     376             264 :                         break;
     377                 :                     }
     378                 :                 }
     379                 :             }
     380                 : 
     381            3801 :             if( bIsNonBlack )
     382                 :             {
     383             360 :                 panLastLineCounts[i]++;
     384                 : 
     385             360 :                 if( panLastLineCounts[i] > nMaxNonBlack )
     386             360 :                     continue; 
     387                 :             }
     388                 :             else
     389            3441 :                 panLastLineCounts[i] = 0;
     390                 : 
     391           13764 :             for( iBand = 0; iBand < nSrcBands; iBand++ )
     392                 :             {
     393           10323 :                 if( bNearWhite )
     394            1467 :                     pabyLine[i * nDstBands + iBand] = 255;
     395                 :                 else
     396            8856 :                     pabyLine[i * nDstBands + iBand] = 0;
     397                 :             }
     398            3441 :             if( nSrcBands != nDstBands )
     399            2457 :                 pabyLine[i * nDstBands + nDstBands - 1] = 0;
     400                 :         }
     401                 :     }
     402                 : 
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Horizontal Checking.                                            */
     405                 : /* -------------------------------------------------------------------- */
     406             600 :     if( bDoHorizontalCheck )
     407                 :     {
     408             400 :         int nNonBlackPixels = 0;
     409                 : 
     410             400 :         if( iStart < iEnd )
     411             200 :             iDir = 1;
     412                 :         else
     413             200 :             iDir = -1;
     414                 : 
     415            2891 :         for( i = iStart; i != iEnd; i += iDir )
     416                 :         {
     417                 :             int iBand;
     418            2891 :             int bIsNonBlack = FALSE;
     419                 : 
     420           10394 :             for( iBand = 0; iBand < nSrcBands; iBand++ )
     421                 :             {
     422            7903 :                 if( bNearWhite )
     423                 :                 {
     424            1300 :                     if( (255 - pabyLine[i * nDstBands + iBand]) > nNearDist )
     425                 :                     {
     426             100 :                         bIsNonBlack = TRUE;
     427             100 :                         break;
     428                 :                     }
     429                 :                 }
     430                 :                 else
     431                 :                 {
     432            6603 :                     if( pabyLine[i * nDstBands + iBand] > nNearDist )
     433                 :                     {
     434             300 :                         bIsNonBlack = TRUE;
     435             300 :                         break;
     436                 :                     }
     437                 :                 }
     438                 :             }
     439                 : 
     440            2891 :             if( bIsNonBlack )
     441                 :             {
     442             400 :                 nNonBlackPixels++;
     443                 : 
     444             400 :                 if( nNonBlackPixels > nMaxNonBlack )
     445             400 :                     return;
     446                 :             }
     447                 :             else
     448            2491 :                 nNonBlackPixels = 0;
     449                 : 
     450            9964 :             for( iBand = 0; iBand < nSrcBands; iBand++ )
     451                 :             {
     452            7473 :                 if( bNearWhite )
     453            1200 :                     pabyLine[i * nDstBands + iBand] = 255;
     454                 :                 else
     455            6273 :                     pabyLine[i * nDstBands + iBand] = 0;
     456                 :             }
     457            2491 :             if( nSrcBands != nDstBands )
     458            1794 :                 pabyLine[i * nDstBands + nDstBands - 1] = 0;
     459                 :         }
     460                 :     }
     461                 : 
     462                 : }

Generated by: LTP GCOV extension version 1.5