![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Всем здрасьте...
Вот тут бъюсь над такой проблемкой: Есть PainBox, на который выводится картинка. Надо поверх этой картинки еще нарисовать полупрозрачный цветной прямоугольник (один цвет). Координаты прямоугольника есть (TRect). Сложность в том, что надо нарисовать его быстро. Вариант создания большого битмапа с альфа-каналом и копирования его части на картинку держу как запасной, т.к. размер прямоугольника вычисляется динамически, а еще один огромный битмап в памяти держать не очень хочется. Есть у кого какие идеи? ЗЫ. Ограничение - не использовать сторонних доп. библиотек, типа Graphics32 и т.п. Можно использовать DevExpress, бо как он уже в проекте используется. Код отрисовки: Код:
procedure TCutImageFrame.pbImagePaint(Sender: TObject);
var
R, FaceTop, FaceBottom : TRect;
begin
inherited;
pbImage.Canvas.StretchDraw(FImageRect,FImage);
If FHasPoints Then
Begin
R := Rect(Min(FStartPt.X,FEndPt.X),Min(FStartPt.Y,FEndPt.Y),Max(FStartPt.X,FEndPt.X),Max(FStartPt.Y,FEndPt.Y));
pbImage.Canvas.DrawFocusRect(R);
// Вот эти прямоугольники хочется сделать полупрозрачным цветом.
GetFaceRects(R,FaceTop,FaceBottom); // Вычисление координат прямоугольников
pbImage.Canvas.DrawFocusRect(FaceTop);
pbImage.Canvas.DrawFocusRect(FaceBottom);
End;
end;Последний раз редактировалось lmikle, 02.12.2012 в 20:43. |
|
#2
|
||||
|
||||
|
а если создать небольшой битмап, как раз под расчитанный прямоугольник, копировать из PaintBox картинку этого прямоугольника, наложить полупрозрачный прямоугольник и вывести отдельным PaintBox'ом в нужном месте над оригинальным PaintBox' ом (чтобы не затирать оригинальную картинку)
|
|
#3
|
||||
|
||||
|
Точно не помню, но кажется делал так:
Код:
workcanvas.Pen.Mode:=pmMerge ; workcanvas.Pen.Color:=clblue; workcanvas.Brush.Color:=clblue; //прямоугольник |
|
#4
|
||||
|
||||
|
Изврат но: GetDiBits обеих картинок и смешивать байты в нужной пропорции.
|
|
#5
|
|||
|
|||
|
Цитата:
Попробую. Цитата:
Как уже писал, данная операция должна производиться быстро, поэтому варант с прямой работой с пикселами скорее всего не подойдет. Слишком долго. Думал в сторону GDI/GDI+, но еще не смотрел... Цитата:
Дело в том, что координаты прямоугольника вычисляются налету. Если нужный битмап создавать заранее, то он может оказаться очень большим, чего не хотелось бы, и так в памяти висит оригинальная картинка. Если битмап создавать в процессе работы при вызове отрисовки, то чем это лучше работы с пикселами? Те же тормоза будут - пока создашь (переразмеришь битмап), пока на нем отрисуешься, а потом опять уже его отрисовывать с альфа каналом. Собственно, думал может кто знает как отрисовать просто прямоугольник с альфа каналом. Как видно из кода, пока просто рисуется фокусный прямоугольник, что не очень наглядно... |
|
#6
|
||||
|
||||
|
попробовал на Gdiplus:
Код:
procedure TForm1.PaintBox1Paint(Sender: TObject); var graphics: GpGraphics; brush: GpSolidFill; // f, c1, c2: Int64; begin PaintBox1.Canvas.Draw(0, 0, Image1.Picture.Graphic); // QueryPerformanceFrequency(f); // QueryPerformanceCounter(c1); GdipCreateFromHDC(PaintBox1.Canvas.Handle, graphics); GdipCreateSolidFill($80ffff00, brush); GdipFillRectangleI(graphics, brush, 0, 0, 640, 480); GdipDeleteBrush(brush); GdipDeleteGraphics(graphics); // QueryPerformanceCounter(c2); // Caption:=IntToStr((c2-c1) div (f div 1000)); end; ![]() |
|
#7
|
||||
|
||||
|
отставить панику! двойная буферизация спасает ситуацию.
|
|
#8
|
||||
|
||||
|
Я через GetDIBits (точнее его предшественника) отрисовываю тень, кусок кода естественно на ассемблере.
|
|
#9
|
|||
|
|||
|
Цитата:
ОК, проблему решил через AlphaBlend. Надо теперь только немного оптимизировть... Вот эта функция, мож кому пригодится. Нарыл на ExpertsExchange. Код:
procedure TCutImageFrame.BlendRectangle(Canvas:TCanvas;R:TRect;C:TColor;MixPercent:Byte); Var tmpBMP:TBitmap; Blend:_BLENDFUNCTION; begin tmpBMP:=TBitmap.Create; try tmpBMP.Width:=1; tmpBMP.Height:=1; tmpBMP.Canvas.Pixels[0,0]:=C; Blend.BlendOp:=AC_SRC_OVER; Blend.BlendFlags:=0; Blend.SourceConstantAlpha:=(50+255*MixPercent) Div 100; Blend.AlphaFormat:=0; AlphaBlend(Canvas.Handle,R.Left,R.Top,R.Right-R.Left,R.Bottom-R.Top,tmpBMP.Canvas.Handle,0,0,1,1,Blend); finally tmpBMP.Free; end; end; |
|
#10
|
||||
|
||||
|
Знакомый код, уже и не помню чем он меня тогда не устроил, а больше с ним не экспериментировал.
|
|
#11
|
|||
|
|||
|
Цитата:
Ну не знаю, чем он тебя не устроил. Отрисовка - то что хотелось. По скорости, даже на не самой быстрой машинке (сейчас AMD Athlon M320), устраивает даже в таком виде (собственно, у меня он в отрисовке маркеров, когда юзер выделяет квадрат на картинке). |