static int compress_file_blockDependency(char* input_filename, char* output_filename, int compressionlevel)
{
    void* (*initFunction)       (const char*);
    int   (*compressionFunction)(void*, const char*, char*, int, int, int);
    int   (*nextBlockFunction)  (void*, char*, int);
    int   (*freeFunction)       (void*);
    void* ctx;
    unsigned long long filesize = 0;
    unsigned long long compressedfilesize = 0;
    unsigned int checkbits;
    char* in_buff, *in_blockStart;
    char* out_buff;
    FILE* finput;
    FILE* foutput;
    clock_t start, end;
    unsigned int blockSize, inputBufferSize;
    size_t sizeCheck, header_size;
    void* streamChecksumState=NULL;

    // Init
    start = clock();
    if ((displayLevel==2) && (compressionlevel>=3)) displayLevel=3;

    if (compressionlevel<3)
    {
        initFunction = LZ4IO_LZ4_createStream;
        compressionFunction = LZ4IO_LZ4_compress_limitedOutput_continue;
        nextBlockFunction = LZ4_saveDict;
        freeFunction = LZ4_free;
    }
    else
    {
        initFunction = LZ4_createHC;
        compressionFunction = LZ4_compressHC2_limitedOutput_continue;
        nextBlockFunction = LZ4IO_LZ4_slideInputBufferHC;
        freeFunction = LZ4_free;
    }

    get_fileHandle(input_filename, output_filename, &finput, &foutput);
    blockSize = LZ4S_GetBlockSize_FromBlockId (blockSizeId);

    // Allocate Memory
    inputBufferSize = 64 KB + blockSize;
    in_buff  = (char*)malloc(inputBufferSize);
    out_buff = (char*)malloc(blockSize+CACHELINE);
    if (!in_buff || !out_buff) EXM_THROW(31, "Allocation error : not enough memory");
    in_blockStart = in_buff + 64 KB;
    if (compressionlevel>=3) in_blockStart = in_buff;
    if (streamChecksum) streamChecksumState = XXH32_init(LZ4S_CHECKSUM_SEED);
    ctx = initFunction(in_buff);

    // Write Archive Header
    *(unsigned int*)out_buff = LITTLE_ENDIAN_32(LZ4S_MAGICNUMBER);   // Magic Number, in Little Endian convention
    *(out_buff+4)  = (1 & _2BITS) << 6 ;                             // Version('01')
    *(out_buff+4) |= (blockIndependence & _1BIT) << 5;
    *(out_buff+4) |= (blockChecksum & _1BIT) << 4;
    *(out_buff+4) |= (streamChecksum & _1BIT) << 2;
    *(out_buff+5)  = (char)((blockSizeId & _3BITS) << 4);
    checkbits = XXH32((out_buff+4), 2, LZ4S_CHECKSUM_SEED);
    checkbits = LZ4S_GetCheckBits_FromXXH(checkbits);
    *(out_buff+6)  = (unsigned char) checkbits;
    header_size = 7;
    sizeCheck = fwrite(out_buff, 1, header_size, foutput);
    if (sizeCheck!=header_size) EXM_THROW(32, "Write error : cannot write header");
    compressedfilesize += header_size;

    // Main Loop
    while (1)
    {
        unsigned int outSize;
        unsigned int inSize;

        // Read Block
        inSize = (unsigned int) fread(in_blockStart, (size_t)1, (size_t)blockSize, finput);
        if( inSize==0 ) break;   // No more input : end of compression
        filesize += inSize;
        DISPLAYLEVEL(3, "\rRead : %i MB   ", (int)(filesize>>20));
        if (streamChecksum) XXH32_update(streamChecksumState, in_blockStart, inSize);

        // Compress Block
        outSize = compressionFunction(ctx, in_blockStart, out_buff+4, inSize, inSize-1, compressionlevel);
        if (outSize > 0) compressedfilesize += outSize+4; else compressedfilesize += inSize+4;
        if (blockChecksum) compressedfilesize+=4;
        DISPLAYLEVEL(3, "==> %.2f%%   ", (double)compressedfilesize/filesize*100);

        // Write Block
        if (outSize > 0)
        {
            int sizeToWrite;
            * (unsigned int*) out_buff = LITTLE_ENDIAN_32(outSize);
            if (blockChecksum)
            {
                unsigned int checksum = XXH32(out_buff+4, outSize, LZ4S_CHECKSUM_SEED);
                * (unsigned int*) (out_buff+4+outSize) = LITTLE_ENDIAN_32(checksum);
            }
            sizeToWrite = 4 + outSize + (4*blockChecksum);
            sizeCheck = fwrite(out_buff, 1, sizeToWrite, foutput);
            if (sizeCheck!=(size_t)(sizeToWrite)) EXM_THROW(33, "Write error : cannot write compressed block");
        }
        else   // Copy Original
        {
            * (unsigned int*) out_buff = LITTLE_ENDIAN_32(inSize|0x80000000);   // Add Uncompressed flag
            sizeCheck = fwrite(out_buff, 1, 4, foutput);
            if (sizeCheck!=(size_t)(4)) EXM_THROW(34, "Write error : cannot write block header");
            sizeCheck = fwrite(in_blockStart, 1, inSize, foutput);
            if (sizeCheck!=(size_t)(inSize)) EXM_THROW(35, "Write error : cannot write block");
            if (blockChecksum)
            {
                unsigned int checksum = XXH32(in_blockStart, inSize, LZ4S_CHECKSUM_SEED);
                * (unsigned int*) out_buff = LITTLE_ENDIAN_32(checksum);
                sizeCheck = fwrite(out_buff, 1, 4, foutput);
                if (sizeCheck!=(size_t)(4)) EXM_THROW(36, "Write error : cannot write block checksum");
            }
        }
        {
            size_t sizeToMove = 64 KB;
            if (inSize < 64 KB) sizeToMove = inSize;
            nextBlockFunction(ctx, in_blockStart - sizeToMove, (int)sizeToMove);
            if (compressionlevel>=3) in_blockStart = in_buff + 64 KB;
        }
    }

    // End of Stream mark
    * (unsigned int*) out_buff = LZ4S_EOS;
    sizeCheck = fwrite(out_buff, 1, 4, foutput);
    if (sizeCheck!=(size_t)(4)) EXM_THROW(37, "Write error : cannot write end of stream");
    compressedfilesize += 4;
    if (streamChecksum)
    {
        unsigned int checksum = XXH32_digest(streamChecksumState);
        * (unsigned int*) out_buff = LITTLE_ENDIAN_32(checksum);
        sizeCheck = fwrite(out_buff, 1, 4, foutput);
        if (sizeCheck!=(size_t)(4)) EXM_THROW(37, "Write error : cannot write stream checksum");
        compressedfilesize += 4;
    }

    // Status
    end = clock();
    DISPLAYLEVEL(2, "\r%79s\r", "");
    DISPLAYLEVEL(2, "Compressed %llu bytes into %llu bytes ==> %.2f%%\n",
        (unsigned long long) filesize, (unsigned long long) compressedfilesize, (double)compressedfilesize/filesize*100);
    {
        double seconds = (double)(end - start)/CLOCKS_PER_SEC;
        DISPLAYLEVEL(4, "Done in %.2f s ==> %.2f MB/s\n", seconds, (double)filesize / seconds / 1024 / 1024);
    }

    // Close & Free
    freeFunction(ctx);
    free(in_buff);
    free(out_buff);
    fclose(finput);
    fclose(foutput);

    return 0;
}