Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  07:36[Войти] | [Зарегистрироваться]
Ответ на вопрос № 66358

06-11-2008 05:20
Здравствуйте. Помогите разобраться.
Имеется следующий код:

TfrmMain = class(TForm)
  ...
  private
    { Private declarations }
    btmImage1: TBitmap;
    btmImage2: TBitmap;
  ...
  end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
...
  btmImage1 := TBitmap.Create;
  btmImage1.Width := Image1.Width;
  btmImage1.Height := Image1.Height;
...
end;


procedure TfrmMain.Button1Click(Sender: TObject);
var
  R: Integer;
begin
  with btmImage1 do  {Если заменить на Image1, то все работает так как надо}
    begin
      PatBlt(Canvas.Handle, 0, 0, Width, Height, WHITENESS);

      Canvas.Pen.Color := clBlack;

      R := SetMapMode(Canvas.Handle, MM_ISOTROPIC);


      // Изменение направления координатных осей
      SetWindowExtEx(Canvas.Handle, 1, 1, nil);
      SetViewportExtEx(Canvas.Handle, - 1, - 1, nil);
      // Изменение расположения начала координат
      SetViewportOrgEx(Canvas.Handle, Width, Height, nil);

      Canvas.Rectangle(10, 10, 50, 30);

      SetMapMode(Canvas.Handle, R);
    end;

  Image1.Canvas.Draw(0,0,btmImage1);
end;

В результате выполнения Button1Click объект Image1 просто заполяется белым цветом.
Если же выполнить рисование непосредственно на Image1, то отрисовка пройдет нормально.
В чем причина?

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

07-11-2008 02:55
нигде не нашел почему так следует делать
Это же Виндоус, так что только опытным путём. (разбираться и перечитывать MSDN времени нет)

при вызове метода SaveToFile, преобразование параметров осей у приемника btmImage2 не требуется?
Скорее всего (ну это же Виндоус), при сохранении, контект Bitmap.Canvas приводится к необходимому для сохранения виду, после чего его можно копировать в другие стандартные контексты без преобразования осей.

07-11-2008 02:10 | Сообщение от автора вопроса
Для Александр Пугачёв:
Главная проблема здесь в том, что происходит смена параметров осей. Поэтому чтобы скопировать из одного Bitmap в другой необходимо, чтобы оси у них были настроены идентично.
Спасибо действительно работает, только нигде не нашел почему так следует делать и почему при вызове метода SaveToFile, преобразование параметров осей у приемника btmImage2 не требуется?

07-11-2008 01:57 | Сообщение от автора вопроса
Для Антон Григорьев и ploop:
Всё было праивльно сказано. TImage - это когда надо отображать одну отдельно взятую готовую картинку. Как только вы собираете картинку из нескольких элементов, пусть даже каждый из этих элементов является bitmap'ом, про TImage лучше забыть - не приспособлен он для этого, глюков очень много.

Старожилы Круглого стола уже устали отвечать на вопросы, связанные с этими глюками. Но люди почему-то обычно предпочитают не слушать хорошие советы и выкидывать TImage на фиг, а с упорством, достойным лучшего применения, прыгать и прыгать на эти грабли.

Иля я не правильно объясняю или вы понять не можете, НЕ ИСПОЛЬЗУЮ Я В РЕАЛЬНОЙ РАБОТЕ TImage. ИСПОЛЬЗУЮ TBitmap, а TImage здесь был лишь для ИЛЛЮСТРАЦИИ.

И следующий код работает неверно и там НЕТ TImage:


  with btmImage1 do
    begin
      PatBlt(Canvas.Handle, 0, 0, Width, Height, WHITENESS);

      Canvas.Pen.Color := clBlack;

      R := SetMapMode(Canvas.Handle, MM_ISOTROPIC);


      // Изменение направления координатных осей
      SetWindowExtEx(Canvas.Handle, 1, 1, nil);
      SetViewportExtEx(Canvas.Handle, - 1, - 1, nil);
      // Изменение расположения начала координат
      SetViewportOrgEx(Canvas.Handle, Width, Height, nil);

      Canvas.Rectangle(10, 10, 50, 30);

      SetMapMode(Canvas.Handle, R);
    end;

  { если поставить сюда btmImage1.SaveToFile('c:\test1.bmp') то все работает верно}

  btmImage2.Canvas.Draw(0,0,btmImage1);
  btmImage2.SaveToFile('c:\test2.bmp'); {Для контроля}



Так что не в TImage дело.

P.S. Старожилы читайте внимательней сообщения.

07-11-2008 01:42
Главная проблема здесь в том, что происходит смена параметров осей. Поэтому чтобы скопировать из одного Bitmap в другой необходимо, чтобы оси у них были настроены идентично.

