static
int _TIFFPartialReadStripArray( TIFF* tif, TIFFDirEntry* dirent,
                                int strile, uint64* panVals )
{
    static const char module[] = "_TIFFPartialReadStripArray";
#define IO_CACHE_PAGE_SIZE 4096

    size_t sizeofval;
    const int bSwab = (tif->tif_flags & TIFF_SWAB) != 0;
    int sizeofvalint;
    uint64 nBaseOffset;
    uint64 nOffset;
    uint64 nOffsetStartPage;
    uint64 nOffsetEndPage;
    tmsize_t nToRead;
    tmsize_t nRead;
    uint64 nLastStripOffset;
    int iStartBefore;
    int i;
    const uint32 arraySize = tif->tif_dir.td_stripoffsetbyteallocsize;
    unsigned char buffer[2 * IO_CACHE_PAGE_SIZE];

    assert( dirent->tdir_count > 4 );

    if( dirent->tdir_type == TIFF_SHORT )
    {
        sizeofval = sizeof(uint16);
    }
    else if( dirent->tdir_type == TIFF_LONG )
    {
        sizeofval = sizeof(uint32);
    }
    else if( dirent->tdir_type == TIFF_LONG8 )
    {
        sizeofval = sizeof(uint64);
    }
    else if( dirent->tdir_type == TIFF_SLONG8 )
    {
        /* Non conformant but used by some images as in */
        /* https://github.com/OSGeo/gdal/issues/2165 */
        sizeofval = sizeof(int64);
    }
    else
    {
        TIFFErrorExt(tif->tif_clientdata, module,
                 "Invalid type for [Strip|Tile][Offset/ByteCount] tag");
        panVals[strile] = 0;
        return 0;
    }
    sizeofvalint = (int)(sizeofval);

    if( tif->tif_flags&TIFF_BIGTIFF )
    {
        uint64 offset = dirent->tdir_offset.toff_long8;
        if( bSwab )
            TIFFSwabLong8(&offset);
        nBaseOffset = offset;
    }
    else
    {
        uint32 offset = dirent->tdir_offset.toff_long;
        if( bSwab )
            TIFFSwabLong(&offset);
        nBaseOffset = offset;
    }
    /* To avoid later unsigned integer overflows */
    if( nBaseOffset > (uint64)TIFF_INT64_MAX )
    {
        TIFFErrorExt(tif->tif_clientdata, module,
                 "Cannot read offset/size for strile %d", strile);
        panVals[strile] = 0;
        return 0;
    }
    nOffset = nBaseOffset + sizeofval * strile;
    nOffsetStartPage =
        (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
    nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;

    if( nOffset + sizeofval > nOffsetEndPage )
        nOffsetEndPage += IO_CACHE_PAGE_SIZE;
#undef IO_CACHE_PAGE_SIZE

    nLastStripOffset = nBaseOffset + arraySize * sizeofval;
    if( nLastStripOffset < nOffsetEndPage )
        nOffsetEndPage = nLastStripOffset;
    if( nOffsetStartPage >= nOffsetEndPage )
    {
        TIFFErrorExt(tif->tif_clientdata, module,
                 "Cannot read offset/size for strile %d", strile);
        panVals[strile] = 0;
        return 0;
    }
    if (!SeekOK(tif,nOffsetStartPage))
    {
        panVals[strile] = 0;
        return 0;
    }

    nToRead = (tmsize_t)(nOffsetEndPage - nOffsetStartPage);
    nRead = TIFFReadFile(tif, buffer, nToRead);
    if( nRead < nToRead )
    {
        TIFFErrorExt(tif->tif_clientdata, module,
                 "Cannot read offset/size for strile around ~%d", strile);
        return 0;
    }
    iStartBefore = -(int)((nOffset - nOffsetStartPage) / sizeofval);
    if( strile + iStartBefore < 0 )
        iStartBefore = -strile;
    for( i = iStartBefore;
         (uint32)(strile + i) < arraySize &&
         _TIFFUnsanitizedAddUInt64AndInt(nOffset, (i + 1) * sizeofvalint) <= nOffsetEndPage;
         ++i )
    {
        if( dirent->tdir_type == TIFF_SHORT )
        {
            uint16 val;
            memcpy(&val,
                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
                   sizeof(val));
            if( bSwab )
                TIFFSwabShort(&val);
            panVals[strile + i] = val;
        }
        else if( dirent->tdir_type == TIFF_LONG )
        {
            uint32 val;
            memcpy(&val,
                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
                   sizeof(val));
            if( bSwab )
                TIFFSwabLong(&val);
            panVals[strile + i] = val;
        }
        else if( dirent->tdir_type == TIFF_LONG8 )
        {
            uint64 val;
            memcpy(&val,
                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
                   sizeof(val));
            if( bSwab )
                TIFFSwabLong8(&val);
            panVals[strile + i] = val;
        }
        else /* if( dirent->tdir_type == TIFF_SLONG8 ) */
        {
            /* Non conformant data type */
            int64 val;
            memcpy(&val,
                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
                   sizeof(val));
            if( bSwab )
                TIFFSwabLong8((uint64*) &val);
            panVals[strile + i] = (uint64) val;
        }
    }
    return 1;
}