C # WinForms - DrawImage без потери анимации - PullRequest
1 голос
/ 28 ноября 2011

Как DrawImage без потери анимации?

        pictureBox1.Image = new Bitmap(20, 20);
        Graphics g = Graphics.FromImage(pictureBox1.Image);
        Image i = Properties.Resources.SuperMario; //Animated GIF; sprite; 20px X 20px
        g.DrawImage(i, 
            new Rectangle(0, 0, 20, 20),
            new Rectangle(0, 0, 20, 20),
            GraphicsUnit.Pixel);
        pictureBox1.Refresh();

Приведенные выше коды копируют часть изображения из анимированного листа спрайта (формат GIF) в PictureBox 'Image.К сожалению, анимация потеряна.

Это спрайт: http://www.google.com/imgres?q=sprite+20x20&um=1&hl=en&client=firefox-a&rls=org.mozilla:en-US:official&biw=1067&bih=671&tbm=isch&tbnid=ulN4JRy6N4ToSM:&imgrefurl=http://nkelsch.deviantart.com/art/Super-Mario-20x20-Sprites-83482505&docid=GOCF1PgjPytbPM&imgurl=http://www.deviantart.com/download/83482505/Super_Mario_20x20_Sprites_by_nkelsch.gif&w=251&h=356&ei=4orQTvXPIKePiAerio24Dg&zoom=1&iact=hc&vpx=89&vpy=154&dur=7579&hovh=267&hovw=188&tx=131&ty=137&sig=107474527571502851152&page=1&tbnh=122&tbnw=86&start=0&ndsp=18&ved=1t:429,r:0,s:0

Заранее спасибо.

Ответы [ 5 ]

1 голос
/ 29 ноября 2011
    class WinForm : Form
    {
        bool FrameLoop = false;
        int FrameIndex = 0;
        int FrameCount = 0;
        FrameDimension FrameDimension = null;
        List<int> DelayTime = new List<int>();
        Image img;

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            this.DoubleBuffered = true;
            img = Image.FromFile("C:\\debug.gif");
            if (img.FrameDimensionsList != null)
                foreach (Guid i in img.FrameDimensionsList)
                {
                    FrameDimension = new FrameDimension(i);
                    FrameCount = img.GetFrameCount(FrameDimension);
                }
            if (FrameCount > 1)
            {
                foreach (PropertyItem i in img.PropertyItems)
                {
                    if (i.Id == 0x5100)
                    {
                        for (int j = 0; j < FrameCount; j++)
                        {
                            DelayTime.Add(BitConverter.ToInt32(i.Value, j * 4));
                        }
                    }
                    else if (i.Id == 0x5101)
                    {
                        FrameLoop = true;
                    }
                }
                this.BeginInvoke(new EventHandler(Animation));
            }
        }

        private void Animation(object sender,EventArgs e)
        {
            img.SelectActiveFrame(FrameDimension, FrameIndex);
            this.Refresh();
            Application.DoEvents();
            Thread.Sleep(DelayTime[FrameIndex] * 10);

            FrameIndex++;
            if (FrameIndex >= FrameCount)
            {
                if (FrameLoop)
                    FrameIndex = 0;
                else
                    return;
            }
            Animation(sender, e);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (img == null)
                return;
            e.Graphics.DrawImage(img, new Point(0, 0));
            //base.OnPaint(e);
        }
    }
1 голос
/ 28 ноября 2011

Вы можете перейти по ссылке, чтобы получить исходный код http://www.codeproject.com/KB/GDI-plus/NGif.aspx

1 голос
/ 28 ноября 2011

Загрузите весь gif в графическом окне и расположите его так, чтобы в графическом окне отображалась только соответствующая часть. Вот как работают спрайты. Вам не нужно копировать часть определенного кадра, потому что да, это явно потеряло бы анимацию.

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

1 голос
/ 28 ноября 2011

PictureBox по сути понимает анимированные GIF-файлы.

Почему вам нужно нарисовать его вручную в вашем методе обновления?

Этого должно быть достаточно, чтобы сделать PictureBox, установить анимированный GIF как Image из PictureBox.

Также убедитесь, что вы не запускаете какой-либо код блокировки в потоке графического интерфейса, поскольку это не позволит запустить анимацию.

1 голос
/ 28 ноября 2011

Вы должны будете использовать какой-то таймер / поток, чтобы постоянно обновлять изображение с правильной скоростью анимации.graphics.drawImage рисует изображение только один раз во время его вызова, оно не понимает анимацию.

Если вы действительно хотите использовать этот метод анимации, вы должны держать переменную вокруг, чтобы удерживать индекс кадра.Удалите компонент Timer на форму и включите его с интервалом анимации.Когда таймер сработает, увеличьте счетчик кадров, затем очистите и перерисовайте графический блок, используя границы кадра с новым индексом.Вы должны обернуть свой счетчик кадров обратно в 0, когда он превышает максимальный кадр в вашей анимации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...