¿La descompresión se detiene entre el archivo y el archivo de salida lleno de ceros (píxeles negros)?

StackOverflow https://stackoverflow.com/questions/8339118

Pregunta

Estoy tratando de aplicar la compresión DCT (transformación de coseno discreto) en un archivo BMP (mapa de bits). Tengo un archivo de CA que estoy ejecutando en Turbo C ++. Esto en realidad no se está comprimiendo, pero estaba tratando de implementar el DCT e IDCT. El código es el siguiente:

/*
the image to be compressed is a bmp with 24 bpp and
with name "college4.bmp" of dimensions 200*160 ie 25*20- 8*8 blocks
o/p is college2.dat
format: 8 bit signed integers starting rowwise from 0,0 to 8,8
the coefficients order is blue,green,red
for the block no 1 then 2 and soon
*/

#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define WIDTH 25
#define HEIGHT 20

typedef struct {
    unsigned int type;
    unsigned long int filesize;
    unsigned int reserved1,reserved2;
    unsigned long int offset;
} BMPHEAD;

typedef struct {
    unsigned long int infosize;
    unsigned long int width,height;
    unsigned int planes,bitsperpixel;
    unsigned long int compression;
    unsigned long int sizeimage;
    long int xpelspermeter,ypelspermeter;
    unsigned long int colorused,colorimportant;
} INFOHEAD;

typedef struct {
    char rgbquad[4];
} colortable;

BMPHEAD bmphead;
INFOHEAD infohead;
FILE *bmp_fp1,*bmp_fp2;
int buf[WIDTH][8][8][3],buf1[WIDTH][8][8][3];
float pi=3.14159265,DCTcoeff[8][8][8][8];

void generatedctcoeff() {
    int y, i, j, x;
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            for (x = 0; x < 8; x++) {
                for (y = 0; y < 8; y++) {
                    DCTcoeff[i][j][x][y] = cos(((2 * y + 1) * pi * j) / 16)
                            * cos(((2 * x + 1) * i * pi) / 16);
                }
            }
        }
    }
}

void outputtofile1() {                     // Write into college2.dat
    int i, j, x, y, blockno;              // One block at a time, buf contains pixel 
    int redcoef, greencoef, bluecoef;     // data of one row of blocks
    float gijred, gijgreen, gijblue, c, ci, cj;
    c = 1 / (sqrt(2));
    for (blockno = 0; blockno < WIDTH; blockno++) {
        for (i = 0; i < 8; i++) {
            for (j = 0; j < 8; j++) {
                gijred = 0;
                gijgreen = 0;
                gijblue = 0;
                for (x = 0; x < 8; x++) {
                    for (y = 0; y < 8; y++) {
                        gijblue = gijblue + DCTcoeff[i][j][x][y]
                                * buf[blockno][x][y][0];
                        gijgreen = gijgreen + DCTcoeff[i][j][x][y]
                                * buf[blockno][x][y][1];
                        gijred = gijred + DCTcoeff[i][j][x][y]
                                * buf[blockno][x][y][2];
                    }
                }
                ci = cj = 1.0;
                if (i == 0)
                    ci = c;
                if (j == 0)
                    cj = c;
                gijblue = ci * cj * gijblue / 4;
                gijgreen = ci * cj * gijgreen / 4;
                gijred = ci * cj * gijred / 4;
                bluecoef = (int) gijblue;
                greencoef = (int) gijgreen;
                redcoef = (int) gijred;
                fprintf(bmp_fp2, "%d %d %d ", bluecoef, greencoef, redcoef);
            }
        }
    } /* end of one block processing */
}

void compressimage() {
    int rowcount,x,y;
    bmp_fp1=fopen("college4.bmp","r");
    bmp_fp2=fopen("college2.dat","w");
    printf("generating coefficients...\n");
    generatedctcoeff();
    if(bmp_fp1==NULL) {
        printf("can't open");
        return;
    }
    printf("compressing....\n");
    fread(&bmphead,1,sizeof(bmphead),bmp_fp1);
    fread(&infohead,1,sizeof(infohead),bmp_fp1);
    fseek(bmp_fp1,bmphead.offset,SEEK_SET);
    for(rowcount=0;rowcount<HEIGHT;rowcount++) {
        for(y=0;y<8;y++) {
            for(x=0;x<infohead.width;x++) {
                buf[x/8][x%8][y][0]=(int)fgetc(bmp_fp1);
                buf[x/8][x%8][y][1]=(int)fgetc(bmp_fp1);
                buf[x/8][x%8][y][2]=(int)fgetc(bmp_fp1);
            }
        }
        outputtofile1();         //output contents of buf after dct to file
    }
    fclose(bmp_fp1);
    fclose(bmp_fp2);
}

void outputtofile2() {                                 //output buf to college3.bmp
    int i, j, x, y, blockno;                        // buf now contains coefficients
    float pxyred, pxygreen, pxyblue, c, ci, cj;     // a temp buffer buf1 used to 
    c = 1 / (sqrt(2));                              // store one row of block of
    for (blockno = 0; blockno < WIDTH; blockno++) { // decoded pixel values
        for (x = 0; x < 8; x++)
            for (y = 0; y < 8; y++) {
                pxyred = 0;
                pxygreen = 0;
                pxyblue = 0;
                for (j = 0; j < 8; j++) {
                    cj = 1.0;
                    if (j == 0)
                        cj = c;
                    for (i = 0; i < 8; i++) {
                        ci = 1.0;
                        if (i == 0)
                            ci = c;
                        pxyblue = pxyblue + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][0];
                        pxygreen = pxygreen + ci * cj
                        * DCTcoeff[i][j][y][x] * buf[blockno][i][j][1];
                        pxyred = pxyred + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][2];
                    }
                }
                pxyblue /= 4;
                pxygreen /= 4;
                pxyred /= 4;
                buf1[blockno][y][x][0] = pxyblue;
                buf1[blockno][y][x][1] = pxygreen;
                buf1[blockno][y][x][2] = pxyred;
            }
    }
    for (y = 0; y < 8; y++) {
        for (blockno = 0; blockno < WIDTH; blockno++)
            for (x = 0; x < 8; x++) {
                fprintf(bmp_fp2, "%c%c%c", (char) buf1[blockno][x][y][0],
                        (char) buf1[blockno][x][y][1],
                        (char) buf1[blockno][x][y][2]);
            }
    }
}

void uncompressimage() {
    int blue,green,red,rowcount,colcount,i,j;
    bmp_fp1=fopen("college2.dat","r");
    bmp_fp2=fopen("college3.bmp","w");
    printf("generating coefficients...\n");
    generatedctcoeff();
    if (bmp_fp1==NULL) {
        printf("open failed");
        return;
    }
    printf("uncompressing....\n");
    bmphead.type=0x4d42;
    bmphead.filesize=30518;
    bmphead.reserved1=0;
    bmphead.reserved2=0;
    bmphead.offset=sizeof(bmphead)+sizeof(infohead);
    infohead.infosize=sizeof(infohead);
    infohead.width=200;
    infohead.height=160;
    infohead.planes=1;
    infohead.bitsperpixel=24;
    infohead.compression=0;
    infohead.sizeimage=0;
    infohead.xpelspermeter=3780;
    infohead.ypelspermeter=3780;
    infohead.colorused=0;
    infohead.colorimportant=0;
    fwrite(&bmphead,sizeof(BMPHEAD),1,bmp_fp2);
    fwrite(&infohead,sizeof(INFOHEAD),1,bmp_fp2);
    for(rowcount=0;rowcount<HEIGHT;rowcount++) {
        for(colcount=0;colcount<WIDTH;colcount++) {
            for(i=0;i<8;i++) {
                for(j=0;j<8;j++) {
                    fscanf(bmp_fp1,"%d",&blue);
                    fscanf(bmp_fp1,"%d",&green);
                    fscanf(bmp_fp1,"%d",&red);
                    buf[colcount][i][j][0]=blue;
                    buf[colcount][i][j][1]=green;
                    buf[colcount][i][j][2]=red;
                }
            }
        }
        outputtofile2();
    }
    fclose(bmp_fp1);
    fclose(bmp_fp2);
}

int main() {
    printf("opening files...\n");
    compressimage();
    printf("opening files...again\n");
    uncompressimage();
    printf("successful decompression\nenter any key\n");
    return 0;
}

Aquí está la imagen que estoy usando como entradaInput image

(Imrry El sitio convirtió el BMP en PNG. Puede convertirlo de nuevo a BMP para usarlo) Aquí está la imagen que se genera:

Output which is incorrect

El archivo universitario3.bmp que se crea es de tamaño 200x160 y de 93.8 kb, pero hasta el cuarto de la imagen ha decodificado los coeficientes correctamente, pero luego el archivo está lleno de píxeles negros. He tomado una captura de pantalla del O/P, ya que decía que no es un BMP válido mientras cargaba. Estoy sentado en este problema desde febrero de 2004. Si alguien puede decirme donde hay un error, estaría muy agradecido. He analizado el archivo de salida y encontré un EOF directamente en el lugar donde los píxeles comienzan a ser negros. Leí otras preguntas sobre el tema y descubrí que los factores de conversión CI, CJ, se han utilizado de manera incorrecta. Mientras codificaba también me había confundido con los índices X, Y, I y J. Así que espero que este problema resuelva en unos días.

¿Fue útil?

Solución

Aparentemente, el problema en el código anterior está en cómo abre sus archivos.

Esto es lo que debería estar en su código (tenga en cuenta los modos abiertos especificados explícitamente, binario y texto):

void compressimage() {
...
    bmp_fp1=fopen("college4.bmp","rb");
    bmp_fp2=fopen("college2.dat","wt");
...
}

void uncompressimage() {
...
    bmp_fp1=fopen("college2.dat","rt");
    bmp_fp2=fopen("college3.bmp","wb");
...
}

Con eso y definiciones de estructura ligeramente alteradas:

#pragma pack(push,1)

typedef struct {
    unsigned short int type;
    unsigned long int filesize;
    unsigned short int reserved1,reserved2;
    unsigned long int offset;
} BMPHEAD;

typedef struct {
    unsigned long int infosize;
    unsigned long int width,height;
    unsigned short int planes,bitsperpixel;
    unsigned long int compression;
    unsigned long int sizeimage;
    long int xpelspermeter,ypelspermeter;
    unsigned long int colorused,colorimportant;
} INFOHEAD;

typedef struct {
    char rgbquad[4];
} colortable;

#pragma pack(pop)

Puedo compilar su programa con éxito utilizando 3 compiladores diferentes (Turbo C ++, Open Watcom, GCC) y obtener la imagen de salida deseada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top