Index: bsb_read.c
===================================================================
--- bsb_read.c	(revision 16169)
+++ bsb_read.c	(working copy)
@@ -166,7 +166,7 @@
 BSBInfo *BSBOpen( const char *pszFilename )
 
 {
-    FILE	*fp;
+    FILE	*fp,*fpLineOffset;
     char	achTestBlock[1000];
     char        szLine[1000];
     int         i, bNO1 = FALSE;
@@ -412,10 +412,11 @@
     }
 
 /* -------------------------------------------------------------------- */
-/*      Initialize line offset list.                                    */
+/*      Initialize memory for line offset list.                         */
+/*      This also includes the offset for the offset list at the end    */
 /* -------------------------------------------------------------------- */
     psInfo->panLineOffset = (int *) 
-        VSIMalloc2(sizeof(int), psInfo->nYSize);
+        VSIMalloc2(sizeof(int), 1 + psInfo->nYSize);
     if (psInfo->panLineOffset == NULL)
     {
         CPLError( CE_Failure, CPLE_OutOfMemory, 
@@ -424,11 +425,76 @@
         BSBClose( psInfo );
         return NULL;
     }
-    for( i = 0; i < psInfo->nYSize; i++ )
-        psInfo->panLineOffset[i] = -1;
 
+/* -------------------------------------------------------------------- */
+/*       Open the file again to read the line offset list               */
+/* -------------------------------------------------------------------- */
+    fpLineOffset = VSIFOpenL( pszFilename, "rb" );
+    if( fpLineOffset == NULL )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed, 
+                  "Couldn't open file '%s' to build line offset list", pszFilename );
+    }
+    else
+    {
+        /* Seek fpLineOffset to point the last 4 byte integer which points
+	 * the offset of the first line */
+        if( VSIFSeekL( fpLineOffset, -4, SEEK_END ) != 0 )
+        {
+            /* This error need not lead to an abort. */
+            CPLError( CE_Failure, CPLE_FileIO,
+                "Problem while seeking to last integer in %s.", pszFilename );
+            if( fpLineOffset != NULL )
+                VSIFCloseL( fpLineOffset );
+        }
+        else
+        {
+            /* build the list from file's index table */
+            /* To overcome endian compatibility issues individual
+	     * bytes are being read instead of the whole integers. */
+            GByte k[4];
+	    int listIsOK = 1;
+            VSIFReadL(k, 1, 4, fpLineOffset);//last 4 bytes
+            if( VSIFSeekL( fpLineOffset,
+                        (psInfo->panLineOffset[psInfo->nYSize] = (k[0]<<24)+(k[1]<<16)+(k[2]<<8)+k[3]), SEEK_SET ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO, 
+                    "Seek to offset 0x%08x for first line offset failed.", 
+                    psInfo->panLineOffset[psInfo->nYSize]);
+            }
+            else
+            {
+                for(i=0; i < psInfo->nYSize ; i++)
+                {
+                    VSIFReadL(k, 1, 4, fpLineOffset);
+                    psInfo->panLineOffset[i] = (k[0]<<24)+(k[1]<<16)+(k[2]<<8)+k[3];
+                }
+                /* Simple checks for the integrity of the list */
+                for(i=0; i < psInfo->nYSize ; i++)
+                {
+                    if((psInfo->panLineOffset[i] < psInfo->panLineOffset[i+1] - psInfo->nXSize) ||
+				    (psInfo->panLineOffset[i] > psInfo->panLineOffset[i+1]))
+                    {
+                        listIsOK = 0;
+                        break;
+		    }
+                }
+                if( fpLineOffset != NULL )
+                    VSIFCloseL( fpLineOffset );
+		if(listIsOK)
+                    return psInfo;
+            }
+            if( fpLineOffset != NULL )
+                VSIFCloseL( fpLineOffset );
+        }
+    }
+
+    /* If we can't build the offset list for some reason we just
+     * initialize the offset list to indicate "no value" (except for the first). */
     psInfo->panLineOffset[0] = 
         VSIFTellL( fp ) - psInfo->nBufferSize + psInfo->nBufferOffset;
+    for( i = 1; i <= psInfo->nYSize; i++ )
+        psInfo->panLineOffset[i] = -1;
 
     return psInfo;
 }
@@ -503,6 +569,7 @@
 
 /************************************************************************/
 /*                          BSBReadScanline()                           */
+/* @param nScanline zero based line number                              */
 /************************************************************************/
 
 int BSBReadScanline( BSBInfo *psInfo, int nScanline, 
@@ -588,27 +655,36 @@
     
 /* -------------------------------------------------------------------- */
 /*      Read and expand runs.                                           */
+/*      If for some reason the buffer is not filled,                    */
+/*      just repeat the process until the buffer is filled.             */
 /* -------------------------------------------------------------------- */
-    while( (byNext = BSBGetc(psInfo,psInfo->bNO1)) != 0 )
+    while( (long) VSIFTellL( fp ) - psInfo->nBufferSize + psInfo->nBufferOffset <= psInfo->panLineOffset[nScanline+1] )
     {
-        int	nPixValue;
-        int     nRunCount, i;
+        while( (byNext = BSBGetc(psInfo,psInfo->bNO1)) != 0 )
+        {
+            int	    nPixValue;
+            int     nRunCount, i;
 
-        nPixValue = (byNext & byValueMask) >> nValueShift;
+            nPixValue = (byNext & byValueMask) >> nValueShift;
 
-        nRunCount = byNext & byCountMask;
+            nRunCount = byNext & byCountMask;
 
-        while( (byNext & 0x80) != 0 )
-        {
-            byNext = BSBGetc( psInfo, psInfo->bNO1 );
-            nRunCount = nRunCount * 128 + (byNext & 0x7f);
-        }
+            while( (byNext & 0x80) != 0 )
+            {
+                byNext = BSBGetc( psInfo, psInfo->bNO1 );
+                nRunCount = nRunCount * 128 + (byNext & 0x7f);
+            }
 
-        if( iPixel + nRunCount + 1 > psInfo->nXSize )
-            nRunCount = psInfo->nXSize - iPixel - 1;
+            if( iPixel + nRunCount + 1 > psInfo->nXSize )
+                nRunCount = psInfo->nXSize - iPixel - 1;
 
-        for( i = 0; i < nRunCount+1; i++ )
-            pabyScanlineBuf[iPixel++] = (unsigned char) nPixValue;
+            for( i = 0; i < nRunCount+1; i++ )
+            {
+                pabyScanlineBuf[iPixel++] = (unsigned char) nPixValue;
+                if(iPixel == psInfo->nXSize)
+                    break; /* Don't overwrite to the line buffer */
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -622,10 +698,12 @@
 
 /* -------------------------------------------------------------------- */
 /*      Remember the start of the next line.                            */
+/*      But only if it is not already known.                            */
 /* -------------------------------------------------------------------- */
     if( iPixel == psInfo->nXSize && nScanline < psInfo->nYSize-1 )
-        psInfo->panLineOffset[nScanline+1] = 
-            VSIFTellL( fp ) - psInfo->nBufferSize + psInfo->nBufferOffset;
+        if(psInfo->panLineOffset[nScanline+1] == -1)
+            psInfo->panLineOffset[nScanline+1] = 
+                VSIFTellL( fp ) - psInfo->nBufferSize + psInfo->nBufferOffset;
 
     if( iPixel != psInfo->nXSize )
     {