У меня всё нормально работает, предлагаю свой код:


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
           Image1: TImage;
           Button1: TButton;
           PaintBox1: TPaintBox;
           procedure FormCreate(Sender: TObject);
           procedure Button1Click(Sender: TObject);
           procedure PaintBox1Paint(Sender: TObject);
  private
           { Private declarations }
           btmImage1: TBitmap;
           btmImage2: TBitmap;
  public
           { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  R, R2, R3: Integer;
begin
  with btmImage1 do
           begin
            PatBlt(Canvas.Handle, 0, 0, Width, Height, WHITENESS);

            Canvas.Pen.Color := clBlack;

            R := SetMapMode(Canvas.Handle, MM_ISOTROPIC);

            // Изменение направления координатных осей
            SetWindowExtEx(Canvas.Handle, 1, 1, nil);
            SetViewportExtEx(Canvas.Handle, -1, -1, nil);
            // Изменение расположения начала координат
            SetViewportOrgEx(Canvas.Handle, Width, Height, nil);

            Canvas.Rectangle(10, 10, 50, 30);

           end;

  with btmImage2 do
           begin
            R2 := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
            SetWindowExtEx(Canvas.Handle, 1, 1, nil);
            SetViewportExtEx(Canvas.Handle, -1, -1, nil);
            SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
            BitBlt(btmImage2.Canvas.Handle, 0, 0, btmImage2.Width, btmImage2.Height,
                     btmImage1.Canvas.Handle, 0, 0, SRCCOPY);
           end;

  with Image1 do
           begin
            R3 := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
            SetWindowExtEx(Canvas.Handle, 1, 1, nil);
            SetViewportExtEx(Canvas.Handle, -1, -1, nil);
            SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
            BitBlt(Canvas.Handle, 0, 0, Width, Height,
                     btmImage1.Canvas.Handle, 0, 0, SRCCOPY);
           end;

           SetMapMode(btmImage1.Canvas.Handle, R);
           SetMapMode(btmImage2.Canvas.Handle, R2);
           SetMapMode(btmImage2.Canvas.Handle, R3);

           PaintBox1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  btmImage1 := TBitmap.Create;
  btmImage1.Width := Image1.Width;
  btmImage1.Height := Image1.Height;

  btmImage2 := TBitmap.Create;
  btmImage2.Width := Image1.Width;
  btmImage2.Height := Image1.Height;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
           BitBlt(PaintBox1.Canvas.Handle, 0, 0, PaintBox1.Width, PaintBox1.Height,
                     btmImage2.Canvas.Handle, 0, 0, SRCCOPY);
end;

end.


07-11-2008 01:39
И еще немного поясню:

function TImage.GetCanvas: TCanvas;
var
  Bitmap: TBitmap;
begin
  if Picture.Graphic = nil then
  begin
           Bitmap := TBitmap.Create; // Создаётся промежуточный битмап
           try
            Bitmap.Width := Width;
            Bitmap.Height := Height;
            Picture.Graphic := Bitmap; // Битмап копируется (Assign) в новый объект Graphic
           finally
            Bitmap.Free;
           end;
  end;
  if Picture.Graphic is TBitmap then
           Result := TBitmap(Picture.Graphic).Canvas
  // Далее идёт обращение к Canvas довольно сложного объекта Graphic, где-то там и проблема
  else
           raise EInvalidOperation.Create(SImageCanvasNeedsBitmap);
end;


Про это и говорят, что TImage создан для показа статичных изображений

07-11-2008 01:28
Вы невнимательно прочли.
P.S. Данный код является лишь иллюстрацией проблемы.


Всё было праивльно сказано. TImage - это когда надо отображать одну отдельно взятую готовую картинку. Как только вы собираете картинку из нескольких элементов, пусть даже каждый из этих элементов является bitmap'ом, про TImage лучше забыть - не приспособлен он для этого, глюков очень много.

Старожилы Круглого стола уже устали отвечать на вопросы, связанные с этими глюками. Но люди почему-то обычно предпочитают не слушать хорошие советы и выкидывать TImage на фиг, а с упорством, достойным лучшего применения, прыгать и прыгать на эти грабли.

07-11-2008 01:25
и именно для них хочется понят в чем заключается проблема и как ее решить.
Вам говорят, что проблема не с битмапами, а с выводом на TImage, т.к. он не предназначен для этого.

Такой вариант вариант работает, но не подходит по ряду причин: напрмер, если я захочу, вывести отрисовать на одном Image1 несколько объектов TBitmap.
Соберите в промежуточный битмап все остальные и отрисуйте. Но еще раз повторю, это не хороший вариант. Лучше использовать PaintBox.

07-11-2008 01:07 | Сообщение от автора вопроса
Для Александр Пугачёв:
В таком случае советую использовать PaintBox и собирать итоговое изображение по событию OnPaint.
Хотя, я бы собирал итоговое изображение в промежуточный Bitmap, а потом отрисовывал бы в PaintBox.

Компонент Image плохо подходит для задач отрисовки в Runtime, я данный компонент использую в основном для показа картинок из файлов.

Вы невнимательно прочли.
P.S. Данный код является лишь иллюстрацией проблемы. Исходная же задача:
- есть несколько "теневых" слоёв, которые являются объектами TBitmap.
- есть "визуальный" слой (тоже TBitmap) который компануется из "теневых".
т.е. вся работа ведется с объектами TBitmap, и именно для них хочется понят в чем заключается проблема и как ее решить.

07-11-2008 00:59
P.S. Данный код является лишь иллюстрацией проблемы. Исходная же задача:
- есть несколько "теневых" слоёв, которые являются объектами TBitmap.
- есть "визуальный" слой (тоже TBitmap) который компануется из "теневых".
т.е. вся работа ведется с объектами TBitmap, и именно для них хочется понят в чем заключается проблема и как ее решить.


В таком случае советую использовать PaintBox и собирать итоговое изображение по событию OnPaint.
Хотя, я бы собирал итоговое изображение в промежуточный Bitmap, а потом отрисовывал бы в PaintBox.

Компонент Image плохо подходит для задач отрисовки в Runtime, я данный компонент использую в основном для показа картинок из файлов.

07-11-2008 00:22 | Сообщение от автора вопроса
Для ploop:
Битмап выводится куда угодно, хоть прямо на форму. Если уж так хочется TImage использовать - работает такой вариант:

Image1.Picture.Assign(btmImage1);


Такой вариант вариант работает, но не подходит по ряду причин: напрмер, если я захочу, вывести отрисовать на одном Image1 несколько объектов TBitmap.

Для Александр Пугачёв:
...Проверяется просто:
btmImage1.SaveToFile('c:\test.bmp');

Действительно все работает, и самое интересное, что если поставить вызов метода SaveToFile, перед вызовом Draw, то и отрисуется все нормально... пошел изучать таинство SaveToFile :)

