Witajcie:)
Męczę się z tym już drugi dzień i nie mogę sobie poradzić. Otóż chciałbym stworzyć
funkcję, która wyciągnie mi bitmapę zawartą w rekordzie EMR_STRETCHDIBITS metapliku.
Wszystko by było OK, gdyby nie problem z wyciągnięciem tej bitmapy w czystej postaci,
tzn. żeby nie było żadnych przesunięć treści obrazka w stosunku do lewego górnego rogu
canvasa (np. formy) na którym maluję bitmapę oraz bez jej rozciągnięcia lub zwężenia,
żeby wyglądała jak oryginał, co można sprawdzić udostępnionym programem MS Photo Editor.
Metapliki, które chciałbym przekazać Wam do zbadania to testowy obrazek kratki pochodzący
z dokumentów Worda 2000 i Excela 2000 (z pewnych względów musi mi to działać na tak starym
Offic'ie).
Wiadomo, obrazek zaszyty w metafile może mieć dołączone dodatkowe dane "offsetowe",
które służą np. do odpowiedniego spozycjonowania (sformatowania) po przeniesieniu obiektu
z jednego dokumentu do innego. A ja chciałbym te dane zignorować , ponieważ interesuje mnie
tylko sama bitmapa.
No i każdy z obrazków został w Wordzie lub Excelu skopiowany do schowka, a potem
odczytany i zapisany do plików "emf" przy użyciu takiego kodu:
Var
HMetaFile: HENHMETAFILE;
OpenClipboard(0);
HMetaFile:=GetClipboardData(CF_ENHMETAFILE);
CopyEnhMetaFile(HMetaFile, PChar('d:\Metaplik.emf')); //zrzut obrazka ze schowka do pliku 'emf'
DeleteEnhMetaFile(HMetaFile);
CloseClipboard;
I teraz chciałbym ten obrazek wypakować z tego metapliku, a zrobiłem to jak dotąd tak:
// --- funkcja callback -------
Function MyEnhMetaFunc(DisplaySurface: HDC; var MetafileTable: THandleTable; Var MetafileRecord: TEnhMetaRecord; ObjectCount: Integer; var Data: Longint): Integer; stdcall;
Var
strukt:PEMRSTRETCHDIBITS;
begin
If MetafileRecord.iType = EMR_STRETCHDIBITS then
begin
strukt:=PEMRSTRETCHDIBITS(@MetafileRecord); //dostęp do danych struktury
PlayEnhMetaFileRecord(DisplaySurface, MetafileTable, MetafileRecord, ObjectCount);
Result:=0;
end;
End;
//--- odczytanie obrazka------------
procedure TForm1.Button1Click(Sender: TObject);
begin
OpenClipboard(0);
HMetaFile:=GetEnhMetaFile(PChar('d:\SiatkaWord.emf')); //'d:\SiatkaExcel.emf'
SetClipboardData(CF_ENHMETAFILE, HMetaFile); //dodatkowe wklejenie do schowka
CloseClipboard;
EnumEnhMetaFile(Canvas.Handle, HMetaFile, @MyEnhMetaFunc, nil, Rect( 0,0, 584, 500));
DeleteEnhMetaFile(HMetaFile);
end;
Dodatkowo odczytany plik metafile jest kopiowany do schowka, żeby można było wkleić
zawarty w nim obrazek do MS Photo Editor-a i się przekonać, że da się poprawnie odczytać
"na czysto" bitmapkę zawartą w Metafile.
Problem mam też z ustawieniem szerokości i wysokości obrazka na canvasie docelowym,
bo choć w tym przypadku są mi znane rozmiary obrazka (584/500), ale gdybym miał do czynienia
z bitmapą o nieznanych wymiarach, też musiałbym je skądś pobrać. Próbowałem czytać
dane zawarte w rekordzie EMRSTRETCHDIBITS, tzn. xDest i yDest oraz cxSrc i cySrc, ale
to nie zawsze dawało właściwe rozmiary i offset obrazka (zmienna 'strukt')
Struktura EMRSTRETCHDIBITS wyglada tak:
typedef struct tagEMRSTRETCHDIBITS {
EMR emr;
RECTL rclBounds;
LONG xDest;
LONG yDest;
LONG xSrc;
LONG ySrc;
LONG cxSrc;
LONG cySrc;
DWORD offBmiSrc;
DWORD cbBmiSrc;
DWORD offBitsSrc;
DWORD cbBitsSrc;
DWORD iUsageSrc;
DWORD dwRop;
LONG cxDest;
LONG cyDest;
} EMRSTRETCHDIBITS, *PEMRSTRETCHDIBITS;
a w niej struktura:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
a w niej:
tag BITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;
Jakoś nie potrafię tego poskładać w jakiś działający uniwersalny kod, żeby uzyskać oryginalną bitmapę
jak w MS Photo Editor.
Z pewnych względów nie chciałbym stosować funkcji PlayEnhMetaFile, która w przypadku użycia jej
do czytania z dokumentów Office 2000 dodaje jakieś cienie do treści bitmapy, a mi zależy żeby
uzyskać oryginał, również przy użyciu tego pakietu, a chyba tylko metoda czytania rekordu
EMRSTRETCHDIBITS może to zapewnić.
Więc tak, tu Wam wrzuciłem wszystko co pomoże Wam skumać w czym problem:
http://www.sendspace.pl/file/NTO59scO/
czyli:
- dwa pliki emf (z Worda i Excela) do odczytania zawartej w nich oryginalnej bimapy
- screenshoty mojego programu "Screen1" i Screen2" pokazujące jak niepoprawnie wygląda odczyt
bitmapy przy użyciu mojego programu (z Worda i Excela) - fajny programik "MetafileExplorer" do podglądu rekordów metafile, można zobaczyć jak wygląda
struktura rekordu EMRSTRETCHDIBITS - bitmapę przedstawiającą kratkę będącą oryginalnym obrazkiem, który był wklejony w dokumenty
Worda2000 i Excela2000 (w Wordzie celowo był zwężony w pionie i rozciągnięty w poziomie,
co nie powinno przeszkodzić w poprawnym odczycie z metafile, MS Photo Editor daje przecie radę) - MS Photo Editor - do testowania prawidłowego ekstraktowania bitmapy z metapliku
Bardzo proszę o wskazówki, a najlepiej o jakiś przykładowy kod.
Pzdr.
Marogo