Конференция "Media" » Алгоритм Wu
 
  • Dmk © (12.03.16 18:14) [0]
    Привет! Может кто сталкивался с алгоритмом Wu? Есть 2 функции, но обе работают некорректно.

    Ссылка на результат работы функций:
    http://postimg.org/image/5bn15901l/

    Функция 2. В ней пикселы перекрываются.

    procedure CircleAA2(ABitmap: TScreenBitmap; dX, dY: integer; radius: integer; AColor: TColorRef; dAlpha, dOpacity: byte);
    var
     fAlpha, pAlpha: byte;
     cX, cY: integer;
     rX, rY: integer;
     rX2, rY2: integer;
     x, y: double;
     Q: integer;
     error: single;

    procedure Set4Pixels(cX, cY, deltaX, deltaY: integer; iAlpha, iOpacity: byte);
    begin
     SetPixelInRect(ABitmap, cX + deltaX, cY + deltaY, AColor, iAlpha, iOpacity);
     SetPixelInRect(ABitmap, cX - deltaX, cY + deltaY, AColor, iAlpha, iOpacity);
     SetPixelInRect(ABitmap, cX + deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
     SetPixelInRect(ABitmap, cX - deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
    end;

    begin
     cX := dX;
     cY := dY;
     rX := radius;
     rY := radius;
     rX2 := rX * rX;
     rY2 := rY * rY;

     // upper and lower halves
     Q := round(rX2 / sqrt(rX2 + rY2));

     x := 0;
     while (x <= Q) do
     begin
       y := rY * Sqrt(1 - x * x / rX2);
       error := y - floor(y);
       fAlpha := Round(error * dAlpha);
       pAlpha := dAlpha - fAlpha;
       Set4Pixels(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set4Pixels(cX, cY, floor(x), floor(y) + 1, fAlpha, dOpacity);
       x := x + 1;
     end;

     // right and left halves
     Q := round(rY2 / sqrt(rX2 + rY2));

     y := 0;
     while (y <= Q) do
     begin
       x := rX * Sqrt(1 - y * y / rY2);
       error := x - floor(x);
       fAlpha := Round(error * dAlpha);
       pAlpha := dAlpha - fAlpha;
       Set4Pixels(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set4Pixels(cX, cY, floor(x) + 1, floor(y), fAlpha, dOpacity);
       y := y + 1;
     end;
    end;

  • Dmk © (12.03.16 18:16) [1]
    Функция 1 - еще не доделана, но суть та же - перекрывающиеся пикселы.
    Они или заползают друг на друга или не дорисовываются.

    procedure CircleAA(ABitmap: TScreenBitmap; dX, dY: integer; radius: integer; AColor: TColorRef; dAlpha, dOpacity: byte);
    var
     iX, iY: double;
     fX, fY: double;
     x, y: integer;
     fAlpha, pAlpha: byte;
     dRadius: double;
     xyEQ: boolean;

    const
     PI: double = 3.1415926535897932384626433832795;

    begin
     iX := 0;
     iY := 0;
     x := 0;
     y := 0;

     xyEQ := False;

     //1-й квадрант, X
     SetPixelInRect(ABitmap, dX, dY - radius, AColor, dAlpha, dOpacity);
     //2-й квадрант, Y
     SetPixelInRect(ABitmap, dX + radius, dY, AColor, dAlpha, dOpacity);
     //3-й квадрант, X
     SetPixelInRect(ABitmap, dX, dY + radius, AColor, dAlpha, dOpacity);
     //4-й квадрант, Y
     SetPixelInRect(ABitmap, dX - radius, dY, AColor, dAlpha, dOpacity);

     //dRadius := radius * Cos(PI / 4);

     //Значение с Windows калькулятора более точное, чем вычисление через Cos
     dRadius := radius * 0.99990604980155050801971795294044;

     while (x <= y) do
     begin
       //Вычисление точного значения координаты Y
       iY := Sqrt(radius * radius - x * x);
       y := Floor(Int(iY)); //Целая часть Y
       fY := (iY - y); //Дробная часть Y
       fAlpha := Floor(fY * dAlpha); //Альфа дробного остатка пиксела
       pAlpha := dAlpha - fAlpha; //Альфа пиксела

       if (x > 0) and (x < y) then
       begin
         //Квадрант 1, X
         SetPixelInRect(ABitmap, dX + x, dY - y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX + x, dY - y - 1, AColor, fAlpha, dOpacity);

         //Квадрант 2, X
         SetPixelInRect(ABitmap, dX + x, dY + y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX + x, dY + y + 1, AColor, fAlpha, dOpacity);

         //Квадрант 3, X
         SetPixelInRect(ABitmap, dX - x, dY + y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX - x, dY + y + 1, AColor, fAlpha, dOpacity);

         //Квадрант 4, X
         SetPixelInRect(ABitmap, dX - x, dY - y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX - x, dY - y - 1, AColor, fAlpha, dOpacity);
       end;

       if (x = y) then
       begin
         InfoMessage(Form3.Handle, 'iY: ' + IntToStr(y)+ ' ' + 'fY: ' + FloatToStrF(fY, ffNumber, 18, 2));

         xyEQ := True;

         //Квадрант 1, X
         SetPixelInRect(ABitmap, dX + x, dY - y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX + x, dY - y - 1, AColor, fAlpha, dOpacity);

         //Квадрант 2, X
         SetPixelInRect(ABitmap, dX + x, dY + y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX + x, dY + y + 1, AColor, fAlpha, dOpacity);

         //Квадрант 3, X
         SetPixelInRect(ABitmap, dX - x, dY + y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX - x, dY + y + 1, AColor, fAlpha, dOpacity);

         //Квадрант 4, X
         SetPixelInRect(ABitmap, dX - x, dY - y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX - x, dY - y - 1, AColor, fAlpha, dOpacity);
       end;

       x := x + 1;
     end;

     x := 0;
     y := 0;

     while (y <= x) do
     begin
       //Вычисление точного значения координаты Y
       iX := Sqrt(radius * radius - y * y);
       x := Floor(Int(iX)); //Целая часть X
       fX := (iX - x); //Дробная часть X
       fAlpha := Floor(fX * dAlpha); //Альфа дробного остатка пиксела
       pAlpha := dAlpha - fAlpha; //Альфа пиксела

       if (y > 0) and (y < x) then
       begin
         //Квадрант 1, Y
         SetPixelInRect(ABitmap, dX + x, dY - y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX + x + 1, dY - y, AColor, fAlpha, dOpacity);

         //Квадрант 2, Y
         SetPixelInRect(ABitmap, dX + x, dY + y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX + x + 1, dY + y, AColor, fAlpha, dOpacity);

         //Квадрант 3, Y
         SetPixelInRect(ABitmap, dX - x, dY + y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX - x - 1, dY + y, AColor, fAlpha, dOpacity);

         //Квадрант 4, Y
         SetPixelInRect(ABitmap, dX - x, dY - y, AColor, pAlpha, dOpacity);
         SetPixelInRect(ABitmap, dX - x - 1, dY - y, AColor, fAlpha, dOpacity);
       end;

       y := y + 1;
     end;
    end;

  • Dmk © (12.03.16 18:18) [2]
    В некоторых случаях x=y вообще отсутствует.
    Хочется понять, в чем проблема. Не хватает точности сопроцессора?
  • Pavia © (12.03.16 18:27) [3]
    Рисуешь ты 4 сегмента. Рисовать надо по кругу. Последний пиксель сегмента не рисуешь. Начальный(нуливой) пиксель рисуешь у каждого сегмента. Так у тебя не будет дублирования и пропусков.

    Тоже самое с квадратом.
  • Dmk © (12.03.16 20:08) [4]
    Тут другая тема. Все рисуется правильно при альфа = 1. При 0.5 видно перекрывающиеся пикселы. Вот этого я и хочу избежать. Чтобы при любом диаметре и альфе был идеальный "пушистый" круг :) Даже при дробном диаметре.

    Потому что при радиусах 49 - 56 все рисуется идеально, как и должно быть. До 49 и после 56 почему то точность пропадает. Потом идеальный промежуток 189-196. Потом опять разрывы.

    Насколько я понимаю, тут 1 пиксел расползается то ли по окружности, то ли еще куда, т.к. при заданном радиусе, скажем 42, получается диаметр 85. 1 пиксел появляется из округлений до целого.
  • Dmk © (12.03.16 20:48) [5]
    Видимо X дробный надо делать, а не целочисленный.
  • Pavia © (12.03.16 20:52) [6]

    > Тут другая тема. Все рисуется правильно при альфа = 1. При
    > 0.5 видно перекрывающиеся пикселы.

    Ну так я о чём вам толкую. У вас пискели смежных сегментов перекрываются.

    Где может быть такое перекрьыие только в начале и в конце.
    Подставим


    x := 0;                                      // X=0
     while (x <= Q) do
     begin
       y := rY * Sqrt(1 - x * x / rX2);   // y=rY
       error := y - floor(y);                 // error=0
       fAlpha := Round(error * dAlpha);// fAlpha=0
       pAlpha := dAlpha - fAlpha;        // pAlpha=dAlpha=пусть 0.5
       Set4Pixels(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set4Pixels(cX, cY, floor(x), floor(y) + 1, fAlpha, dOpacity);
       x := x + 1;
     end;


    Откуда deltaX=0, deltaY=rY
    procedure Set4Pixels(cX, cY, deltaX, deltaY: integer; iAlpha, iOpacity: byte);
    begin
     SetPixelInRect(ABitmap, cX + deltaX, cY + deltaY, AColor, iAlpha, iOpacity); // cX + deltaX=cX, cY + deltaY=cY+rY
     SetPixelInRect(ABitmap, cX - deltaX, cY + deltaY, AColor, iAlpha, iOpacity); //
    cX + deltaX=cX, cY + deltaY=cY+rY
     SetPixelInRect(ABitmap, cX + deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
     SetPixelInRect(ABitmap, cX - deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
    end;

    Вот вам сразуже на первом шаге у вас перекрытие.
    Что-бы такого не было рисуйте все сегменты в одном направлении к примеру по часовой стрелки. Только последний пиксель в сегменте не рисуете.

    var
     fAlpha, pAlpha: byte;
     cX, cY: integer;
     rX, rY: integer;
     rX2, rY2: integer;
     x, y: double;
     Q: integer;
     error: single;

    procedure Set2Pixels1(cX, cY, deltaX, deltaY: integer; iAlpha, iOpacity: byte);
    begin
     SetPixelInRect(ABitmap, cX + deltaX, cY + deltaY, AColor, iAlpha, iOpacity);
    //Перемещаем  SetPixelInRect(ABitmap, cX - deltaX, cY + deltaY, AColor, iAlpha, iOpacity);
     SetPixelInRect(ABitmap, cX + deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
    //Перемещаем   SetPixelInRect(ABitmap, cX - deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
    end;

    procedure Set2Pixels2(cX, cY, deltaX, deltaY: integer; iAlpha, iOpacity: byte);
    begin
     SetPixelInRect(ABitmap, cX - deltaX, cY + deltaY, AColor, iAlpha, iOpacity);
     SetPixelInRect(ABitmap, cX - deltaX, cY - deltaY, AColor, iAlpha, iOpacity);
    end;

    begin
     cX := dX;
     cY := dY;
     rX := radius;
     rY := radius;
     rX2 := rX * rX;
     rY2 := rY * rY;

     // upper and lower halves
     Q := round(rX2 / sqrt(rX2 + rY2));

     x := 0;
     while (x < Q) do  // Не дорисовываем последний пиксель
     begin
       y := rY * Sqrt(1 - x * x / rX2);
       error := y - floor(y);
       fAlpha := Round(error * dAlpha);
       pAlpha := dAlpha - fAlpha;
       Set2Pixels1(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set2Pixels1(cX, cY, floor(x), floor(y) + 1, fAlpha, dOpacity);
       x := x + 1;
     end;

     // right and left halves
     Q := round(rY2 / sqrt(rX2 + rY2));

     y := 0;
     while (y < Q) do // Не дорисовываем последний пиксель
     begin
       x := rX * Sqrt(1 - y * y / rY2);
       error := x - floor(x);
       fAlpha := Round(error * dAlpha);
       pAlpha := dAlpha - fAlpha;
       Set2Pixels1(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set2Pixels1(cX, cY, floor(x) + 1, floor(y), fAlpha, dOpacity);
       y := y + 1;
     end;

    // Рисуем оставшиеся сегменты
    // У вас они часть рисовались, по часовой другая против.
    // Так что разворачиваем оставшиеся. Что-бы все рисовались в одну сторону.
     cX := dX;
     cY := dY;
     rX := radius;
     rY := radius;
     rX2 := rX * rX;
     rY2 := rY * rY;

     // upper and lower halves
     Q := round(rX2 / sqrt(rX2 + rY2));

     x := rX;
     while (x >= 0) do // Не дорисовываем последний пиксель
     begin
       y := rY * Sqrt(1 - x * x / rX2);
       error := y - floor(y);
       fAlpha := Round(error * dAlpha);
       pAlpha := dAlpha - fAlpha;
       Set2Pixels2(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set2Pixels2(cX, cY, floor(x), floor(y) + 1, fAlpha, dOpacity);
       x := x - 1;
     end;
     // right and left halves
     Q := round(rY2 / sqrt(rX2 + rY2));

     y := rY;
     while (y >= 0) do  // Не дорисовываем последний пиксель
     begin
       x := rX * Sqrt(1 - y * y / rY2);
       error := x - floor(x);
       fAlpha := Round(error * dAlpha);
       pAlpha := dAlpha - fAlpha;
       Set2Pixels2(cX, cY, floor(x), floor(y), pAlpha, dOpacity);
       Set2Pixels2(cX, cY, floor(x) + 1, floor(y), fAlpha, dOpacity);
       y := y - 1;
     end;

    end;


    Код не проверял но должен работаь
  • Dmk © (12.03.16 21:14) [7]
    >Pavia ©   (12.03.16 20:52) [6]
    Да не. Не о том речь. Центральный пиксел то не делится. Отсюда и расхождение. На рисунке видно, что пикселы не доливаются до конца. В вашем варианте получилось то же что и у меня. Я тоже дошел до этого момента и завис. Тут X дробный нужен иначе никак. Если взять Линию Ву, то там и X и Y дробные. Поэтому она получается ровненькая. Тут так же надо.
  • Dmk © (12.03.16 21:41) [8]
    Тут вот такая ерунда получается:
    http://hostingkartinok.com/show-image.php?id=d86b12c0e4e88151e8294ce3e0aad95d

    Вращение вокруг 1 пиксела прибавляет его к окружности. Отсюда и разрывы.
  • Dmk © (12.03.16 21:44) [9]
    Зная это тут надо или x,y на единицу смещать для каждого квадранта или дробный X, Y делать с шагом меньше единицы.
  • NoUser © (12.03.16 21:58) [10]
    Не хватает точности сопроцессора?
    Ага, ))   https://habrahabr.ru/company/xakep/blog/257897/


    >  //dRadius := radius * Cos(PI / 4);
    >  //Значение с Windows калькулятора более точное, чем вычисление через Cos
    >  dRadius := radius * 0.99990604980155050801971795294044;


    тут c радианами все хорошо?

    Кроме Floor и Int есть еще Trunc, Frac, Round, Ceil.
  • Dmk © (12.03.16 22:37) [11]
    NoUser ©   (12.03.16 21:58) [10]

    Спасибо, но косинус выкинут за ненадобностью.
    Заменил на Round — пока лидер среди округления :)
    Разрывы стали совсем маленькими ;)))
  • Dmk © (13.03.16 07:32) [12]
    Странно, но Cos(45) выдает полную чушь. Сто-то около 0.52, а Sin(45) около 0.85.
    sqrt(2)/2 - правильно - 0.707....
  • Pavia © (13.03.16 09:41) [13]

    > Странно, но Cos(45) выдает полную чушь. Сто-то около 0.52,
    >  а Sin(45) около 0.85.sqrt(2)/2 - правильно - 0.707....

    Если хочется работать. Ляг поспи и всё пройдёт. :-)
    Обычно в Cos и Sin  принимают на вход значения в радианах.
    Cos(45 рад.)=0.52
    Cos(45°/180°*(Pi рад))=0.707
  • Dmk © (13.03.16 10:39) [14]
    Pavia ©   (13.03.16 09:41) [13]
    Не знал, спасибо. Думал как в калькуляторе в градусах.

    Пока удалось найти величину разрыва:
    http://hostingkartinok.com/show-image.php?id=1d087e2954724b890129e4aa5bec2cc1
    Если в минус, то функция недостаточна. Если в плюс, то перекрытие.
    Не учил я математику хорошо.

    Вопрос: как привести функцию обратно в линейную величину? Т.е. действие обратное косинусу?
  • Dmk © (13.03.16 11:17) [15]
    >Вопрос: как привести функцию обратно в линейную величину? Т.е. действие обратное косинусу?
    Все, разобрался. sqrt(2).
  • NoUser © (13.03.16 14:11) [16]
    > Не учил я математику хорошо ))

    http://festival.1september.ru/articles/613708/

    Учим наизусть! Арккосинус.
  • Dmk © (13.03.16 14:17) [17]
    >Учим наизусть!
    Для чего? Кроме того я уже нашел, то что мне надо. Спасибо!
  • Dmk © (14.03.16 07:27) [18]
    Научился компенсировать альфу при превышении функции:
    http://hostingkartinok.com/show-image.php?id=edb39c0d876b66ae5604d27c028ea278

    Не пойму что делать если x=y? В цикле по X и в цикле по Y эти пикселы (x=y) встречаются дважды. Если ослабить альфу ровно в 2 раза, то получаются провалы (разрывы). Пока не понял что делать. Видимо надо как то от максимума функции считать. Максимум у меня считается так:
    cosX2 := sqrt(2);
     cosX := cosX2/2;
     maxX := cosX * radius;


    В общем вопрос остается открытым: как компенсировать альфу при x=y? Разницы функции в данной точке идет в плюс, т.е. разрыв.
  • Dmk © (14.03.16 07:28) [19]
    Вот весь код процедуры:

    procedure CircleAA(ABitmap: TScreenBitmap; dX, dY: integer; radius: integer; AColor: TColorRef; dAlpha, dOpacity: byte);
    var
     iX, iY: double;
     fX, fY: double;
     x, y: integer;
     fAlpha, pAlpha: byte;
     iR: double;
     xInc, yInc: double;
     fxInc, fyInc: double;
     maxX, maxY: double;
     difX, difY: double;
     cosX, cosY: double;
     cosX2: double;
     aP: double;

     //X - т.е. ближе к горизонтали
     procedure Set8XPixels(sX, sY, deltaX, deltaY: integer; sColor: TColorRef; pixelAlpha, fracAlpha, sOpacity: byte);
     begin
       //Квадрант 1, X
       SetPixelInRect(ABitmap, sX + deltaX, sY - deltaY, sColor, pixelAlpha, sOpacity);
       SetPixelInRect(ABitmap, sX + deltaX, sY - deltaY - 1, sColor, fracAlpha, sOpacity);
       //Квадрант 2, X
       SetPixelInRect(ABitmap, sX + deltaX, sY + deltaY, sColor, pixelAlpha, sOpacity);
       SetPixelInRect(ABitmap, sX + deltaX, sY + deltaY + 1, sColor, fracAlpha, sOpacity);
       //Квадрант 3, X
       SetPixelInRect(ABitmap, sX - deltaX, sY + deltaY, sColor, pixelAlpha, sOpacity);
       SetPixelInRect(ABitmap, sX - deltaX, sY + deltaY + 1, sColor, fracAlpha, sOpacity);
       //Квадрант 4, X
       SetPixelInRect(ABitmap, sX - deltaX, sY - deltaY, sColor, pixelAlpha, sOpacity);
       SetPixelInRect(ABitmap, sX - deltaX, sY - deltaY - 1, sColor, fracAlpha, sOpacity);
     end;

     //Y - т.е. ближе к вертикали
     procedure Set8YPixels(sX, sY, deltaX, deltaY: integer; sColor: TColorRef; pixelAlpha, fracAlpha, sOpacity: byte);
     begin
       //Квадрант 1, Y
       SetPixelInRect(ABitmap, sX + deltaX, sY - deltaY, sColor, pixelAlpha, dOpacity);
       SetPixelInRect(ABitmap, sX + deltaX + 1, sY - deltaY, sColor, fracAlpha, dOpacity);
       //Квадрант 2, Y
       SetPixelInRect(ABitmap, sX + deltaX, sY + deltaY, sColor, pixelAlpha, dOpacity);
       SetPixelInRect(ABitmap, sX + deltaX + 1, sY + deltaY, sColor, fracAlpha, dOpacity);
       //Квадрант 3, Y
       SetPixelInRect(ABitmap, sX - deltaX, sY + deltaY, sColor, pixelAlpha, dOpacity);
       SetPixelInRect(ABitmap, sX - deltaX - 1, sY + deltaY, sColor, fracAlpha, dOpacity);
       //Квадрант 4, Y
       SetPixelInRect(ABitmap, sX - deltaX, sY - deltaY, sColor, pixelAlpha, dOpacity);
       SetPixelInRect(ABitmap, sX - deltaX - 1, sY - deltaY, sColor, fracAlpha, dOpacity);
     end;

     procedure CorrectAlpha(funcDifference: double; var pixelAlpha, fracAlpha: byte);
     var
       dA: byte;

     begin
       //Перекрытие функции (-f(x)) на последнем шаге
       //Нужно ослабить альфу пиксела
       if (funcDifference < 0) then
       begin
         dA := Round((-funcDifference) * cosX2 * 100 * aP);
         if dA < pixelAlpha then
           pixelAlpha := pixelAlpha - dA else
           pixelAlpha := 0;
         if dA < fracAlpha then
           fracAlpha := fracAlpha - dA else
           fracAlpha := 0;
       end
       else
       //Разрыв функции (+f(x)) на последнем шаге
       //Нужно усилить альфу пиксела
       if (funcDifference > 0) then
       begin
         dA := Round((funcDifference) * cosX2 * 100 * aP);
         if (dA + pixelAlpha) < dAlpha then
           pixelAlpha := pixelAlpha + dA else
           pixelAlpha := dAlpha;
         if (dA + fracAlpha) < dAlpha then
           fracAlpha := fracAlpha + dA else
           fracAlpha := dAlpha;
       end;
     end;

    begin
     //Альфа для пикселов в нулевом положении
     fAlpha := Round(dAlpha * 0.5);
     //1-й квадрант, X
     SetPixelInRect(ABitmap, dX, dY - radius, AColor, fAlpha, dOpacity);
     SetPixelInRect(ABitmap, dX, dY - radius + 1, AColor, fAlpha, dOpacity);
     //2-й квадрант, Y
     SetPixelInRect(ABitmap, dX + radius, dY, AColor, fAlpha, dOpacity);
     SetPixelInRect(ABitmap, dX + radius - 1, dY, AColor, fAlpha, dOpacity);
     //3-й квадрант, X
     SetPixelInRect(ABitmap, dX, dY + radius, AColor, fAlpha, dOpacity);
     SetPixelInRect(ABitmap, dX, dY + radius - 1, AColor, fAlpha, dOpacity);
     //4-й квадрант, Y
     SetPixelInRect(ABitmap, dX - radius, dY, AColor, fAlpha, dOpacity);
     SetPixelInRect(ABitmap, dX - radius + 1, dY, AColor, fAlpha, dOpacity);

     //1% альфы
     aP := dAlpha / 100;

     //Вычтем пол пиксела из радиуса
     //чтобы компенсировать логический
     //центральный пиксел
     iR := radius - 0.5;

     cosX2 := sqrt(2);
     cosX := cosX2/2;
     cosY := cosX;
     maxX := cosX * iR;
     maxY := maxX;

     //Линейный шаг по X
     xInc := iR / radius;
     yInc := xInc;

     //Функциональный шаг
     fxInc := xInc * cosX;
     fyInc := yInc * cosY;

     //дробные X и Y
     iX := 0;
     iY := 0;

     //Целочисленные X и Y
     x := 0;
     y := 0;

     //Пока (X > Y)
     repeat
       //Дробный Y
       iY := Sqrt(iR * iR - iX * iX);
       y := Round(Int(iY)); //Целая часть Y
       fY := (iY - y); //Дробная часть Y
       fAlpha := Round(fY * dAlpha); //Альфа дробного остатка пиксела
       pAlpha := dAlpha - fAlpha; //Альфа пиксела

         {difX := (maxX - iX);
         CorrectAlpha(difX, pAlpha, fAlpha);
         InfoMessage(Form3.Handle, 'x = y: ' +
                                   'макс f(X): ' + FloatToStrF(maxX, ffNumber, 18, 4) + '  ' +
                                   'iX: ' + FloatToStrF(iX, ffNumber, 18, 4) + '  ' +
                                   'difX: ' + FloatToStrF(difX, ffNumber, 18, 4));}

       if (iX > maxX) then
       begin
         if (x = y) then
         begin
         end
         else
         begin
           difX := (maxX - iX);
           CorrectAlpha(difX, pAlpha, fAlpha);
         end;
       end;

       //Пропустим нулевые пикселы
       //т.к. они уже стоят
       if (x > 0) then
       begin
         Set8XPixels(dX, dY, x, y, AColor, pAlpha, fAlpha, dOpacity);
       end;

       //Следующий дробный X
       iX := iX + xInc;
       //Округленный X
       x := Round(iX);
     until (x > y);

     //дробные X и Y
     iX := 0;
     iY := 0;

     //Целочисленные X и Y
     x := 0;
     y := 0;

     //Пока (Y > X)
     repeat
       //Дробный X
       iX := Sqrt(iR * iR - iY * iY);
       x := Round(Int(iX)); //Целая часть X
       fX := (iX - x); //Дробная часть X
       fAlpha := Round(fX * dAlpha); //Альфа дробного остатка пиксела
       pAlpha := dAlpha - fAlpha; //Альфа пиксела

       if (iY > maxY) then
       begin
         if (x = y) then
         begin
         end
         else
         begin
           difY := (maxY - iY);
           CorrectAlpha(difY, pAlpha, fAlpha);
         end;
       end;

       //Пропустим нулевые пикселы
       //т.к. они уже стоят
       if (y > 0) then
       begin
         Set8YPixels(dX, dY, x, y, AColor, pAlpha, fAlpha, dOpacity);
       end;

       iY := iY + yInc;
       y := Round(iY);
     until (y > x);
    end;

 
Конференция "Media" » Алгоритм Wu
Есть новые Нет новых   [134427   +37][b:0][p:0.01]