拼图:设置一个图片相同的大小和位置到另一个图像 [英] Picture Puzzle: Set one Image to the same size and position to another image

查看:354
本文介绍了拼图:设置一个图片相同的大小和位置到另一个图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我已经问过你为我画谜(问题<一href=\"http://stackoverflow.com/questions/13488809/picture-puzzle-spaces-gaps-between-grid-rows/13488942\">Original问)。

today I already asked you a question for my picture puzzle (Original Question).

我开始重写我的code有更好的表现。而我得到的最重要的部分完成了!

I started to rewrite my code for better performance. And I got the most important part done!

不过,我还有一个问题..我产生一个灰色的叠加图像隐藏图像,而是因为我要处理我不能设置固定的宽度和高度值的面具图片动态大小。所以可能不是全貌堆焊我的面具。

But I have another problem.. I generate a gray overlay image to hide the image, but because I want to handle dynamic size of pictures I cannot set fixed width and height values for the "mask". So probably not the whole picture is overlayed with my "mask".

是否有人有一个解决方案?我不知道如何我的掩模的位置和大小,准确地设置的图像的位置和大小。

Does somebody have a solution for this? I don't know how to set the position and size of my mask exactly to the position and size of the picture.

我连着示范截屏。

XAML:

<Window x:Class="PicturePuzzle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Loaded="WindowLoaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="80" />
        </Grid.RowDefinitions>

        <Grid x:Name="grid"
              Margin="5"
              HorizontalAlignment="Center"
              VerticalAlignment="Top">

            <Image x:Name="imgPicture"
                   HorizontalAlignment="Stretch"
                   VerticalAlignment="Stretch"
                   Source="Images/puzzle.gif"
                   Stretch="Uniform" />
            <Image x:Name="imgMask" RenderOptions.EdgeMode="Aliased" />
        </Grid>

        <StackPanel Grid.Row="1"
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center">
            <StackPanel Margin="0,0,0,10" Orientation="Horizontal">
                <Button x:Name="btnStart"
                        Width="60"
                        Margin="0,0,5,0"
                        Click="BtnStartClick"
                        Content="Start" />
                <Button x:Name="btnStop"
                        Width="60"
                        Click="BtnStopClick"
                        Content="Stop"
                        IsEnabled="False" />
                <ToggleButton x:Name="btnSolution"
                              Margin="5,0,0,0"
                              Checked="btnSolution_Checked"
                              Content="Lösung anzeigen"
                              Unchecked="btnSolution_Unchecked" />
            </StackPanel>
            <Slider x:Name="slSpeed"
                    IsDirectionReversed="True"
                    Maximum="10"
                    Minimum="1"
                    ValueChanged="SlSpeedValueChanged"
                    Value="10" />
        </StackPanel>
    </Grid>
</Window>

codebehind:

Codebehind:

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace PicturePuzzle
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            _positionAlphaValues = new Dictionary<Point, byte>();

            _images = new List<FileInfo>();
            using (var s = new StreamReader("Images.txt"))
            {
                while (!s.EndOfStream)
                {
                    var line = s.ReadLine();

                    if (string.IsNullOrWhiteSpace(line))
                    {
                        continue;
                    }

                    var fi = new FileInfo(line);

                    if (!fi.Exists)
                    {
                        continue;
                    }

                    _images.Add(fi);
                }
            }
        }

        private const int MaxQuadsX = 5;
        private const int MaxQuadsY = 5;

        private readonly List<FileInfo> _images;

        private DispatcherTimer _timer;
        private DispatcherTimer _alphaTimer;
        private WriteableBitmap _bitmap;
        private Size _size;
        private List<Point> _positions;
        private Dictionary<Point, byte> _positionAlphaValues;
        private int _tickCounter;
        private int _imageCounter;
        private int _quadWidth;
        private int _quadHeight;


        private void WindowLoaded(object sender, RoutedEventArgs e)
        {
            _size = imgPicture.RenderSize;

            var width = (int)Math.Ceiling(_size.Width);
            var height = (int)Math.Ceiling(_size.Height);

            _quadWidth = width / MaxQuadsX;
            _quadHeight = height / MaxQuadsY;

            imgPicture.Width = _quadWidth * MaxQuadsX - 5;
            imgPicture.Height = _quadHeight * MaxQuadsY - 5;

            _bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);

            imgMask.Source = _bitmap;
        }

        #region Click handlers

        private void BtnStartClick(object sender, RoutedEventArgs e)
        {
            btnStart.IsEnabled = false;
            btnStop.IsEnabled = true;
            btnSolution.IsChecked = false;

            // set the real picture
            _imageCounter = 0;
            _images.Shuffle();
            SetPuzzlePicture();

            _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(slSpeed.Value / 10) };
            _timer.Tick += TimerTick;
            _timer.Start();

            _alphaTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.1) };
            _alphaTimer.Tick += AlphaTimerOnTick;
            _alphaTimer.Start();
        }

        private void BtnStopClick(object sender, RoutedEventArgs e)
        {
            btnStart.IsEnabled = true;
            btnStop.IsEnabled = false;

            _timer.Stop();
            _alphaTimer.Stop();
        }

        private void SlSpeedValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (_timer != null)
            {
                _timer.Interval = TimeSpan.FromSeconds(slSpeed.Value / 10);
            }
        }


        private void btnSolution_Checked(object sender, RoutedEventArgs e)
        {
            btnStop.IsEnabled = false;

            StopTimers();

            imgMask.Visibility = Visibility.Hidden;
        }

        private void btnSolution_Unchecked(object sender, RoutedEventArgs e)
        {
            btnStart.IsEnabled = true;
            btnStop.IsEnabled = false;

            ResetMaskImage();
        }

        #endregion

        private void SetPuzzlePicture()
        {
            _positionAlphaValues.Clear();

            ResetMaskImage();

            var imgFile = _images[_imageCounter++];

            var image = new BitmapImage();
            image.BeginInit();
            image.UriSource = new Uri(imgFile.FullName, UriKind.Absolute);
            image.EndInit();

            imgPicture.Source = image;
        }

        private void TimerTick(object sender, EventArgs e)
        {
            if (_tickCounter >= _positions.Count)
            {
                if (_imageCounter >= _images.Count)
                {
                    _timer.Stop();

                    btnStart.IsEnabled = true;
                    btnStop.IsEnabled = false;

                    return;
                }

                SetPuzzlePicture();
            }

            var randomPoint = _positions[_tickCounter++];

            _positionAlphaValues.Add(randomPoint, 255);
        }

        private void AlphaTimerOnTick(object sender, EventArgs eventArgs)
        {
            var updatedList = new Dictionary<Point, byte>();

            foreach (var e in _positionAlphaValues)
            {
                var newValue = e.Value - (11 - slSpeed.Value) * 5;

                if (newValue <= 0)
                {
                    continue;
                }

                SetAlphaChannel(e.Key, (byte)newValue);
                updatedList.Add(e.Key, (byte)newValue);
            }

            _positionAlphaValues = updatedList;
        }

        private void StopTimers()
        {
            if (_timer != null)
            {
                _timer.Stop();
            }

            if (_alphaTimer != null)
            {
                _alphaTimer.Stop();
            }
        }

        private void ResetMaskImage()
        {
            imgMask.Visibility = Visibility.Visible;

            var width = _quadWidth * MaxQuadsX;
            var height = _quadHeight * MaxQuadsY;
            var size = width * height * 4;

            var buffer = new byte[size];

            for (int i = 0; i < size; i++)
            {
                buffer[i++] = 128;
                buffer[i++] = 128;
                buffer[i++] = 128;
                buffer[i] = 255;
            }

            var area = new Int32Rect(0, 0, width, height);
            _bitmap.WritePixels(area, buffer, width * 4, 0);

            _positions = GetPositions();
            _tickCounter = 0;
        }

        private void SetAlphaChannel(Point point, byte alpha)
        {
            var size = _quadWidth * _quadHeight * 4;
            var buffer = new byte[size];

            for (int i = 0; i < size; i++)
            {
                buffer[i++] = 128;
                buffer[i++] = 128;
                buffer[i++] = 128;
                buffer[i] = alpha;
            }

            var startX = (int)point.X * _quadWidth;
            var startY = (int)point.Y * _quadHeight;

            var area = new Int32Rect(startX, startY, _quadWidth, _quadHeight);
            _bitmap.WritePixels(area, buffer, _quadWidth * 4, 0);
        }

        private List<Point> GetPositions()
        {
            var generated = new List<Point>();

            for (int y = 0; y < MaxQuadsY; y++)
            {
                for (int x = 0; x < MaxQuadsX; x++)
                {
                    var point = new Point(x, y);

                    generated.Add(point);
                }
            }

            generated.Shuffle();

            return generated;
        }
    }
}

Extensions.cs

Extensions.cs

using System;
using System.Collections.Generic;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace PicturePuzzle
{
    public static class Extensions
    {
        public static Color GetPixel(this WriteableBitmap wbm, int x, int y)
        {
            if (y > wbm.PixelHeight - 1 || x > wbm.PixelWidth - 1)
                return Color.FromArgb(0, 0, 0, 0);

            if (y < 0 || x < 0)
                return Color.FromArgb(0, 0, 0, 0);

            if (!wbm.Format.Equals(PixelFormats.Bgra32))
                return Color.FromArgb(0, 0, 0, 0);

            IntPtr buff = wbm.BackBuffer;
            int stride = wbm.BackBufferStride;
            Color c;

            unsafe
            {
                var pbuff = (byte*)buff.ToPointer();
                int loc = y * stride + x * 4;

                c = Color.FromArgb(
                  pbuff[loc + 3],
                  pbuff[loc + 2], pbuff[loc + 1],
                  pbuff[loc]);
            }

            return c;
        }

        public static void Shuffle<T>(this IList<T> list)
        {
            var rng = new Random();
            int n = list.Count;
            while (n > 1)
            {
                n--;
                int k = rng.Next(n + 1);
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }
}

例Images.txt(有可能成为你的输出文件夹中,图像也):

Example Images.txt (has to be in your output folder, the images also):

Desert.jpg
Hydrangeas.jpg
Jellyfish.jpg
Koala.jpg
Lighthouse.jpg
Penguins.jpg
Tulips.jpg
androids.gif
Chrysanthemum.jpg

和截屏视频:截屏链接

感谢您的帮助!

推荐答案

您可以设置的Horizo​​ntalAlignment VerticalAlignment 你的面具图片为填补像这样:

You can set the HorizontalAlignment and VerticalAlignment of your mask Image to Stretch and the Stretch to Fill like so:

&lt;图像的Horizo​​ntalAlignment =拉伸VerticalAlignment =弹力X:NAME =imgMask拉伸=填充RenderOptions.EdgeMode =别名/&GT;

这将导致掩模图像来填充网格,这将在大小以其他图像

This will cause the mask image to fill the grid, which will be sized to the other image.

这篇关于拼图:设置一个图片相同的大小和位置到另一个图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