Changeset 12529

Show
Ignore:
Timestamp:
10/24/07 20:37:12 (9 months ago)
Author:
warmerdam
Message:

Added LoadInterlacedChunk??() method to handle loading big interlaced
files in big chunks (100MB per chunk) (#1893).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • sandbox/warmerdam/1.4-esri/gdal/frmts/png/pngdataset.cpp

    r10646 r12529  
    101101    void        CollectMetadata(); 
    102102    CPLErr      LoadScanline( int ); 
     103    CPLErr      LoadInterlacedChunk( int ); 
    103104    void        Restart(); 
    104105 
     
    407408} 
    408409 
    409  
    410 /************************************************************************/ 
    411 /*                            LoadScanline()                            */ 
    412 /************************************************************************/ 
    413  
    414 CPLErr PNGDataset::LoadScanline( int nLine ) 
    415  
    416 
    417     int   i; 
    418     int   nPixelOffset; 
    419  
    420     CPLAssert( nLine >= 0 && nLine < GetRasterYSize() ); 
    421  
    422     if( nLine >= nBufferStartLine && nLine < nBufferStartLine + nBufferLines) 
    423         return CE_None; 
     410/************************************************************************/ 
     411/*                        LoadInterlacedChunk()                         */ 
     412/************************************************************************/ 
     413 
     414CPLErr PNGDataset::LoadInterlacedChunk( int iLine ) 
     415 
     416
     417    int nPixelOffset; 
    424418 
    425419    if( nBitDepth == 16 ) 
     
    428422        nPixelOffset = 1 * GetRasterCount(); 
    429423 
    430     if( setjmp( sSetJmpContext ) != 0 ) 
    431         return CE_Failure; 
    432  
    433 /* -------------------------------------------------------------------- */ 
    434 /*      If the file is interlaced, we will load the entire image        */ 
    435 /*      into memory using the high level API.                           */ 
    436 /* -------------------------------------------------------------------- */ 
    437     if( bInterlaced ) 
    438     { 
    439         png_bytep       *png_rows; 
    440          
    441         CPLAssert( pabyBuffer == NULL ); 
    442  
    443         if( nLastLineRead != -1 ) 
    444         { 
    445             Restart(); 
    446             if( setjmp( sSetJmpContext ) != 0 ) 
    447                 return CE_Failure; 
    448         } 
    449  
    450         nBufferStartLine = 0; 
    451         nBufferLines = GetRasterYSize(); 
     424/* -------------------------------------------------------------------- */ 
     425/*      Was is the biggest chunk we can safely operate on?              */ 
     426/* -------------------------------------------------------------------- */ 
     427#define MAX_PNG_CHUNK_BYTES 100000000 
     428 
     429    int         nMaxChunkLines =  
     430        MAX(1,MAX_PNG_CHUNK_BYTES / (nPixelOffset * GetRasterXSize())); 
     431    png_bytep  *png_rows; 
     432 
     433    if( nMaxChunkLines > GetRasterYSize() ) 
     434        nMaxChunkLines = GetRasterYSize(); 
     435 
     436/* -------------------------------------------------------------------- */ 
     437/*      Allocate chunk buffer, if we don't already have it from a       */ 
     438/*      previous request.                                               */ 
     439/* -------------------------------------------------------------------- */ 
     440    nBufferLines = nMaxChunkLines; 
     441    if( nMaxChunkLines + iLine > GetRasterYSize() ) 
     442        nBufferStartLine = GetRasterYSize() - nMaxChunkLines; 
     443    else 
     444        nBufferStartLine = iLine; 
     445 
     446    if( pabyBuffer == NULL ) 
     447    { 
    452448        pabyBuffer = (GByte *)  
    453             VSIMalloc(nPixelOffset*GetRasterXSize()*GetRasterYSize()); 
     449            VSIMalloc(nPixelOffset*GetRasterXSize()*nMaxChunkLines); 
    454450         
    455451        if( pabyBuffer == NULL ) 
     
    461457            return CE_Failure; 
    462458        } 
    463  
    464         png_rows = (png_bytep*)CPLMalloc(sizeof(png_bytep) * GetRasterYSize()); 
    465         for( i = 0; i < GetRasterYSize(); i++ ) 
    466             png_rows[i] = pabyBuffer + i * nPixelOffset * GetRasterXSize(); 
    467  
    468         png_read_image( hPNG, png_rows ); 
    469  
    470         CPLFree( png_rows ); 
    471  
    472         nLastLineRead = GetRasterYSize() - 1; 
    473  
     459#ifdef notdef 
     460        if( nMaxChunkLines < GetRasterYSize() ) 
     461            CPLDebug( "PNG",  
     462                      "Interlaced file being handled in %d line chunks.\n" 
     463                      "Performance is likely to be quite poor.", 
     464                      nMaxChunkLines ); 
     465#endif 
     466    } 
     467 
     468/* -------------------------------------------------------------------- */ 
     469/*      Do we need to restart reading?  We do this if we aren't on      */ 
     470/*      the first attempt to read the image.                            */ 
     471/* -------------------------------------------------------------------- */ 
     472    if( nLastLineRead != -1 ) 
     473    { 
     474        Restart(); 
     475        if( setjmp( sSetJmpContext ) != 0 ) 
     476            return CE_Failure; 
     477    } 
     478 
     479/* -------------------------------------------------------------------- */ 
     480/*      Allocate and populate rows array.  We create a row for each     */ 
     481/*      row in the image, but use our dummy line for rows not in the    */ 
     482/*      target window.                                                  */ 
     483/* -------------------------------------------------------------------- */ 
     484    int        i; 
     485    png_bytep  dummy_row = (png_bytep)CPLMalloc(nPixelOffset*GetRasterXSize()); 
     486    png_rows = (png_bytep*)CPLMalloc(sizeof(png_bytep) * GetRasterYSize()); 
     487 
     488    for( i = 0; i < GetRasterYSize(); i++ ) 
     489    { 
     490        if( i >= nBufferStartLine && i < nBufferStartLine + nBufferLines ) 
     491            png_rows[i] = pabyBuffer  
     492                + (i-nBufferStartLine) * nPixelOffset * GetRasterXSize(); 
     493        else 
     494            png_rows[i] = dummy_row; 
     495    } 
     496 
     497    png_read_image( hPNG, png_rows ); 
     498 
     499    CPLFree( png_rows ); 
     500    CPLFree( dummy_row ); 
     501 
     502    nLastLineRead = nBufferStartLine + nBufferLines - 1; 
     503 
     504    return CE_None; 
     505
     506 
     507/************************************************************************/ 
     508/*                            LoadScanline()                            */ 
     509/************************************************************************/ 
     510 
     511CPLErr PNGDataset::LoadScanline( int nLine ) 
     512 
     513
     514    int   nPixelOffset; 
     515 
     516    CPLAssert( nLine >= 0 && nLine < GetRasterYSize() ); 
     517 
     518    if( nLine >= nBufferStartLine && nLine < nBufferStartLine + nBufferLines) 
    474519        return CE_None; 
    475     } 
     520 
     521    if( nBitDepth == 16 ) 
     522        nPixelOffset = 2 * GetRasterCount(); 
     523    else 
     524        nPixelOffset = 1 * GetRasterCount(); 
     525 
     526    if( setjmp( sSetJmpContext ) != 0 ) 
     527        return CE_Failure; 
     528 
     529/* -------------------------------------------------------------------- */ 
     530/*      If the file is interlaced, we will load the entire image        */ 
     531/*      into memory using the high level API.                           */ 
     532/* -------------------------------------------------------------------- */ 
     533    if( bInterlaced ) 
     534        return LoadInterlacedChunk( nLine ); 
    476535 
    477536/* -------------------------------------------------------------------- */