Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 Нарисовать строку на изображении в image  [new]
mraklbrw
Member

Откуда: Брянск
Сообщений: 270
Добрый день.
Недавно начал изучать WPF(перешёл с WinForms), возникла надобность нанести строку из TextBox на изображение, загруженное в Image и поместить получившееся изображение в image2.

+ Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Watermark_Guru
{
    /// <summary>
    /// Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        BitmapImage bm1;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //bm1 = new BitmapImage();
        }

        // Кнопка - открыть файл
        private void btn1_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string path = "";
                Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
                Nullable<bool> result = dlg.ShowDialog();
                if (result == true) path = dlg.FileName; // Получение пути выбранного в диалоге файла

                bm1 = new BitmapImage();
                bm1.BeginInit();
                bm1.UriSource = new Uri(path, UriKind.Relative);
                bm1.CacheOption = BitmapCacheOption.OnLoad;
                bm1.EndInit();

                im1.Source = bm1;
            }
            catch (Exception)
            {
                MessageBox.Show("Path doesn't exists.");
            }
        }

        // Кнопка - сгенерировать 2-ое изображение
        private void btn3_Click(object sender, RoutedEventArgs e)
        {
            string watermark_text = tb1.Text;

            DrawingVisual dv = new DrawingVisual();
            DrawingContext dc = dv.RenderOpen();
            dc.DrawLine(new Pen(Brushes.Black, 1.0), new Point(40, 40), new Point(200, 200));
            dc.Close();

            RenderTargetBitmap bm2 = new RenderTargetBitmap(400, 300, 126, 126, PixelFormats.Pbgra32);

            
            bm2.Render(dv);

            im2.Source = bm2;

        }
    }
}



У меня выходит просто нарисованная линия, т.к. содержимое из image не знаю, как скопировать в image2 или в новый bitmap и уже на нём что-нибудь нарисовать.
6 июн 17, 18:11    [20544465]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
iMrTidy
Member

Откуда:
Сообщений: 775
mraklbrw,

Все что связано с оформлением (за редким исключением) следует писать в XAML. Для Вашего случая можно поступить так:

    <Grid>
        <Image Source="...путь к изображению..." />
        <TextBox Background="70FFFFFF" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontSize="50" Text="Test" />
    </Grid>
7 июн 17, 18:12    [20548056]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
mraklbrw
Member

Откуда: Брянск
Сообщений: 270
iMrTidy,

а как сохранить изображение вместе с надписью в textbox-е в новый файл(например, 2.bmp) ?
8 июн 17, 22:16    [20551598]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
iMrTidy
Member

Откуда:
Сообщений: 775
mraklbrw
iMrTidy,

а как сохранить изображение вместе с надписью в textbox-е в новый файл(например, 2.bmp) ?


Довльно редко требуются такие вещи. А для чего?
Как правило есть возможно сделать задачу проще.

XAML:
+
<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" ContentRendered="Window_ContentRendered">
    <Grid Name="myGrid">
        <Image MaxWidth="300" Source="D:\Test\Capture.jpg" />
        <TextBox BorderBrush="Transparent" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontSize="50" Text="Test" />
    </Grid>
</Window>


C#:
+
        public MainWindow()
        {
            InitializeComponent();
        }

        public void RenderTargetBitmapExample()
        {
            var size = new Size(myGrid.ActualWidth, myGrid.ActualHeight); //Size object will be used to define Bitmap.
            var bmp = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32); //Bitmap for rendering from visual object.

            var drawingvisual = new DrawingVisual();
            using (DrawingContext context = drawingvisual.RenderOpen())
            {
                context.DrawRectangle(new VisualBrush(myGrid), null, new Rect(new Point(), size)); //Here we decide what visual object and its size.
                context.Close();
            }
            bmp.Render(drawingvisual);

            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bmp));
            var fs = new FileStream(@"d:\test\test.png", FileMode.Create);
            encoder.Save(fs);
        }

        private void Window_ContentRendered(object sender, EventArgs e)
        {
            RenderTargetBitmapExample();
        }
    }
9 июн 17, 00:07    [20551756]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
iMrTidy
Member

Откуда:
Сообщений: 775
mraklbrw,

Сохранять в файл Вам возможно и не требуется, это лишь для примера.
9 июн 17, 09:56    [20552060]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
mraklbrw
Member

