来自 deflate“未知边缘案例”的畸形 PNG 像素数据

问题描述 投票:0回答:1

在过去的两个月里,我一直在实现一个 png/deflate 解码器,(出于各种原因但主要是出于学习目的)但在某些情况下只返回正确的预期数据。

在此表中,我收集了我一直用于该程序的文件(以及文件本身)的一些详细信息,以备您查看时使用:

状态 图片 方块型 Lz77 获得(如果失败) 标题信息(仅限块类型 2)
作品 Color checker pattern 2 HLIT: 29HDIST: 23HCLEN: 14Header cls: {0,3,3,3,3,4,0,4,0, 3,0,4,0,4,0,4,0,4}
作品 A grid with grayscale pixels 1
没用 10x10 noise image 2 0 0 0 1 2 257 4 0 3 1 4 0 5 6 7 8 0 9 10 11 0 12 0 3 0 13 14 1 15 0 1 16 17 258 - 此处失败 [ 9 11 ] - 程序尝试读取在 33 大小的列表上向后 36 个符号 HLIT: 2HDIST: 13HCLEN: 12Header cls: {2,4,4,4,0,2,0,4,0, 5,0,5,0,4,0,3}
没用 1 1 255 255 255 0 260 0 1 1 261 6 0 0 0 183 262 8 3 2 261 5 1 270 0 0 272 0 9 6 51 255 176 266 0 - 此处失败 [ 26 141 ] -程序尝试读取8334 个符号在 34 大小的列表中向后
返回格式错误的数据 Some random colors 2 可能有些数据格式不正确 HLIT: 4HDIST: 10HCLEN: 14Header cls: {0,4,3,3,0,0,0,3,0, 4,0,3,0,2,0,4,0,4}

这里是我如何实现 deflate 的一个片段(或 MRE)(该程序需要图像路径作为参数;我尽力让它以最少的代码行运行):

#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>

//Quick table for ll distinction
uint16_t qtfld[5][2] = {
    {269,1},{273,2},
    {277,3},{281,4},
    {285,5}
};

//Quick table for distance distinction
uint8_t qtfdd[13][2] = {
    {6,1},{8,2},{9,3},
    {12,4},{14,5},{16,6},
    {18,7},{20,8},{22,9},
    {24,10},{26,11},{28,12},
    {30,13}
};

uint32_t FlipEndian(
    uint32_t value,
    uint32_t SToFlip
){
    if(SToFlip==0){return 0;}
    else{
        uint32_t reversed = 0;
        for(uint32_t w = 0; w <= SToFlip; w++){
            uint32_t lshift = 0;
            uint32_t rshift = 0;
            lshift = value<<(31-w);
            rshift = lshift>>31;
            reversed = (rshift<<((SToFlip-1)-w)) | reversed;
        }
        return reversed;
    }
}

uint16_t** GenCodes(
    uint16_t* cl_table,
    uint16_t* symbol_table,
    uint32_t both_tables_size
){
    //Finaltable
    uint32_t sizecodes = both_tables_size * sizeof(uint16_t*);
    uint16_t** codes = (uint16_t**)malloc(sizecodes);

    for(uint32_t i=0; i<both_tables_size; i++){
        codes[i] = (uint16_t*)malloc(3*sizeof(uint16_t));
    }

    //List for the sorting and frequency obtaining of the cl codes
    uint32_t size = both_tables_size*sizeof(uint16_t);
    int16_t* used_cls = (int16_t*)malloc(size);

    for(uint32_t i=0; i<both_tables_size; i++){
        used_cls[i] = -1;
    }

    //The aforementioned sorted cl table
    uint32_t cl_amount = 15*sizeof(uint16_t*);
    uint16_t** sorted_cl_frequencies = (uint16_t**)malloc(cl_amount);

    for(uint32_t c=0; c<15; c++){
        sorted_cl_frequencies[c] = (uint16_t*)malloc(2*sizeof(uint16_t));
    }

    for(uint32_t i=0; i<both_tables_size; i++){
        uint16_t min_cl = 15;
        uint8_t cl_usage = 0;

        for(uint32_t j=0; j<both_tables_size; j++){
            uint16_t current_cl = cl_table[i];

            for(uint32_t k=0; k<both_tables_size; k++){
                if(current_cl == used_cls[k]){
                    cl_usage = 1;
                    break;
                }
            }

            if(cl_usage==0){
                if(current_cl<min_cl){min_cl = current_cl;}
            }
        }

        if(cl_usage==0){
            uint32_t cl_counter = 0;

            for(uint32_t a=0; a<both_tables_size; a++){
                if(cl_table[a]==min_cl){cl_counter++;}
            }

            sorted_cl_frequencies[min_cl][0] = min_cl;
            sorted_cl_frequencies[min_cl][1] = cl_counter;
            used_cls[i] = min_cl;
        }
    }

    //Huffman code algorithm
    uint16_t code = 0;

    for(uint32_t i = 1; i <= 15; i++) {
        if(i<15){
            uint16_t prevfreq = sorted_cl_frequencies[i-1][1];
            uint16_t prevcl = sorted_cl_frequencies[i][0];
            code = (code + prevfreq) << 1;

            uint16_t aum = 0; 

            for(uint32_t j = 0;j<both_tables_size;j++){
                if(prevcl==cl_table[j]){
                    codes[j][0] = symbol_table[j];
                    codes[j][1] = cl_table[j];
                    codes[j][2] = FlipEndian(code+aum,cl_table[j]);
                    aum+=1;
                }
            }
        }
    }

    for(uint8_t i=0; i<15; i++){
        free(sorted_cl_frequencies[i]);
    }    

    free(used_cls);
    free(sorted_cl_frequencies);
    return codes;
}

