C format plików graficznych

0

Cześć,

mam do napisania mały program w C wyświetlający informacje o plikach graficznych takie jak rozmiar, ilość kolorów, kompresja.
Pliki to jpg, gif, tif, bmp, png.

O ile z bmp sobie poradziłem, jest na wiki BITMAPFILEHEADER, o tyle z pozostałymi mam problem :/. Nie widzę, żadnych funkcji, typów, ani opisów pozostałych formatów.

0
int png(FILE *fileptr);
typedef struct _PngSignature
{
    BYTE Signature[8];  /* Identifier (always 89504E470D0A1A0Ah) */
} PNGSIGNATURE;

typedef struct _PngChunk
{
    DWORD DataLength;   /* Size of Data field in bytes */
    DWORD Type;         /* Code identifying the type of chunk */
    BYTE  Data[];       /* The actual data stored by the chunk */
    DWORD Crc;          /* CRC-32 value of the Type and Data fields */
} PNGCHUNK;

typedef struct _IHDRChunk
{
    DWORD Width;        /* Width of image in pixels */
    DWORD Height;       /* Height of image in pixels */
    BYTE BitDepth;      /* Bits per pixel or per sample */
    BYTE ColorType;     /* Color interpretation indicator */
    BYTE Compression;   /* Compression type indicator */
    BYTE Filter;        /* Filter type indicator */
    BYTE Interlace;     /* Type of interlacing scheme used */
} IHDRCHUNK;

int png(FILE *fileptr)
{
	PNGSIGNATURE syg;
	PNGCHUNK pngchunk;
	IHDRCHUNK ihdrchunk;

	fread(&syg, sizeof(PNGSIGNATURE),1,fileptr);
	fread(&pngchunk, sizeof(PNGCHUNK),1,fileptr);
	fread(&ihdrchunk, sizeof(IHDRCHUNK),1,fileptr);

	printf("Szerokosc %ld, wysokosc %ld, rozmiar %ld", ihdrchunk.Width ,ihdrchunk.Height);
	fclose(fileptr);

	return 0;
}

int bmp(FILE *fileptr)
{
	BITMAPINFOHEADER bitmapInfoHeader; //our bitmap file header
	BITMAPFILEHEADER bitmapFileHeader;

	fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER),1,fileptr);

	//verify that this is a bmp file by check bitmap id
	if (bitmapFileHeader.bfType !=0x4D42)
	{
	fclose(fileptr);
	return 1;
	}

	fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER),1,fileptr);

//	printf("Szerokosc %ld, wysokosc %ld, rozmiar %ld",bitmapInfoHeader.biWidth, bitmapInfoHeader.biheight, bitmapInfoHeader.biSizeImage);
	fclose(fileptr);

	return 0;
}
 

No dobra, na podstawie http://www.fileformat.info/format/png/egff.htm Napisałem to co wyżej. Ale jest problem z _PngChunk, BYTE Data[]; może mieć różną wielkość.

Jak to ominąć ? Właściwie jest mi potrzebne tylko IHDRChunk, ale nie wiem jak dojść do tego bez czytania poprzednich.

0
DWORD DataLength;

fread(&syg, ...);

fread(&DataLength, 4, 1, fileptr);
fseek(fileptr, DataLength + 8, SEEK_CUR);

fread(&ihdrchunk, ... );
0

um.. wiem ze to malo wnoszace pytanie, ale skoro masz tyle formatow, nie mozesz uzyc jakies biblioteki graficznej? nie wiem, strzelam, http://www.imagemagick.org/Magick++/ ? troche szkoda czasu na reimplementowanie, latwo o blad.. pytam, bo nie napisales ze "musisz" pisac od zera.. jakkolwiek fajna zabawa jesli masz za duzo czasu i Cie to interesuje, czy tez wredna robota jesli ktos Ci kazal robic to recznie..

0

Niestety wredna robota dla kolegi... Muszę ręcznie

0x666 Zrobilem tak jak napisałeś, ale dostaję złe liczby ..

 int png(FILE *fileptr)
{
	PNGSIGNATURE syg;
	PNGCHUNK pngchunk;
	IHDRCHUNK ihdrchunk;
	DWORD DataLength;

	fread(&syg, sizeof(PNGSIGNATURE),1,fileptr);
fread(&DataLength, 4, 1, fileptr);
fseek(fileptr, DataLength + 8, SEEK_CUR);
	fread(&ihdrchunk, sizeof(IHDRCHUNK),1,fileptr);

	printf("Szerokosc %ld, wysokosc %ld, rozmiar %ld", ihdrchunk.Width ,ihdrchunk.Height);
	fclose(fileptr);

	return 0;
}
0

Zrobilem tak jak napisałeś (...)

A ja się zasugerowałem Twoim kodem, i to był błąd. Przecież po **PNGSIGNATURE **następuje IHDRCHUNK, a nie jak u Ciebie PNGCHUNK.

0

Dobra, przyjrzałem się opisowi nieco dokładniej. Są dwie sprawy, których nie bierzesz pod uwagę:

  • każdy blok danych zaczyna się od nagłówka:
DWORD DataLength; /* Size of Data field in bytes */
DWORD Type; /* Code identifying the type of chunk */

kończy się DWORDem, zawierającym sumę kontrolną. Czyli czytasz mniej więcej tak

DWORD DataLength;
char Type[4];

...

fread(&DataLength, 4, 1, fileptr);
fread(Type, 4, 1, fileptr);

if(memcmp(Type, "IHDR", 4) == 0)
{
	/*tu czytasz strukturę IHDRCHUNK  */
	
	fseek(fileptr, 4, SEEK_CUR); // przeskakujemy CRC
}
else 
{
	/* pomijamy cały blok */
	fseek(fileptr, SWAP_ENDIAN(DataLength) + 4, SEEK_CUR);
}
 
  • wszystkie wartości liczbowe są w big endianie, procesory z rodziny x86 śmigają na little endianie. Zatem zanim zaczniesz interpretować jakiekolwiek liczby z tego pliku, zmień kolejność bajtów.
0

Pokaż kod.

p.s. nie używaj komentarzy do kontynuowania wątku.

0

Już się trochę zgubiłem, nie weim czy ten syg ma być czy nie, w każdym razie nie działa z nim ani bez.

int png(FILE *fileptr)
{
	PNGSIGNATURE syg;
	PNGCHUNK pngchunk;
	IHDRCHUNK ihdrchunk;
    DWORD DataLength;
    char Type[4];

	fread(&syg, sizeof(PNGSIGNATURE),1,fileptr);
    fread(&DataLength, 4, 1, fileptr);
    fread(Type, 4, 1, fileptr);
     
    if(memcmp(Type, "IHDR", 4) == 0)
    {
	fread(&ihdrchunk, sizeof(IHDRCHUNK),1,fileptr);
     
    fseek(fileptr, 4, SEEK_CUR); // przeskakujemy CRC
    }
	else
	{
	/* pomijamy cały blok */
	fseek(fileptr, SWAP_ENDIAN(DataLength) + 4, SEEK_CUR);
	}
 

	printf("Szerokosc %ld, wysokosc %ld, rozmiar %ld", ihdrchunk.Width ,ihdrchunk.Height);
	fclose(fileptr);

	return 0;
} 
0

"Ten syg" też ma być, bo taki jest format pliku - zajrzyj do jego opisu. Błąd jest w linii 26. Przeczytaj jeszcze raz, co napisałem w drugim punkcie na temat endianów?

Usuń blok else, bo w tym kontekście nie ma on sensu.

0

Ma ktoś może kod czytający plik binarnie - gif, tif, jpg i wyświetlający informacje o nich ? Nic nie mogę znaleźć działającego

1 użytkowników online, w tym zalogowanych: 0, gości: 1