Mamy problem z wyjściem TMetaFileCanvas podczas rysowania obrazu do współrzędnej poza rozdzielczością ekranu. Operacje wektorowe wydają się nie mieć żadnych problemów, ale operacje obrazowe są po prostu "ignorowane". Jeśli narysujemy ten sam obraz do współrzędnych w granicach ekranu, nie ma problemów.Kopiowanie grafiki na TMetaFileCanvas poza wymiarami ekranu
Na przykład. To SSCCE wytworzy 4 pliki wyjściowe. Wariant bitmapy nie ma żadnych problemów i będzie działał zgodnie z oczekiwaniami z czerwonym kwadratem w lewym górnym rogu dla inscreen.bmp
i czerwonym kwadratem w prawym dolnym rogu dla outsidescreen.bmp
. Plik meta inscreen.emf
działa zgodnie z oczekiwaniami z czerwonym kwadratem narysowanym w lewym górnym rogu. outsidescreen.emf
nie działa i rysowana jest tylko linia.
program Project6;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Types,
Windows,
Vcl.Graphics;
const
SIZECONST = 3000; // should be larger than your screen resolution
OFFSET = 1500;
function GetMyMetafile(const aHDC: HDC): TMetafile;
var
metcnv: TMetafileCanvas;
begin
Result := TMetafile.Create;
Result.SetSize(500, 500);
metcnv := TMetafileCanvas.Create(Result, aHDC);
metcnv.Brush.Color := clRed;
metcnv.FillRect(Rect(0, 0, 500, 500));
metcnv.Free;
end;
procedure OutputToMetaFile(const aFilename: string; const aStartOffset,
aEndOffset, aMaxSize: Integer; aGraphic: TGraphic; aHDC: HDC);
var
metafile: TMetafile;
metcnv: TMetafileCanvas;
begin
metafile := TMetafile.Create;
try
metafile.SetSize(aMaxSize, aMaxSize);
metcnv := TMetafileCanvas.Create(metafile, aHDC);
try
// draw it somewhere offscreen
metcnv.StretchDraw(Rect(aStartOffset, aStartOffset, aEndOffset, aEndOffset), aGraphic);
metcnv.MoveTo(aStartOffset, aStartOffset);
metcnv.LineTo(aEndOffset, aEndOffset);
finally
metcnv.Free;
end;
metafile.SaveToFile(aFilename);
finally
metafile.Free;
end;
end;
procedure OutputToBitmap(const aFilename: string; const aStartOffset,
aEndOffset, aMaxSize: Integer; aGraphic: TGraphic);
var
bmp: TBitmap;
begin
bmp := TBitmap.Create;
try
bmp.SetSize(aMaxSize, aMaxSize);
bmp.Canvas.StretchDraw(Rect(aStartOffset, aStartOffset, aEndOffset, aEndOffset), aGraphic);
bmp.Canvas.MoveTo(aStartOffset, aStartOffset);
bmp.Canvas.LineTo(aEndOffset, aEndOffset);
bmp.SaveToFile(aFilename);
finally
bmp.Free;
end;
end;
var
mygraph: TMetafile;
bigBitmap: TBitmap;
begin
bigBitmap := TBitmap.Create;
try
bigBitmap.PixelFormat := pf24bit;
Assert(bigBitmap.HandleType = bmDIB, 'Handle Type should be a DIB');
bigBitmap.Width := SIZECONST;
bigBitmap.Height := SIZECONST;
mygraph := GetMyMetafile(bigBitmap.Canvas.Handle);
OutputToMetaFile('inscreen.emf', 0, 1000, SIZECONST, mygraph, bigBitmap.Canvas.Handle);
OutputToMetaFile('outsidescreen.emf', OFFSET, SIZECONST-1, SIZECONST, mygraph, bigBitmap.Canvas.Handle);
// do the same using bitmap
OutputToBitmap('inscreen.bmp', 0, 1000, SIZECONST, mygraph);
OutputToBitmap('outsidescreen.bmp', OFFSET, SIZECONST-1, SIZECONST, mygraph);
finally
bigBitmap.Free;
mygraph.Free;
end;
end.
Czy ktoś może zobaczyć, na czym polega problem lub czy znasz jakieś obejście tego problemu?
Aktualizacja
powinno mam włączone to kiedy pierwotnie zadawane pytanie. Testowaliśmy przy użyciu HDC dla dużej bitmapy i wyświetliliśmy ten sam problem. Zaktualizowałem przykładowy kod, aby to pokazać.
Aktualizacja 2
Niestety rozwiązanie jest wciąż nieuchwytny nawet po dobroci. Każda operacja BitBlt poza rozmiarem ekranu nie jest rysowana.
Oto ekstrakcja operacji MetaFile gdy obraz jest w granicach ekranu koordynuje:
R0001: [001] EMR_HEADER (s=108) {{ Bounds(500,500,18138,18129), Frame(0,0,105000,105000), ver(0x10000), size(688), recs(33), handles(2), pals(0), dev_pix(1080,1920), dev_mil(381,677), pixf_size(0), pixf_ofs(0), openGL(0) }}
R0002: [033] EMR_SAVEDC (s=8)
R0003: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0004: [028] EMR_SETMETARGN (s=8)
R0005: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0006: [037] EMR_SELECTOBJECT (s=12) {Stock object: 7=OBJ_PEN.(PS_SOLID | COSMETIC)}
R0007: [037] EMR_SELECTOBJECT (s=12) {Stock object: 14=OBJ_FONT}
R0008: [025] EMR_SETBKCOLOR (s=12) {0x00FFFFFF}
R0009: [024] EMR_SETTEXTCOLOR (s=12) {0x00000000}
R0010: [018] EMR_SETBKMODE (s=12) {iMode(2=OPAQUE)}
R0011: [019] EMR_SETPOLYFILLMODE (s=12) {iMode(1=ALTERNATE)}
R0012: [020] EMR_SETROP2 (s=12) {iMode(13=R2_COPYPEN)}
R0013: [021] EMR_SETSTRETCHBLTMODE (s=12) {iMode(1=BLACKONWHITE)}
R0014: [022] EMR_SETTEXTALIGN (s=12) {iMode(0= TA_LEFT TA_TOP)}
R0015: [013] EMR_SETBRUSHORGEX (s=16) {ptlOrigin(0,0)}
R0016: [058] EMR_SETMITERLIMIT (s=12) {Limit:0.000}
R0017: [027] EMR_MOVETOEX (s=16) { ptl(0,0)}
R0018: [035] EMR_SETWORLDTRANSFORM (s=32) {xform(eDx:500.000000, eDy:500.000000, eM11:5.039683, eM12:0.000000, eM21:0.000000, eM22:5.037203)}
R0019: [036] EMR_MODIFYWORLDTRANSFORM (s=36) {iMode(4=MWT_??), xform(eDx:500.000000, eDy:500.000000, eM11:5.039683, eM12:0.000000, eM21:0.000000, eM22:5.037203)}
R0020: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0021: [070] EMR_GDICOMMENT (s=40) {GDI.Begin Group}
R0022: [039] EMR_CREATEBRUSHINDIRECT (s=24) {ihBrush(1), style(0=BS_SOLID, color:0x000000FF)}
R0023: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0024: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0025: [076] EMR_BITBLT (s=100) {rclBounds(500,500,18138,18129), Dest[x:0, y:0, cx:3500, cy:3500)], dwRop(0x00F00021), Src[x:0, y:0, xform(eDx:0.000000, eDy:0.000000, eM11:1.000000, eM12:0.000000, eM21:0.000000, eM22:1.000000), BkColor:0x00000000, iUsage:0, offBmi:0, Bmi:0, offBits:0, Bits:0]}
R0026: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0027: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0028: [040] EMR_DELETEOBJECT (s=12) {ihObject(1)}
R0029: [070] EMR_GDICOMMENT (s=20) {GDI.End Group}
R0030: [034] EMR_RESTOREDC (s=12) {iRelative(-1)}
R0031: [027] EMR_MOVETOEX (s=16) { ptl(500,500)}
R0032: [054] EMR_LINETO (s=16) { ptl(1000,1000)}
R0033: [014] EMR_EOF (s=20) {nPalEntries:0, offPalEntries:16, nSizeLast:20}
Oto ekstrakcja operacji MetaFile gdy obraz jest poza granicami współrzędnych ekranu :
R0001: [001] EMR_HEADER (s=108) {{ Bounds(1500,1500,2999,2999), Frame(0,0,105000,105000), ver(0x10000), size(588), recs(32), handles(2), pals(0), dev_pix(1080,1920), dev_mil(381,677), pixf_size(0), pixf_ofs(0), openGL(0) }}
R0002: [033] EMR_SAVEDC (s=8)
R0003: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0004: [028] EMR_SETMETARGN (s=8)
R0005: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0006: [037] EMR_SELECTOBJECT (s=12) {Stock object: 7=OBJ_PEN.(PS_SOLID | COSMETIC)}
R0007: [037] EMR_SELECTOBJECT (s=12) {Stock object: 14=OBJ_FONT}
R0008: [025] EMR_SETBKCOLOR (s=12) {0x00FFFFFF}
R0009: [024] EMR_SETTEXTCOLOR (s=12) {0x00000000}
R0010: [018] EMR_SETBKMODE (s=12) {iMode(2=OPAQUE)}
R0011: [019] EMR_SETPOLYFILLMODE (s=12) {iMode(1=ALTERNATE)}
R0012: [020] EMR_SETROP2 (s=12) {iMode(13=R2_COPYPEN)}
R0013: [021] EMR_SETSTRETCHBLTMODE (s=12) {iMode(1=BLACKONWHITE)}
R0014: [022] EMR_SETTEXTALIGN (s=12) {iMode(0= TA_LEFT TA_TOP)}
R0015: [013] EMR_SETBRUSHORGEX (s=16) {ptlOrigin(0,0)}
R0016: [058] EMR_SETMITERLIMIT (s=12) {Limit:0.000}
R0017: [027] EMR_MOVETOEX (s=16) { ptl(0,0)}
R0018: [035] EMR_SETWORLDTRANSFORM (s=32) {xform(eDx:1500.000000, eDy:1500.000000, eM11:15.108969, eM12:0.000000, eM21:0.000000, eM22:15.101533)}
R0019: [036] EMR_MODIFYWORLDTRANSFORM (s=36) {iMode(4=MWT_??), xform(eDx:1500.000000, eDy:1500.000000, eM11:15.108969, eM12:0.000000, eM21:0.000000, eM22:15.101533)}
R0020: [115] EMR_SETLAYOUT (s=12) {iMode(0=<default>)}
R0021: [070] EMR_GDICOMMENT (s=40) {GDI.Begin Group}
R0022: [039] EMR_CREATEBRUSHINDIRECT (s=24) {ihBrush(1), style(0=BS_SOLID, color:0x000000FF)}
R0023: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0024: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0025: [037] EMR_SELECTOBJECT (s=12) {Table object: 1=OBJ_BRUSH.(BS_SOLID)}
R0026: [037] EMR_SELECTOBJECT (s=12) {Stock object: 0=OBJ_BRUSH.(BS_SOLID)}
R0027: [040] EMR_DELETEOBJECT (s=12) {ihObject(1)}
R0028: [070] EMR_GDICOMMENT (s=20) {GDI.End Group}
R0029: [034] EMR_RESTOREDC (s=12) {iRelative(-1)}
R0030: [027] EMR_MOVETOEX (s=16) { ptl(1500,1500)}
R0031: [054] EMR_LINETO (s=16) { ptl(2999,2999)}
R0032: [014] EMR_EOF (s=20) {nPalEntries:0, offPalEntries:16, nSizeLast:20}
Widać bardzo wyraźnie, że brakuje operacji BilBlt (R0025 w pierwszym).
Próbowaliśmy tego. Powinienem był to uwzględnić w pytaniu. Zaktualizuję pytanie za pomocą przykładu kodu, używając dużej bitmapy, która wykazuje ten sam problem. – Graymatter
Bounty przyznane za tę odpowiedź. Myślę, że odpowiedź leży albo w urządzeniu referencyjnym, które trzeba utworzyć, albo musimy czekać na naprawę systemu Windows. – Graymatter