Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

СообЧА. Программирование на Delphi


Служба Рассылок Subscribe.Ru проекта Citycat.Ru


 

Мир Delphi

Pixelsoftware

  Подписчиков: 3450 
   

.::::: СообЧа - Программирование на Delphi :::::.

  ї 2000 - 2001COOLer  Дизайн: Yoghurt 
   

 

Оглавление

  В выпуске  Рассылка СообЧА 
    
 
Рассылки Subscribe.Ru
СообЧа (СООБщество ЧАйников). Обмен опытом, вопросы, ответы.

 Назад к оглавлению  
  
  Конкурсы и предложения... 
 
  
  • Участвуйте в конкурсе "Статья месяца" и вы выиграете книгу по Delphi от магазина ОЗОН. В конце каждого месяца Вами будет выбран лучший автор, который и получит книгу. Присылайте ваши статьи на  pixel@novgorod.net . Авторов просим строго придерживаться тематики рассылки.

Хотите поучаствовать в нашем проекте, вы умеете работать с OpenGL или DX? Присоединяйтесь вместе мы напишем классную RPG ... То что готово, уже есть на скриншотах в разделе проект... Желательны(Хотя не обязательны , по ходу сами все поймете) знания Borland C++ Builder или Delphi в сфере графики(или просто кодеры).Все абсолютно свободно freewareно и бесплатно. ПОЛНЫЙ ДОСТУП К НАШИМ ИСХОДНИКАМ.

+Требуется помощь по поиску софта в сети.

+Требуется опытный образец заголовка файла для карты.

 

10:00-12:00 Оптимизация и ее применение.

12:00-15:00 VCl

15:00-17:00 Системный API

17:00-21:00 БД обсуждение

после 22:05 в чате появляюсь я(периодически)

p.s тему соблюдать не обязательно

  • Предлагаем вашему вниманию еще одну идею, вы посылаете мне письмо с вопросом по дельфи , а я публикую ответ в рубрике FAQ. Одно условие, с БД не преставать я в этой области не фонтан... :(  pixel@novgorod.net 

  • Нравится ли вам наша рассылка?

  • Да

    Нет

    Не успел оценить

     Назад к оглавлению  
      
      Выбор лучшего. 
     
      
    ув. Подписчики. пожалуйста оцените труд данных авторов отдав свой голос за того, кого вы считаете достойным. 31 июля по итогам голосования лучшему автору будет подарена книга от магазина "ОЗОН". Если вы хотите увидить своё имя среди авторов - то прочитайте условия конкурса Выбери лучшего
    Pixel
    PILOT
    Art
    Anatoly
     Назад к оглавлению  
      
     F.a.Q 
     
      

    Как рисовать прямо на экране?

    Procedure DrawOnScreen;
    Var DC:HDC;
    DesktopCanvas:TCanvas;
    begin
    DC:=GetDC(0);   // получили DC экрана
    try
    DesktopCanvas:=TCanvas.Create;
    DesktopCanvas.Handle:=DC;

    здесь само рисование

    finally
    ReleaseDC(0,DC);
    DesktopCanvas.Free;
    end;
    end;

    Как получить серийный номер тома жесткого диска?

    procedure TForm1.Button1Click(Sender: TObject);
    var
    VolumeName,
    FileSystemName : array [0..MAX_PATH-1] of Char;
    VolumeSerialNo : DWord;
    MaxComponentLength,
    FileSystemFlags : Integer;
    begin
    GetVolumeInformation('C:\',VolumeName,MAX_PATH,@VolumeSerialNo,
    MaxComponentLength,FileSystemFlags,
    FileSystemName,MAX_PATH);
    Memo1.Lines.Add('VName = '+VolumeName);
    Memo1.Lines.Add('SerialNo = $'+IntToHex(VolumeSerialNo,8));
    Memo1.Lines.Add('CompLen = '+IntToStr(MaxComponentLength));
    Memo1.Lines.Add('Flags = $'+IntToHex(FileSystemFlags,4));
    Memo1.Lines.Add('FSName = '+FileSystemName);
    end;

     

    Автор:Pixel( pixel@novgorod.net http://pixelsoft.narod.ru )
    ї COOLer 

     Назад к оглавлению  
      
     Dll 
     

     

     


    самая простая длл

     

    library MyDll;

     

    uses

    Windows;

     

    function SomeFunc(I: Integer): Integer; stdcall;

    begin

    if Odd(I) then Result := 3 * I + 1

    else Result := I div 2;

    end;


    exports

    SomeFunc;

    begin

    end.

     

    И вот модуль импорта, который вы можете включить в любой проект, которому необходим доступ к функциям DLL

    unit MyDllImport;

    interface
    uses
    Windows;
     
    function SomeFunc(I: Integer): Integer; stdcall;

    implementation
    function SomeFunc; external 'mydll.dll';
    end.

     

     

     

    Автор:Pixel( pixel@novgorod.net http://pixelsoft.narod.ru )

    ї COOLer

     Назад к оглавлению  
      
     Размытие. 
     
      
    Ну вот, добрались и до фильтров. В неформальных испытаниях этот код оказался вдвое быстрее, чем это делает Adobe Photoshop. Мне кажется есть множество фильтров, которые можно переделать или оптимизировать для быстроты обработки изображений.

    Ядро гауссовой функции exp(-(x^2 + y^2)) есть разновидность формулы f(x)*g(y), которая означает, что мы можем выполнить двумерную свертку, делая последовательность одномерных сверток - сначала мы свертываем каждую строчку изображения, затем - каждую колонку. Хороший повод для ускорения (N^2 становится N*2). Любая свертка требует некоторого место для временного хранения результатов - ниже в коде программа BlurRow как раз распределяет и освобождает память для каждой колонки. Вероятно это должно ускорить обработку изображения, правда не ясно насколько.

    Поле "size" в записи TKernel ограничено значением 200. Фактически, если вы хотите использовать еще больший радиус, это не вызовет проблем - попробуйте со значениями radius = 3, 5 или другими. Для большого количества данных методы свертки на поверку оказываются эффективнее преобразований Фурье (как показали опыты).

    Еще один комментарий все же необходим: гауссово размывание имеет одно магическое свойство, а именно - вы можете сначала размыть каждую строчку (применить фильтр), затем каждую колонку - фактически получается значительно быстрее, чем двумерная свертка.

    Во всяком случае вы можете сделать так

     

    unit GBlur2;

    interface

    uses Windows, Graphics;

    type

    PRGBTriple = ^TRGBTriple;
    TRGBTriple = packed record
    b: byte; //легче для использования чем типа rgbtBlue...
    g: byte;
    r: byte;
    end;

    PRow = ^TRow;
    TRow = array[0..1000000] of TRGBTriple;

    PPRows = ^TPRows;
    TPRows = array[0..1000000] of PRow;


    const MaxKernelSize = 100;

    type

    TKernelSize = 1..MaxKernelSize;

    TKernel = record
    Size: TKernelSize;
    Weights: array[-MaxKernelSize..MaxKernelSize] of single;
    end;
    //идея заключается в том, что при использовании TKernel мы игнорируем
    //Weights (вес), за исключением Weights в диапазоне -Size..Size.

    procedure GBlur(theBitmap: TBitmap; radius: double);

    implementation

    uses SysUtils;

    procedure MakeGaussianKernel(var K: TKernel; radius: double;
    MaxData, DataGranularity: double);
    //Делаем K (гауссово зерно) со среднеквадратичным отклонением = radius.
    //Для текущего приложения мы устанавливаем переменные MaxData = 255,
    //DataGranularity = 1. Теперь в процедуре установим значение
    //K.Size так, что при использовании K мы будем игнорировать Weights (вес)
    //с наименее возможными значениями. (Малый размер нам на пользу,
    //поскольку время выполнения напрямую зависит от
    //значения K.Size.)
    var j: integer; temp, delta: double; KernelSize: TKernelSize;
    begin
    for j:= Low(K.Weights) to High(K.Weights) do
    begin
    temp:= j/radius;
    K.Weights[j]:= exp(- temp*temp/2);
    end;

    //делаем так, чтобы sum(Weights) = 1:

    temp:= 0;
    for j:= Low(K.Weights) to High(K.Weights) do
    temp:= temp + K.Weights[j];
    for j:= Low(K.Weights) to High(K.Weights) do
    K.Weights[j]:= K.Weights[j] / temp;


    //теперь отбрасываем (или делаем отметку "игнорировать"
    //для переменной Size) данные, имеющие относительно небольшое значение -
    //это важно, в противном случае смазавание происходим с малым радиусом и
    //той области, которая "захватывается" большим радиусом...
    KernelSize:= MaxKernelSize;
    delta:= DataGranularity / (2*MaxData);
    temp:= 0;
    while (temp < delta) and (KernelSize > 1) do
    begin
    temp:= temp + 2 * K.Weights[KernelSize];
    dec(KernelSize);
    end;

    K.Size:= KernelSize;

    //теперь для корректности возвращаемого результата проводим ту же
    //операцию с K.Size, так, чтобы сумма всех данных была равна единице:


    temp:= 0;
    for j:= -K.Size to K.Size do
    temp:= temp + K.Weights[j];
    for j:= -K.Size to K.Size do
    K.Weights[j]:= K.Weights[j] / temp;

    end;

    function TrimInt(Lower, Upper, theInteger: integer): integer;
    begin
    if (theInteger <= Upper) and (theInteger >= Lower) then
    result:= theInteger
    else
    if theInteger > Upper then
    result:= Upper
    else
    result:= Lower;
    end;

    function TrimReal(Lower, Upper: integer; x: double): integer;
    begin
    if (x < upper) and (x >= lower) then
    result:= trunc(x)
    else
    if x > Upper then
    result:= Upper
    else
    result:= Lower;
    end;

    procedure BlurRow(var theRow: array of TRGBTriple; K: TKernel; P: PRow);
    var j, n, LocalRow: integer; tr, tg, tb: double; //tempRed и др.
    w: double;
    begin

    for
    j:= 0 to High(theRow) do
    begin
    tb:= 0;
    tg:= 0;
    tr:= 0;
    for n:= -K.Size to K.Size do
    begin
    w:= K.Weights[n];

    //TrimInt задает отступ от края строки...
    with theRow[TrimInt(0, High(theRow), j - n)] do
    begin
    tb:= tb + w * b;
    tg:= tg + w * g;
    tr:= tr + w * r;
    end;
    end;
    with P[j] do
    begin
    b:= TrimReal(0, 255, tb);
    g:= TrimReal(0, 255, tg);
    r:= TrimReal(0, 255, tr);
    end;
    end;

    Move(P[0], theRow[0], (High(theRow) + 1) * Sizeof(TRGBTriple));
    end;

    procedure GBlur(theBitmap: TBitmap; radius: double);
    var Row, Col: integer; theRows: PPRows; K: TKernel; ACol: PRow; P:PRow;
    begin
    if (theBitmap.HandleType <> bmDIB) or (theBitmap.PixelFormat <> pf24Bit) then
    raise exception.Create('GBlur может работать только с 24-битными изображениями');

    MakeGaussianKernel(K, radius, 255, 1);
    GetMem(theRows, theBitmap.Height * SizeOf(PRow));
    GetMem(ACol, theBitmap.Height * SizeOf(TRGBTriple));

    //запись позиции данных изображения:
    for Row:= 0 to theBitmap.Height - 1 do
    theRows[Row]:= theBitmap.Scanline[Row];

    //размываем каждую строчку:
    P:= AllocMem(theBitmap.Width*SizeOf(TRGBTriple));
    for Row:= 0 to theBitmap.Height - 1 do
    BlurRow(Slice(theRows[Row]^, theBitmap.Width), K, P);

    //теперь размываем каждую колонку
    ReAllocMem(P, theBitmap.Height*SizeOf(TRGBTriple));
    for Col:= 0 to theBitmap.Width - 1 do
    begin

    //- считываем первую колонку в TRow:
    for Row:= 0 to theBitmap.Height - 1 do
    ACol[Row]:= theRows[Row][Col];


    BlurRow(Slice(ACol^, theBitmap.Height), K, P);

    //теперь помещаем обработанный столбец на свое место в данные изображения:
    for Row:= 0 to theBitmap.Height - 1 do
    theRows[Row][Col]:= ACol[Row];
    end;

    FreeMem(theRows);
    FreeMem(ACol);
    ReAllocMem(P, 0);
    end;

    end.

    procedure TForm1.Button1Click(Sender: TObject);
    var b: TBitmap;
    begin

    if not openDialog1.Execute then exit;

    b:= TBitmap.Create;
    b.LoadFromFile(OpenDialog1.Filename);
    b.PixelFormat:= pf24Bit;
    Canvas.Draw(0, 0, b);
    GBlur(b, StrToFloat(Edit1.text));
    Canvas.Draw(b.Width, 0, b);
    b.Free;
    end;

    Имейте в виду, что 24-битные изображения при системной 256-цветной палитре требуют некоторых дополнительных хитростей, так как эти изображения не только выглядят в таком случае немного "странными", но и серьезно нарушают работу фильтра.



     

    Ваш "квадратный" Автор ( pixel@novgorod.net http://pixelsoft.narod.ru )
    ї COOLer


    Zaluskiy Anton(COOLer)    - ведущий проекта    "Мир Delphi"



    о3он TopList


    http://subscribe.ru/
    E-mail: ask@subscribe.ru
    Отписаться Рейтингуется SpyLog

    В избранное