在过去的2个月里,我一直在实现一个png/deflate解码器(出于各种原因,但主要是为了学习目的),但在某些情况下只返回正确的预期数据。
在这个表中,我收集了一些我在程序中使用的文件(和文件本身)的详细信息,以防您想要检查它们:
| 国家|图像|块型|获得Lz 77(如果未通过)|标题信息(仅限数据块类型2)|
| --------------|--------------|--------------|--------------|--------------|
| 作品|Color checker pattern|二||**HLIT:**29,**HDIST:**23,HCLEN:14,Header 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|二|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 17258 -此处失败[ 9 11 ]****-程序尝试在33大小的列表上向后读取36个符号|**HLIT:**2,**HDIST:**13,HCLEN:12,Header 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 272 0 9 6 51 255 176266 0 -在此处失败[ 26 141 ]****-程序尝试在34大小的列表上向后读取8334个符号||
| 返回格式错误的数据|Some random colors|二|可能有些数据格式不正确|**HLIT:**4,**HDIST:**10,**HCLEN:**14,Header 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;
}
1条答案
按热度按时间yhuiod9q1#
以下是块解码器避免缓冲区溢出的最小修复:
就像原来的一样,它不处理多个IDAT块。
我一直在测试10x10的噪声图像,它似乎是块类型1(而不是表中所示的2)。
来自
Static(&bit,idatpointer,arbitrary_size)
的结果(您打印的是十进制而不是十六进制的相同数据):与我将96字节的IDAT块数据写入文件,然后使用
pigz -d < idat.in | xxd
解压缩得到的结果不匹配:请注意,我没有在每条扫描线上反转过滤器字节(0x00)1(即移除第10i个字节)。如果我这样做,前4个字节将是:0x00 0x00 0x01 0x02,显然与0x00 0x72 x01 0x1e不匹配。
看看DEFLATE压缩数据格式规范1.3版,这些神奇的数字看起来对固定的霍夫曼码(3.2.6)来说是正确的,除了
if((nofvfb+256)>264 && (nofvfb+256)<285){
和if((nofvfb+88)<=287 && (nofvfb+88)>=280 && !ignore){
块,但我没有研究过它。这将帮助你向前迈出一大步。我不知道为什么你需要在比较点亮值之前添加这些偏移量。如果你想使用自己的LZ77实现,我建议你独立测试。你也可以考虑使用zlib(或其他现有的实现,而不是编写你的至少一个垫脚石。