Конференция "WinAPI" » Сглаживание при использовании SetWindowExtEx и SetViewportExtEx
 
  • Line (27.05.13 18:45) [0]
    В коде предпросмотра печати используются функции 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); // Задаем размер (extent) области отображения в логических(!) единицах
     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

    Кто-нибудь знает как избежать таких искажений? Может быть сглаживание можно включить или вообще по другому все сделать?
  • MBo © (28.05.13 05:19) [1]
    SetStretchBltMode c HALFTONE в данном случае работает?
  • Line (28.05.13 10:26) [2]
    Добавил 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); // Задаем размер (extent) области отображения в логических(!) единицах
     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.
  • Павиа (28.05.13 12:52) [3]
    Линия двоиться из-за того что масштаб не кратен 2.

    GDI не рисует дробно. Поэтому HALFTONE не поможет.
    Как вариант сменить GDI на что-нибудь поприличнее. К примеру AggPas

    А вообще сжатие это операция с потерью данных. Т.е точность теряется и искажения будут по любому. Посмотри как это делается в фотошпе или автокоде. На предпросмотре общие четы. А если нажать то отображается 1к 1 без масштабиования, но обрезанная.
  • Line (28.05.13 13:30) [4]

    > Линия двоиться из-за того что масштаб не кратен 2.
    Понятно :(



    > GDI не рисует дробно. Поэтому HALFTONE не поможет.
    > Как вариант сменить GDI на что-нибудь поприличнее. К примеру
    > AggPas

    Посмотрел AggPas. Она похоже не адаптировалась для Delphi 2009 и выше.
    У меня на XE не компилится. Какие еще есть альтернативы? Может GDI+?


    > А вообще сжатие это операция с потерью данных. Т.е точность
    > теряется и искажения будут по любому. Посмотри как это делается
    > в фотошпе или автокоде. На предпросмотре общие четы. А если
    > нажать то отображается 1к 1 без масштабиования, но обрезанная.

    Мне надо примерно как в Ворде. Там в предпросмотре даже при очень маленьком масштабе структура табличек сохраняется.
  • Павиа (28.05.13 14:16) [5]

    > Может GDI+?

    Должна. Но я не знаток GDI+
  • Dimka Maslov © (28.05.13 21:02) [6]
    Рисуем превью в метафайл, а не в битмап и масштабируем его. На худой конец делаем свою процедуру масштабирования растра через бикубическую интерполяцию.
  • brother © (29.05.13 13:56) [7]
    > Она похоже не адаптировалась для Delphi 2009 и выше.

    http://www.crossgl.com/aggpas/

    Updated version (D2009 & D2010) of AggPas library is available here.

  • Line (29.05.13 15:14) [8]
    > brother ©   (29.05.13 13:56) [7]
    Что-то я это пропустил :)

    Я уже воспользовался советом Dimka Maslov. Так действительно удобнее.

    Всем спасибо!
 
Конференция "WinAPI" » Сглаживание при использовании SetWindowExtEx и SetViewportExtEx
Есть новые Нет новых   [134428   +40][b:0][p:0.003]