Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 1 | 2 | 3 |

 

  Вопрос: C# : Очень медленно работает код! Добавлено: 04.09.10 11:05  

Автор вопроса:  Лёха | Web-сайт: supersait16.ucoz.ru
В этом коде производится приращение значений r,g,b - по выбору(из ComboBox)
public partial class LavelsRGB : Form
    {
        Bitmap IMG = null;
        BitmapData BmpData = null;
        IntPtr PixPointer = IntPtr.Zero;
        byte[] MSV = null;

        const int Level_R = 0;
        const int Level_G = 1;
        const int Level_B = 2;

        int Step = 0;
        int _Width = 0;
        int _Height = 0;

        public LavelsRGB(Bitmap MainBitmap)
        {
            InitializeComponent();
            if (MainBitmap == null)
                throw new ArgumentException();
            else
            {
                IMG = MainBitmap;
                PreviewBox.Image = (Image)IMG;
            }
            switch (IMG.PixelFormat)
            {
                case PixelFormat.Alpha | PixelFormat.Format32bppArgb | PixelFormat.Format32bppPArgb:
                    {
                        Step = 4;
                        break;
                    }
                case PixelFormat.Format24bppRgb:
                    {
                        Step = 3;
                        break;
                    }
                default:
                    {
                        throw new ArgumentException("Неподходящий формат пикселей!");
                        break;
                    }
            }
            _Width = IMG.Width;
            _Height = IMG.Height;
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            textBox1.Text = trackBar1.Value.ToString();
            int Color_Buffer = 0;
            if (IMG != null)
            {
                BmpData = IMG.LockBits(new Rectangle(0, 0, IMG.Width, IMG.Height),
                    ImageLockMode.ReadWrite, IMG.PixelFormat);
                PixPointer = BmpData.Scan0;
                MSV = new byte[_Height * _Width * Step];
                Marshal.Copy(PixPointer, MSV, 0, MSV.Length);
                switch (comboBox1.SelectedIndex)
                {
                    case Level_R:
                        {
                            for (int AX = 0; AX < BmpData.Width; AX++)
                            {
                                for (int AY = 0; AY < BmpData.Height; AY++)
                                {
                                    Color_Buffer = MSV[((AY * _Width + AX) * Step) + 2];
                                    if ((Color_Buffer != 255) && (Color_Buffer > 0))
                                    {
                                        if (Color_Buffer + trackBar1.Value > 255)
                                            MSV[((AY * _Width + AX) * Step) + 2] = 255;
                                        else if (Color_Buffer + trackBar1.Value < 0)
                                            MSV[((AY * _Width + AX) * Step) + 2] = 1;
                                        else
                                            MSV[((AY * _Width + AX) * Step) + 2] += Convert.ToByte(trackBar1.Value);
                                    }
                                }
                            }
                            break;
                        }
                    case Level_G:
                        {
                            for (int AX = 0; AX < BmpData.Width; AX++)
                            {
                                for (int AY = 0; AY < BmpData.Height; AY++)
                                {
                                    Color_Buffer = MSV[((AY * _Width + AX) * Step) + 1];
                                    if ((Color_Buffer != 255) && (Color_Buffer > 0))
                                    {
                                        if (Color_Buffer + trackBar1.Value > 255)
                                            MSV[((AY * _Width + AX) * Step) + 1] = 255;
                                        else if (Color_Buffer + trackBar1.Value < 0)
                                            MSV[((AY * _Width + AX) * Step) + 1] = 1;
                                        else
                                            MSV[((AY * _Width + AX) * Step) + 1] += Convert.ToByte(trackBar1.Value);
                                    }
                                }
                            }
                            break;
                        }
                    case Level_B:
                        {
                            for (int AX = 0; AX < BmpData.Width; AX++)
                            {
                                for (int AY = 0; AY < BmpData.Height; AY++)
                                {
                                    Color_Buffer = MSV[((AY * _Width + AX) * Step) + 0];
                                    if ((Color_Buffer != 255) && (Color_Buffer > 0))
                                    {
                                        if (Color_Buffer + trackBar1.Value > 255)
                                            MSV[((AY * _Width + AX) * Step) + 0] = 255;
                                        else if (Color_Buffer + trackBar1.Value < 0)
                                            MSV[((AY * _Width + AX) * Step) + 0] = 1;
                                        else
                                            MSV[((AY * _Width + AX) * Step) + 0] += Convert.ToByte(trackBar1.Value);
                                    }
                                }
                            }
                            break;
                        }
                }
                Marshal.Copy(MSV, 0, PixPointer, MSV.Length);
                IMG.UnlockBits(BmpData);
                PreviewBox.Image = (Image)IMG;
            }
        }

    }

Он обробатывает изображение 1024x768 24bpp за 20сек(наверно даже медленнее чем Get/Set Pixel).
В статьях написано что через Lock/Unlock Bits работает быстро, а на деле - 20сек.Это так и должно быть или я коряво написал?

Ответить

  Ответы Всего ответов: 41  

Номер ответа: 1
Автор ответа:
 UnDeAdZak



Вопросов: 80
Ответов: 476
 Профиль | | #1 Добавлено: 04.09.10 11:42
А ты посчитай. 1024*768 = 786432 раза будет проходить твой цикл. Притом каждый раз будет грузится по 24бита информации о цвете.

Ответить

Номер ответа: 2
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #2
Добавлено: 04.09.10 13:09
А как от этого избавиться?

Ответить

Номер ответа: 3
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #3 Добавлено: 04.09.10 14:33
Это так и должно быть или я коряво написал?

Это ты коряво написал...
Зачем тебе циклы по AX и AY? Ширина и высота тут роли не играют.. У тебя есть массив байт в который ты скопировал данные о цвете(MSV).. вот с ним и работай!
Там должен быть 1 цикл по этому массиву.. В зависимости от формата обрабатываешь каждый 3 или 4 байт этого массива и все.. А ты по стопиццот раз прокручиваешь все это в циклах..
Там есть одно НО! Байты расположены в обратном порядке.. т.е. BGRA и BGR соответственно.. Это значит, что твой цикл должен начинаться с позиции байта нужного цвета и шаг приращения тоже будет разным в зависимости от формата(3 или 4). И за 1 проход цикла ты изменишь нужный канал.. Если все верно сделаешь то код будет работать сотые доли секунды..
Надеюсь, объяснил достаточно понятно..

Ответить

Номер ответа: 4
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #4
Добавлено: 04.09.10 15:56
А на примере можешь показать?

Ответить

Номер ответа: 5
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #5 Добавлено: 04.09.10 16:27
лениво..

Ответить

Номер ответа: 6
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #6
Добавлено: 04.09.10 17:25
Напиши пожалуйста...

Ответить

