WPF: Экспорт Canvas'a в BMP
От: czz  
Дата: 01.05.11 21:21
Оценка:
Здравствуйте!
Есть Canvas (WPF), заполняемый в процессе работы программы (в том числе изменяется и размер). Стоит задача экспортировать его в файл BMP/PNG.
Гугл помог найти несколько вариантов решения, но все они приводят к получению черного BMP файла или прозрачного PNG файла (замечу, что фон Canvas'a задан белым).

Например, код:

        public static void SaveCanvasToFile(Canvas surface, string filename)
        {
            // Save current canvas transform
            //Transform transform = surface.LayoutTransform;
            // reset current transform (in case it is scaled or rotated)
            surface.LayoutTransform = null;

            // Get the size of canvas
            Size size = new Size(surface.Width, surface.Height);
            // Measure and arrange the surface
            // VERY IMPORTANT
            surface.Measure(size);
            surface.Arrange(new Rect(size));
            surface.UpdateLayout();
            // Create a render bitmap and push the surface to it
            RenderTargetBitmap renderBitmap =
              new RenderTargetBitmap(
                (int)size.Width,
                (int)size.Height,
                96d,
                96d,
                PixelFormats.Pbgra32);
            renderBitmap.Render(surface);

            // Create a file stream for saving image
            using (FileStream outStream = new FileStream(filename, FileMode.Create))
            {
                // Use png encoder for our data
                BmpBitmapEncoder encoder = new BmpBitmapEncoder();
                // push the rendered bitmap to it
                encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
                // save the data to the stream
                encoder.Save(outStream);
            }
}


Что я делаю не так и что можно предпринять?
wpf
Re: WPF: Экспорт Canvas'a в BMP
От: MxMsk Португалия  
Дата: 01.05.11 21:43
Оценка:
Здравствуйте, czz, Вы писали:

czz> // Get the size of canvas

czz> Size size = new Size(surface.Width, surface.Height);
czz> // Measure and arrange the surface
czz> // VERY IMPORTANT
czz> surface.Measure(size);
czz> surface.Arrange(new Rect(size));
czz> surface.UpdateLayout();
Вместо всего этого правильнее вызвать InvalidateMeasure и UpdateLayout. И далее использовать ActualWidth и ActualHeight канваса для создания битмэпа.

czz> // Create a render bitmap and push the surface to it

czz> RenderTargetBitmap renderBitmap =
czz> new RenderTargetBitmap(
czz> (int)size.Width,
czz> (int)size.Height,
czz> 96d,
czz> 96d,
czz> PixelFormats.Pbgra32);
czz> renderBitmap.Render(surface);
Думаю, здесь стоит тормознуть и загрузить битмэп в Image, чтобы быть уверенным в отсутствии ошибки в самом экспорте в файл.
Re[2]: WPF: Экспорт Canvas'a в BMP
От: czz  
Дата: 01.05.11 21:55
Оценка:
Сделал — не помогло. При загрузке в Image получается прозрачный Image

Здравствуйте, MxMsk, Вы писали:

MM>Здравствуйте, czz, Вы писали:


MM>Вместо всего этого правильнее вызвать InvalidateMeasure и UpdateLayout. И далее использовать ActualWidth и ActualHeight канваса для создания битмэпа.



MM>Думаю, здесь стоит тормознуть и загрузить битмэп в Image, чтобы быть уверенным в отсутствии ошибки в самом экспорте в файл.
Re: WPF: Экспорт Canvas'a в BMP
От: czz  
Дата: 01.05.11 22:06
Оценка:
Интересно, что этот код, оказывается, нормально ест другую канву. Но чем она принципиально отличается от нужной, мне не понятно.
Та, которую алгоритм ест имеет Auto размеры, а нужная фиксированные, но изменяемые кодом вручную.

Вообще опишу задачу, чтобы предотвратить ненужные костыли.
Программа рисует WPF'ом различные графики на нескольких закладках TabControl'a. Задача — всех их экспортировать. Размеры Canvas'ов на закладках — Auto, поэтому, пока закладка не будет хоть раз открыта, на соответствующей ей канве ничего рисовать нельзя (неизвестны размеры, а даже если известны рендера все равно не будет, как я понимаю, пока не откроешь вкладку. Отлавливаю момент первого ресайза чтобы нарисовать изображение).
Ну вот я подумал что бы экспортировать сделаю канву на текущей закладке и проведу цикл "отрисовка-экмпорт" для всех графиков .
У меня есть ощущение, что куда-то закрались сильные костыли. Как лучше поступить?)

Спасибо!
Re[2]: WPF: Экспорт Canvas'a в BMP
От: czz  
Дата: 02.05.11 07:47
Оценка:
А во, заметил, что если целевую канву подвинуть в верхний левый угол, то вроде работает. Делается снимок как бы левого верхнего куска окна с размерами канвы. Из-за чего это может быть?
Re[2]: WPF: Экспорт Canvas'a в BMP
От: MxMsk Португалия  
Дата: 02.05.11 07:50
Оценка:
Здравствуйте, czz, Вы писали:

czz>Вообще опишу задачу, чтобы предотвратить ненужные костыли.

czz>Программа рисует WPF'ом различные графики на нескольких закладках TabControl'a. Задача — всех их экспортировать. Размеры Canvas'ов на закладках — Auto, поэтому, пока закладка не будет хоть раз открыта, на соответствующей ей канве ничего рисовать нельзя (неизвестны размеры, а даже если известны рендера все равно не будет, как я понимаю, пока не откроешь вкладку. Отлавливаю момент первого ресайза чтобы нарисовать изображение).
czz>Ну вот я подумал что бы экспортировать сделаю канву на текущей закладке и проведу цикл "отрисовка-экмпорт" для всех графиков .
czz>У меня есть ощущение, что куда-то закрались сильные костыли. Как лучше поступить?)
В TabControl-е есть засада в том, что контент невыбранных вкладок не входит в дерево элементов. Это значит, что часть биндингов и ресурсов может просто не действовать, пока вкладка неактивна. Далее, ты уверен, что элементы вкладки действительно лежат на Канвасе, а не просто расположены в соседней ветви дерева? Приведи хотя-бы примерный код, каким образом определяется содержимое вкладки, где там размещается Канвас.
Re: WPF: Экспорт Canvas'a в BMP
От: Pavel Dvorkin Россия  
Дата: 02.05.11 08:13
Оценка:
Здравствуйте, czz, Вы писали:

czz>
czz>        public static void SaveCanvasToFile(Canvas surface, string filename)
czz>            renderBitmap.Render(surface);

czz>


czz>Что я делаю не так и что можно предпринять?


Я не работаю с WPF, но могу отметить, что такое обычно происходит при попытке рендерить в контекст(канву), в котором выбрана монохромная битовая карта. Откуда Canvas взята и что в ней за карта ?
With best regards
Pavel Dvorkin
Re[2]: WPF: Экспорт Canvas'a в BMP
От: MxMsk Португалия  
Дата: 02.05.11 09:24
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Я не работаю с WPF, но могу отметить, что такое обычно происходит при попытке рендерить в контекст(канву), в котором выбрана монохромная битовая карта. Откуда Canvas взята и что в ней за карта ?

Тут такая нестыковочка. Canvas в WPF — это не то, что в большинстве остальных Фреймворков. Можно считать, что это просто аналог Panel из Windows Forms. Так что автор пытается рендерить WPF контент в битовую карту формата Pbgra32.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.