Newer
Older
Import / research / video-compression / block / decompress / decompress.cpp
/*
 * =====================================================================================
 *
 *       Filename:  build-table.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  03/04/2011 22:11:22
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  John Ryland (jryland), jryland@xiaofrog.com
 *        Company:  InvertedLogic
 *
 * =====================================================================================
 */
#include <QApplication>
#include <QPixmap>
#include <QImage>
#include <stdio.h>
#include "../dct.h"


unsigned char clamp(int x)
{
    if (x < 0)
        return 0;
    if (x > 255)
        return 255;
    return x;
}

void readImage(FILE *f, unsigned char *image)
{
    int prevBlockDCT[64];
    memset(prevBlockDCT, 0, 64*sizeof(int));

    for (int j = 0; j < 32; j++) {
        for (int i = 0; i < 32; i++) {
            unsigned char method = 0;
            unsigned char bpp = 0;
            unsigned char lut_count = 0;
            unsigned char min = 255;
            unsigned char scale = 0;
            fread(&method, 1, 1, f);
            bpp = (method >> 3) & 0x7;
            method = (method >> 6) & 0x3;

            if ( method == 0 ) {
                fread(&min, 1, 1, f);
                if ( bpp == 0 ) {
                    for (int y = 0; y < 16; y++)
                        for (int x = 0; x < 16; x++) {
                            image[512*(j*16+y)+i*16+x] = min;
                        }
                } else {
                    for (int y = 0; y < 16; y++)
                        for (int x = 0; x < 16; x+=(8/bpp)) {
                            unsigned char pix = 0;
                            fread(&pix, 1, 1, f);
                            for (int k = 0; k < (8/bpp); k++) {
                                image[512*(j*16+y)+i*16+x+(8/bpp)-k-1] = (pix & ((1<<bpp)-1)) + min;
                                pix >>= bpp;
                            }
                        } 
                }
            } else if ( method == 1 ) {
                fread(&lut_count, 1, 1, f);
                unsigned char lut[256];
                for (unsigned int c = 0; c < lut_count; c++) {
                    unsigned char ch;
                    fread(&ch, 1, 1, f);
                    lut[c] = ch;
                }
                if ( bpp == 0 ) {
                } else {
                    for (int y = 0; y < 16; y++)
                        for (int x = 0; x < 16; x+=(8/bpp)) {
                            unsigned char pix = 0;
                            fread(&pix, 1, 1, f);
                            for (int k = 0; k < (8/bpp); k++) {
                                image[512*(j*16+y)+i*16+x+(8/bpp)-k-1] = lut[(pix & ((1<<bpp)-1))];
                                pix >>= bpp;
                            }
                        }
                }
            } else {

                for (int s1 = 0; s1 < 2; s1++) {
                    for (int t1 = 0; t1 < 2; t1++) {
                        int blockDCT[64];
                        memset(blockDCT, 0, 64*sizeof(int));

                        unsigned long long zeros = 0;
                        fread(&zeros, 8, 1, f);

                        unsigned char b2;
                        //fread(&b2, 1, 1, f);
                        int bitsBuffered = 0;
                        unsigned long bits = 0;

                        for (int x = 0; x < 64; x++) {


                            if ( zeros & (1LL << (63-x)) ) {
                                blockDCT[x] = 0;
                            } else {
                                //fread(&b2, 1, 1, f);
                                //blockDCT[x] = (signed char)b2;

// 0x0001

#if 1
                                int count = 0;
                                 //   bitsBuffered -= 5;
                                 //   count += 5;
                                if (bitsBuffered == 0) {
                                    fread(&b2, 1, 1, f);
                                    bits = (bits << 8) | b2;
                                    bitsBuffered += 8;
                                }
                                while ( ((bits & (1 << (bitsBuffered-1))) == 0) && (count < 8) ) {
                                    count++;
                                    bitsBuffered--;
                                    if (bitsBuffered == 0) {
                                        fread(&b2, 1, 1, f);
                                        bits = (bits << 8) | b2;
                                        bitsBuffered += 8;
                                    }
                                }
                                int llut[8] = { -1, 1, -2, 2, -3, 3, -4, 4 };
                                //if ( ((bits & (1 << (bitsBuffered))) == 1) ) {
                                if ( count < 8 ) {
                                    bitsBuffered--;
                                    blockDCT[x] = llut[count];
                                } else {
                                    //bitsBuffered++;// += 8;
                                    if (bitsBuffered < 8) {
                                        fread(&b2, 1, 1, f);
                                        bits = (bits << 8) | b2;
                                        bitsBuffered += 8;
                                    }
                                    blockDCT[x] = (signed char)((bits >> (bitsBuffered-8)) & 0xFF);
                                    bitsBuffered -= 8;
                                }
#else
                                if (bitsBuffered < 8) {
                                    fread(&b2, 1, 1, f);
                                    bits <<= 8;
                                    bits |= b2;
                                    bitsBuffered += 8;
                                }
                                if ( bits & (1 << (bitsBuffered-1)) ) {
                                //if ( ((bits >> (bitsBuffered-1)) & (0xFF>>7) ) == 0x1 ) {
                                    blockDCT[x] = -1;
                                    bitsBuffered--;
                                } else if ( bits & (1 << (bitsBuffered-2)) ) {
                                //} else if ( ((bits >> ((unsigned)bitsBuffered-2)) & (0xFF>>6) ) == 0x1 ) {
                                    blockDCT[x] = (int)1;
                                    bitsBuffered -= 2;
                                //} else if ( bits & (1 << (bitsBuffered-3)) ) {
                                } else if ( ((bits >> (bitsBuffered-3)) & (0x7) ) == 0x1 ) {
                                    blockDCT[x] = -2;
                                    bitsBuffered -= 3;
                                //} else if ( bits & (1 << (bitsBuffered-4)) ) {
                                } else if ( ((bits >> (bitsBuffered-4)) & (0xF) ) == 0x1 ) {
                                    blockDCT[x] = 2;
                                    bitsBuffered -= 4;
                                //} else if ( bits & (1 << (bitsBuffered-5)) ) {
                                } else if ( ((bits >> (bitsBuffered-5)) & (0xFF>>3) ) == 0x1 ) {
                                    blockDCT[x] = -3;
                                    bitsBuffered -= 5;
                                //} else if ( bits & (1 << (bitsBuffered-6)) ) {
                                } else if ( ((bits >> (bitsBuffered-6)) & (0xFF>>2) ) == 0x1 ) {
                                    blockDCT[x] = 3;
                                    bitsBuffered -= 6;
                                } else if ( ((bits >> (bitsBuffered-7)) & (0xFF>>1) ) == 0x1 ) {
                                    blockDCT[x] = -4;
                                    bitsBuffered -= 7;
                                } else if ( ((bits >> (bitsBuffered-8)) & 0xFF) == 0x1 ) {
                                    blockDCT[x] = 4;
                                    bitsBuffered -= 8;
                                
                                } else {
                                    while (bitsBuffered < 16) {
                                        fread(&b2, 1, 1, f);
                                        bits <<= 8;
                                        bits |= b2;
                                        bitsBuffered += 8;
                                    }
                                    //blockDCT[x] = bits & (0xFF << (bitsBuffered-16));
                                    blockDCT[x] = (signed char)((bits >> (bitsBuffered-16)) & 0xFF);
                                    //if ( blockDCT[x] > 128 )
                                    //    blockDCT[x] = blockDCT[x] - 256;
                                    bitsBuffered -= 16;
                                }
#endif
                            }
                        }
                        /*
                        fread(&b2, 1, 1, f);
                        if (b2 != 0xAB) 
                        {
                            if (b2 != 0xFF) {
                                printf("framing error %i != %i\n", b2, 0xFF);
                                exit(-1);
                            }
                            fread(&b2, 1, 1, f);
                            if (b2 != 0xAB) {
                                printf("framing error %i != %i\n", b2, 0xAB);
                                exit(-1);
                            }
                        }
                        */

                        blockDCT[0] += prevBlockDCT[0];
                        blockDCT[2] += blockDCT[1];

                        for (int x = 0; x < 64; x++)
                            prevBlockDCT[x] = blockDCT[x];

                        int pixels[64];
                        decodeDCT(blockDCT, pixels);
                        for (int y = 0; y < 8; y++)
                            for (int x = 0; x < 8; x++) 
                                image[512*(j*16+y+s1*8)+i*16+x+t1*8] = clamp(pixels[y*8+x]);
                    }
                }

/*
                for (int s1 = 0; s1 < 2; s1++) {
                    for (int t1 = 0; t1 < 2; t1++) {
                        int blockDCT[64];
                        memset(blockDCT, 0, 64*sizeof(int));
                        unsigned char count;
                        fread(&count, 1, 1, f);
                        for (int x = 0; x < count; x++) {
                        //for (int x = 0; x < 64; x++) {
                            signed int ch;
                            fread(&ch, 4, 1, f);
                            blockDCT[x] = ch;
                        }
                        int pixels[64];
                        decodeDCT(blockDCT, pixels);
                        for (int y = 0; y < 8; y++)
                            for (int x = 0; x < 8; x++) 
                                image[512*(j*16+y+s1*8)+i*16+x+t1*8] = clamp(pixels[y*8+x]);
                    }
                }
*/

                /*
                fread(&min, 1, 1, f);
                fread(&scale, 1, 1, f);
                for (int y = 0; y < 16; y++)
                    for (int x = 0; x < 16; x+=2) {
                        unsigned char pix1;
                        unsigned char pix2;
                        fread(&pix1, 1, 1, f);
                        pix2 = pix1 & 0xF;
                        pix1 >>= 4;
                        pix2 <<= scale;
                        pix1 <<= scale;
                        pix2 += min;
                        pix1 += min;
                        image[512*(j*16+y)+i*16+x+0] = pix1;
                        image[512*(j*16+y)+i*16+x+1] = pix2;
                    }
                */
            }

        }
    }

}
/*
            unsigned char method = 0;
            unsigned char bpp = 0;
            unsigned char lut_count = 0;

            if ( range < 16 ) {
                method = (method << 6) | (bpp << 3) | lut_count;
                fwrite(&method, 1, 1, f);
                fwrite(&min, 1, 1, f);
                //fwrite(&scale, 1, 1, f);
                if ( bpp == 0 ) {
                } else {
                    for (int y = 0; y < 16; y++)
                        for (int x = 0; x < 16; x+=(8/bpp)) {
                            unsigned char pix = 0;
                            for (int k = 0; k < (8/bpp); k++)
                                pix = (pix << bpp) | (image[512*(j*16+y)+i*16+x+k] - min);
                            fwrite(&pix, 1, 1, f);
                        } 
                }
            } else if ( distinctValueCount < 16 ) {

                method = 1;
                //lut_count = (distinctValueCount + 1) / 2;
                method = (method << 6) | (bpp << 3) | lut_count;
                fwrite(&method, 1, 1, f);
                fwrite(&distinctValueCount, 1, 1, f);
                unsigned char lut[256];
                unsigned char t = 0;
                for (unsigned int c = 0; c <= 255; c++) {
                    if ( count[c] ) {
                        unsigned char ch = c;
                        fwrite(&ch, 1, 1, f);
                        lut[c] = t;
                        t++;
                    }
                }
                if ( bpp == 0 ) {
                } else {
                    for (int y = 0; y < 16; y++)
                        for (int x = 0; x < 16; x+=(8/bpp)) {
                            unsigned char pix = 0;
                            for (int k = 0; k < (8/bpp); k++)
                                pix = (pix << bpp) | lut[image[512*(j*16+y)+i*16+x+k]];
                            fwrite(&pix, 1, 1, f);
                        }
                }


                method = 2;
                method = (method << 6) | (bpp << 3) | lut_count;
                fwrite(&method, 1, 1, f);
                fwrite(&min, 1, 1, f);
                fwrite(&scale, 1, 1, f);
                for (int y = 0; y < 16; y++)
                    for (int x = 0; x < 16; x+=2) {
                        unsigned char pix1 = image[512*(j*16+y)+i*16+x+0];
                        unsigned char pix2 = image[512*(j*16+y)+i*16+x+1];
                        pix1 -= min;
                        pix1 >>= scale;
                        pix2 -= min;
                        pix2 >>= scale;
                        pix1 = (pix1 << 4) | pix2;
                        fwrite(&pix1, 1, 1, f);
                    }
            }
*/