Номер ответа: 7
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #7 Добавлено: 04.09.10 18:10
В общем случае это должно выглядеть примерно так:
  1.  
  2. using System;
  3. using System.Drawing;
  4. using System.Drawing.Imaging;
  5. using System.Runtime.InteropServices;
  6.  
  7. namespace VbNet.Ru
  8. {
  9.     public class ImageHelper
  10.     {
  11.         public event EventHandler ImageChanged;
  12.         private static PixelFormat allowed = PixelFormat.Format24bppRgb | PixelFormat.Format32bppRgb | PixelFormat.Format32bppArgb;
  13.  
  14.         int bytesInPixel;
  15.         byte[] originBytes;
  16.  
  17.         public ImageHelper(Bitmap origin)
  18.         {
  19.             if (origin == null) throw new ArgumentNullException();
  20.             if ((allowed & origin.PixelFormat) != origin.PixelFormat) throw new NotSupportedException();
  21.  
  22.             Image = new Bitmap(origin);
  23.             Initialize();
  24.         }
  25.  
  26.         private void Initialize()
  27.         {
  28.             bytesInPixel = (Image.PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3;
  29.             originBytes = new byte[Image.Width * Image.Height * bytesInPixel];
  30.             BitmapData bitmapData = Image.LockBits(new Rectangle(0, 0, Image.Width, Image.Height), ImageLockMode.ReadOnly, Image.PixelFormat);
  31.             Marshal.Copy(bitmapData.Scan0, originBytes, 0, originBytes.Length);
  32.             Image.UnlockBits(bitmapData);
  33.         }
  34.  
  35.         public void SetLevel(Levels level, int offset)
  36.         {
  37.             if (offset < -255 || offset > 255) throw new ArgumentOutOfRangeException();
  38.             byte[] imageBytes = new byte[originBytes.Length];
  39.             BitmapData bitmapData = Image.LockBits(new Rectangle(0, 0, Image.Width, Image.Height), ImageLockMode.ReadWrite, Image.PixelFormat);
  40.             IntPtr pointer = bitmapData.Scan0;
  41.             Marshal.Copy(pointer, imageBytes, 0, imageBytes.Length);
  42.             for (int i = (int)level; i < imageBytes.Length; i += bytesInPixel)
  43.             {
  44.                 int value = originBytes+offset;
  45.                 if (value > 255) value = 255;
  46.                 if (value < 0) value = 0;
  47.                 imageBytes = (byte)value;
  48.             }
  49.             Marshal.Copy(imageBytes, 0, pointer, imageBytes.Length);
  50.             Image.UnlockBits(bitmapData);
  51.             OnImageChanged();
  52.         }
  53.  
  54.         #region properties...
  55.         public Bitmap Image { get; private set; }
  56.         #endregion
  57.         #region OnImageChanged
  58.         public virtual void OnImageChanged()
  59.         {
  60.             if (ImageChanged != null)
  61.                 ImageChanged(this, EventArgs.Empty);
  62.         }
  63.         #endregion
  64.     }
  65. }




Пример использования (тестовый проект C# FW 3.5) выложил тут:
http://clip2net.com/s/w2v5

Ответить

Номер ответа: 8
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #8 Добавлено: 04.09.10 18:27
тут косяк форума.. переменную i в квадратных скобках он расценил как тег форматирования.. поэтому код бери из исходников..

Ответить

Номер ответа: 9
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #9
Добавлено: 04.09.10 23:41
Огромное спасибо!

Ответить

Номер ответа: 10
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #10 Добавлено: 05.09.10 09:03
Тут львиная доля времени тратится на копирование куска памяти в массив байт и обратно, и в идеале, этот код можно еще ускорить. Поскольку мы имеем указатель на первый байт картинки в памяти(Scan0) то, заюзав unsafe mode + указатель, можно ничего не копируя модифицировать данные о цвете напрямую в памяти. Но для этого ты должен быть знаком с С++ и указателями..

Ответить

Номер ответа: 11
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #11
Добавлено: 06.09.10 18:46
Сделал так как ты сказал,но вот что он делает(в исходнике всё работает нормльно,а у меня...) - http://www.supersait16.ucoz.ru/FTP/snimok.jpg
  1. public partial class LavelRGB : Form
  2.     {
  3.         public enum CorrectionLevel
  4.         {
  5.             Blue = 0, Green = 1, Red = 2
  6.         }
  7.  
  8.         public Bitmap IMG;
  9.  
  10.         private int BytesInPixel;
  11.         private byte[] OriginBytes;
  12.  
  13.         public LavelRGB(Bitmap MainBitmap)
  14.         {
  15.             InitializeComponent();
  16.             if (MainBitmap == null)
  17.             {
  18.                 throw new ArgumentNullException();
  19.             }
  20.  
  21.             if (MainBitmap.PixelFormat == PixelFormat.Format32bppArgb)
  22.             {
  23.                 BytesInPixel = 4;
  24.             }
  25.             else if (MainBitmap.PixelFormat == PixelFormat.Format24bppRgb)
  26.             {
  27.                 BytesInPixel = 3;
  28.             }
  29.             else
  30.             {
  31.                 throw new NotSupportedException("Неподходяший формат пикселей!");
  32.             }
  33.             IMG = new Bitmap(MainBitmap);
  34.             PreviewBox.Image = (Image)IMG;
  35.             Initialize();
  36.         }
  37.         private void Initialize()
  38.         {
  39.             OriginBytes = new byte[IMG.Height * IMG.Width * BytesInPixel];
  40.             BitmapData BmpData = IMG.LockBits(new Rectangle(0, 0, IMG.Width, IMG.Height),
  41.                 ImageLockMode.ReadOnly, IMG.PixelFormat);
  42.             Marshal.Copy(BmpData.Scan0, OriginBytes, 0, OriginBytes.Length);
  43.             IMG.UnlockBits(BmpData);
  44.         }
  45.         private void CorrectLevel(CorrectionLevel Level, int Offset)
  46.         {
  47.             if ((Offset < -255) || (Offset > 255))
  48.                 throw new ArgumentException();
  49.             byte[] ImageBytes = new byte[OriginBytes.Length];
  50.             BitmapData BData = IMG.LockBits(new Rectangle(0, 0, IMG.Width, IMG.Height),
  51.                 ImageLockMode.ReadWrite, IMG.PixelFormat);
  52.             IntPtr Pointer = BData.Scan0;
  53.             Marshal.Copy(Pointer, ImageBytes, 0, ImageBytes.Length);
  54.             for (int I = Convert.ToInt32(Level); I < ImageBytes.Length; I += BytesInPixel)
  55.             {
  56.                 int Value = OriginBytes + Offset;
  57.                 if (Value > 255) Value = 255;
  58.                 if (Value < 0) Value = 0;
  59.                 ImageBytes = Convert.ToByte(Value);
  60.             }
  61.             Marshal.Copy(ImageBytes, 0, Pointer, ImageBytes.Length);
  62.             IMG.UnlockBits(BData);
  63.             PreviewBox.Image = (Image)IMG;
  64.         }
  65.         public Bitmap MainImage
  66.         {
  67.             get { return IMG; }
  68.         }
  69.  
  70.         private void Track_Red_Scroll(object sender, EventArgs e)
  71.         {
  72.             ValueRed.Text = Track_Red.Value.ToString();
  73.             CorrectLevel(CorrectionLevel.Red, Track_Red.Value);
  74.         }
  75.  
  76.         private void ValueRed_TextChanged(object sender, EventArgs e)
  77.         {
  78.             Track_Red.Value = Convert.ToInt32(ValueRed.Text);
  79.         }
  80.  
  81.         private void Track_Green_Scroll(object sender, EventArgs e)
  82.         {
  83.             ValueGreen.Text = Track_Green.Value.ToString();
  84.             CorrectLevel(CorrectionLevel.Green, Track_Green.Value);
  85.         }
  86.  
  87.         private void ValueGreen_TextChanged(object sender, EventArgs e)
  88.         {
  89.             Track_Green.Value = Convert.ToInt32(ValueGreen.Text);
  90.         }
  91.  
  92.         private void Track_Blue_Scroll(object sender, EventArgs e)
  93.         {
  94.             ValueBlue.Text = Track_Blue.Value.ToString();
  95.             CorrectLevel(CorrectionLevel.Blue, Track_Blue.Value);
  96.         }
  97.  
  98.         private void ValueBlue_TextChanged(object sender, EventArgs e)
  99.         {
  100.             Track_Blue.Value = Convert.ToInt32(ValueBlue.Text);
  101.         }
  102.     }

Ответить

Номер ответа: 12
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #12
Добавлено: 06.09.10 18:47
В чём проблема?

Ответить

Номер ответа: 13
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #13 Добавлено: 06.09.10 19:02
В чём проблема?

в руках...

Ответить

Номер ответа: 14
Автор ответа:
 Лёха



Вопросов: 20
Ответов: 79
 Web-сайт: supersait16.ucoz.ru
 Профиль | | #14
Добавлено: 06.09.10 19:21
Наверно,что я не правильно написал? ...проверил-вроде так как надо

Ответить

Номер ответа: 15
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #15 Добавлено: 06.09.10 19:29
Дружище, без обид - включай моцк.. Я потратил время, чтоб написать для тебя рабочий пример, а ты не желаешь потратить время чтоб найти косяк в своем коде?

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам