![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Аналоговые часы
исследователь © (2007-08-18 18:14:00)Такой вопрос: пишу программку-прото аналоговые часики, для души, с поддержкой скинов. Есть красивые картинки скинов, но фон циферблата в них градиентный. Отсюда вопрос: как закрашивать стрелку по событию таймера так, чтобы не было ее видно, ведь ее нужно будет отрисовывать в другом месте.
@!!ex (2007-08-21 09:40:00) [41]> [54] antonn © (20.08.07 23:15)
С лупой смотрел, особой разницы не заметил.
Но при ближайшем рассмотрении действительно зубцы есть.
Будет время сегодня вечером чуть модифицирую, чтобы не было зубцов.
ИМХо применять альясинг ко всей картинке, при рисовании одной линии - слегка расточительно....
исследователь (2007-08-21 03:04:00) [42]Я ошибаюсь? Вы поправьте меня, если я не прав.
исследователь (2007-08-21 02:11:00) [43]Хм, не на каждую - у идет от 0 до (высота div 3) -1
antonn (2007-08-21 01:58:00) [44]DestRow := SourceBitmap.ScanLine[y]; - это на каждую строку выходного битмапа, т.е. равно высоте битмапа.
просто получается так. На этом увеличенном битмапе в левом верхнем углу выходит сжатое изображение, которое копируется на канву (можно сохранить битмап в файл перед CanvasOut.CopyRect() и посмотреть, на фоне большой копии в углу будет сжатое со сглаживаением)
исследователь (2007-08-21 01:40:00) [45]Почему мы в DestRow загоняем ср. знач. пикселей, ведь на 12 строк destrow - Это всего четыре строки?
antonn (2007-08-21 01:32:00) [46]
> Так с того, что мы вписали среднее значение, как я и сказал,
> что случилось?
для фона - ничего, а вот для тех частей, где нарисована стрелка - там будет темнее (тем темнее, чем больше там видно стрелки).
Допустим фон, был один пиксель, его размножили:
0 0 0
0 0 0
0 0 0
если его теперь сложить из этих 9 пикселей, то среднее будет 0, как и изначальное.
нарисовали стрелку под углом, она "слегка" задела несколько пикселей
1 1 0
1 0 0
0 0 0
теперь сренее будет не 0, а с "примесью" стрелки.
вообще для эксперимента можно натыкать в код типа такого
botmap.savetromfile('C:\1.bmp'); и в панте в приближении рассмореть эти пиксели:)
DestRow - это строка выходного битмапа, в него загоняется среднее значение канала из 9 пикселей. Все равно не понял, в чем вопрос:)
исследователь (2007-08-21 01:13:00) [47]Так с того, что мы вписали среднее значение, как я и сказал, что случилось?
Смущает строчка DestRow, ведь это строки (в битмапе на 12 строк) номер 0, 1, 2 и 3. Почему только они?
antonn (2007-08-21 01:07:00) [48]берется изображение, увеличивается в три раза "квадратным способом", т.е. без всяких сглаживаний, просто "увеличиваются" пиксели в три раза.
при вызове Alias просто берем 9 пикселей (в квадрате 3*3) и для каждого канала считаем среднее значение, и это значение вписываем в результирующий битмап. Для фона ничего не изменится, потому как эти 9 пикселей будут одинаковы.
Про строчку не понял, где какая строка смущает? :)
исследователь (2007-08-21 00:56:00) [49]Я уже должен Вам отвесить огромный поклон. Но можно еще последнийх три вопроса: на основе чего работает алгоритм AA? Как я понял, берется цветовой массив каждой из строк картинки, затем в ней анализируются по три смежных индекса массива (как я понял, идут тройки: R1G1B1R2G2B2... верно?), это происходит в каждой из смежныхъ строк, затем идет замена в одной определенной строчке (ЧТО это за строка, объясните! Почему именно она?), цветовых составляющих, и это что-тьо дает. Это втрой вопрос - что? И третий - верно ли я понял? :)
antonn (2007-08-21 00:43:00) [50]для красоты можно умножить на 3 и прибавить 1, так они будут лучше смазаны.
кстати, толщину линии тоже на 3 нужно умножить:)
исследователь (2007-08-21 00:40:00) [51]Понял, просто Cx и CY тоже ж на 3 надо умножать
исследователь (2007-08-21 00:40:00) [52]Понял, просто Cx и CY тоже ж на 3 надо умножать
исследователь (2007-08-21 00:34:00) [53]Спасибо, но стрелки теперь не по центру рисуются.
antonn (2007-08-21 00:27:00) [54]BitmapPrepare(tm3, tm1.Canvas, rect(0,0,tm1.Width,tm1.Height));
подставить вместо
BitBlt(tm3.Canvas.Handle,
0,0,
tm3.Width,tm3.Height,
tm1.Canvas.Handle, 0,0, SRCCOPY);
image1.Picture.Assign(tm3); из DrawArrows убрать
Alias(tm3, tm2.Canvas, Rect(0,0, tm3.Width,tm3.Height)); - размеры выводимой области равны изначальной - rect(0,0,tm1.Width,tm1.Height)
исследователь (2007-08-21 00:02:00) [55]Что я делаю:
1. в форм крит
Гружу в tm1 циферблат
Увеличиваю в три раза в tm3
для проверки кидаю в TImage, бред там
по тику таймера считаю углы и закрашиваю все циферблатом (походу тут баг, т.к. размеры не совпадают)
рисую стрелки
делаю АА
вывожу на форму
исследователь (2007-08-20 23:58:00) [56]В общем, ничего не выходит. Процедура делания скина вырезана для уменьшения поста.
unit uMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
TfrmMain = class(TForm)
timer1: TTimer;
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure timer1Timer(Sender: TObject);
private
{ Private declarations }
procedure DrawArrows(c1, c2, c3 : TColor);
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
CX, CY, HArrow, MArrow, SArrow : Integer;
HA, MA, SA : Real;
H, M, S, MS : word;
tm1, tm2, tm3 : TBitmap;
implementation
{$R *.dfm}
procedure Alias(var SourceBitmap:TBitmap; CanvasOut:TCanvas; _R:TRect);
const
MaxPixelCount = MaxInt div SizeOf(TRGBTriple);
type
PRGBArray = ^TRGBArray;
TRGBArray = array[0..MaxPixelCount-1] of TRGBTriple;
var
x,y,cx,cy,cxi,totr,totg,totb,i: Integer;
Row1,Row2,Row3,DestRow: PRGBArray;
begin
for Y:=0 to (SourceBitmap.Height div 3)-1 do begin
cy := y*3;
DestRow := SourceBitmap.ScanLine[y];
Row1:=SourceBitmap.ScanLine[cy];
Row2:=SourceBitmap.ScanLine[cy+1];
Row3:=SourceBitmap.ScanLine[cy+2];
for x := 0 to (SourceBitmap.Width div 3)-1 do begin
cx := x*3;
totr := 0; totg := 0; totb := 0;
for i := 0 to 2 do begin
cxi := cx + i;
totr := totr + Row1[cxi].rgbtRed + Row2[cxi].rgbtRed + Row3[cxi].rgbtRed;
totg := totg + Row1[cxi].rgbtGreen + Row2[cxi].rgbtGreen + Row3[cxi].rgbtGreen;
totb := totb + Row1[cxi].rgbtBlue + Row2[cxi].rgbtBlue + Row3[cxi].rgbtBlue;
end;
DestRow[x].rgbtRed := totr div 9;
DestRow[x].rgbtGreen := totg div 9;
DestRow[x].rgbtBlue := totb div 9;
end;
end;
CanvasOut.CopyRect(_R,SourceBitmap.Canvas,rect(0,0,SourceBitmap.Width div 3,SourceBitmap.Height div 3));
end;
procedure BitmapPrepare(var SourceBitmap:Tbitmap; CanvasOut:TCanvas; _R:TRect);
begin
SourceBitmap.PixelFormat:=pf24bit;
SourceBitmap.Width:=(_r.Right-_r.Left)*3;
SourceBitmap.Height:=(_r.Bottom-_r.Top)*3;
SourceBitmap.Canvas.CopyRect(rect(0,0,SourceBitmap.Width,SourceBitmap.Height),Ca nvasOut,_R);
end;
procedure TfrmMain.DrawArrows(c1, c2, c3: TColor);
var r : LongBool;
begin
with tm3.Canvas do
begin
SetBkMode(Handle, Transparent);
Pen.Color := clBlack;
Font.Name := 'Arial';
Font.Style := [fsBold];
TextOut(tm2.Width-60, tm2.Height div 2-8, Copy(DateToStr(Now),1,2));
Pen.Color := c1;
MoveTo(CX, CY);
Pen.Width := 4;
LineTo(CX+Round(HArrow * 3 * sin(HA)), CY-Round(HArrow * 3 * cos(HA)));
MoveTo(CX, CY);
Pen.Color := c2;
Pen.Width := 3;
LineTo(CX+Round(MArrow * 3 * sin(MA)), CY-Round(MArrow * 3 * cos(MA)));
Pen.Color := c3;
Pen.Width := 2;
MoveTo(CX, CY);
LineTo(CX+Round(SArrow * 3 * sin(SA)), CY-Round(SArrow * 3 *cos(SA)));
end;
image1.Picture.Assign(tm3);
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
HArrow := CX - 30;
MArrow := CX - 50;
SArrow := CX - 70;
tm3 := TBitmap.Create;
tm1 := TBitmap.Create;
tm2 := TBitmap.Create;
tm1.LoadFromFile('background.bmp');
tm2.Height:=tm1.Height;
tm2.Width := tm1.Width;
BitmapPrepare(tm3, tm1.Canvas, rect(0,0,tm1.Width,tm1.Height));
CX := tm1.Width div 2;
CY := tm1.Height div 2;
timer1timer(sender);
// frmMain.clientWidth := tm1.Width;
//frmMain.clientHeight := tm1.Height;
// SetWindowRgn(Self.Handle, BitmapToRgn(tm1), True);
end;
procedure TfrmMain.timer1Timer(Sender: TObject);
begin
DecodeTime(Time, H, M, S, MS);
HA := (H/6 + M/360 + S/21600)*PI + PI;
MA := (M/30 + S/1800)*PI + PI;
SA := (S/30 + MS/30000)*PI + PI;
BitBlt(tm3.Canvas.Handle,
0,0,
tm3.Width,tm3.Height,
tm1.Canvas.Handle, 0,0, SRCCOPY);
DrawArrows(clRed, clGreen, clBlue);
Alias(tm3, tm2.Canvas, Rect(0,0, tm3.Width,tm3.Height));
BitBlt(Canvas.Handle, 0,0,Width,Height, tm2.Canvas.Handle,0,0, SRCCOPY);
end;
end.
antonn (2007-08-20 23:44:00) [57]через CopyRect()
там в примере есть код, который на определенной области рисует сглаженные линии. Создается временный битмап, размерами в 3 раза больше нужной области.
var _Bitmap:Tbitmap;
begin
_Bitmap:=TBitmap.Create;
try
BitmapPrepare(_Bitmap,Image1.Picture.Bitmap.Canvas,rect(10,10,200,200)); //берем прямоугольник, в котором будет рисовать, и увеличия ваего в 3 раза копируем на временный битмап
//дальше работаем с _Bitmap.canvas как нам надо
_Bitmap.Canvas.Pen.Width:=3; //устанавливаем толщину в 3 раз больше
_Bitmap.Canvas.Ellipse(20*3,20*3,80*3,80*3);
_Bitmap.Canvas.MoveTo(50*3-1,60*3-1); //все координаты в 3 раза больше (хотя для лучшего эффекта, можно отнять еденицу - будет более смазано и качественно, главное не переборщить:))
_Bitmap.Canvas.LineTo(5*3,15*3);
_Bitmap.Canvas.Brush.Style:=bsclear;
_Bitmap.canvas.Font.Size:=_Bitmap.canvas.Font.Size*3; //тут правда косячно с размером...
_Bitmap.canvas.TextOut(2,2,'Im - super :)');
Alias(_Bitmap,Image1.Picture.Bitmap.Canvas,rect(10,10,200,200)); //вывод временного битмапа с уменьшением на "лицевой" битмап
finally
_Bitmap.Free;
end;
end;
исследователь (2007-08-20 23:43:00) [58]Я по глупости своей пишу
tm1.LoadFromFile('back.bmp');
// tm1 - это перем. типа TBitmap
tm1.width:=tm1.width*3;
tm1.height:=tm1.height*3;
tm1.stretchdraw(rect(0,0,tm1.width,tm1.height), tm1);
но это бред, не работает.
исследователь (2007-08-20 23:40:00) [59]А как увеличить фон?
antonn (2007-08-20 23:39:00) [60]ага, но потом при сжатии фон и останется каким был