//OverallSlicedDataGathering
uint16_t OSDG(
    uint8_t* list, 
    uint32_t* biotl, //bitindexonthelist
    uint8_t sogd //sizeofgivendata
){
    uint32_t currentbyte = (uint32_t)floor((*biotl/8));
    uint32_t landingbyte = (uint32_t)floor((((*biotl-1)+sogd)/8));
    uint16_t final_data = 0;
   
    if(landingbyte>currentbyte){
        if(landingbyte>(currentbyte+1)){
            uint8_t bocb = 8-(*biotl%8);//bitsoncurrentbyte

            uint8_t slice1 = list[currentbyte]>>(8-bocb);

            uint8_t bonb = sogd-bocb;//bitsonnextbyte

            uint8_t slice2 = list[landingbyte] << (8-bonb);

            slice2 = slice2>>(8-bonb);

            uint16_t walls = 0;

            uint8_t middleslice = list[currentbyte+1];
            walls = (slice2<<(bocb+8)) | (middleslice<<bocb) | slice1;
            final_data = walls;
        }
        else{
            uint8_t bocb = 8-(*biotl%8);//bitsoncurrentbyte

            uint8_t slice1 = list[currentbyte]>>(8-bocb);

            uint8_t bonb = sogd-bocb;//bitsonnextbyte

            uint8_t slice2 = list[landingbyte] << (8-bonb);

            slice2 = slice2>>(8-bonb);

            uint16_t walls = 0;
            walls = (slice2<<(bocb)) | slice1;
            final_data = walls;
        }
    }
    else{
        //alongpartsifthereis
        uint8_t apiti = (*biotl%8)+sogd;
        
        //ShapedData
        uint8_t sd = list[currentbyte] << (8-apiti);

        sd = sd >> (8-sogd);
        final_data = (uint16_t)sd;
    }

    *biotl += sogd;
    return final_data; 
}

