|
|
Регистрация | << Правила форума >> | 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' ом (чтобы не затирать оригинальную картинку)
Понять, что хочет заказчик - бесценно, ведь он платит MasterCard |
#3
|
||||
|
||||
Точно не помню, но кажется делал так:
Код:
workcanvas.Pen.Mode:=pmMerge ; workcanvas.Pen.Color:=clblue; workcanvas.Brush.Color:=clblue; //прямоугольник |
#4
|
||||
|
||||
Изврат но: GetDiBits обеих картинок и смешивать байты в нужной пропорции.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#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 (точнее его предшественника) отрисовываю тень, кусок кода естественно на ассемблере.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#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
|
||||
|
||||
Знакомый код, уже и не помню чем он меня тогда не устроил, а больше с ним не экспериментировал.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#11
|
|||
|
|||
Цитата:
Ну не знаю, чем он тебя не устроил. Отрисовка - то что хотелось. По скорости, даже на не самой быстрой машинке (сейчас AMD Athlon M320), устраивает даже в таком виде (собственно, у меня он в отрисовке маркеров, когда юзер выделяет квадрат на картинке). |