none
BitmapCacheBrush повторная перерисовка RRS feed

  • Вопрос

  • Хочу использовать BitmapCacheBrush для перетаскивания visual на своем UserControl (выбрал потому что работает быстрее VisualBrush), но обнаружилась проблема - при перетаскивании кисть рисует картинку не с верхнего левого угла, а отрисовывает ту часть, которая была на этом месте при самой первой отрисовке. (то есть похоже на то, как будто я картинку накрыл листом бумаги с вырезанным квадратом посередине и передвигаю этот лист - картинка не двигается, а вижу я только ту часть, которая в квадрате - аналогия может и не совсем понятная, но сложно объяснить)

    помогите, пожалуйста, решить данную проблему.

    21 июля 2012 г. 13:39

Ответы

  • Откровенно говоря происходит вырывание из контекста и трудно понять, почему у вас именно такие решения. Во-первых BitmapCache и BitmapCacheBrush используются для буферизации векторных рисунков, то есть тех что нарисованы в XAML с помощью примитивов рисования. То есть эти штуки превращают вектор в растр, а вы уже работаете с растровым объектом и делаете ряд не понятных мне манипуляций (как я и сказал и за оторванности от контекста). Аппаратное ускорение к растру применяться автоматом, поэтому я набросал простой пример быстрого изменения размеров изображения по скролингу. Работает очень шустро даже с объемными изображениями.

    XAML:

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
        <Grid>
            <ScrollViewer PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">
                <Image Name="ZoomImage" Source="Ваша картинка" Height="10" Width="10"></Image>
            </ScrollViewer>
        </Grid>
    </Window>

    Код:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    class MainWindow
    {
    	private void ScrollViewer_PreviewMouseWheel(System.Object sender, System.Windows.Input.MouseWheelEventArgs e)
    	{
    		if (e.Delta > 0) {
    			ZoomImage.Height += 50;
    			ZoomImage.Width += 50;
    		} else {
    			ZoomImage.Height -= 50;
    			ZoomImage.Width -= 50;
    		}
    	}
    }
    Либо я так и не понял что вы хотите сделать.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа Abolmasov Dmitry 26 июля 2012 г. 11:43
    25 июля 2012 г. 5:13
    Отвечающий

Все ответы

  • BitmapCacheBrush используется для многократного повторения сложной визуальной кисти, а вам нужен BitmapCache.

    Вот есть пример его использования.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    21 июля 2012 г. 15:03
    Отвечающий
  • BitmapCache уже использую, но при перетаскивании сложного Visual объекта с помощью VisualBrush образуется большая задержка, перетаскивается не в реальном времени, а со сдвигом где-то на секунду, думал решить данную проблему(

    Пробовал рендерить Visual на RenderTargetBitmap, а потом при перетаскивании рисовать картинку с помощью DrawImage, но тоже получается с задержкой, нет ли какого-то быстрого способа реализовать перетаскивание Visual с кучей объектов?

    21 июля 2012 г. 21:23
  • Ну тут еще бы знать организацию перетаскивания. Вы можете кинуть простой пример, что бы можно было понять что не так?

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    22 июля 2012 г. 6:01
    Отвечающий
  • Пожалуйста не бросайте топик без ответа. Если вы решили проблему, то поделитесь решением. Если проблема не решена, то поделитесь кодом для тестирования и воспроизведения вашей проблемы. Так помочь будет легче.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    24 июля 2012 г. 12:53
    Отвечающий
  • Пример, к сожалению, предоставить пока не могу, работаю над ним. На данный момент использую VisualBrush и                        

                            RenderOptions.SetCachingHint(_imageBrush, CachingHint.Cache);
                            RenderOptions.SetCacheInvalidationThresholdMinimum(_imageBrush, 0.5);
                            RenderOptions.SetCacheInvalidationThresholdMaximum(_imageBrush, 2.0);

    ну и BitmapCache, конечно.

    Огорчает факт отсутствия возможности аппаратного рендеринга изображения из Visual.

    Чтобы не плодить топиков, можете, пожалуйста, помочь с идеей как реализовать быстрое увеличение изображения по колесику мыши, например, сейчас делаю так:

     private static BitmapSource ZoomImageWithBuffer(Rect rect, BitmapSource image, int width, int heigth)
            {
                var visual = new DrawingVisual();
                using (var drawingContext = visual.RenderOpen())
                {
                    drawingContext.DrawImage(image, rect);
                }
    
                var bitmap = new RenderTargetBitmap(width, heigth, 96, 96, PixelFormats.Default);
                bitmap.Render(visual);
                bitmap.Freeze();
    
                return bitmap;
            }

    Но за колесиком оно не поспевает, может есть какой-то способ отрисовки Visual используя все аппаратные возможности, хотя бы с помощью Interop Directx?


    24 июля 2012 г. 19:08
  • Откровенно говоря происходит вырывание из контекста и трудно понять, почему у вас именно такие решения. Во-первых BitmapCache и BitmapCacheBrush используются для буферизации векторных рисунков, то есть тех что нарисованы в XAML с помощью примитивов рисования. То есть эти штуки превращают вектор в растр, а вы уже работаете с растровым объектом и делаете ряд не понятных мне манипуляций (как я и сказал и за оторванности от контекста). Аппаратное ускорение к растру применяться автоматом, поэтому я набросал простой пример быстрого изменения размеров изображения по скролингу. Работает очень шустро даже с объемными изображениями.

    XAML:

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
        <Grid>
            <ScrollViewer PreviewMouseWheel="ScrollViewer_PreviewMouseWheel">
                <Image Name="ZoomImage" Source="Ваша картинка" Height="10" Width="10"></Image>
            </ScrollViewer>
        </Grid>
    </Window>

    Код:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data;
    using System.Diagnostics;
    class MainWindow
    {
    	private void ScrollViewer_PreviewMouseWheel(System.Object sender, System.Windows.Input.MouseWheelEventArgs e)
    	{
    		if (e.Delta > 0) {
    			ZoomImage.Height += 50;
    			ZoomImage.Width += 50;
    		} else {
    			ZoomImage.Height -= 50;
    			ZoomImage.Width -= 50;
    		}
    	}
    }
    Либо я так и не понял что вы хотите сделать.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    • Помечено в качестве ответа Abolmasov Dmitry 26 июля 2012 г. 11:43
    25 июля 2012 г. 5:13
    Отвечающий