P.S. Данный код является лишь иллюстрацией проблемы. Исходная же задача:
- есть несколько "теневых" слоёв, которые являются объектами TBitmap.
- есть "визуальный" слой (тоже TBitmap) который компануется из "теневых".
т.е. вся работа ведется с объектами TBitmap, и именно для них хочется понят в чем заключается проблема и как ее решить.

06-11-2008 23:19
Битмап выводится куда угодно, хоть прямо на форму. Если уж так хочется TImage использовать - работает такой вариант:

Image1.Picture.Assign(btmImage1);


06-11-2008 14:16
Попробовал данный код, и получил удивительный результат: до строчки

Image1.Canvas.Draw(0,0,btmImage1);

всё отлично работает.


Проверяется просто:

btmImage1.SaveToFile('c:\test.bmp');

и смотрим файл - там все правильно нарисовано.

Так что здесь неправильно отрабатывается отрисовка на Image1 из btmImage1.

Также проверил следующим образом: кинул на форму PaintBox и по событию OnPaint пишу следующее:


procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  bitblt(PaintBox1.Canvas.handle, 0, 0, PaintBox1.Width, PaintBox1.height, btmImage1.Canvas.Handle, 0, 0, SRCCOPY);
end;


отображается всё корректно.

06-11-2008 12:34 | Комментарий к предыдущим ответам
Попробуйте сразу после создания btmImage1 сделать btmImage1.PixelFormat:=pf24Bit;
Я пробовал. И другие варианты. Ничего... А досканально разобраться времени нет.

06-11-2008 12:22
Попробуйте сразу после создания btmImage1 сделать

btmImage1.PixelFormat:=pf24Bit;


Не уверен, что поможет, но попробовать стоит.

Ещё есть подозрение, что у созданной вручную картинки не такие dpi, как у загруженной из файла. Попробуйте покопать в этом направлении.

06-11-2008 09:50
Выяснил, если убрать SetMapMode(Canvas.Handle, R) - начинает работать. Но неправильно. В принципе код то правильный, но почему не работает - выяснять надо...

06-11-2008 07:34 | Сообщение от автора вопроса
plool
Попробуйте переписать без with, может, не к тому Canvas обращение идёт.
Нет конструкция with тут не причем (результат работы без with точно такой же)

06-11-2008 06:13
Попробуйте переписать без with, может, не к тому Canvas обращение идёт.

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Жили у бабуси два веселых гуся. Один белый, другой КАКОЙ?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования