wavemain.cpp

来自「this is source code for image compressio」· C++ 代码 · 共 802 行 · 第 1/2 页

CPP
802
字号
    image.LoadRawFile(fname,512,512);

    // transform.
    Wavelet *cw = &wAntonini;
    cw->Transform(image,NSTEPS);

    //printf("Number of zeros = %d\n",image.SetZeroBelow(2.0));

    // init some subband data & alloc memory for data in each subband
    struct stBlock *subband = new struct stBlock[NBANDS];
    AllocSubBands(image, subband, NSTEPS);

    // separate subband data & find max & min values in each subband.
    InitSubBands(image, subband);

    // Find the bitallocation for the bands
    int *BitAllocation = new int[NBANDS];
    double TargetRate = 0.32;                   // BitsPerPixel for the target image.
    CalcBitAllocation(subband, BitAllocation, NBANDS, 12, TargetRate);
    //int BitAllocation[] = {7,7,6,7,6,5,5,5,4,4,4,4,3,2,0,0};

    // quantize all the coeffs into the 'symbols' array.
    for(i=0; i<=NBANDS-1; i++)
    {
        int nLevels = (1<<BitAllocation[i]);
        UniformQuant *uq = new UniformQuant(subband[i].maxcoeff, subband[i].mincoeff, nLevels);
        subband[i].uq = uq;

        double *coeffs = subband[i].coeffs;
        unsigned int *symbols = subband[i].symbols;

        for(int j=subband[i].ncoeffs; j>0; j--)
            *symbols++ = uq->Symbol(*coeffs++);
    }

    // open the output file.
    FILE *fp = fopen("wletn.cmp","wb");
    BitStream bs(fp);

    // write the file header.
    bs.WriteBits(image.width, 16);
    bs.WriteBits(image.height, 16);
    bs.WriteBits(NSTEPS, 16);

    // write each band of data.
    for(i=0; i<NBANDS; i++)
    {
        unsigned int nlevels = (1<<BitAllocation[i]);
        UniformQuant *uq = subband[i].uq;

        // write quantizer header.
        uq->WriteHeader(bs);

        // write the symbols.
        if (nlevels>1)      // if nlevels==1, then all symbols are the same
        {                   // hence no need to write them to the file.
            ArithEncoder aec(&bs);
            aec.SetNumSyms(nlevels);
            aec.InitEncode();

            unsigned int *symbols = subband[i].symbols;
            for(j = subband[i].ncoeffs; j>0; j--)
            {
                aec.Encode(*symbols++);
            }

            aec.Flush();
        }
    }
    bs.Flush();
    fclose(fp);

    delete[] BitAllocation;
    FreeSubbands(subband, NBANDS);
    for(i=0; i<NBANDS; i++)
        delete subband[i].uq;
    delete[] subband;
}

