Как переиспользовать один и тот же bitmap при многократной отрисовке в EMF?
Мне нужно много раз отрисовывать большой TBitmap32 в EMF. Каждый раз битмап один и тот же, но его смещение и размер могут меняться.
Если рисовать наивно (кейс 1), то все работает хорошо, но размер EMF огромен, потому что он сохраняет новую копию битмапа для каждой операции отрисовки.
Было бы здорово, если бы EMF позволял повторно использовать один и тот же исходный битмап в вызовах отрисовки, но это, похоже, не работает (кейс 2).
Использование кисти могло бы быть хорошим решением, но её экземпляры нельзя независимо масштабировать.
Пример кода:
procedure CreateStretchedBitmapEMF(aMode: Integer; const aMetafilePath: string);
var
Metafile: TMetafile;
MetafileCanvas: TMetafileCanvas;
Bitmap32: TBitmap32;
begin
Metafile := TMetafile.Create;
Metafile.Width := 800;
Metafile.Height := 600;
MetafileCanvas := TMetafileCanvas.Create(Metafile, 0);
Bitmap32 := TBitmap32.Create;
Bitmap32.LoadFromFile('sample.bmp'); // 1000x1000px
case aMode of
1: // Работает, но размер файла 39mb
for var i := 0 to 9 do
StretchBlt(MetafileCanvas.Handle, i * 60, i * 40, 100, 100, Bitmap32.Handle, 0, 0, Bitmap32.Width, Bitmap32.Height, SRCCOPY);
2: // Работает, но размер файла 39mb
begin
var TempBitmap := TBitmap.Create;
TempBitmap.PixelFormat := pf32bit;
TempBitmap.Width := Bitmap32.Width;
TempBitmap.Height := Bitmap32.Height;
Bitmap32.DrawTo(TempBitmap.Canvas.Handle, 0, 0);
var CompatibleDC: HDC := CreateCompatibleDC(MetafileCanvas.Handle);
var OldBitmap: HGDIOBJ := SelectObject(CompatibleDC, TempBitmap.Handle);
for var i := 0 to 9 do
StretchBlt(MetafileCanvas.Handle, i * 60, i * 40, 100, 100, CompatibleDC, 0, 0, TempBitmap.Width, TempBitmap.Height, SRCCOPY);
SelectObject(CompatibleDC, OldBitmap);
DeleteDC(CompatibleDC);
end;
3: // Не работает как надо, но размер файла 3.9mb
begin
var TempBitmap := TBitmap.Create;
TempBitmap.PixelFormat := pf32bit;
TempBitmap.Width := Bitmap32.Width;
TempBitmap.Height := Bitmap32.Height;
Bitmap32.DrawTo(TempBitmap.Canvas.Handle, 0, 0);
var PatternBrush := CreatePatternBrush(TempBitmap.Handle);
var OldBrush := SelectObject(MetafileCanvas.Handle, PatternBrush);
for var i := 0 to 9 do
begin
SetRectRgn(PatternBrush, 0, 0, 100, 100);
FillRect(MetafileCanvas.Handle, Rect(i * 60, i * 40, i * 60 + 100, i * 40 + 100), PatternBrush);
end;
SelectObject(MetafileCanvas.Handle, OldBrush);
DeleteObject(PatternBrush);
end;
end;
Bitmap32.Free;
MetafileCanvas.Free;
Metafile.SaveToFile(aMetafilePath);
Metafile.Free;
end;
Примеры 1 и 2 выглядят хорошо, но занимают слишком много места. Размер EMF увеличивается при каждой операции рисования (несмотря на то, что исходное растровое изображение одно и то же):
[![введите сюда описание изображения][1]][1]
Пример 3 занимает меньше места, но выглядит неправильно:
[![введите сюда описание изображения][2]][2]
Вопрос - как переиспользовать один битмап для многократной отрисовки с разными размерами в EMF?
[1]: https://i.sstatic.net/TiTrYBJj.png
[2]: https://i.sstatic.net/vUqnGAo7.png