void dumpImage(int s, unsigned char *image, int depth)
{
    QImage outputImage(s, s, QImage::Format_RGB888);
    for (int y = 0; y < s; y++) {
        for (int x = 0; x < s; x++) {
            unsigned char p = image[y*s+x];
            unsigned int p2 = p;
            p2 = (p2 << 16) | (p2 << 8) | p2;
            outputImage.setPixel(x, y, p2);
        }
    }
    outputImage.save(QString("output%1.png").arg(depth));
}

#include <math.h>

void compareImage(int s, unsigned char *image)
{
    unsigned int totalDiff = 0;
    QImage originalImage("original.png");
    QImage outputImage(s, s, QImage::Format_RGB888);
    int diffCounts[256];
    memset(diffCounts, 0, 256*sizeof(int));
    for (int y = 0; y < s; y++) {
        for (int x = 0; x < s; x++) {
            unsigned char p = image[y*s+x];
            unsigned char o = originalImage.pixel(x, y) & 0xFF;
            int px2 = p - o;
            //signed char py2 = px2 + ;
            unsigned char pi2 = px2 + 128;
            printf("%i,", px2);
            unsigned int p2 = (pi2 << 16) | (pi2 << 8) | pi2;
            outputImage.setPixel(x, y, p2);
            totalDiff += (int)fabs(px2);
            diffCounts[px2+128]++;
        }
    }
    FILE *fd = fopen("diff.img", "w");
    for (int y = 0; y < s; y++) {
        for (int x = 0; x < s; x++) {
            unsigned char p = image[y*s+x];
            unsigned char o = originalImage.pixel(x, y) & 0xFF;
            signed char px2 = (signed char)(p - o);
                                if ( c > -4 && c <= 4 ) {
                                    int llut[9] = { 7,5,3,1,0,2,4,6,8 };
                                    int t = llut[c + 4];
                                    bitsBuffered += t;
                                    bits <<= t;
                                    bits |= 1;
                                } else {
                                    bitsBuffered += 16;
                                    bits <<= 16;
                                    bits |= (unsigned char)(c & 0xFF);
                                }
                                while ( bitsBuffered >= 8 ) {
                                    unsigned long long b = (bits >> (bitsBuffered - 8)) & 0xFF;
                                    unsigned char b2 = (unsigned char)b;
                                    fwrite(&b2, 1, 1, f);
                                    bitsBuffered -= 8;
                                    //bits >>= 8;
                                }
            fwrite(&px2, 1, 1, fd);
        }
    }
    fclose(fd);
    for (int i = -16; i < 17; i++) {
        printf(" diff counts [%i] = %i\n", i, diffCounts[i+128]);
    }
    outputImage.save("difference.png");
    outputImage.save("difference.bmp");
    outputImage.save("difference.jpg");
    outputImage.save("difference.tif");
    printf("total diff: %i\n", totalDiff);
    printf("average diff: %i\n", totalDiff / (512*512));
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

printf("starting\n");
    initTables();

    const int size = 512*512;
    unsigned char *image = (unsigned char *)malloc(size);
printf("alloced mem\n");
    memset(image, 0, size);
printf("zeroed mem\n");

    FILE *f = fopen("blah.out", "r");
    //readTree(f, &headNode, 0, 512, 512, true);
    readImage(f, image);
    fclose(f);
printf("read tree\n");

    dumpImage(512, image, 0);
    compareImage(512, image);

    return 0;//app.exec();
}