Откуда: Брянск
Сообщений: 270
iMrTidy,

Спасибо за пример, но возник ещё такой вопрос:
почему при изменении текста в textbox вручную пользователем при сохранении он сохраняет картинку с этим текстом, а при изменении текста в TextBox программно изменения не происходят(сохраняется картинка с надписью Test).

+ Сохранение изображения

// Кнопка - изменить текст
        private void btn3_Click(object sender, RoutedEventArgs e)
        {
            TB_2.Text= tb1.Text; // TB2 - это textBox с надписью Test, а tb1 - это там, где пользователь что-то пишет

            Thread.Sleep(250);

            RenderTargetBitmapExample();

        }

        public void RenderTargetBitmapExample()
        {
            var size = new Size(myGrid.ActualWidth, myGrid.ActualHeight); //Size object will be used to define Bitmap.
            var bmp = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32); //Bitmap for rendering from visual object.

            var drawingvisual = new DrawingVisual();
            using (DrawingContext context = drawingvisual.RenderOpen())
            {
                context.DrawRectangle(new VisualBrush(myGrid), null, new Rect(new Point(), size)); //Here we decide what visual object and its size.
                context.Close();
            }
            bmp.Render(drawingvisual);

            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bmp));
            var fs = new FileStream(@"test.png", FileMode.Create);
            encoder.Save(fs);
        }


Возможно это происходит из-за того, что мы в XAML жёстко задали текст - Test и нужно как-то по другому его перезаписать?
9 июн 17, 12:31    [20552780]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
iMrTidy
Member

Откуда:
Сообщений: 775
mraklbrw,

В WPF код "позади" окна/контрола не приветствуется, т.к. это нарушет принципы MVVM. Очень рекомендую почитать литературу на тему WPF/MVVM.

Картинка не меняется программно, т.к. XAML часть не успевает ее перерисовать, это можно решить добавив .UpdateLayout(); сразу после присвоения нового значения, но я не рекомендую это.

Я не зря спросил про цель. Возможно Вам вообще не нужно ничего делать в XAML, а написать все кодом. Но раз уж Вы упомянули, что есть пользователь, то лучше сделать так:

XAML:
+
<Window x:Class="VisualElementToBitmap.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:VisualElementToBitmap"
        mc:Ignorable="d"
        Title="MainWindow" Height="500" Width="525">
    <StackPanel>
        <Grid Name="myGrid">
            <Image Source="Resources\Capture.JPG" />
            <Label Name="myLabel" BorderBrush="Transparent" Background="Transparent" HorizontalAlignment="Center" VerticalAlignment="Center" FontWeight="Bold" FontSize="50"
                   Content="{Binding ElementName=txt, Path=Text}" />
        </Grid>
        <StackPanel>
            <Label Content="User text:" />
            <TextBox Name="txt" Text="User Test" Margin="5,5,0,0" />
            <Button Width="Auto" HorizontalAlignment="Left" Margin="5,5,0,0" Content="Generate image" Click="Button_Click" />
        </StackPanel>
    </StackPanel>
</Window>


C#:
+
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        public void RenderTargetBitmapExample()
        {
            var size = new Size(myGrid.ActualWidth, myGrid.ActualHeight); //Size object will be used to define Bitmap.
            var bmp = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32); //Bitmap for rendering from visual object.

            var drawingvisual = new DrawingVisual();
            using (DrawingContext context = drawingvisual.RenderOpen())
            {
                context.DrawRectangle(new VisualBrush(myGrid), null, new Rect(new Point(), size)); //Here we decide what visual object and its size.
                context.Close();
            }
            bmp.Render(drawingvisual);

            var encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(bmp));
            var fs = new FileStream(@"c:\test\test.png", FileMode.Create);
            encoder.Save(fs);
            fs.Close();
            fs.Dispose();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            RenderTargetBitmapExample();
        }
    }
9 июн 17, 13:36    [20553131]     Ответить | Цитировать Сообщить модератору
 Re: Нарисовать строку на изображении в image  [new]
mraklbrw
Member

Откуда: Брянск
Сообщений: 270
iMrTidy,

Благодарю Вас. Вы мне очень помогли.
9 июн 17, 22:06    [20554439]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить