Obsah
1. Rozbor obsahu jednoduchého souboru typu WMF
2. Program určený pro analýzu hlaviček souborů typu WMF
3. Analyzovaná hlavička demonstračního souboru typu WMF
4. Program určený pro výpis všech příkazů GDI v souborech WMF
5. Analyzované názvy všech GDI příkazů demonstračního souboru typu WMF
6. Interpretace jednotlivých příkazů GDI
7. Literatura a odkazy na internetu
8. Obsah dalšího pokračování tohoto seriálu
1. Rozbor obsahu jednoduchého souboru typu WMF
V předchozí části tohoto seriálu jsme si zevrubně popsali jak základní, tak i rozšiřující hlavičku používanou v grafických souborech typu WMF. Základní hlavičku obsahují všechny soubory, rozšiřující hlavička, která může (i když je to dnes málo pravděpodobné) způsobit problémy při interpretaci těchto souborů staršími aplikacemi, je přítomna pouze tehdy, když je do WMF vložena programově, protože funkce WinAPI, tj. aplikační programové rozhraní operačního systému Microsoft Windows, vytváří pouze soubory WMF se základní hlavičkou. Minule jsme si také řekli, jakým způsobem jsou uloženy jednotlivé příkazy GDI (GDI je grafický subsystém Microsoft Windows), které vlastně představují zápis barvových, geometrických i rastrových informací o uloženém obrázku. Dnes si na dvojici programů ukážeme, jakým způsobem je možné načítat údaje z obou hlaviček i z jednotlivých GDI příkazů. Demonstrační soubor typu WMF, který je použitý v dalším textu, je možné získat pod tímto odkazem. Další, většinou velmi jednoduché, grafické soubory uložené v tomto formátu si stáhněte zde.
2. Program určený pro analýzu hlaviček souborů typu WMF
Dnešní první demonstrační program slouží pro načtení základní i rozšiřující hlavičky souborů typu WMF. Základní hlavička je přečtena vždy, rozšiřující hlavička pouze v případě, že je na základě obsahu prvních čtyř bytů souborů detekována. Program pracuje velmi jednoduše: nejdříve se načte první čtveřice bytů, z jejíhož obsahu se pozná, jestli soubor obsahuje pouze základní hlavičku nebo i rozšiřující hlavičku. Pokud tato čtveřice má (po její interpretaci jako celého čísla uloženého ve formátu little-endian) hodnotu 0×9ac6cdd7, přečte se i rozšiřující hlavička. Posléze se program přesune opět na začátek souboru a načte rozšířenou hlavičku (pokud je přítomna) a základní hlavičku. Následně je vhodným způsobem inerpretován a vypsán obsah obou hlaviček (jsou provedeny délky uložené v twipsech na „lidské“ jednotky, proveden převod z dvoubytových slov na byty apod.). Předpokladem pro úspěšný překlad a běh programu je platforma, na které má datový typ int bitovou délku minimálně 32 bitů a short int bitovou délku minimálně 16 bitů. Také na platformách s pořadím bytů big-endian bude zapotřebí upravit funkce pro načtení slov a dvojslov.
// --------------------------------------------------------------------
// Demonstracni program urceny pro nacteni hlavicky a popr. i rozsirene
// hlavicky souboru typu WMF (Windows MetaFile)
// Autor: Pavel Tisnovsky
// --------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define HR "-------------------------------------------"
typedef unsigned short Word;
typedef unsigned int Dword;
typedef struct {
Word FileTypeStorage;
Word HeaderSize;
Word Version;
Dword FileSize;
Word NumOfObjects;
Dword MaxRecordSize;
Word ParametersNumb;
} WmfHeader;
typedef struct {
Dword Password;
Word Handle;
short LeftCorn;
short TopCorn;
short RightCorn;
short BottomCorn;
Word Twip_p_Inch;
Dword Reserved;
Word Checksum;
} WmfExtra;
// --------------------------------------------------------------------
// prevod delkovych jednotek zadanych v "twipech" na palce
// --------------------------------------------------------------------
float twip2inch(short twip, Word Twip_p_Inch)
{
return (float)twip/(float)Twip_p_Inch;
}
// --------------------------------------------------------------------
// prevod delkovych jednotek zadanych v "twipech" na milimetry
// --------------------------------------------------------------------
float twip2mm(short twip, Word Twip_p_Inch)
{
return 25.4*(float)twip/(float)Twip_p_Inch;
}
// --------------------------------------------------------------------
// pomocna funkce pro vypis hodnoty jednoho z okraju obaloveho obdelniku
// --------------------------------------------------------------------
void showCorner(const char *msg, short twip, Word twip_p_Inch)
{
printf("%s %+6d twip(s) = %6.3f palcu = %6.2f mm\n",
msg, twip, twip2inch(twip, twip_p_Inch), twip2mm(twip, twip_p_Inch)
);
}
// --------------------------------------------------------------------
// funkce, ktera nacte a zobrazi informace z hlavicky a popr. i
// rozsirene hlavicky souboru typu WMF
// --------------------------------------------------------------------
int wmfHeaderInfo(char *path)
{
// lokalni makro pro nacteni jednoho primitivniho datoveho typu
// ze souboru s kontrolou, zda se nacteni opravdu podarilo
// parametry: misto, kam se ma prectena informace ulozit
// delka typu
// vstupni soubor
#define READ_ITEM(item, type, fin) \
if ((fread(&item, sizeof(type), 1, fin))!=1) {\
printf("Chyba pri cteni souboru!\n");\
return 0;\
}
WmfHeader header;
WmfExtra extraHeader;
Dword firstBytes;
FILE *fin;
// soubor nejprve otevreme
if ((fin=fopen(path, "rb"))==NULL) {
printf("Soubor %s nelze otevrit pro cteni!\n", path);
return 0;
}
// potom nacteme prvnich osm bytu, podle kterych je mozne
// rozpoznat, zda je pritomna rozsirena hlavicka
if ((fread(&firstBytes, 8, 1, fin))!=1) {
printf("Chyba pri cteni ze souboru %s!\n", path);
return 0;
}
// at je ci neni rozsirena hlavicka detekovana, musime se
// presunout zpet na zacatek souboru
fseek(fin, 0L, SEEK_SET);
if (firstBytes==0x9ac6cdd7) {
puts("Je pritomna rozsirujici hlavicka s obsahem:");
puts(HR);
// strukturu, ve ktere se stridaji polozky Word a Dword, nelze obecne
// nacist jednim fread-em kvuli zarovnani na 32bitovych a 64bitovych
// prekladacich
READ_ITEM(extraHeader.Password, Dword, fin)
READ_ITEM(extraHeader.Handle, Word, fin)
READ_ITEM(extraHeader.LeftCorn, short, fin)
READ_ITEM(extraHeader.TopCorn, short, fin)
READ_ITEM(extraHeader.RightCorn, short, fin)
READ_ITEM(extraHeader.BottomCorn, short, fin)
READ_ITEM(extraHeader.Twip_p_Inch, Word, fin)
READ_ITEM(extraHeader.Reserved, Dword, fin)
READ_ITEM(extraHeader.Checksum, Word, fin)
// vypis nactenych informaci
printf("Password: %08x\n", extraHeader.Password);
printf("Cislo souboru: %08d\n", extraHeader.Handle);
showCorner("Levy okraj: ", extraHeader.LeftCorn, extraHeader.Twip_p_Inch);
showCorner("Horni okraj: ", extraHeader.TopCorn, extraHeader.Twip_p_Inch);
showCorner("Pravy okraj: ", extraHeader.RightCorn, extraHeader.Twip_p_Inch);
showCorner("Spodni okraj: ", extraHeader.BottomCorn, extraHeader.Twip_p_Inch);
printf("Twipu na palec: %d\n", extraHeader.Twip_p_Inch);
printf("Rezervovano: %08x\n", extraHeader.Reserved);
printf("Kontrolni soucet: %08x\n", extraHeader.Checksum);
putchar('\n');
}
// nacteni standardni hlavicky formatu WMF
// strukturu, ve ktere se stridaji polozky Word a Dword, nelze obecne
// nacist jednim fread-em kvuli zarovnani na 32bitovych a 64bitovych prekladacich
READ_ITEM(header.FileTypeStorage, Word, fin);
READ_ITEM(header.HeaderSize, Word, fin);
READ_ITEM(header.Version, Word, fin);
READ_ITEM(header.FileSize, Dword, fin);
READ_ITEM(header.NumOfObjects, Word, fin);
READ_ITEM(header.MaxRecordSize, Dword, fin);
READ_ITEM(header.ParametersNumb, Word, fin);
// vypis informaci nactenych ze standardni hlavicky
printf("Obsah standardni hlavicky:\n");
puts(HR);
printf("Ulozeni souboru: %s\n", header.FileTypeStorage==1 ? "na disku":"v RAM");
printf("Velikost hlavicky: %d slov = %d bytu\n", header.HeaderSize, header.HeaderSize<<1);
printf("Verze OS: %x\n", header.Version);
printf("Velikost souboru: %d slov = %d bytu\n", (int)header.FileSize, (int)header.FileSize<<1);
printf("Pocet objektu: %d\n", header.NumOfObjects);
printf("Max. delka zaznamu: %d slov = %d bytu\n", header.FileSize, header.FileSize<<1);
printf("Rezervovano: %x\n", (int)header.ParametersNumb);
fclose(fin);
// makro READ_ITEM je celkem nebezpecne a nikdo jiny by ho nemel pouzit
// -> zajistit jeho "lokalnost"
#undef READ_ITEM
return 1;
}
// --------------------------------------------------------------------
// hlavni funkce, ve ktere se pokusime nacist a zobrazit hlavicku
// souboru typu WMF
// --------------------------------------------------------------------
int main(int argc, char *argv[])
{
if (argc!=2) {
printf("Pouziti: wmf_head soubor.wmf\n");
return 0;
}
wmfHeaderInfo(argv[1]);
return 0;
}
// --------------------------------------------------------------------
// finito
// --------------------------------------------------------------------
3. Analyzovaná hlavička demonstračního souboru typu WMF
V první kapitole je uveden odkaz na demonstrační soubor typu WMF, který byl vytvořen v aplikaci OpenOffice.org. Po překladu prvního programu a jeho spuštění s parametrem wmf.wmf (což je onen WMF soubor z OpenOffice.org) je zjištěno, že tento WMF soubor obsahuje základní i rozšiřující hlavičku s následujícími údaji (všimněte si zejména rozměrů kreslicí plochy, kde pravděpodobně při exportu došlo k nepřesné interpretaci šířky, která byla nastavena přesně na 20 cm):
Je pritomna rozsirujici hlavicka s obsahem:
-------------------------------------------
Password: 9ac6cdd7
Cislo souboru: 00000000
Levy okraj: +0 twip(s) = 0.000 palcu = 0.00 mm
Horni okraj: +0 twip(s) = 0.000 palcu = 0.00 mm
Pravy okraj: +19973 twip(s) = 7.863 palcu = 199.73 mm
Spodni okraj: +28333 twip(s) = 11.155 palcu = 283.33 mm
Twipu na palec: 2540
Rezervovano: 00000000
Kontrolni soucet: 00007e55
Obsah standardni hlavicky:
-------------------------------------------
Ulozeni souboru: na disku
Velikost hlavicky: 9 slov = 18 bytu
Verze OS: 300
Velikost souboru: 870 slov = 1740 bytu
Pocet objektu: 16
Max. delka zaznamu: 870 slov = 1740 bytu
Rezervovano: 0
4. Program určený pro výpis všech příkazů GDI v souborech WMF
Dnešní druhý program je poněkud složitější než program předchozí, protože se v něm snažíme najít názvy všech funkcí GDI (grafického subsystému Microsoft Windows), které jsou v souboru typu WMF umístěny. Klíčovou část tohoto programu tvoří tabulka wmfFunctions, která obsahuje jak symbolické názvy GDI funkcí s prefixem META, tak i jejich číselný kód. Program nejprve přeskočí základní a popř. i rozšiřující hlavičku souboru a poté ve smyčce načítá hlavičky jednotlivých záznamů. Z nich zjistí, jak délku záznamu (ta je nutná pro přeskočení těla), tak i číslo GDI funkce, kterou se pokusí najít v již zmíněné tabulce wmfFunctions. Může se stát, že nějaká funkce nebude nalezena (trojský kůň?, neúplný hlavičkový soubor wingdi.h dodávaný k MinGW?), potom se vypíše informace „* nenalezeno *“. Posledním záznamem uloženým ve WMF souborech je záznam s číslem GDI funkce 0, a ten není nalezen nikdy (taková funkce neexistuje). I u tohoto programu je předpokladem pro jeho úspěšný překlad a běh platforma, na které má datový typ int bitovou délku minimálně 32 bitů a short int bitovou délku minimálně 16 bitů. Také na platformách s pořadím bytů big-endian bude zapotřebí upravit funkce pro načtení slov a dvojslov.
// --------------------------------------------------------------------
// Demonstracni program urceny pro nacteni vsech zaznamu ze souboru
// typu WMF (Windows MetaFile)
// Autor: Pavel Tisnovsky
// --------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define HR "-------------------------------------------"
typedef unsigned short Word;
typedef unsigned int Dword;
// struktura standardni hlavicky WMF
typedef struct {
Word FileTypeStorage;
Word HeaderSize;
Word Version;
Dword FileSize;
Word NumOfObjects;
Dword MaxRecordSize;
Word ParametersNumb;
} WmfHeader;
// struktura rozsirujici hlavicky WMF
typedef struct {
Dword Password;
Word Handle;
short LeftCorn;
short TopCorn;
short RightCorn;
short BottomCorn;
Word Twip_p_Inch;
Dword Reserved;
Word Checksum;
} WmfExtra;
// struktura jednoho zaznamu ve WMF
typedef struct {
Dword Size;
Word Function;
Word Parameters[];
} WmfRecord;
// struktura popisujici prevodni tabulku nazev GDI funkce <-> cislo GDI funkce
typedef struct {
char *name;
Word function;
} WmfFunction;
// naplneni prevodni tabulky
WmfFunction wmfFunctions[]={
{"META_SETBKCOLOR", 0x0201},
{"META_SETBKMODE", 0x0102},
{"META_SETMAPMODE", 0x0103},
{"META_SETROP2", 0x0104},
{"META_SETRELABS", 0x0105},
{"META_SETPOLYFILLMODE", 0x0106},
{"META_SETSTRETCHBLTMODE", 0x0107},
{"META_SETTEXTCHAREXTRA", 0x0108},
{"META_SETTEXTCOLOR", 0x0209},
{"META_SETTEXTJUSTIFICATION", 0x020A},
{"META_SETWINDOWORG", 0x020B},
{"META_SETWINDOWEXT", 0x020C},
{"META_SETVIEWPORTORG", 0x020D},
{"META_SETVIEWPORTEXT", 0x020E},
{"META_OFFSETWINDOWORG", 0x020F},
{"META_SCALEWINDOWEXT", 0x0410},
{"META_OFFSETVIEWPORTORG", 0x0211},
{"META_SCALEVIEWPORTEXT", 0x0412},
{"META_LINETO", 0x0213},
{"META_MOVETO", 0x0214},
{"META_EXCLUDECLIPRECT", 0x0415},
{"META_INTERSECTCLIPRECT", 0x0416},
{"META_ARC", 0x0817},
{"META_ELLIPSE", 0x0418},
{"META_FLOODFILL", 0x0419},
{"META_PIE", 0x081A},
{"META_RECTANGLE", 0x041B},
{"META_ROUNDRECT", 0x061C},
{"META_PATBLT", 0x061D},
{"META_SAVEDC", 0x001E},
{"META_SETPIXEL", 0x041F},
{"META_OFFSETCLIPRGN", 0x0220},
{"META_TEXTOUT", 0x0521},
{"META_BITBLT", 0x0922},
{"META_STRETCHBLT", 0x0B23},
{"META_POLYGON", 0x0324},
{"META_POLYLINE", 0x0325},
{"META_ESCAPE", 0x0626},
{"META_RESTOREDC", 0x0127},
{"META_FILLREGION", 0x0228},
{"META_FRAMEREGION", 0x0429},
{"META_INVERTREGION", 0x012A},
{"META_PAINTREGION", 0x012B},
{"META_SELECTCLIPREGION", 0x012C},
{"META_SELECTOBJECT", 0x012D},
{"META_SETTEXTALIGN", 0x012E},
{"META_CHORD", 0x0830},
{"META_SETMAPPERFLAGS", 0x0231},
{"META_EXTTEXTOUT", 0x0a32},
{"META_SETDIBTODEV", 0x0d33},
{"META_SELECTPALETTE", 0x0234},
{"META_REALIZEPALETTE", 0x0035},
{"META_ANIMATEPALETTE", 0x0436},
{"META_SETPALENTRIES", 0x0037},
{"META_POLYPOLYGON", 0x0538},
{"META_RESIZEPALETTE", 0x0139},
{"META_DIBBITBLT", 0x0940},
{"META_DIBSTRETCHBLT", 0x0b41},
{"META_DIBCREATEPATTERNBRUSH", 0x0142},
{"META_STRETCHDIB", 0x0f43},
{"META_EXTFLOODFILL", 0x0548},
{"META_SETLAYOUT", 0x0149},
{"META_DELETEOBJECT", 0x01f0},
{"META_CREATEPALETTE", 0x00f7},
{"META_CREATEPATTERNBRUSH", 0x01F9},
{"META_CREATEPENINDIRECT", 0x02FA},
{"META_CREATEFONTINDIRECT", 0x02FB},
{"META_CREATEBRUSHINDIRECT", 0x02FC},
{"META_CREATEREGION", 0x06FF},
{"* nenalezeno *", 0x0000},
};
// --------------------------------------------------------------------
// prevod delkovych jednotek zadanych v "twipech" na palce
// --------------------------------------------------------------------
float twip2inch(short twip, Word Twip_p_Inch)
{
return (float)twip/(float)Twip_p_Inch;
}
// --------------------------------------------------------------------
// prevod delkovych jednotek zadanych v "twipech" na milimetry
// --------------------------------------------------------------------
float twip2mm(short twip, Word Twip_p_Inch)
{
return 25.4*(float)twip/(float)Twip_p_Inch;
}
// --------------------------------------------------------------------
// pomocna funkce pro vypis hodnoty jednoho z okraju obaloveho obdelniku
// --------------------------------------------------------------------
void showCorner(const char *msg, short twip, Word twip_p_Inch)
{
printf("%s %+6d twip(s) = %6.3f palcu = %6.2f mm\n",
msg, twip, twip2inch(twip, twip_p_Inch), twip2mm(twip, twip_p_Inch)
);
}
// --------------------------------------------------------------------
// prevod cisla GDI funkce na jeji nazev
// --------------------------------------------------------------------
char * getFunctionName(int function)
{
int j;
for (j=0; wmfFunctions[j].function!=function && wmfFunctions[j].function!=0x0000; j++)
;
return wmfFunctions[j].name;
}
// --------------------------------------------------------------------
// funkce, ktera nacte a zobrazi informace z hlavicky a popr. i
// rozsirene hlavicky souboru typu WMF
// --------------------------------------------------------------------
int wmfRecordsInfo(char *path)
{
// delka standardni hlavicky i rozsirujici hlavicky WMF souboru
#define HEADER_LENGTH 18
#define EXT_HEADER_LENGTH 22
#define freadWord(fin) (fgetc((fin)) | fgetc((fin))<<8)
#define freadDword(fin) (fgetc((fin)) | fgetc((fin))<<8 | fgetc((fin))<<16 | fgetc((fin))<<24)
WmfRecord record;
Dword firstBytes;
int cnt=0;
FILE *fin;
// soubor nejprve otevreme
if ((fin=fopen(path, "rb"))==NULL) {
printf("Soubor %s nelze otevrit pro cteni!\n", path);
return 0;
}
// potom nacteme prvnich osm bytu, podle kterych je mozne
// rozpoznat, zda je pritomna rozsirena hlavicka
if ((fread(&firstBytes, 8, 1, fin))!=1) {
printf("Chyba pri cteni ze souboru %s!\n", path);
return 0;
}
// presunout se za souborove hlavicky
if (firstBytes==0x9ac6cdd7) {
fseek(fin, EXT_HEADER_LENGTH+HEADER_LENGTH, SEEK_SET);
}
else
fseek(fin, HEADER_LENGTH, SEEK_SET);
puts(HR);
puts("Record\toffset\tsize\tfunction#\tfunction name");
// cteni vsech zbyvajicich dat v souborech typu WMF
while (!feof(fin)) {
record.Size=freadDword(fin);
record.Function=freadWord(fin);
if (feof(fin)) break;
printf("%5d\t%4d\t%5d\t%04x\t\t%s\n", cnt, (int)ftell(fin), record.Size<<1, record.Function, getFunctionName(record.Function));
cnt++;
// preskocit parametry
// 6 je delka hlavicky zaznamu
fseek(fin, record.Size*2-6, SEEK_CUR);
}
fclose(fin);
return 1;
}
// --------------------------------------------------------------------
// hlavni funkce, ve ktere se pokusime nacist a zobrazit hlavicku
// souboru typu WMF
// --------------------------------------------------------------------
int main(int argc, char *argv[])
{
if (argc!=2) {
printf("Pouziti: wmf_head soubor.wmf\n");
return 0;
}
wmfRecordsInfo(argv[1]);
return 0;
}
// --------------------------------------------------------------------
// finito
// --------------------------------------------------------------------
5. Analyzované názvy všech GDI příkazů demonstračního souboru typu WMF
Pokud spustíme druhý program popsaný v předchozí kapitole na náš demonstrační WMF soubor vytvořený v OpenOffice.org, získáme sekvenci GDI příkazů vypsanou v odstavci níže. Poslední řádek je ve skutečnosti korektní (i když se vypisuje zpráva, že GDI funkce nebyla nalezena), protože WMF soubory skutečně končí záznamem, u nějž je číslo GDI funkce nastaveno na nulu a záznam neobsahuje žádná data – jeho skutečná délka je tedy rovna šesti bytům, což odpovídá velikosti hlavičky každého záznamu. Dále můžeme z výpisu vidět, že původní dokonalá kružnice je rozdělena na polygon s délkou záznamu 1034 bytů (z tohoto údaje lze jednoduše zjistit počet vrcholů), takže zpětný import souboru nutně povede ke ztrátě geometrické informace o původní kružnici.
-------------------------------------------
Record offset size function# function name
0 46 10 020b META_SETWINDOWORG
1 56 10 020c META_SETWINDOWEXT
2 66 8 0102 META_SETBKMODE
3 74 8 0104 META_SETROP2
4 82 16 02fa META_CREATEPENINDIRECT
5 98 8 012d META_SELECTOBJECT
6 106 14 02fc META_CREATEBRUSHINDIRECT
7 120 8 012d META_SELECTOBJECT
8 128 56 02fb META_CREATEFONTINDIRECT
9 184 8 012d META_SELECTOBJECT
10 192 8 012e META_SETTEXTALIGN
11 200 10 0209 META_SETTEXTCOLOR
12 210 8 0107 META_SETSTRETCHBLTMODE
13 218 6 001e META_SAVEDC
14 224 14 0416 META_INTERSECTCLIPRECT
15 238 16 02fa META_CREATEPENINDIRECT
16 254 8 012d META_SELECTOBJECT
17 262 8 01f0 META_DELETEOBJECT
18 270 14 02fc META_CREATEBRUSHINDIRECT
19 284 8 012d META_SELECTOBJECT
20 292 8 01f0 META_DELETEOBJECT
21 300 1034 0538 META_POLYPOLYGON
22 1334 16 02fa META_CREATEPENINDIRECT
23 1350 8 012d META_SELECTOBJECT
24 1358 8 01f0 META_DELETEOBJECT
25 1366 14 02fc META_CREATEBRUSHINDIRECT
26 1380 8 012d META_SELECTOBJECT
27 1388 8 01f0 META_DELETEOBJECT
28 1396 252 0325 META_POLYLINE
29 1648 16 0325 META_POLYLINE
30 1664 16 02fa META_CREATEPENINDIRECT
31 1680 8 012d META_SELECTOBJECT
32 1688 8 01f0 META_DELETEOBJECT
33 1696 14 02fc META_CREATEBRUSHINDIRECT
34 1710 8 012d META_SELECTOBJECT
35 1718 8 01f0 META_DELETEOBJECT
36 1726 28 0324 META_POLYGON
37 1754 8 0127 META_RESTOREDC
38 1762 6 0000 * nenalezeno *
6. Interpretace jednotlivých příkazů GDI
Nejpracnější část analýzy WMF souborů spočívá v interpretaci jednotlivých GDI příkazů. Každý příkaz má obecně jiný počet a typ parametrů, takže samotné zpracování prakticky nelze univerzálně napsat (většinou se skončí u obřího příkazu switch). V následující tabulce je vypsán způsob interpretace parametrů některých nejčastěji používaných GDI příkazů. Každý parametr je uveden indexem či indexy bytů následujících za hlavičkou záznamu.
Příkaz | Popis | Parametry |
---|---|---|
META_SETBKCOLOR | barva pozadí | RGB – byty 0, 1, 2 |
META_CREATEBRUSHINDIRECT | volba štětce (výplň) | RGB – byty 0, 1, 2 |
META_CREATEBRUSH | volba štětce (výplň) | RGB – byty 0, 1, 2 |
META_CREATEPENINDIRECT | volba pera (obrys) | RGB – byty 0, 1, 2 |
META_MOVETO | přes gfx. kurzoru bez kreslení | x – byty 0 a 1, y – byty 2 a 3 |
META_LINETO | přes gfx. kurzoru s kreslením | x – byty 0 a 1, y – byty 2 a 3 |
META_POLYLINE | kresba lomené čáry | počet čar – byt 0, následují souřadnice x a y (každá má dva byty) |
META_POLYGON | kresba vyplněného mnohoúhelníku | stejné jako v předchozím případě |
META_ARC | eliptický oblouk | x1 – byty 0 a 1, y1 – byty 2 a 3, x2 – byty 4 a 5, y2 – byty 6 a 7, xs – byty 8 a 9, ys – byty 10 a 11, xe – byty 12 a 13, ye – byty 14 a 15 |
7. Literatura a odkazy na internetu
- Charles Petzold: Programming Windows,
Microsoft Press, 1998 - Microsoft: Platform SDK,
Microsoft, 1995–2007 - Svoboda Bronislav a kol.: Grafické formáty,
Nakladatelství KOOP, České Budějovice - Wikipedia EN: Windows Metafile,
http://en.wikipedia.org/wiki/Windows_Metafile - Wikipedia EN: Windows Media Format,
http://en.wikipedia.org/wiki/Windows_Media_Format - Microsoft Windows Metafile,
http://wvware.sourceforge.net/caolan/ora-wmf.html - Windows Metafiles, a guide for non-windows programmers,
http://wvware.sourceforge.net/caolan/index.html - Metafile Reference,
http://msdn2.microsoft.com/en-us/library/ms534300.aspx - yFiles 2.3.x graph visualization library and WMF,
http://www.yworks.com/en/products_yfiles_ep_ywmf.htm - yFiles gallery,
http://www.yworks.com/en/products_yfiles_practicalinfo_gallery.htm - libwmf – library for converting WMF files,
http://wvware.sourceforge.net/libwmf.html
8. Obsah dalšího pokračování tohoto seriálu
V následujícím pokračování seriálu o grafických formátech a metaformátech si popíšeme ideového nástupce formátu WMF, kterým je grafický metaformát EMF. Také budou uvedeny jednoduché demonstrační příklady na načítání informací ze souborů typu EMF.