/*
* Demonstracni priklad, ktery nacte a posleze vytiskne vsechny znacky,
* ktere se nachazi v souboru typu JFIF/JPEG.
*
* Autor: Pavel Tisnovsky
*
* Pouziti:
* jpeg_markers image.jpg
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// struktura pro uchovani zakladnich informaci o znackach
typedef struct Marker {
unsigned char value;
char * marker;
char * text;
} Marker;
// pole znamych znacek
Marker markers[]={
{0xd8, "SOI", "Start Of Image"},
{0xd9, "EOI", "End Of Image"},
{0xd0, "RST0", "Restart Marker 0"},
{0xd1, "RST1", "Restart Marker 1"},
{0xd2, "RST2", "Restart Marker 2"},
{0xd3, "RST3", "Restart Marker 3"},
{0xd4, "RST4", "Restart Marker 4"},
{0xd5, "RST5", "Restart Marker 5"},
{0xd6, "RST6", "Restart Marker 6"},
{0xd7, "RST7", "Restart Marker 7"},
{0xda, "SOS", "Start Of Scan"},
{0xe0, "APP0", "Application Marker 0"},
{0xe1, "APP1", "Application Marker 1 (EXIF)"},
{0xe2, "APP2", "Application Marker 2 (EXIF)"},
{0xc4, "DHT", "Define Huffman Table"},
{0xcc, "DAC", "Define Arithmetic Table"},
{0xdb, "DQT", "Define Quantization Table"},
{0xdc, "DNL", "Define Number Of Lines"},
{0xdd, "DRI", "Define Restart Interval"},
{0xfe, "COM", "Comment"},
{0x01, "TEM", "usually causes a decoding error, may be ignored"},
{0xc0, "SOF0", "Start Of Frame (baseline JPEG)"},
{0xc1, "SOF1", "Start Of Frame (baseline JPEG)"},
{0xc2, "SOF2", "usually unsupported"},
{0xc3, "SOF3", "usually unsupported"},
{0xc5, "SOF5", "usually unsupported"},
{0xc6, "SOF6", "usually unsupported"},
{0xc7, "SOF7", "usually unsupported"},
{0xc9, "SOF9", "for arithmetic coding, usually unsupported"},
{0xca, "SOF10", "usually unsupported"},
{0xcb, "SOF11", "usually unsupported"},
{0xcd, "SOF13", "usually unsupported"},
{0xce, "SOF14", "usually unsupported"},
{0xce, "SOF14", "usually unsupported"},
{0xcf, "SOF15", "usually unsupported"},
{0xc8, "JPG", "undefined/reserved (causes decoding error)"},
{0xde, "DHP", "ignore (skip)"},
{0xdf, "EXP", "ignore (skip)"},
{0xef, "APP15", "ignore"},
{0xf0, "JPG0", "ignore (skip)"},
{0xfd, "JPG13", "ignore (skip)"},
{0x00, "***", "neznama znacka"}, // zarazka (musi byt na konci)
};
/*
* Tisk hodnoty znacky
*/
void printMarker(unsigned char byte1, unsigned char byte2, unsigned long int offset)
{
int i=0;
// pokusit se najit znacku v poli markers (nebo alespon zarazku)
while (markers[i].value!=0 && markers[i].value!=byte2)
i++;
printf("%10lu\t0x%08lx\t%02x%02x\t%s\t%s\n", offset, offset, byte1, byte2, markers[i].marker, markers[i].text);
}
/*
* Funkce pro ziskani zakladnich udaju o souboru typu JFIF/JPEG
*/
void printJpegMarkers(FILE *fileJpeg) {
int i;
unsigned char byte1=0, byte2=0;
printf("Offset dec\tOffset hex\tZnacka\tJmeno\tText\n");
// projit celym souborem
while ((i=fgetc(fileJpeg))!=EOF) {
// pokud byl predchozi byte nastaveny na 0xff
if (byte1==0xff) {
byte2=i;
// a druhy byte je v rozsahu 0x01-0xfe
if (byte2>=0x01 && byte2<=0xfe) {
// jedna se o znacku
printMarker(byte1, byte2, ftell(fileJpeg)-2);
}
// zabranit chybne detekci znacky
byte1=0;
}
// test, zda je nacteny byt roven zacatku znacky
if (i==0xff) {
byte1=0xff;
}
}
};
/*
* 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_markers 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 o znackach ulozenych v souborech JFIF/JPEG
printJpegMarkers(fileJpeg);
if (fclose(fileJpeg)==EOF) {
printf("Chyba pri zavirani souboru %s!\n", argv[1]);
return 1;
}
return 0;
}
/*
* finito
*/