|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Масштабирование Jpeg скроллбаром
На данный момент не нашел, как это делать правильно. Существующий вариант таков:
Код:
ImageWiring.AutoSize := true;//взято из интернета, ImageWiring: TImage ImageWiring.AutoSize := false;//взято из интернета ImageWiring.Width := trunc(ImageWiring.Width*(1+(ScrollBarScaleImage.Position - 50)/80)); // стартовое положение скроллбара - 50, при этом масштаб 1:1 ImageWiring.Height := trunc(ImageWiring.Height*(1+(ScrollBarScaleImage.Position - 50)/80)); ImageWiring.Stretch := True; ScrollBarScaleImage.Hint := '1:' + FloatToStr(RoundTo((1+(ScrollBarScaleImage.Position - 50)/80), -2));//показывает размер изображения после передвижения ползунка При подобном способе изображение дергается (перерисовка?) при изменении масштаба скроллбаром, получается некрасиво. Как добиться плавного изменения рисунка без подергиваний? И как показывать хинт скроллбара в процессе перемещения? Последний раз редактировалось diagnost, 02.08.2008 в 00:32. |
#2
|
|||
|
|||
Задача далеко не банальна. Пробовал в ScrollBox поместить PaintBox и выводить изображение на PaintBox.Canvas. Обнаружил, что мерцание получается из-за изменения размера PaintBox при масштабировании картинки. Видимо, при изменении размера PaintBox сам PaintBox сначала перерисовывается с пустым канвасом цветом фона ScrollBox, и лишь после этого я канвас заполняю изображением при вызове процедуры типа Draw. Как это обойти, ума не приложу...
Код:
PaintBox.Height:= ViewH; //заполнение PaintBox фоном - вывод фона на экран, причина мерцания PaintBox.Width := ViewW;//-"- PaintBox.Canvas.Draw(0,0,ScaledBmp)//вывод изображения на экран. Последний раз редактировалось diagnost, 04.08.2008 в 22:25. |
#3
|
|||
|
|||
А можно поинтересоваться? Если скроллбар используется для масштабирования, то чем скроллируется TImage когда масштаб изображения выходит далеко за видимые размеры окна?
Не забывайте делать резервные копии |
#4
|
|||
|
|||
Скроллбоксом. Я помещал TImage в скроллбокс . Но, ИМХО, причина не в скроллбоксе, т.к. даже если изображение меньше скроллбокса и целиком в него влезает, оно подергивается при изменении масштаба.
Я полагаю, надо или найти способ запретить перерисовывать канвас при изменении размера PaintBox'а (если этот способ существует), или выводить поверх PaintBox'а изображение (типа нового слоя), в которое записывать нужные изменения канваса PaintBox'а (тут много проблем). Последний раз редактировалось diagnost, 04.08.2008 в 23:28. |
#5
|
|||
|
|||
Обычно делают так. Масштаб изображения меняют какими-нибудь дополнительными управляющими компонентами: кнопками, "ползунком" (trackbar) и (или) мышой. А скроллбары (полосы внизу и справа) используют для прокрутки изображения чтоб просматривать любые части изображения.
ScrollBarScaleImage - это видимо какой-то свой компонент (типа trackbar'а), с помощью которого и меняется масштаб?. Не забывайте делать резервные копии Последний раз редактировалось san-46, 05.08.2008 в 00:08. |
#6
|
|||
|
|||
Прошу прощения за то, что плохо объясняю.
Да, я вместо trackbar'а использую отдельный скроллбар.У меня так все и есть, как написал san-46. ScrollBarScaleImage - это обычный скроллбар в стороне от скроллбокса (не принадлежащий скроллбоксу). Я его использую для масштабирования рисунка в скроллбоксе. При перемещении ползунка на моем "выносном" "дополнительном" скроллбаре я изменяю размеры PaintBox, который лежит в скроллбоксе. При этом происходит мерцание изображения (из-за изменения размера PaintBox). Все работает (испробовал уже несколько разных способов, два описал в первом и втором сообщении этой темы), только мерцание некрасиво. Не могу избавиться. Пересмотрел много тем на этом форуме, проблему уже поднимали, решения не нашел. Последний раз редактировалось diagnost, 05.08.2008 в 00:59. |
#7
|
|||
|
|||
Цитата:
Вот поэкспериментировал - ничего не дергается, плавно увеличивает масштаб. (Это более правильный вариант). Код:
var BS, BT : TBitmap; procedure TForm1.FormCreate(Sender: TObject); begin BS := TBitmap.Create; BS.LoadFromFile(<FileName>); BT := TBitmap.Create; PaintBox1.ControlStyle := PaintBox1.ControlStyle + [csOpaque]; //обязательно end; procedure TForm1.TrackBar1Change(Sender: TObject); begin PaintBox1.Invalidate; end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin BT.Width := BS.Width + (TrackBar1.Position-1) * 2; BT.Height := BS.Height + (TrackBar1.Position-1) * 2; BT.Canvas.StretchDraw(Rect(0, 0, BT.Width, BT.Height), BS); PaintBox1.Canvas.CopyRect(PaintBox1.ClientRect, BT.Canvas, PaintBox1.ClientRect); end; procedure TForm1.FormDestroy(Sender: TObject); begin BT.Free; BS.Free; end; Да, еще. Код только масштабирует, но не прокручивает картинку. Для прокрутки код надо переделывать-доделывать. Здесь, главное, идея. А идея в том, что исходная картинка храниться в памяти, не высовывается (BS). Хранить исходную обязательно. Масштаб меняется изменением размеров промежуточного bitmap (BT) тоже в памяти. В него перегоняется исходная картинка, которая с помощью StretchDraw меняет свой размер. И последнее действие выводит ЧАСТЬ изображения на канву визуального компонент (здесь PainBox, можно на другие компоненты, которые имеют Canvas). Ага, еще. Скроллбокс здесь не годится. Т.е. PaintBox вставлять в ScrollBox не получится. А систему отображения надо представить в виде окошка, через которое мы видим только часть картинки (CopyRect). При прокрутке (текущий масштаб) просто надо смещать прямоугольник с одним и тем же размером (размер визуального компонента) по вертикали и горизонтали. Как будто мы перемещаем наше окошко по большой картинке. Как с jpeg не знаю, не пытался делать. Насколько помню, ничего особенного, почти все так же. Не забывайте делать резервные копии Последний раз редактировалось san-46, 05.08.2008 в 02:05. |
#8
|
|||
|
|||
Путем долгих проб пришел к варианту использования PaintBox и буферного битмапа. Всю отрисовку с переразмериванием выполняю на битмапе, а в PaintBox.OnDraw (так что-ли) переразмериваю сам PaintBox (если нужно) и делаю CopyRect, который выполняется быстро.
|
#9
|
|||
|
|||
Да у меня почти один в один (разница в мелочах), дергается только при изменении размера PaintBox. Вот хотел попроще способ найти, а получается надо аналог городить скроллбокса
Код:
procedure PaintWiringImage; begin with Form1 do begin PaintBoxImage.Canvas.Draw(0,0,BmpOnScreen); end; end; procedure ScaleWiringImage; var ViewH, ViewW: integer; RScreen: TRect; begin with Form1 do begin ViewH := Round(BmpFromFile.Height * TrackBarScaleImage.Position/100); ViewW := Round(BmpFromFile.Width * TrackBarScaleImage.Position/100); BmpOnScreen.Height:= ViewH; BmpOnScreen.Width := ViewW; RScreen := Rect(0,0,ViewW,ViewH); BmpOnScreen.Canvas.StretchDraw(RScreen, BmpFromFile); PaintBoxImage.Height:= ViewH; PaintBoxImage.Width := ViewW; PaintWiringImage; end; end; Последний раз редактировалось diagnost, 05.08.2008 в 02:25. |
#10
|
|||
|
|||
Цитата:
Я достаточно много в свое время возился с графикой и, в т.ч. масштабированием. Если интересно, конечно, можете посмотреть компонент из этой оперы http://www.delphisources.ru/pages/so...r-graphic.html Цитата:
А чем не устраивает мое предложение? Проще по-моему уже и некуда, а эффект впечатляющий. Надо обратить внимание на строку PaintBox1.ControlStyle := PaintBox1.ControlStyle + [csOpaque]; Вроде мелочь, а именно в ней весь секрет "дерганья". Не забывайте делать резервные копии Последний раз редактировалось san-46, 05.08.2008 в 02:38. |
#11
|
|||
|
|||
1) Ну "проще уж некуда" это слишком сильно сказано. Окошко у меня расширяющееся, на панели сидит.
2) Свой скроллбокс не будет таким красивым, как в Виндоуз 3) Идея хорошая, буду пробовать, хоть и неохота, а деваться некуда 4) Не дергается у меня и без этой строчки. 5) Не очень нравится вот этот нюанс: Код:
procedure TForm1.TrackBar1Change(Sender: TObject); begin PaintBox1.Invalidate; end; procedure TForm1.PaintBox1Paint(Sender: TObject); begin BT.Width := BS.Width + (TrackBar1.Position-1) * 2; BT.Height := BS.Height + (TrackBar1.Position-1) * 2; BT.Canvas.StretchDraw(Rect(0, 0, BT.Width, BT.Height), BS); PaintBox1.Canvas.CopyRect(PaintBox1.ClientRect, BT.Canvas, PaintBox1.ClientRect); end; Последний раз редактировалось diagnost, 05.08.2008 в 03:00. |
#12
|
|||
|
|||
>>4) Не дергается у меня и без этой строчки.
Если не дергается, то тема исчерпана? Изначально проблема была именно в плохой прорисовке, насколько помню. А к какому событию прицеплена процедура ScaleWiringImage;? Не забывайте делать резервные копии |
#13
|
|||
|
|||
Не дергается, если не менять размер PaintBox, а я его менял при масштабировании.
Код:
procedure TForm1.TrackBarScaleImageChange(Sender: TObject); begin ScaleWiringImage; end; procedure TForm1.PaintBoxImagePaint(Sender: TObject); begin PaintWiringImage; end; Задача - написать хороший просмотрщик эл. схем (wiring) автомобилей, с деревом, масштабированием, расшифровкой компонентов. Последний раз редактировалось diagnost, 05.08.2008 в 03:07. |
#14
|
|||
|
|||
Не хилая задачка!!!
А укротить PaintBox при изменении его размеров не получиться. Пробовано, перепробовано. Только дошло, что прокрутка должна быть в окне со скролбарами. Действительно, штатные дельфийские скроллбары убогие до тошноты. Правда можно на проект повесить XPManifest, но и преобразованные скроллбары при этом будут старого стиля (это когда размер движка в них как и кнопки со стрелками и не меняется). Не забывайте делать резервные копии |
#15
|
|||
|
|||
>>Я предлагаю на OnPaint только копировать (см. мой вариант), без лишних вычислений.
Это не вычисления - это кошачьи слезы. Если посмотрите на код, который болтается у меня в линейном графике на событии OnPaint и, который действительно выполняет окаянное количество вычислений, сразу забудете о такой мелочи как перегонка двух bitmap. А потом, это все равно ничего не даст. OnPaint, в действительности ничего не выводит, а только подготавливает все чего надо к выводу, поэтому никакого значения не имеет в какой части кода будут "вычисления" и "вывод изображения", все равно, пока это хозйство полностью не отработает никакого вывода не будет (который, кстати, после этого становиться только в очередь на визуальный вывод). Не партесь по поводу вычислений в OnPaint - делайте чего хотите в одном месте - это же удобнее. Не забывайте делать резервные копии |