/* * Demonstracni priklad, ktery nacte a posleze vytiskne zakladni udaje * o souboru typu JPEG. Vytvoreno s vyuzitim upravene funkce jpeginfo() * Miloslava Vlcka a Zdenka Vladeky (FIT VUT v Brne). * * Autor: Pavel Tisnovsky (vse mimo funkci getJpegInfo()) * * Pouziti: * jpeg_info image.jpg */ #include #include #include /* * Datova struktura se zakladnimi informacemi o JPEG souboru */ typedef struct JpegInfo { int width; // sirka obrazku int height; // vyska obrazku char fname[200]; // jmeno zdrojoveho souboru unsigned long size; // celkova velikost souboru long p_data; // pozice zacatku obrazovychdat v souboru long p_qtab_y; // pozice zacatku kvantizacni tabulky pro slozku Y long p_qtab_c; // pozice zacatku kvantizacni tabulky pro slozku C long p_htab_y_dc; // zacatek Huffmanovy kodove tabulky DC koeficientu slozky Y long p_htab_y_ac; // zacatek Huffmanovy kodove tabulky AC koeficientu slozky Y long p_htab_c_dc; // zacatek Huffmanovy kodove tabulky DC koeficientu slozek CbCr long p_htab_c_ac; // zacatek Huffmanovy kodove tabulky AC koeficientu slozek CbCr unsigned int rstinterval; // restart interval unsigned char sf_y,sf_cb, sf_cr; } JpegInfo; JpegInfo jpegInfo; /* * Funkce pro ziskani zakladnich udaju o souboru typu JFIF/JPEG */ void getJpegInfo(const char *fileName, FILE *fileJpeg, JpegInfo *jpegInfo) { unsigned char b1,b2,so; long l,ll,fl; int ii,i; jpegInfo->width=0; jpegInfo->height=0; fseek(fileJpeg, 0, SEEK_END); ll=ftell(fileJpeg); jpegInfo->size=ll; fseek(fileJpeg, 0, SEEK_SET); fread(&b1, 1, 1, fileJpeg); fread(&b2, 1, 1, fileJpeg); fl=2; if ((b1==0xff) && (b2==0xd8)){ strcpy(jpegInfo->fname, fileName); while (flrstinterval=(b1<<8)+b2; break; } case 0xda: { // kodovana obrazova data jpegInfo->p_data=fl; return; } case 0xdb: { // kvantizacni tabulky fread(&b1,1,1,fileJpeg); if (b1==0) jpegInfo->p_qtab_y=ftell(fileJpeg); else jpegInfo->p_qtab_c=ftell(fileJpeg); if (fl>ftell(fileJpeg)+65){ fseek(fileJpeg, 64, SEEK_CUR); fread(&b1, 1, 1, fileJpeg); if (b1==0) jpegInfo->p_qtab_y=ftell(fileJpeg); else jpegInfo->p_qtab_c=ftell(fileJpeg); } break; } case 0xc4: { // Huffmanovy kodove tabulky for (ii=0; ii<4; ii++) { fread(&b1, 1, 1, fileJpeg); switch (b1){ case 0: jpegInfo->p_htab_y_dc=ftell(fileJpeg);break; case 1: jpegInfo->p_htab_c_dc=ftell(fileJpeg);break; case 16: jpegInfo->p_htab_y_ac=ftell(fileJpeg);break; case 17: jpegInfo->p_htab_c_ac=ftell(fileJpeg);break; }; l=0; for(i=0; i<16; i++) { fread(&b1, 1, 1, fileJpeg); l+=b1; }; fseek(fileJpeg,l,SEEK_CUR); if (ftell(fileJpeg)>=fl) break; }; break; } case 0xc0: { // zakladni informace o obrazku fread(&b1, 1, 1, fileJpeg); fread(&b1, 1, 1, fileJpeg); fread(&b2, 1, 1, fileJpeg); jpegInfo->height=((long)b1<<8)+b2; fread(&b1, 1, 1, fileJpeg); fread(&b2, 1, 1, fileJpeg); jpegInfo->width=((long)b1<<8)+b2; fseek(fileJpeg, 2, SEEK_CUR); fread(&jpegInfo->sf_y, 1, 1, fileJpeg); fseek(fileJpeg, 2, SEEK_CUR); fread(&jpegInfo->sf_cb, 1, 1, fileJpeg); fseek(fileJpeg, 2, SEEK_CUR); fread(&jpegInfo->sf_cr, 1, 1, fileJpeg); break; } }; } } } else { // nenasli jsme znacku -> vadny JPEG soubor return; } return; } /* * Tisk hodnoty offsetu jako dekadicke a hexadecimalni hodnoty */ void printOffset(const char *str, unsigned int value) { printf("%s %10u\t0x%08x\n", str, value, value); } /* * Tisk zakladnich informaci o souboru typu JFIF/JPEG */ void printJpegInfo(JpegInfo *jpegInfo) { printf("Jmeno souboru: %s\n", jpegInfo->fname); printf("Delka souboru: %ld bytu\n", jpegInfo->size); printf("Sirka obrazku: %d pixelu\n", jpegInfo->width); printf("Vyska obrazku: %d pixelu\n", jpegInfo->height); printOffset("Offset zacatku obrazovych dat: ", jpegInfo->p_data); printOffset("Offset zacatku kvantizacni tabulky Y: ", jpegInfo->p_qtab_y); printOffset("Offset zacatku kvantizacni tabulky CbCr: ", jpegInfo->p_qtab_c); printOffset("Offset zacatku Huffmanovy tabulky DC/Y: ", jpegInfo->p_htab_y_dc); printOffset("Offset zacatku Huffmanovy tabulky AC/Y: ", jpegInfo->p_htab_y_ac); printOffset("Offset zacatku Huffmanovy tabulky DC/CbCr:", jpegInfo->p_htab_c_dc); printOffset("Offset zacatku Huffmanovy tabulky AC/CbCr:", jpegInfo->p_htab_c_ac); } /* * Tisk obsahu jedne kvantizacni tabulky */ void printQuantizationTable(FILE *fileJpeg, unsigned int seek) { #define DCTSIZE 8 // velikost bloku DCT #define NUM_QUANT_TBLS 4 // kvantizacni tabulky jsou ocislovany 0..3 int n; // cislo kvantizacni tabulky int prec; // bitova sirka kvantizacnich koeficientu int i, j; // pocitadla smycek fseek(fileJpeg, seek, SEEK_SET); n=fgetc(fileJpeg); n&=0x0F; prec=n>>4; printf("kvantizacni tabulka cislo %d, presnost %d bitu\n", n, prec==0 ? 8:16); // neco je spatne, nekorektni cislo tabulky if (n >= NUM_QUANT_TBLS) { printf("nekorektni cislo kvantizacni tabulky %d!\n", n); return; } // nacist vsech 8x8 kvantizacnich koeficientu for (j=0; jp_qtab_y-1); printf("\nKvantizacni tabulka chrominance Cb Cr (sekvence cik-cak):\n"); printQuantizationTable(fileJpeg, jpegInfo->p_qtab_c-1); } /* * Tisk obsahu jedne Huffmanovy tabulky */ void printHuffmanTable(FILE *fileJpeg) { int i, j; int count=0; int bits_a[16]; printf("tabulka cislo: 0x%02x\n", fgetc(fileJpeg)); puts("hodnoty pro bitove delky:"); for (i=0; i<16; i++) { int bits=fgetc(fileJpeg); count+=bits; printf("Hodnoty pro bitove sekvence delky %02d bitu: %02x\n", i+1, bits); bits_a[i]=bits; } if (count>256) { printf("Nekorektni celkovy pocet ulozenych hodnot!"); return; } else { printf("celkem je v tabulce ulozeno %d hodnot\n", count); } puts("\nHodnoty pro konstrukci binarniho stromu:"); for (j=0; j<16; j++) { printf("sekvence delky %02d bitu: ", j+1); for (i=0; ip_htab_y_dc-1, SEEK_SET); printHuffmanTable(fileJpeg); // vypis stromu printf("\nHuffmanova tabulka pro DC koeficienty chrominance (Cb Cr):\n"); fseek(fileJpeg, jpegInfo->p_htab_c_dc-1, SEEK_SET); printHuffmanTable(fileJpeg); // vypis stromu printf("\nHuffmanova tabulka pro AC koeficienty luminance (Y):\n"); fseek(fileJpeg, jpegInfo->p_htab_y_ac-1, SEEK_SET); printHuffmanTable(fileJpeg); // vypis stromu printf("\nHuffmanova tabulka pro AC koeficienty chrominance (Cb Cr):\n"); fseek(fileJpeg, jpegInfo->p_htab_c_ac-1, SEEK_SET); printHuffmanTable(fileJpeg); // vypis stromu }; /* * Hlavni funkce konzolove aplikace */ int main(int argc, char *argv[]) { FILE *fileJpeg; // kontrola, jestli je z prikazoveho radku zadano jmeno souboru if (argc<=1) { printf("Pouziti jpeg_info image.jpg\n"); return 1; } // pokus o otevreni souboru pro cteni fileJpeg=fopen(argv[1], "rb"); if (!fileJpeg) { printf("Chyba pri otevirani souboru %s pro cteni!\n", argv[1]); return 1; } // ziskani informaci z JPEG souboru a jejich vypis getJpegInfo(argv[1], fileJpeg, &jpegInfo); printJpegInfo(&jpegInfo); printQuantizationTables(fileJpeg, &jpegInfo); printHuffmanTables(fileJpeg, &jpegInfo); if (fclose(fileJpeg)==EOF) { printf("Chyba pri zavirani souboru %s!\n", argv[1]); return 1; } return 0; } /* * finito */