Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Как повысить быстродействие при работе с Gif


Автор: libman 26.6.2007, 19:21
Задача стоит так, необходимо подсчитать количество цветов которые встречаются в картинке. Использую следующий код. Т.к. я не самый великий программист в этом мире то и скорость работы не велика, что можете подсказать для увеличения быстродействия. Мой код ниже.
Есть мысль попробовать с несколькими потоками или я не прав?


 Color[] masOfColor = new Color[256];
            Bitmap bmp = new Bitmap(@"test.gif");
            int NumberOfLast = 0;
            for (int x = 0; x < bmp.Height; x++)
            {
                for (int y = 0; y < bmp.Width; y++)
                {
                    Color c = bmp.GetPixel(y, x);
                    bool flag = false;
                    for (int i = 0; i < NumberOfLast; i++)
                    {
                        if (c == masOfColor[i])
                            flag = true;
                    }
                    if (flag==false)
                    {
                        masOfColor[NumberOfLast] = c;
                        if (NumberOfLast<masOfColor.Length)
                        {
                            NumberOfLast++;
                        }                            
                    }
                }
            }

Автор: libman 26.6.2007, 19:45
Извеняюсь за опечатку в названии темы не Jig а Gif

Автор: stab 26.6.2007, 23:58
всё намного проще: bmp.Palette.Entries.Length вернёт тебе кол-во цветов для индексированных битмапов. GIF как раз-таки индексированный формат.

Добавлено @ 00:06
после тестов стало ясно, что размер палитры для GIF всегда есть спенень двойки, даже если цветов меньше. вот решение:

Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace Vingrad.GifColorCount
{
    class Program
    {
        static void Main(string[] args)
        {
            Bitmap gif = new Bitmap(@"test.gif");
            Console.WriteLine("Color count: {0}", CountColors(gif));
            Console.WriteLine("Palette length: {0}", gif.Palette.Entries.Length);
            Console.ReadLine();
            gif.Dispose();
        }

        public static unsafe byte CountColors(Bitmap bitmap)
        {
            if (bitmap == null || bitmap.PixelFormat != PixelFormat.Format8bppIndexed)
            {
                throw new ArgumentException();
            }

            uint[] colorCounters = new uint[bitmap.Palette.Entries.Length];
            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
            if (data != null)
            {
                byte* pixel = (byte*) data.Scan0;
                for (int y = 0; y < bitmap.Height; y++)
                {
                    for (int x = 0; x < bitmap.Width; x++)
                    {
                        colorCounters[pixel[x]]++;
                    }
                    pixel += data.Stride;
                }
                bitmap.UnlockBits(data);
            }

            byte result = 0;
            for (int i = 0; i < colorCounters.Length; i++)
            {
                if (colorCounters[i] != 0)
                {
                    result++;
                }
            }

            return result;
        }
    }
}


помимо всего прочего, пример можно адаптировать для подсчёта кол-ва вхождений определённого цвета, что уже делается, но не возвращается в качестве результата.

Добавлено @ 00:09
для проекта надо разрешить unsafe код: Project Properties -> Build -> Allow unsafe code

Автор: tol05 27.6.2007, 17:13
Хороший пример. 
cully, ты не мог бы прокомментировать его? Я в графике не силен, хотелось бы подъучиться... smile
в принципе, вот эту часть
Код

 for (int x = 0; x < bitmap.Width; x++)
{
    colorCounters[pixel[x]]++;
}
pixel += data.Stride;

Автор: stab 27.6.2007, 19:52
Цитата(tol05 @  27.6.2007,  21:13 Найти цитируемый пост)
colorCounters[pixel[x]]++;

битмап в формате 8bppIndexed, т.е. один пиксель - один байт, значение этого байта и используется для индексации в массиве счётчиков.

Цитата(tol05 @  27.6.2007,  21:13 Найти цитируемый пост)
pixel += data.Stride;

переход к следующему скану, data.Stride - обычно равно Width * (размер одного пикселя в байтах), но не всегда, т.к. может быть выравнивание или битмап может быть окном в другой битмап.

Автор: tol05 27.6.2007, 20:24
блин, полчаса пялился в твои строчки... И понял!!! 
Спасибо!  smile 


Круто, действительно круто...

Автор: libman 30.6.2007, 12:25
Огромое спасибо

Еще маленький вопрос. как сделать так что бы можно было определить на какой стадии находится выполнение. Т.е. как в методе который вы написали  public static unsafe byte CountColors(Bitmap bitmap), заставить двигаться полоску в компоненте progressBar который мы кинули на форму?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)