//------------------------------------------------------------//
//------------------------------------------------------------//
void zerotree_decode(char *fname)
{
    FILE *fp = fopen(fname,"rb");
    BitStream bs(fp);
    int i;

    //read in the file header.
    int imwidth = bs.ReadBits(16);
    int imheight = bs.ReadBits(16);
    int nsteps = bs.ReadBits(16);
    int nbands = nsteps*3+1;

    // create an empty image.
    Image image;
    image.InitEmptyImage(imwidth, imheight);

    // allocate memory for each subband.
    struct stBlock *subband = new struct stBlock[nbands];
    AllocSubBands(image, subband, nsteps);

    // alloc mem for the sigmap.
    unsigned char *SigMap = new unsigned char[imwidth * imheight];
    for(i=0; i<imwidth*imheight; i++)
        SigMap[i]=-1;

    // read the sigmap.
    ArithDecoder SigmapAdc(&bs);
    SigmapAdc.SetNumSyms(3);
    SigmapAdc.InitDecode();
    for(i=0; i<nbands; i++)
    {
        // parent subband index.
        int pband = ((i-3)>0)?i-3:0;
        for(int y=0; y<subband[i].height; y++)
        {
            for(int x=0; x<subband[i].width; x++)
            {
                if (i==0)       // no zerotrees for root subband.
                {
                    SigMap[(subband[i].y+y)*imwidth+(subband[i].x+x)]=SigmapAdc.Decode();
                }
                else
                {
                    // is the parent symbol not a zerotree root?
                    if (SigMap[(subband[pband].y+(y/2))*imwidth+(subband[pband].x+(x/2))] != 2)
                    {
                        SigMap[(subband[i].y+y)*imwidth+(subband[i].x+x)]=SigmapAdc.Decode();
                    }
                    else    // mark this also as a zerotree root (for its children)
                        SigMap[(subband[i].y+y)*imwidth+(subband[i].x+x)]=2;
                }
            }
        }
    }

    // readin the symbols.
    for(i=0; i<nbands; i++)
    {
        // read in the quantizer header.
        UniformQuant *uq = new UniformQuant();
        uq->ReadHeader(bs);
        subband[i].uq = uq;
        int nlevels = uq->nLevels/2;

        unsigned int *symbols = subband[i].symbols;

        unsigned int zeroSymbol = uq->Symbol(0.0);
        if (nlevels <=1)
        {
            for(int y=0; y<subband[i].height; y++)
                for(int x=0; x<subband[i].width; x++)
                    *symbols++ = zeroSymbol;
        }
        else
        {
            ArithDecoder adc(&bs);
            adc.SetNumSyms(nlevels);
            adc.InitDecode();

            for(int y=0; y<subband[i].height; y++)
            {
                for(int x=0; x<subband[i].width; x++)
                {
                    unsigned int symbol;
                    // insignificant symbol?
                    if (i!=0 && SigMap[(subband[i].y+y)*imwidth+(subband[i].x+x)]==2)
                        symbol = zeroSymbol;
                    else
                        symbol = adc.Decode();

                    *symbols++ = symbol;
                }
            }
        }

        // dequantize
        double *coeffs = subband[i].coeffs;
        symbols = subband[i].symbols;
        int xx=0;
        for(int y=0; y<subband[i].height; y++)
        {
            for(int x=0; x<subband[i].width; x++)
            {
                // reconstruct the MSB
                if (SigMap[(subband[i].y+y)*imwidth+(subband[i].x+x)]==1)
                {
                    *symbols = *symbols | nlevels;
                }
                *coeffs = uq->Value(*symbols++);
                coeffs++;
            }
        }
        image.SetData(subband[i].x, subband[i].y, subband[i].width, subband[i].height, subband[i].coeffs);
    }
    fclose(fp);

    // take inverse transform.
    Wavelet *cw = &wAntonini;
    cw->Inverse(image, nsteps);
    image.SaveRawFile("wletz.raw");

    delete[] SigMap;
    FreeSubbands(subband, nbands);
    for(i=0; i<nbands; i++)
        delete subband[i].uq;
    delete[] subband;
}

//------------------------------------------------------------//
//------------------------------------------------------------//
void zerotree_encode(char *fname)
{
    int i;
    Image image;
    image.LoadRawFile(fname,512,512);

    // transform.
    Wavelet *cw = &wAntonini;
    cw->Transform(image,NSTEPS);

    //printf("Number of zeros = %d\n",image.SetZeroBelow(5.0));

    // init some subband data & alloc memory for data in each subband
    struct stBlock *subband = new struct stBlock[NBANDS];
    AllocSubBands(image, subband, NSTEPS);

    // separate subband data & find max & min values in each subband.
    InitSubBands(image, subband);

    // Find the bitallocation for the bands
    int *BitAllocation = new int[NBANDS];
    double TargetRate = 0.32;                   // BitsperPixel for the target image.

    CalcBitAllocation(subband, BitAllocation, NBANDS, 12, TargetRate);

    // alloc mem for the significance map.
    unsigned char *SigMap = new unsigned char[image.width*image.height];
    for(i=0; i<image.width*image.height; i++)
        SigMap[i] = -1;

    // quantize all the coeffs into the 'symbols' array.
    // also, find if there are any zerotrees, and mark them.
    for(i=NBANDS-1; i>=0; i--)
    {
        int nLevels = (1<<BitAllocation[i]);
        UniformQuant *uq = new UniformQuant(subband[i].maxcoeff, subband[i].mincoeff, nLevels);
        subband[i].uq = uq;

        double *coeffs = subband[i].coeffs;
        unsigned int *symbols = subband[i].symbols;

        // if this is the last subband in the pyramid, child=this itself.
        int childSubband = ((i+3)>=NBANDS)?i:i+3;

        unsigned int zeroSymbol = uq->Symbol(0.0);
        unsigned int zeroTreeSymbol = nLevels;
        unsigned int meanSymbol = uq->Symbol(subband[i].meancoeff);
        unsigned int *childSymbols = subband[childSubband].symbols;

        int childx=subband[childSubband].x;
        int childy=subband[childSubband].y;

        for(int y=0; y<subband[i].height; y++)
        {
            for(int x=0; x<subband[i].width; x++)
            {
                unsigned int symbol = uq->Symbol((*coeffs));

                // store the MSB in the SigMap.
                if (symbol > meanSymbol)         
                    SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)] = 1;
                else 
                    SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)] = 0;

                // not the root band?
                if (i!=0)
                {
                    // a zero? then we can look for zerotrees.
                    if (symbol == zeroSymbol)
                    {
                        // is this the last subband in the pyramid? then mark as zerotree.
                        if (childSubband == i)
                        {
                            symbol = zeroTreeSymbol;

                            // Set SigMap[...] = 2, indicating that this is a zerotree.
                            SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)] = 2;
                        }
                        // are ALL the children also zerotrees?
                        else if (SigMap[(childy+y*2  )*image.width+(childx+x*2  )] == 2 &&
                                 SigMap[(childy+y*2  )*image.width+(childx+x*2+1)] == 2 &&
                                 SigMap[(childy+y*2+1)*image.width+(childx+x*2  )] == 2 &&
                                 SigMap[(childy+y*2+1)*image.width+(childx+x*2+1)] == 2)
                        {
                            symbol = zeroTreeSymbol;
                            SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)] = 2;

                            // Set SigMap[...] = 3 for children, indicating to ignore them.
                            SigMap[(childy+y*2  )*image.width+(childx+x*2  )] = 3;
                            SigMap[(childy+y*2  )*image.width+(childx+x*2+1)] = 3;
                            SigMap[(childy+y*2+1)*image.width+(childx+x*2  )] = 3;
                            SigMap[(childy+y*2+1)*image.width+(childx+x*2+1)] = 3;
                        }
                    }
                }
                // remove the MSB (which is now encoded in the SigMap)
                symbol = (symbol & ((uq->nLevels-1)>>1));
                *symbols++ = symbol;
                
                // removing the MSB means removing the sign of the actual coefficient.
                *coeffs = fabs(*coeffs);
                coeffs++;
            }
        }
    }

    // open the output file.
    FILE *fp = fopen("wletz.cmp","wb");
    BitStream bs(fp);

    // write the file header.
    bs.WriteBits(image.width, 16);
    bs.WriteBits(image.height, 16);
    bs.WriteBits(NSTEPS, 16);

    // write the sigmap.
    ArithEncoder SigmapAec(&bs);
    SigmapAec.SetNumSyms(3);
    SigmapAec.InitEncode();
    for(i=0; i<NBANDS; i++)
    {
        for(int y=0; y<subband[i].height; y++)
        {
            for(int x=0; x<subband[i].width; x++)
            {
                // write the symbol only if it is not marked as ignorable.
                if (SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)] < 3)
                {
                    SigmapAec.Encode(SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)]);
                }
            }
        }
    }
    SigmapAec.Flush();
    printf("Number of bits to code the zerotree = %d\n",bs.numBitsWritten);
    
    // write the symbols into the file.
    for(i=0; i<NBANDS; i++)
    {
        UniformQuant *uq = subband[i].uq;
        unsigned int nLevels = uq->nLevels/2;

        // write band specific data.
        uq->WriteHeader(bs);

        if (nLevels>1)
        {
            ArithEncoder aec(&bs);
            aec.SetNumSyms(nLevels);
            aec.InitEncode();

            unsigned int *symbols = subband[i].symbols;
            for(int y=0; y<subband[i].height; y++)
            {
                for(int x=0; x<subband[i].width; x++)
                {
                    // write the symbol only if it is not a zerotree root or child.
                    if (SigMap[(subband[i].y+y)*image.width+(subband[i].x+x)] < 2)
                        aec.Encode(*symbols);
                    symbols++;
                }
            }
            aec.Flush();
        }
    }
    bs.Flush();
    printf("Total number of bits to code image = %d\n",bs.numBitsWritten);
    fclose(fp);

    delete[] BitAllocation;
    delete[] SigMap;
    FreeSubbands(subband, NBANDS);
    for(i=0; i<NBANDS; i++)
        delete subband[i].uq;
    delete[] subband;
}

//------------------------------------------------------------//
//------------------------------------------------------------//
int main()
{
    normal_encode("lena.raw");      // writes o/p to file wletn.cmp
    normal_decode("wletn.cmp");     // writes o/p to file wletn.raw

    zerotree_encode("lena.raw");    // writes o/p to file wletz.cmp
    zerotree_decode("wletz.cmp");   // writes o/p to file wletz.raw

    return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?