uint16_t* Obtain_CL_From_Bistream(
    uint16_t encoded_cls,
    uint16_t** codes,
    uint32_t size_of_codes,
    uint32_t* bit_index,
    uint8_t* idat_pointer
){
    uint32_t size = sizeof(uint16_t)*encoded_cls;
    uint16_t* finaltable = (uint16_t*)malloc(size);
    //skippedllsymbols
    int16_t sls = -1;
    
    for(uint16_t i=0; i<encoded_cls; i++){
        if(i>sls){
            for(uint32_t j=0; j<size_of_codes; j++){
                uint16_t cc = codes[j][2]; //currentcode
                uint16_t ccl = codes[j][1]; //currentcodelength
                uint16_t ccs = codes[j][0]; //currentcodesymbol

                //retrievedsymbolcodefrombitstream
                uint8_t rscfb = OSDG(idat_pointer,bit_index,ccl);

                *bit_index-= ccl;

                if(rscfb==cc){
                    *bit_index += ccl;
                    //amountofsymbols
                    uint16_t aos = 0;

                    if(ccs==16){
                        uint8_t ntb = OSDG(idat_pointer,bit_index,2);
                        aos = (ntb+3);

                        //previoussymbol
                        uint16_t ps = (uint16_t)(finaltable[i-1]);

                        for(uint16_t x=0 ;x<=aos; x++){
                            finaltable[i+x] = ps;
                        }
                    }
                    else if(ccs==17){
                        //nextthreebits
                        uint8_t ntrb = OSDG(idat_pointer,bit_index,3);
                        aos = (ntrb+3);

                        for(uint16_t x=0; x<=aos; x++){
                            finaltable[i+x] = (uint16_t)(0);
                        }
                    }
                    else if(ccs==18){
                        //nextsevenbits
                        uint8_t nsb = OSDG(idat_pointer,bit_index,7);
                        aos = (nsb+11);

                        for(uint16_t x=0; x<=aos; x++){
                            finaltable[i+x] = (uint16_t)(0);
                        }
                    }
                    else{
                        aos = 1;
                        finaltable[i] = (uint16_t)(ccs);
                    }
                    sls += aos;
                    break;
                }
            }
        }
    }
    return finaltable;
}

uint16_t* Uncompressed(
    uint32_t* bit_index,
    uint8_t* idat_pointer,
    uint32_t arbitrary_size
){
    *bit_index += 5;

    uint16_t len1 = idat_pointer[(uint32_t)floor((*bit_index/8))];
    uint16_t len2 = idat_pointer[(uint32_t)floor((*bit_index/8))+1];
    uint16_t LEN = (len1<<8)|(len2);

    *bit_index += 16;

    uint16_t nlen1 = idat_pointer[(uint32_t)floor((*bit_index/8))];
    uint16_t nlen2 = idat_pointer[(uint32_t)floor((*bit_index/8))+1];
    uint16_t NLEN = ~((nlen1<<8)|(nlen2));

    *bit_index += 16;

    uint32_t size = arbitrary_size*(sizeof(uint16_t));
    uint16_t* data = (uint16_t*)malloc(size);

    for(uint32_t i = 0; i<arbitrary_size; i++){
        data[i] = 0;
    }

    if(LEN==NLEN){
        for(uint32_t i = 0; i<arbitrary_size; i++){
            data[i] = OSDG(idat_pointer,bit_index,8);
        }
    }
    return data;
}

