| 
| 
 | Вопрос # 4 810/ вопрос открыт / | 
 |  Приветствую, уважаемые эксперты!Хотелось бы реализовать следующее.
 Имеется JPG изображение карты одной из областей России, с выделенными разными цветами районами внутри области.
 Необходимо при наведении мыши на наименование района помещенное в Label с периодичностью 1 раз в сек. менять цвет района на clRed.
 Во наговорил...
 Наверно попроще, подскажите, как в Image при загруженном JPG изменить цвет нескольких пикселей, если знаешь их цвет.
 С уважением
 Al_Sha
 
|  |   Вопрос задал: Al_Sha (статус: Посетитель)Вопрос отправлен: 12 декабря 2010, 20:33
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, Al_Sha!Расскажу, как делается, что бы при наведении мышки можно было узнать, что за район. Многие советуют делать хитрые условие, находить замкнутые многоугольники и вспоминать "школьную" геометрию. На самом деле все делается проще. Открываем карту в Paint и сделаем из нее маску. Для этого затираем название, а каждый район закрашиваем уникальным цветом. Цвета могут быть неотличимы на глаз, главное, что бы на карте не было двух разных регионов с одинаковым цветом (в целом, если припустить, что район области может состоять с двух или трех частей, то нужно каждую часть закрасить одним цветом, а можно и разными - появиться некая гибкость). Теперь полученную карту сохраняем в bmp. В jpg можно сохранить, но нужно быть осторожным - может повреждаться цвет. В GIF - кол-во цветов обычно уменьшается до 256, поэтому если выбрать цвета правильно, то можно сэкономить. Можно карту сохранить в bmp, но с размерами в 2 или 4 раза меньше.
 
 Теперь возвращаемся к программе. Кроме основной карты, нужно будет ещё грузить карту-маску, но в память (в TBitmap), видеть пользователю её не нужно. Теперь, когда водим мышкой по карте, проверяем по карте маске цвет. Так как цвета для каждого района уникальные - то мы можем составить массив соответствий цвет-название. Если маску уменьшали, то координаты естественно нужно будет пропорционально уменьшить.
 
 Теперь вернемся к закраске. Если у нас есть такая карта-маска, то делать закраску просто - нужно просто пробежаться по карте-маске, посмотреть, где совпадает цвет с цветом текущего района и подкрасить. Конечно, это все можно хорошо оптимизировать, если для каждого района найти такой прямоугольник, в который он попадает, тогда двойной цикл для поиска будет работать очень быстро.
 
 Теперь последние штрихи. Рисовать на TImage - плохо, потому что медленно. Лучше рисовать в TBitmap, а потом переносить одним движением (то есть вызовом метода CopyRect у Canvas или подобного). При этом, если держать в памяти две картинки, то можно рисовать закрашенный регион только один раз при входе в него, а потом, пока мышка находиться в нем - просто использовать готовый.
 Но есть ещё одна проблема. Рисовать на канве, в которую загружен jpeg - нельзя. Не даст:) Будет говорить, что canvas только readonly. Поэтому нужно все таки грузить в память, а потом отрисовывать.
 
 Полезные ссылки:
 http://www.delphisources.ru/pages/faq/base/jpeg_to_bmp.html
 http://www.delphisources.ru/pages/faq/base/bmp_to_jpeg.html
 http://www.delphisources.ru/pages/faq/base/copyrect_anim.html
 
 Если будут затруднения - пишем в минифорум, разберем:)
 
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 12 декабря 2010, 22:29
 Оценка за ответ: 5
 Комментарий к оценке: Спасибо, итнформация для меня полезная, будем разбираться...С уважением Al_Sha
 |  
 Мини-форум вопросаВсего сообщений: 5; последнее сообщение — 13 декабря 2010, 07:19; участников в обсуждении: 3. 
|   | prorok-kane (статус: Посетитель), 12 декабря 2010, 21:48 [#1]:Можно взять определенную область соответствующую названию и проходится по поверхности цвета выбранного района и закрасить красным, через секунду закрасить цветом по дефулту и покругу. Задай заранее области выделения соответствующей области и проверяй еще цвета!
 |  
|   | prorok-kane (статус: Посетитель), 12 декабря 2010, 21:51 [#2]:for i:=nach_rayonaX to konec_rayonaX do for j:=nach_rayonaY to konec_rayonaY do
 if (Image1.Canvas.Pixels[i,j]=current_color)
 then Image1.Canvas.Pixels[i,j]:=red;
 for i:=nach_rayonaX to konec_rayonaX do
 for j:=nach_rayonaY to konec_rayonaY do
 if (Image1.Canvas.Pixels[i,j]=red;
 then Image1.Canvas.Pixels[i,j]:=current_color;
 Только главное, чтобы красный нигде не встречался!
 В RGB это реально!
 |  
|   | Вадим К (статус: Академик), 12 декабря 2010, 21:56 [#3]:Вот только работать это будет меееедленно, если вообще будет работать   Галочка "подтверждения прочтения" - вселенское зло. |  
|   | prorok-kane (статус: Посетитель), 12 декабря 2010, 21:57 [#4]:Период меняем за счет таймера! Timer1.interval:=1000; //одна секунда
 
 procedure ontimer
 begin
 if n=0
 then
 begin
 //пихаем процедуру закрашивания красным
 n:=1;
 end
 else begin
 //процедура выбранного цвета
 n:=0;
 end;
 end;
 С производительностью действительно возможны проблемы!
 |  
|   | Al_Sha (статус: Посетитель), 13 декабря 2010, 07:19 [#5]:Спасибо всем откликнувшимся. С уважением Al_Sha
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |