LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/core - pcidskcreate.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 180 157 87.2 %
Date: 2011-12-18 Functions: 1 1 100.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the Create() function to create new PCIDSK files.
       4                 :  * 
       5                 :  ******************************************************************************
       6                 :  * Copyright (c) 2009
       7                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
       8                 :  *
       9                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      10                 :  * copy of this software and associated documentation files (the "Software"),
      11                 :  * to deal in the Software without restriction, including without limitation
      12                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13                 :  * and/or sell copies of the Software, and to permit persons to whom the
      14                 :  * Software is furnished to do so, subject to the following conditions:
      15                 :  *
      16                 :  * The above copyright notice and this permission notice shall be included
      17                 :  * in all copies or substantial portions of the Software.
      18                 :  *
      19                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      20                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      22                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      23                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      24                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      25                 :  * DEALINGS IN THE SOFTWARE.
      26                 :  ****************************************************************************/
      27                 : #include "pcidsk.h"
      28                 : #include "pcidsk_config.h"
      29                 : #include "pcidsk_types.h"
      30                 : #include "pcidsk_exception.h"
      31                 : #include "pcidsk_file.h"
      32                 : #include "pcidsk_georef.h"
      33                 : #include "core/pcidsk_utils.h"
      34                 : #include "segment/sysblockmap.h"
      35                 : #include <cassert>
      36                 : #include <cstdlib>
      37                 : #include <cstring>
      38                 : #include <cstdio>
      39                 : 
      40                 : using namespace PCIDSK;
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                               Create()                               */
      44                 : /************************************************************************/
      45                 : 
      46                 : /**
      47                 :  * Create a PCIDSK (.pix) file. 
      48                 :  *
      49                 :  * @param filename the name of the PCIDSK file to create.
      50                 :  * @param pixels the width of the new file in pixels.
      51                 :  * @param lines the height of the new file in scanlines.
      52                 :  * @param channel_count the number of channels to create.
      53                 :  * @param channel_types an array of types for all the channels, or NULL for
      54                 :  * all CHN_8U channels.
      55                 :  * @param options creation options (interleaving, etc)
      56                 :  * @param interfaces Either NULL to use default interfaces, or a pointer
      57                 :  * to a populated interfaces object. 
      58                 :  *
      59                 :  * @return a pointer to a file object for accessing the PCIDSK file. 
      60                 :  */
      61                 : 
      62                 : PCIDSKFile PCIDSK_DLL *
      63              54 : PCIDSK::Create( std::string filename, int pixels, int lines,
      64                 :                 int channel_count, eChanType *channel_types,
      65                 :                 std::string options, const PCIDSKInterfaces *interfaces )
      66                 : 
      67                 : {
      68                 : /* -------------------------------------------------------------------- */
      69                 : /*      Use default interfaces if none are passed in.                   */
      70                 : /* -------------------------------------------------------------------- */
      71              54 :     PCIDSKInterfaces default_interfaces;
      72              54 :     if( interfaces == NULL )
      73               0 :         interfaces = &default_interfaces;
      74                 : 
      75                 : /* -------------------------------------------------------------------- */
      76                 : /*      Default the channel types to all 8U if not provided.            */
      77                 : /* -------------------------------------------------------------------- */
      78              54 :     std::vector<eChanType> default_channel_types;
      79                 : 
      80              54 :     if( channel_types == NULL )
      81                 :     {
      82               2 :         default_channel_types.resize( channel_count+1, CHN_8U );
      83               2 :         channel_types = &(default_channel_types[0]);
      84                 :     }
      85                 :    
      86                 : /* -------------------------------------------------------------------- */
      87                 : /*      Validate parameters.                                            */
      88                 : /* -------------------------------------------------------------------- */
      89              54 :     const char *interleaving = NULL;
      90              54 :     std::string compression = "NONE";
      91              54 :     bool nozero = false;
      92              54 :     bool nocreate = false;
      93              54 :     bool externallink = false;
      94              54 :     int  blocksize = 127;
      95                 : 
      96              54 :     UCaseStr( options );
      97                 : 
      98              54 :     if(strncmp(options.c_str(),"PIXEL",5) == 0 )
      99               0 :         interleaving = "PIXEL";
     100              54 :     else if( strncmp(options.c_str(),"BAND",4) == 0 )
     101              50 :         interleaving = "BAND";
     102               4 :     else if( strncmp(options.c_str(),"TILED",5) == 0 )
     103                 :     {
     104               3 :         interleaving = "FILE";
     105               3 :         ParseTileFormat( options, blocksize, compression );
     106                 :     }
     107               1 :     else if( strncmp(options.c_str(),"FILE",4) == 0 )
     108                 :     {
     109               1 :         if( strncmp(options.c_str(),"FILENOCREATE",12) == 0 )
     110               0 :             nocreate = true;
     111               1 :         else if( strncmp(options.c_str(),"FILELINK",8) == 0 )
     112                 :         {
     113               0 :             nocreate = true;
     114               0 :             externallink = true;
     115                 :         }
     116               1 :         interleaving = "FILE";
     117                 :     }
     118                 :     else
     119                 :         ThrowPCIDSKException( "PCIDSK::Create() options '%s' not recognised.", 
     120               0 :                               options.c_str() );
     121                 : 
     122              54 :     if( strstr(options.c_str(),"NOZERO") != NULL )
     123               0 :         nozero = true;
     124                 : 
     125                 : /* -------------------------------------------------------------------- */
     126                 : /*      Validate the channel types.                                     */
     127                 : /* -------------------------------------------------------------------- */
     128              54 :     int channels[7] = {0,0,0,0,0,0,0};
     129                 :     int chan_index;
     130              54 :     bool regular = true;
     131                 : 
     132             145 :     for( chan_index=0; chan_index < channel_count; chan_index++ )
     133                 :     {
     134             171 :         if( chan_index > 0 
     135              40 :             && ((int) channel_types[chan_index]) 
     136              40 :                 < ((int) channel_types[chan_index-1]) )
     137               0 :             regular = false;
     138                 :         
     139              91 :         channels[((int) channel_types[chan_index])]++;
     140                 :     }
     141                 :     
     142              54 :     if( !regular && strcmp(interleaving,"FILE") != 0 )
     143                 :     {
     144                 :         ThrowPCIDSKException( 
     145                 :            "Requested mixture of band types not supported for interleaving=%s.",
     146               0 :            interleaving );
     147                 :     }
     148                 :     
     149                 : /* -------------------------------------------------------------------- */
     150                 : /*      Create the file.                                                */
     151                 : /* -------------------------------------------------------------------- */
     152              56 :     void *io_handle = interfaces->io->Open( filename, "w+" );
     153                 : 
     154              52 :     assert( io_handle != NULL );
     155                 : 
     156                 : /* ==================================================================== */
     157                 : /*      Establish some key file layout information.                     */
     158                 : /* ==================================================================== */
     159              52 :     int image_header_start = 1;                    // in blocks
     160              52 :     uint64 image_data_start, image_data_size=0;    // in blocks
     161              52 :     uint64 segment_ptr_start, segment_ptr_size=64; // in blocks
     162                 :     int pixel_group_size, line_size;               // in bytes
     163              52 :     int image_header_count = channel_count;
     164                 : 
     165                 : /* -------------------------------------------------------------------- */
     166                 : /*      Pixel interleaved.                                              */
     167                 : /* -------------------------------------------------------------------- */
     168              52 :     if( strcmp(interleaving,"PIXEL") == 0 )
     169                 :     {
     170                 :         pixel_group_size = 
     171               0 :             channels[0] + // CHN_8U
     172               0 :             channels[1] * DataTypeSize(CHN_16U) + 
     173               0 :             channels[2] * DataTypeSize(CHN_16S) + 
     174               0 :             channels[3] * DataTypeSize(CHN_32R) +
     175               0 :             channels[4] * DataTypeSize(CHN_C16U) +
     176               0 :             channels[5] * DataTypeSize(CHN_C16S) +
     177               0 :             channels[6] * DataTypeSize(CHN_C32R);
     178                 :             //channels[0] + channels[1]*2 + channels[2]*2 + channels[3]*4;
     179               0 :         line_size = ((pixel_group_size * pixels + 511) / 512) * 512;
     180               0 :         image_data_size = (((uint64)line_size) * lines) / 512;
     181                 : 
     182                 :         // TODO: Old code enforces a 1TB limit for some reason.
     183                 :     }
     184                 : 
     185                 : /* -------------------------------------------------------------------- */
     186                 : /*      Band interleaved.                                               */
     187                 : /* -------------------------------------------------------------------- */
     188              52 :     else if( strcmp(interleaving,"BAND") == 0 )
     189                 :     {
     190                 :         pixel_group_size = 
     191              48 :             channels[0] + // CHN_8U
     192              48 :             channels[1] * DataTypeSize(CHN_16U) + 
     193              48 :             channels[2] * DataTypeSize(CHN_16S) + 
     194              48 :             channels[3] * DataTypeSize(CHN_32R) +
     195              48 :             channels[4] * DataTypeSize(CHN_C16U) +
     196              48 :             channels[5] * DataTypeSize(CHN_C16S) +
     197             240 :             channels[6] * DataTypeSize(CHN_C32R);
     198                 :         // BAND interleaved bands are tightly packed.
     199                 :         image_data_size = 
     200              48 :             (((uint64)pixel_group_size) * pixels * lines + 511) / 512;
     201                 : 
     202                 :         // TODO: Old code enforces a 1TB limit for some reason.
     203                 :     }
     204                 : 
     205                 : /* -------------------------------------------------------------------- */
     206                 : /*      FILE/Tiled.                                                     */
     207                 : /* -------------------------------------------------------------------- */
     208               4 :     else if( strcmp(interleaving,"FILE") == 0 )
     209                 :     {
     210                 :         // For some reason we reserve extra space, but only for FILE.
     211               4 :         if( channel_count < 64 )
     212               4 :             image_header_count = 64;
     213                 : 
     214               4 :         image_data_size = 0;
     215                 : 
     216                 :         // TODO: Old code enforces a 1TB limit on the fattest band.
     217                 :     }
     218                 : 
     219                 : /* -------------------------------------------------------------------- */
     220                 : /*      Place components.                                               */
     221                 : /* -------------------------------------------------------------------- */
     222              52 :     segment_ptr_start = image_header_start + image_header_count*2;
     223              52 :     image_data_start = segment_ptr_start + segment_ptr_size;
     224                 : 
     225                 : /* ==================================================================== */
     226                 : /*      Prepare the file header.                                        */
     227                 : /* ==================================================================== */
     228              52 :     PCIDSKBuffer fh(512);
     229                 : 
     230                 :     char current_time[17];
     231              52 :     GetCurrentDateTime( current_time );
     232                 : 
     233                 :     // Initialize everything to spaces.
     234              52 :     fh.Put( "", 0, 512 );
     235                 : 
     236                 : /* -------------------------------------------------------------------- */
     237                 : /*      File Type, Version, and Size                                    */
     238                 : /*  Notice: we get the first 4 characters from PCIVERSIONAME. */
     239                 : /* -------------------------------------------------------------------- */
     240                 :     // FH1 - magic format string.
     241              52 :     fh.Put( "PCIDSK", 0, 8 );
     242                 : 
     243                 :     // FH2 - TODO: Allow caller to pass this in.
     244              52 :     fh.Put( "SDK V1.0", 8, 8 );
     245                 : 
     246                 :     // FH3 - file size later.
     247              52 :     fh.Put( (image_data_start + image_data_size), 16, 16 );
     248                 :     
     249                 :     // FH4 - 16 characters reserved - spaces.
     250                 : 
     251                 :     // FH5 - Description
     252              52 :     fh.Put( filename.c_str(), 48, 64 );
     253                 : 
     254                 :     // FH6 - Facility
     255              52 :     fh.Put( "PCI Inc., Richmond Hill, Canada", 112, 32 );
     256                 : 
     257                 :     // FH7.1 / FH7.2 - left blank (64+64 bytes @ 144)
     258                 : 
     259                 :     // FH8 Creation date/time
     260              52 :     fh.Put( current_time, 272, 16 );
     261                 : 
     262                 :     // FH9 Update date/time
     263              52 :     fh.Put( current_time, 288, 16 );
     264                 : 
     265                 : /* -------------------------------------------------------------------- */
     266                 : /*      Image Data                                                      */
     267                 : /* -------------------------------------------------------------------- */
     268                 :     // FH10 - start block of image data
     269              52 :     fh.Put( image_data_start+1, 304, 16 );
     270                 : 
     271                 :     // FH11 - number of blocks of image data.
     272              52 :     fh.Put( image_data_size, 320, 16 );
     273                 : 
     274                 :     // FH12 - start block of image headers.
     275              52 :     fh.Put( image_header_start+1, 336, 16 );
     276                 : 
     277                 :     // FH13 - number of blocks of image headers.
     278              52 :     fh.Put( image_header_count*2, 352, 8);
     279                 : 
     280                 :     // FH14 - interleaving.
     281              52 :     fh.Put( interleaving, 360, 8);
     282                 : 
     283                 :     // FH15 - reserved - MIXED is for some ancient backwards compatability.
     284              52 :     fh.Put( "MIXED", 368, 8);
     285                 : 
     286                 :     // FH16 - number of image bands.
     287              52 :     fh.Put( channel_count, 376, 8 );
     288                 : 
     289                 :     // FH17 - width of image in pixels.
     290              52 :     fh.Put( pixels, 384, 8 );
     291                 : 
     292                 :     // FH18 - height of image in pixels.
     293              52 :     fh.Put( lines, 392, 8 );
     294                 : 
     295                 :     // FH19 - pixel ground size interpretation.
     296              52 :     fh.Put( "METRE", 400, 8 );
     297                 :     
     298                 :     // TODO:
     299                 :     //PrintDouble( fh->XPixelSize, "%16.9f", 1.0 );
     300                 :     //PrintDouble( fh->YPixelSize, "%16.9f", 1.0 );
     301              52 :     fh.Put( "1.0", 408, 16 );
     302              52 :     fh.Put( "1.0", 424, 16 );
     303                 : 
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Segment Pointers                                                */
     306                 : /* -------------------------------------------------------------------- */
     307                 :     // FH22 - start block of segment pointers.
     308              52 :     fh.Put( segment_ptr_start+1, 440, 16 );
     309                 : 
     310                 :     // fH23 - number of blocks of segment pointers.
     311              52 :     fh.Put( segment_ptr_size, 456, 8 );
     312                 : 
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Number of different types of Channels                           */
     315                 : /* -------------------------------------------------------------------- */
     316                 :     // FH24.1 - 8U bands.
     317              52 :     fh.Put( channels[0], 464, 4 );
     318                 : 
     319                 :     // FH24.2 - 16S bands.
     320              52 :     fh.Put( channels[1], 468, 4 );
     321                 : 
     322                 :     // FH24.3 - 16U bands.
     323              52 :     fh.Put( channels[2], 472, 4 );
     324                 : 
     325                 :     // FH24.4 - 32R bands.
     326              52 :     fh.Put( channels[3], 476, 4 );
     327                 :     
     328                 :     // FH24.5 - C16U bands
     329              52 :     fh.Put( channels[4], 480, 4 );
     330                 :     
     331                 :     // FH24.6 - C16S bands
     332              52 :     fh.Put( channels[5], 484, 4 );
     333                 :     
     334                 :     // FH24.7 - C32R bands
     335              52 :     fh.Put( channels[6], 488, 4 );
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Write out the file header.                                      */
     339                 : /* -------------------------------------------------------------------- */
     340              52 :     interfaces->io->Write( fh.buffer, 512, 1, io_handle );
     341                 : 
     342                 : /* ==================================================================== */
     343                 : /*      Write out the image headers.                                    */
     344                 : /* ==================================================================== */
     345              52 :     PCIDSKBuffer ih( 1024 );
     346                 : 
     347              52 :     ih.Put( " ", 0, 1024 );
     348                 : 
     349                 :     // IHi.1 - Text describing Channel Contents
     350              52 :     ih.Put( "Contents Not Specified", 0, 64 );
     351                 : 
     352                 :     // IHi.2 - Filename storing image.
     353              52 :     if( strncmp(interleaving,"FILE",4) == 0 )
     354               4 :         ih.Put( "<unintialized>", 64, 64 );
     355                 :     
     356              52 :     if( externallink )
     357                 :     {
     358                 :         // IHi.6.7 - IHi.6.10
     359               0 :         ih.Put( 0, 250, 8 ); 
     360               0 :         ih.Put( 0, 258, 8 );
     361               0 :         ih.Put( pixels, 266, 8 );
     362               0 :         ih.Put( lines, 274, 8 );
     363                 :     }
     364                 : 
     365                 :     // IHi.3 - Creation time and date.
     366              52 :     ih.Put( current_time, 128, 16 );
     367                 : 
     368                 :     // IHi.4 - Creation time and date.
     369              52 :     ih.Put( current_time, 144, 16 );
     370                 : 
     371              52 :     interfaces->io->Seek( io_handle, image_header_start*512, SEEK_SET );
     372                 : 
     373             141 :     for( chan_index = 0; chan_index < channel_count; chan_index++ )
     374                 :     {
     375              89 :         ih.Put(DataTypeName(channel_types[chan_index]).c_str(), 160, 8);    
     376                 : 
     377              89 :         if( strncmp("TILED",options.c_str(),5) == 0 )
     378                 :         {
     379                 :             char sis_filename[65];
     380               3 :             sprintf( sis_filename, "/SIS=%d", chan_index );
     381               3 :             ih.Put( sis_filename, 64, 64 );
     382                 : 
     383                 :             // IHi.6.7 - IHi.6.10
     384               3 :             ih.Put( 0, 250, 8 ); 
     385               3 :             ih.Put( 0, 258, 8 );
     386               3 :             ih.Put( pixels, 266, 8 );
     387               3 :             ih.Put( lines, 274, 8 );
     388                 : 
     389                 :             // IHi.6.11
     390               3 :             ih.Put( 1, 282, 8 );
     391                 :         }
     392                 : 
     393              89 :         interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
     394                 :     }
     395                 : 
     396             304 :     for( chan_index = channel_count; 
     397                 :          chan_index < image_header_count; 
     398                 :          chan_index++ )
     399                 :     {
     400             252 :         ih.Put( "", 160, 8 );
     401             252 :         ih.Put( "<unintialized>", 64, 64 );
     402             252 :         ih.Put( "", 250, 40 );
     403                 : 
     404             252 :         interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
     405                 :     }
     406                 : 
     407                 : /* ==================================================================== */
     408                 : /*      Write out the segment pointers, all spaces.                     */
     409                 : /* ==================================================================== */
     410              52 :     PCIDSKBuffer segment_pointers( (int) (segment_ptr_size*512) );
     411              52 :     segment_pointers.Put( " ", 0, (int) (segment_ptr_size*512) );
     412                 : 
     413              52 :     interfaces->io->Seek( io_handle, segment_ptr_start*512, SEEK_SET );
     414                 :     interfaces->io->Write( segment_pointers.buffer, segment_ptr_size, 512, 
     415              52 :                            io_handle );
     416                 : 
     417                 : /* -------------------------------------------------------------------- */
     418                 : /*      Ensure we write out something at the end of the image data      */
     419                 : /*      to force the file size.                                         */
     420                 : /* -------------------------------------------------------------------- */
     421              52 :     if( image_data_size > 0 )
     422                 :     {
     423                 :         interfaces->io->Seek( io_handle, (image_data_start + image_data_size)*512-1,
     424              45 :                               SEEK_SET );
     425              45 :         interfaces->io->Write( "\0", 1, 1, io_handle );
     426                 :     }
     427                 :     
     428                 : /* -------------------------------------------------------------------- */
     429                 : /*      Close the raw file, and reopen as a pcidsk file.                */
     430                 : /* -------------------------------------------------------------------- */
     431              52 :     interfaces->io->Close( io_handle );
     432                 : 
     433              52 :     PCIDSKFile *file = Open( filename, "r+", interfaces );
     434                 : 
     435                 : /* -------------------------------------------------------------------- */
     436                 : /*      Create a default georeferencing segment.                        */
     437                 : /* -------------------------------------------------------------------- */
     438                 :     file->CreateSegment( "GEOref", 
     439                 :                          "Master Georeferencing Segment for File",
     440             104 :                          SEG_GEO, 6 );
     441                 : 
     442                 : /* -------------------------------------------------------------------- */
     443                 : /*      If the dataset is tiled, create the file band data.             */
     444                 : /* -------------------------------------------------------------------- */
     445             104 :     if( strncmp(options.c_str(),"TILED",5) == 0 )
     446                 :     {
     447               3 :         file->SetMetadataValue( "_DBLayout", options ); 
     448                 : 
     449                 :         // For sizing the SysBMDir we want an approximate size of the
     450                 :         // the imagery.
     451                 :         uint64 rough_image_size = 
     452               3 :             (channels[0] + // CHN_8U
     453               3 :              channels[1] * DataTypeSize(CHN_16U) + 
     454               3 :              channels[2] * DataTypeSize(CHN_16S) + 
     455               3 :              channels[3] * DataTypeSize(CHN_32R) +
     456               3 :              channels[4] * DataTypeSize(CHN_C16U) +
     457               3 :              channels[5] * DataTypeSize(CHN_C16S) +
     458               3 :              channels[6] * DataTypeSize(CHN_C32R)) 
     459              21 :             * (pixels * (uint64) lines);
     460               3 :         uint64 sysbmdir_size = ((rough_image_size / 8192) * 28) / 512;
     461                 : 
     462               3 :         sysbmdir_size = (int) (sysbmdir_size * 1.1 + 100);
     463                 :         int segment = file->CreateSegment( "SysBMDir", 
     464                 :                                            "System Block Map Directory - Do not modify.",
     465               3 :                                            SEG_SYS, sysbmdir_size );
     466                 :         
     467                 :         SysBlockMap *bm = 
     468               6 :             dynamic_cast<SysBlockMap *>(file->GetSegment( segment ));
     469                 : 
     470               6 :         for( chan_index = 0; chan_index < channel_count; chan_index++ )
     471                 :         {
     472                 :             bm->CreateVirtualImageFile( pixels, lines, blocksize, blocksize,
     473                 :                                         channel_types[chan_index], 
     474               3 :                                         compression );
     475                 :         }
     476                 :     }
     477                 : 
     478                 : /* -------------------------------------------------------------------- */
     479                 : /*      If we have a non-tiled FILE interleaved file, should we         */
     480                 : /*      create external band files now?                                 */
     481                 : /* -------------------------------------------------------------------- */
     482              52 :     if( strncmp(interleaving,"FILE",4) == 0 
     483                 :         && strncmp(options.c_str(),"TILED",5) != 0 
     484                 :         && !nocreate )
     485                 :     {
     486               2 :         for( chan_index = 0; chan_index < channel_count; chan_index++ )
     487                 :         {
     488               1 :             PCIDSKChannel *channel = file->GetChannel( chan_index + 1 );
     489               1 :             int pixel_size = DataTypeSize(channel->GetType());
     490                 : 
     491                 :             // build a band filename that uses the basename of the PCIDSK
     492                 :             // file, and adds ".nnn" based on the band. 
     493               1 :             std::string band_filename = filename;
     494                 :             char ext[5];
     495               1 :             sprintf( ext, ".%03d", chan_index+1 );
     496                 :             
     497               1 :             size_t last_dot = band_filename.find_last_of(".");
     498               1 :             if( last_dot != std::string::npos 
     499                 :                 && (band_filename.find_last_of("/\\:") == std::string::npos
     500                 :                     || band_filename.find_last_of("/\\:") < last_dot) )
     501                 :             {
     502               1 :                 band_filename.resize( last_dot );
     503                 :             }
     504                 : 
     505               1 :             band_filename += ext;
     506                 : 
     507                 :             // Now build a version without a path. 
     508               1 :             std::string relative_band_filename;
     509               1 :             size_t path_div = band_filename.find_last_of( "/\\:" );
     510               1 :             if( path_div == std::string::npos )
     511               0 :                 relative_band_filename = band_filename;
     512                 :             else
     513               1 :                 relative_band_filename = band_filename.c_str() + path_div + 1;
     514                 :             
     515                 :             // create the file - ought we write the whole file?
     516               1 :             void *band_io_handle = interfaces->io->Open( band_filename, "w" );
     517               1 :             interfaces->io->Write( "\0", 1, 1, band_io_handle );
     518               1 :             interfaces->io->Close( band_io_handle );
     519                 : 
     520                 :             // Set the channel header information.
     521                 :             channel->SetChanInfo( relative_band_filename, 0, pixel_size, 
     522               1 :                                   pixel_size * pixels, true );
     523                 :         }
     524                 :     }
     525                 : 
     526              52 :     return file;
     527                 : }

Generated by: LCOV version 1.7