uint16_t* Static(
    uint32_t* bit_index,
    uint8_t* idat_pointer,
    uint32_t arbitrary_size
){
    uint32_t size = arbitrary_size*(sizeof(uint16_t));
    uint16_t* data = (uint16_t*)malloc(size);
    uint8_t EOT_found=0;

    for(uint32_t i=0; i<arbitrary_size; i++){
        if(EOT_found){break;}
        uint8_t ignore=0;

        //newobtainedfixedvaluefrombitstream
        int16_t nofvfb = (int16_t)OSDG(idat_pointer,bit_index,8);
        nofvfb = FlipEndian(nofvfb,8);
        *bit_index-=8;

        if((nofvfb-48)<=143 && (nofvfb-48)>=0){
            *bit_index+=8;
            data[i] = (nofvfb-48);
            ignore=1;
        }
        nofvfb = (int16_t)OSDG(idat_pointer,bit_index,9);
        nofvfb = FlipEndian(nofvfb,9);
        *bit_index-=9;

        if((nofvfb-256)<=255 && (nofvfb-256)>=144){
            if(ignore==0){
                data[i] = (nofvfb-256);
                *bit_index+=9;
                ignore=1;
            }
        }
        nofvfb = (int16_t)OSDG(idat_pointer,bit_index,7);
        nofvfb = FlipEndian(nofvfb,7);
        *bit_index-=7;

        if((nofvfb+256)<=279 && (nofvfb+256)>=256){
            if(ignore==0){
                *bit_index+=7;
                if((nofvfb+256)!=256){
                    data[i] = (nofvfb+256);
                    ignore=1;

                    if((nofvfb+256)>264 && (nofvfb+256)<285){
                        for(uint32_t j=0;j<5;j++){
                            if((nofvfb+256)<qtfld[j][0]){
                                i+=1;
                                //readoffsetbitsoflength
                                uint8_t robol = (uint8_t)OSDG(idat_pointer,bit_index,qtfld[j][1]);
                                data[i] = robol;
                                break;
                            }
                        }
                    }
                    i+=1;

                    //distancereturnedvaluebybits
                    uint8_t drvbb = (uint8_t)OSDG(idat_pointer,bit_index,5);
                    drvbb = FlipEndian(drvbb,5);
                    data[i] = drvbb;

                    if(drvbb>3){
                        for(uint32_t k=0;k<13;k++){
                            if(drvbb<qtfdd[k][0]){
                                i+=1;
                                //readoffsetbitsofdistance
                                uint8_t robod = (uint8_t)OSDG(idat_pointer,bit_index,qtfdd[k][1]);
                                data[i] = robod;
                                break;
                            }
                        }
                    }
                }
                else{
                    data[i] = (nofvfb+256);
                    ignore=1;
                    EOT_found=1;
                }
            }
        }
    
        nofvfb = (int16_t)OSDG(idat_pointer,bit_index,8);
        nofvfb = FlipEndian(nofvfb,8);
        *bit_index-=8;

        if((nofvfb+88)<=287 && (nofvfb+88)>=280){
            if(ignore==0){
                *bit_index+=8;

                data[i] = (nofvfb+88);
                ignore=1;
                
                if((nofvfb+88)>264 && (nofvfb+88)<285){
                    for(uint32_t j=0;j<5;j++){
                        if((nofvfb+88)<qtfld[j][0]){
                            i+=1;
                            //readoffsetbitsoflength
                            uint8_t robol = (uint8_t)OSDG(idat_pointer,bit_index,qtfld[j][1]);
                            data[i] = robol;
                            break;
                        }
                    }
                }
                i+=1;

                //distancereturnedvaluebybits
                uint8_t drvbb = (uint8_t)OSDG(idat_pointer,bit_index,5);
                drvbb = FlipEndian(drvbb,5);
                data[i] = drvbb;

                if(drvbb>3){
                    for(uint32_t k=0;k<13;k++){
                        if(drvbb<qtfdd[k][0]){
                            i+=1;
                            //readoffsetbitsofdistance
                            uint8_t robod = (uint8_t)OSDG(idat_pointer,bit_index,qtfdd[k][1]);
                            data[i] = robod;
                            break;
                        }
                    }
                }
            }
        }
    }
    return data;
}

