-
В коде предпросмотра печати используются функции SetWindowExtEx и SetViewportExtEx для задания области отображения. Но так как разрешение при печати большое, а окно предпросмотра по сравнению с ним маленькое, то происходит сильное уменьшение изображения, что приводит к искажениям. Для примера накидал небольшой пример:
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
h, w: Integer;
h2, w2: Integer;
x: Integer;
begin
h := 4000;
w := 5000;
h2 := 600;
w2 := 600;
SetMapMode(Image1.Canvas.Handle, MM_ANISOTROPIC); SetWindowExtEx(Image1.Canvas.Handle, h, w, nil); SetViewportExtEx(Image1.Canvas.Handle, h2, w2, nil);
Image1.Canvas.Font.PixelsPerInch := 600;
Image1.Canvas.Pen.Width :=1;
Image1.Canvas.Pen.Color := clBlack;
Image1.Canvas.FillRect(Rect(0, 0, 4000, 4000));
for i := 0 to 10 do
begin
Image1.Canvas.MoveTo(10, i*90);
Image1.Canvas.LineTo(4000, i*90);
Image1.Canvas.MoveTo(10, i*90 + 1);
Image1.Canvas.LineTo(4000, i*90 + 1);
Image1.Canvas.MoveTo(i*90, 10);
Image1.Canvas.LineTo(i*90, 4000);
Image1.Canvas.MoveTo(i*90 + 1, 10);
Image1.Canvas.LineTo(i*90 + 1, 4000);
end;
end;
http://yadi.sk/d/dqa9S-5o5DqxOКто-нибудь знает как избежать таких искажений? Может быть сглаживание можно включить или вообще по другому все сделать?
-
SetStretchBltMode c HALFTONE в данном случае работает?
-
Добавил HALFTONE - не помогает. procedure TForm1.Button2Click(Sender: TObject);
var
i: Integer;
h, w: Integer;
h2, w2: Integer;
x: Integer;
begin
h := 4000;
w := 5000;
h2 := 600;
w2 := 600;
SetMapMode(Image1.Canvas.Handle, MM_ANISOTROPIC); SetWindowExtEx(Image1.Canvas.Handle, h, w, nil); SetViewportExtEx(Image1.Canvas.Handle, h2, w2, nil);
SetStretchBltMode(Image1.Canvas.Handle, HALFTONE);
Image1.Canvas.Font.PixelsPerInch := 600;
Image1.Canvas.Pen.Width :=1;
Image1.Canvas.Pen.Color := clBlack;
Image1.Canvas.FillRect(Rect(0, 0, 4000, 4000));
for i := 0 to 10 do
begin
Image1.Canvas.MoveTo(10, i*90);
Image1.Canvas.LineTo(4000, i*90);
Image1.Canvas.MoveTo(10, i*90 + 1);
Image1.Canvas.LineTo(4000, i*90 + 1);
Image1.Canvas.MoveTo(i*90, 10);
Image1.Canvas.LineTo(i*90, 4000);
Image1.Canvas.MoveTo(i*90 + 1, 10);
Image1.Canvas.LineTo(i*90 + 1, 4000);
end;
end; Пробовал рисовать на большой битмапе и потом сжимать изобржение - тоже не прокатило, они должны быть размером больше 7000*5000 пикселей, при создании такой битмапы выдается out of memory.
-
Линия двоиться из-за того что масштаб не кратен 2.
GDI не рисует дробно. Поэтому HALFTONE не поможет. Как вариант сменить GDI на что-нибудь поприличнее. К примеру AggPas
А вообще сжатие это операция с потерью данных. Т.е точность теряется и искажения будут по любому. Посмотри как это делается в фотошпе или автокоде. На предпросмотре общие четы. А если нажать то отображается 1к 1 без масштабиования, но обрезанная.
-
> Линия двоиться из-за того что масштаб не кратен 2. Понятно :(
> GDI не рисует дробно. Поэтому HALFTONE не поможет. > Как вариант сменить GDI на что-нибудь поприличнее. К примеру > AggPas
Посмотрел AggPas. Она похоже не адаптировалась для Delphi 2009 и выше. У меня на XE не компилится. Какие еще есть альтернативы? Может GDI+?
> А вообще сжатие это операция с потерью данных. Т.е точность > теряется и искажения будут по любому. Посмотри как это делается > в фотошпе или автокоде. На предпросмотре общие четы. А если > нажать то отображается 1к 1 без масштабиования, но обрезанная.
Мне надо примерно как в Ворде. Там в предпросмотре даже при очень маленьком масштабе структура табличек сохраняется.
-
> Может GDI+?
Должна. Но я не знаток GDI+
-
Рисуем превью в метафайл, а не в битмап и масштабируем его. На худой конец делаем свою процедуру масштабирования растра через бикубическую интерполяцию.
-
> Она похоже не адаптировалась для Delphi 2009 и выше. http://www.crossgl.com/aggpas/Updated version (D2009 & D2010) of AggPas library is available here.
-
> brother © (29.05.13 13:56) [7] Что-то я это пропустил :)
Я уже воспользовался советом Dimka Maslov. Так действительно удобнее.
Всем спасибо!
|