uint16_t* Dynamic(
    uint32_t* bit_index,
    uint8_t* idat_pointer,
    uint32_t arbitrary_size
){
    uint8_t HLIT = (uint8_t)OSDG(idat_pointer,bit_index,5);
    printf("\nHLIT: %d",HLIT);
    uint8_t HDIST = (uint8_t)OSDG(idat_pointer,bit_index,5);
    printf("\nHDIST: %d",HDIST);
    uint8_t HCLEN = (uint8_t)OSDG(idat_pointer,bit_index,4);
    printf("\nHCLEN: %d",HCLEN);
    uint16_t newcl_clorder[19] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
    //List of CLs
    uint16_t* CL_cl_lengths = (uint16_t*)malloc(sizeof(uint16_t)*(HCLEN + 4));

    printf("\nHeader cls\n");
    uint8_t not_zero_cls_counter = 0;
    for(uint32_t i = 0; i < (HCLEN + 4); i++){
        uint8_t CL_cl = (uint8_t)OSDG(idat_pointer,bit_index,3);

        CL_cl_lengths[newcl_clorder[i]] = CL_cl;
        printf("%d,",CL_cl_lengths[newcl_clorder[i]]);
        if(CL_cl!=0){
            not_zero_cls_counter++;
        }
    }

    uint32_t size = sizeof(uint16_t)*not_zero_cls_counter;
    //sorted header cl symbols
    uint16_t* shcs = (uint16_t*)malloc(size);
    //sorted header cl cl
    uint16_t* shcc = (uint16_t*)malloc(size);

    int8_t* used_cls = (int8_t*)malloc(sizeof(int8_t)*not_zero_cls_counter);

    for(uint8_t i=0; i<not_zero_cls_counter; i++){used_cls[i]=-1;}

    for(uint8_t i=0; i<not_zero_cls_counter; i++){
        uint8_t smallestsymbol = 18;
        uint8_t smallestsymbol_index = 2;

        for(uint8_t j=0; j<(HCLEN + 4); j++){
            uint8_t used_cls_usage = 0;
            uint16_t newavailablesymbol = newcl_clorder[j];

            for(uint8_t k=0; k<not_zero_cls_counter; k++){
                if(newavailablesymbol==used_cls[k]){
                    used_cls_usage = 1;
                    break;
                }
            }

            if(used_cls_usage==0){
                uint8_t newsymbcl = CL_cl_lengths[newcl_clorder[j]];
                if(newavailablesymbol<smallestsymbol && newsymbcl != 0){
                    smallestsymbol = newavailablesymbol;
                    smallestsymbol_index = j;
                }
            }
        }

        shcs[i] = newcl_clorder[smallestsymbol_index];
        shcc[i] = CL_cl_lengths[newcl_clorder[smallestsymbol_index]];
        used_cls[i] = newcl_clorder[smallestsymbol_index];
    }

    uint16_t** header_cl_symbols = GenCodes(shcc,shcs,not_zero_cls_counter); 

    ///////////Obtainingofllcodes
    uint16_t* zeroed_ll_cls = Obtain_CL_From_Bistream(
        (257+HLIT),header_cl_symbols,
        not_zero_cls_counter,
        bit_index,idat_pointer
    );

    uint16_t* ll_cl = (uint16_t*)malloc(sizeof(uint16_t)*288);
    uint16_t* ll_symbols = (uint16_t*)malloc(sizeof(uint16_t)*288);

    //finalsizeofnotzeroedlls
    uint32_t fsonzl = 0;
    uint32_t ll_omitter = 0;

    for(uint32_t i=0; i<(257+HLIT);i++){
        if(zeroed_ll_cls[i]!=0){
            ll_cl[i-ll_omitter] = zeroed_ll_cls[i];
            ll_symbols[i-ll_omitter]=i;
            fsonzl+=1;
        }
        else{ll_omitter+=1;}
    }

    uint16_t** ll_codes = GenCodes(ll_cl,ll_symbols,fsonzl);
    printf("\nLL generated codes:");
    for(uint32_t l=0; l<fsonzl; l++){
        printf("\nsymbol: %d, ",ll_codes[l][0]);
        printf("cl: %d, ",ll_codes[l][1]);
        printf("code: %d",ll_codes[l][2]);
    }

    ///////////Obtainingofdistcodes
    uint16_t* zeroed_dist_cls = Obtain_CL_From_Bistream(
        (HDIST+1),header_cl_symbols,
        not_zero_cls_counter,
        bit_index,idat_pointer
    );

    uint16_t* dist_cl = (uint16_t*)malloc(sizeof(uint16_t)*32);
    uint16_t* dist_symbols = (uint16_t*)malloc(sizeof(uint16_t)*32);

    //finalsizeofnotzeroeddist
    uint32_t fsonzd = 0;
    uint32_t dist_omitter = 0;

    for(uint32_t i=0; i<(HDIST+1);i++){
        if(zeroed_dist_cls[i]!=0){
            dist_cl[i-dist_omitter] = zeroed_dist_cls[i];
            dist_symbols[i-dist_omitter] = i;
            fsonzd+=1;
        }
        else{dist_omitter+=1;}
    }

    uint16_t** dist_codes = GenCodes(dist_cl,dist_symbols,fsonzd);
    printf("\nDistance generated codes:");
    for(uint32_t d=0; d<fsonzd; d++){
        printf("\nsymbol: %d, ",dist_codes[d][0]);
        printf("cl: %d, ",dist_codes[d][1]);
        printf("code: %d",dist_codes[d][2]);
    }

    ///////////bitstreamdecryption

    uint32_t bsize = arbitrary_size*(sizeof(uint16_t));
    uint16_t* data = (uint16_t*)malloc(bsize);

    for(uint32_t i=0; i<arbitrary_size; i++){data[i]=0;}

    int ofsfld = -1;
    uint8_t megabreak = 0;

    for(int i=0; i<arbitrary_size; i++){
        if(megabreak==1){break;}
        if(i>ofsfld){
            for(uint16_t j=0; j<=fsonzl; j++){
                uint16_t cc = ll_codes[j][2]; //currentcode
                uint16_t ccl = ll_codes[j][1]; //currentcodelength
                uint16_t ccs = ll_codes[j][0]; //currentcodesymbol

                //retrievedllsymbolcodefrombistream
                uint16_t rlscfb = OSDG(idat_pointer,bit_index,ccl);
                *bit_index -= ccl;

                if(rlscfb==cc){
                    *bit_index += ccl;
                    data[i] = ccs;
                    ofsfld+=1;

                    if(ccs==256){megabreak=1;break;}
                    if(ccs>256){
                        uint8_t aum = 0;
                                
                        if(ccs>264 && ccs!=285){
                            for(uint8_t t=0; t<5; t++){
                                if(ccs<qtfld[t][0]){
                                    //readoffset
                                    data[(i+1)] = OSDG(idat_pointer,bit_index,qtfld[t][1]);
                                    aum=1;
                                    ofsfld+=1;
                                    break;
                                }
                            }
                        }

                        for(uint32_t k=0; k<=fsonzd; k++){
                            uint16_t dcc = dist_codes[k][2]; //distancecc
                            uint16_t dccl = dist_codes[k][1]; //distanceccl
                            uint16_t dccs = dist_codes[k][0]; //distanceccs

                            //retrieveddistancesymbolcodefrombistream
                            uint8_t rdscfb = OSDG(idat_pointer,bit_index,dccl);
                            *bit_index -= dccl;

                            if(rdscfb==dcc){
                                *bit_index += dccl;
                                ofsfld += 1;

                                data[(i+(1+aum))] = dccs;

                                if(dccs>3){
                                    for(uint8_t e=0; e<13; e++){
                                        if(dccs<qtfdd[e][0]){
                                            //readoffset
                                            data[(i+(2+aum))] = OSDG(idat_pointer,bit_index,qtfdd[e][1]);
                                            ofsfld += 1;
                                            break;
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }
                    break;
                }
            }
        }
    }

    for(uint8_t i=0; i<not_zero_cls_counter; i++){
        free(header_cl_symbols[i]);
    }   
    free(header_cl_symbols);

    free(CL_cl_lengths);
    free(shcs);
    free(shcc);
    free(used_cls);
    
    free(ll_symbols);
    free(ll_cl);

    for(uint8_t i=0; i<fsonzl; i++){
        free(ll_codes[i]);
    }
    free(ll_codes);

    free(dist_symbols);
    free(dist_cl);

    for(uint8_t i=0; i<fsonzd; i++){
        free(dist_codes[i]);
    }
    free(dist_codes);

    return data;
}

uint16_t lengthAr[29][2] = {
    {257,3},    {258,4},
    {259,5},    {260,6},
    {261,7},    {262,8},
    {263,9},    {264,10},    
    {265,11},    {266,13},    
    {267,15},    {268,17},    
    {269,19},    {270,23},    
    {271,27},    {272,31},    
    {273,35},    {274,43},    
    {275,51},    {276,59},    
    {277,67},    {278,83},    
    {279,99},    {280,115},    
    {281,131},    {282,163},    
    {283,195},    {284,227},    
    {285,258}
};

uint16_t distanceAr[30][2] = {
    {0,1},    {1,2},
    {2,3},    {3,4},
    {4,5},    {5,7},
    {6,9},    {7,13},
    {8,17},    {9,25},
    {10,33},    {11,49},
    {12,65},    {13,97},
    {14,129},    {15,193},
    {16,257},    {17,385},
    {18,513},    {19,769},
    {20,1025},    {21,1537},
    {22,2049},    {23,3073},
    {24,4097},    {25,6145},
    {26,8193},    {27,12289},
    {28,16385},    {29,24577}
};

uint8_t* Lz77(
    uint16_t* lz77_pointer,
    uint32_t arbitrary_size
){
    //currentindexfordecrypteddata
    uint32_t cifdd = 0;

    uint8_t* data = (uint8_t*)malloc(arbitrary_size*sizeof(uint8_t));

    //lengtharraysizeonvariable
    uint16_t lason = (uint16_t)floor((sizeof(lengthAr)/sizeof(lengthAr[0])));

    //distancearraysizeonvariable
    uint16_t dason = (uint16_t)floor((sizeof(distanceAr)/sizeof(distanceAr[0])));

    uint8_t megabreak = 0;

    for(uint32_t i=0; i<arbitrary_size; i++){
        printf("\ndata at %d: %d",i,lz77_pointer[i]);
        if(lz77_pointer[i]==256 || megabreak==1){break;}
        if(lz77_pointer[i]>256){
            uint32_t rs = 0; //repeatsize
            int dtg = 0; //distancetogo

            for(uint16_t j=0; j<lason; j++){
                if(lz77_pointer[i]==lengthAr[j][0]){
                    i+=1;

                    //offsetbitslength
                    uint16_t obl = 0;
                    if(lengthAr[j][0]>264 && lengthAr[j][0] != 285){
                        obl = lz77_pointer[i];
                        i+=1;
                    }

                    rs = (lengthAr[j][1])+obl;

                    for(uint16_t k=0; k<dason; k++){
                        if(lz77_pointer[i]==distanceAr[k][0]){
                            uint16_t obd = 0;

                            if(distanceAr[k][0]>3){
                                i+=1;
                                obd = lz77_pointer[i];
                            }

                            dtg = (distanceAr[k][1])+obd;
                            break;
                        }
                    }
                    break;
                }
            }

            printf("\nLength: %d",rs);
            printf("\nDistance: %d",dtg);

            int backpos = cifdd-dtg;

            if(backpos<0){
                printf("\nERROR: Reading negative indexes");
                break;
            }

            for(uint32_t s=0; s<rs; s++){
                data[cifdd+s] = data[backpos+s];   
            }

            cifdd+=rs;
        }
        else{
            data[cifdd] = lz77_pointer[i];
            cifdd += 1;
        }
    }
    return data;
}

int main(
    int nop, //numberofparameters
    char** pl //parameterlist
){
    uint8_t png[32768];
    FILE* fp;
    fp = fopen(pl[1],"r");

    fread(png,sizeof(uint8_t),32768,fp);
    fclose(fp);

    uint32_t idatsize = 0;
    uint8_t* idatpointer = NULL;

    for(uint32_t i=8; i<32768; i++){
        uint32_t chunksize = (png[i]<<24)|(png[i+1]<<16)|(png[i+2]<<8)|(png[i+3]);
        
        i += 4;
        if(png[i]==73 && png[i+1]==68 && png[i+2]==65 && png[i+3]==84){
            idatpointer = (uint8_t*)malloc((chunksize-6)*sizeof(uint8_t));
        }

        i += 4;
        if(idatpointer!=NULL){
            for(uint32_t j=0;j<chunksize-4;j++){
                idatpointer[j] = png[(i+2)+j];
            }
            break;
        }

        i += chunksize;
        i += 3;
    }

    uint32_t imgx = (png[16]<<24)|(png[17]<<16)|(png[18]<<8)|(png[19]);
    uint32_t imgy = (png[20]<<24)|(png[21]<<16)|(png[22]<<8)|(png[23]);
    uint32_t colortype = png[25];

    uint8_t samples_per_pixel = 0;
    if(colortype==0){samples_per_pixel=1;}
    else if(colortype==2){samples_per_pixel=3;}
    else if(colortype==3){samples_per_pixel=1;}
    else if(colortype==4){samples_per_pixel=2;}
    else if(colortype==6){samples_per_pixel=4;}
    
    uint32_t bit = 0;
    uint8_t islastbit = (uint8_t)OSDG(idatpointer,&bit,1);
    uint8_t btype = (uint8_t)OSDG(idatpointer,&bit,2);
    printf("\nbtype: %d",btype);

    uint16_t* lz77_pointer = NULL;
    uint32_t arbitrary_size = (((imgx*imgy)*samples_per_pixel)+imgy)+idatsize;

    if(btype==0){lz77_pointer = Uncompressed(&bit,idatpointer,arbitrary_size);}
    else if(btype==1){lz77_pointer = Static(&bit,idatpointer,arbitrary_size);}
    else if(btype==2){lz77_pointer = Dynamic(&bit,idatpointer,arbitrary_size);}

    printf("\nLzz7 symbols: ");
    for(uint32_t i = 0; i<arbitrary_size; i++){
        printf("%d ",lz77_pointer[i]);
    }

    uint8_t* deencryped_data = Lz77(lz77_pointer,arbitrary_size);

    printf("\nDecompressed data: ");
    for(uint32_t i = 0; i<arbitrary_size; i++){
        printf("%d ",deencryped_data[i]);
    }

    int8_t c = getchar();
    free(deencryped_data);
    return 0;
}
c png deflate lz77
1个回答
1
投票

这里是块解码器的最小修复,以避免缓冲区溢出:

const uint8_t signature[8] = {137, 'P', 'N', 'G', '\r', '\n', 26, '\n' };
#define CHUNK_LENGTH_LEN 4
#define CHUNK_TYPE_LEN 4
#define CHUNK_CRC_LEN 4
#define COMPRESSION_METHOD_FLAGS_CODE_LEN 1
#define ADDITIONAL_FLAGS_CHECK_BITS_LEN 1
#define CHECK_VALUE_LEN 4

// ...
    uint8_t *idatpointer = NULL;
    for(uint32_t i=sizeof(signature);;) {
        uint32_t chunksize = (png[i]<<24)|(png[i+1]<<16)|(png[i+2]<<8)|(png[i+3]);
        i += CHUNK_LENGTH_LEN;

        if(!strncmp((char *) png + i, "IDAT", CHUNK_TYPE_LEN)) {
            idatpointer = png + i + CHUNK_TYPE_LEN + COMPRESSION_METHOD_FLAGS_CODE_LEN + ADDITIONAL_FLAGS_CHECK_BITS_LEN;
        }
        if(!strncmp((char *) png + i, "IEND", CHUNK_TYPE_LEN))
            break;
        i += CHUNK_TYPE_LEN;
        i += chunksize;
        i += CHUNK_CRC_LEN;
    }

就像原来的一样,它不处理多个 IDAT 块。

我一直在测试 10x10 噪声图像,它似乎是 blocktype 1(不是表中所示的 2)。

Static(&bit,idatpointer,arbitrary_size)
的结果(您打印的数据与十进制相同,而不是十六进制):

(gdb) x/55xh lz77_pointer
0x55555555b890: 0x0072  0x011e  0x0011  0x0024  0x0108  0x0002  0x0114  0x0002
0x55555555b8a0: 0x0010  0x0062  0x001b  0x000c  0x0117  0x0000  0x000e  0x0028
0x55555555b8b0: 0x005e  0x0068  0x000b  0x0089  0x00bf  0x00ee  0x011f  0x0019
0x55555555b8c0: 0x004d  0x007a  0x0024  0x00a2  0x0100  0x0000  0x0000  0x0000
0x55555555b8d0: 0x0000  0x0000  0x0000  0x0000  0x0000  0x0000  0x0000  0x0000
0x55555555b8e0: 0x0000  0x0000  0x0000  0x0000  0x0000  0x0000  0x0000  0x0000
0x55555555b8f0: 0x0000  0x0000  0x0000  0x0000  0x0000  0x0000  0x0000

与我将 96 字节的 IDAT 块数据写入文件然后使用

pigz -d < idat.in | xxd
解压缩得到的结果不匹配:

00000000: 0000 0001 0200 0000 0301 0400 0506 0708  ................
00000010: 0009 0a0b 000c 0003 000d 0e01 0f00 0110  ................
00000020: 1100 0000 0312 1314 1514 030a 0016 1718  ................
00000030: 0300 0000 191a 1b00 0114 1c01 1d1e 031f  ................
00000040: 1400 0014 1401 2000 2122 0023 2400 2500  ...... .!".#$.%.
00000050: 2627 0100 0028 0329 0003 2a2b 142c 002d  &'...(.)..*+.,.-
00000060: 2e00 2f00 1430 0000 0114 3132 0133       ../..0....12.3

请注意,我没有在每个扫描行上反转过滤字节 (0x00)1(即删除第 10i 个字节)。如果我这样做,前 4 个字节将是:0x00 0x00 0x01 0x02 显然不匹配 0x00 0x72 x01 0x1e.

查看DEFLATE Compressed Data Format Specification version 1.3那些神奇的数字看起来适合固定霍夫曼代码(3.2.6),除了

if((nofvfb+256)>264 && (nofvfb+256)<285){
 if((nofvfb+88)<=287 && (nofvfb+88)>=280 && !ignore){
块,但我还没有研究它。这应该可以帮助您向前迈出一大步。我不知道为什么在比较点亮值之前需要添加这些偏移量。如果你想使用你自己的 LZ77 实现,我建议你独立测试它。您也可以考虑使用 zlib(或其他现有的实现,而不是编写您的至少一个垫脚石。

© www.soinside.com 2019 - 2024. All rights reserved.